Detect Java annotation-based WebSocket listeners: @OnMessage, @MessageMapping */
| 685 | |
| 686 | /* Detect Java annotation-based WebSocket listeners: @OnMessage, @MessageMapping */ |
| 687 | static void java_process_annotation(CBMExtractCtx *ctx, TSNode annotation) { |
| 688 | TSNode name_node = ts_node_child_by_field_name(annotation, TS_FIELD("name")); |
| 689 | if (ts_node_is_null(name_node)) { |
| 690 | return; |
| 691 | } |
| 692 | char *name = cbm_node_text(ctx->arena, name_node, ctx->source); |
| 693 | if (!name) { |
| 694 | return; |
| 695 | } |
| 696 | |
| 697 | if (strcmp(name, "OnMessage") == 0 || strcmp(name, "OnOpen") == 0 || |
| 698 | strcmp(name, "OnClose") == 0) { |
| 699 | const char *func_name = enclosing_function_qn(ctx, annotation); |
| 700 | const char *channel_name = func_name ? func_name : "(websocket)"; |
| 701 | push_channel(ctx, channel_name, "websocket", CBM_CHANNEL_LISTEN, annotation); |
| 702 | } else if (strcmp(name, "MessageMapping") == 0) { |
| 703 | /* @MessageMapping("/path") — extract the path */ |
| 704 | TSNode args = ts_node_child_by_field_name(annotation, TS_FIELD("arguments")); |
| 705 | if (!ts_node_is_null(args)) { |
| 706 | const char *path = extract_channel_name(ctx, args, NULL); |
| 707 | if (path) { |
| 708 | push_channel(ctx, path, "spring_websocket", CBM_CHANNEL_LISTEN, annotation); |
| 709 | return; |
| 710 | } |
| 711 | } |
| 712 | push_channel(ctx, "(spring_ws)", "spring_websocket", CBM_CHANNEL_LISTEN, annotation); |
| 713 | } else if (strcmp(name, "ServerEndpoint") == 0) { |
| 714 | TSNode args = ts_node_child_by_field_name(annotation, TS_FIELD("arguments")); |
| 715 | if (!ts_node_is_null(args)) { |
| 716 | const char *path = extract_channel_name(ctx, args, NULL); |
| 717 | if (path) { |
| 718 | push_channel(ctx, path, "websocket", CBM_CHANNEL_LISTEN, annotation); |
| 719 | return; |
| 720 | } |
| 721 | } |
| 722 | } |
| 723 | } |
| 724 | |
| 725 | static void extract_channels_java(CBMExtractCtx *ctx) { |
| 726 | TSNodeStack stack; |
no test coverage detected