| 6080 | } |
| 6081 | |
| 6082 | static void extract_lisp_def(CBMExtractCtx *ctx, TSNode node) { |
| 6083 | CBMArena *a = ctx->arena; |
| 6084 | if (ts_node_named_child_count(node) < 2) { |
| 6085 | return; |
| 6086 | } |
| 6087 | char *head = cbm_node_text(a, ts_node_named_child(node, 0), ctx->source); |
| 6088 | if (!lisp_is_def_head(head)) { |
| 6089 | return; |
| 6090 | } |
| 6091 | TSNode target = ts_node_named_child(node, 1); |
| 6092 | const char *tk = ts_node_type(target); |
| 6093 | TSNode name_node = target; |
| 6094 | // (define (foo args) ...) — the name is the head symbol of the nested list. |
| 6095 | if ((strcmp(tk, "list") == 0 || strcmp(tk, "list_lit") == 0) && |
| 6096 | ts_node_named_child_count(target) > 0) { |
| 6097 | name_node = ts_node_named_child(target, 0); |
| 6098 | } |
| 6099 | if (ts_node_is_null(name_node)) { |
| 6100 | return; |
| 6101 | } |
| 6102 | char *name = cbm_node_text(a, name_node, ctx->source); |
| 6103 | if (!name || !name[0]) { |
| 6104 | return; |
| 6105 | } |
| 6106 | /* struct/record/type defining forms produce a type node, not a callable |
| 6107 | * (Racket `(struct point ...)`, Clojure `(defrecord ...)`, etc.). */ |
| 6108 | const char *lisp_label = "Function"; |
| 6109 | if (strcmp(head, "struct") == 0 || strcmp(head, "define-struct") == 0 || |
| 6110 | strcmp(head, "define-record-type") == 0 || strcmp(head, "defrecord") == 0 || |
| 6111 | strcmp(head, "deftype") == 0) { |
| 6112 | lisp_label = "Struct"; |
| 6113 | } else if (strcmp(head, "definterface") == 0 || strcmp(head, "defprotocol") == 0) { |
| 6114 | lisp_label = "Interface"; |
| 6115 | } |
| 6116 | CBMDefinition def; |
| 6117 | memset(&def, 0, sizeof(def)); |
| 6118 | def.name = name; |
| 6119 | def.qualified_name = cbm_fqn_compute(a, ctx->project, ctx->rel_path, name); |
| 6120 | def.label = lisp_label; |
| 6121 | def.file_path = ctx->rel_path; |
| 6122 | def.start_line = ts_node_start_point(node).row + TS_LINE_OFFSET; |
| 6123 | def.end_line = ts_node_end_point(node).row + TS_LINE_OFFSET; |
| 6124 | def.lines = (int)(def.end_line - def.start_line + TS_LINE_OFFSET); |
| 6125 | def.is_exported = true; |
| 6126 | cbm_defs_push(&ctx->result->defs, a, def); |
| 6127 | } |
| 6128 | |
| 6129 | /* Kotlin ERROR-node class recovery. |
| 6130 | * |
no test coverage detected