(node: any)
| 117 | } |
| 118 | |
| 119 | function visit(node: any) { |
| 120 | let kind = typeToKind.get(node.type); |
| 121 | // Rust maps `function_item` to BOTH `function` and `method`, so the flat |
| 122 | // type→kind map can't tell them apart (last write wins). Disambiguate by |
| 123 | // context: a `fn` enclosed in an impl/trait block is a method, otherwise a |
| 124 | // free function. |
| 125 | if (lang === 'rust' && node.type === 'function_item') { |
| 126 | let cur = node.parent; |
| 127 | let insideImplOrTrait = false; |
| 128 | while (cur) { |
| 129 | if (cur.type === 'impl_item' || cur.type === 'trait_item') { insideImplOrTrait = true; break; } |
| 130 | cur = cur.parent; |
| 131 | } |
| 132 | kind = insideImplOrTrait ? 'method' : 'function'; |
| 133 | } |
| 134 | if (kind) { |
| 135 | const name = getName(node); |
| 136 | if (name) { |
| 137 | const parentName = getEnclosingNamedSymbol(node); |
| 138 | // Build a tiny signature: first line of the symbol, capped |
| 139 | const sig = (node.text ?? '').split('\n')[0]?.slice(0, 200) ?? ''; |
| 140 | symbols.push({ |
| 141 | name, |
| 142 | kind, |
| 143 | startLine: node.startPosition.row + 1, |
| 144 | endLine: node.endPosition.row + 1, |
| 145 | startColumn: node.startPosition.column, |
| 146 | parentName: parentName ?? undefined, |
| 147 | signature: sig, |
| 148 | }); |
| 149 | } |
| 150 | } |
| 151 | for (let i = 0; i < node.childCount; i++) { |
| 152 | const c = node.child(i); |
| 153 | if (c) visit(c); |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | visit(root); |
| 158 | return symbols; |
no test coverage detected