Something went wrong. Try again.
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394/* eslint-disable @typescript-eslint/no-explicit-any */import type { SymbolInfo } from '@/contracts/code-intelligence';
/** Extract a declaration, unwrapping export/decorator containers. */export function declarationSymbol(node: any, source: string, kinds: ReadonlyMap<string, string>): SymbolInfo | undefined { const wrapped = node.namedChildren?.find((child: any) => kinds.has(child.type)); const declaration = wrapped ?? node; const kind = kinds.get(declaration.type); if (!kind) return undefined; const nameNode = declaration.childForFieldName?.('name') ?? declaration.childForFieldName?.('left'); const name = nameNode?.text ?? declarationName(declaration) ?? (declaration.type === 'impl_item' ? implName(declaration) : undefined); if (!name) return undefined; const start = declaration.startPosition.row; const end = Math.max(start, declaration.endPosition.row); const firstLineEnd = source.indexOf('\n', declaration.startIndex); const line = source.slice(declaration.startIndex, firstLineEnd < 0 ? source.length : firstLineEnd); const signature = compactSignature(line); return { name, kind, range: [start, end], signature };}
function declarationName(node: any): string | undefined { const preferred = new Set(['type_identifier', 'identifier', 'field_identifier', 'property_identifier']); const visit = (candidate: any): string | undefined => { if (preferred.has(candidate.type)) return candidate.text; const named = candidate.childForFieldName?.('name'); if (named?.text) return named.text; for (const child of candidate.namedChildren ?? []) { const found = visit(child); if (found) return found; } return undefined; }; return visit(node);}
function implName(node: any): string | undefined { const target = node.childForFieldName?.('type')?.text; if (target) return target; const text = node.text.replace(/^impl\s+/, '').replace(/\s*\{[\s\S]*$/, '').trim(); return text.split(/\s+for\s+/).pop()?.trim() || 'impl';}
function compactSignature(line: string): string { return line .trim() .replace(/\s+/g, ' ') .replace(/\s*\{.*$/, '') .slice(0, 240);}
/** Collect a top-level declaration and selected nested declarations in source order. */export function declarationSymbols( node: any, source: string, kinds: ReadonlyMap<string, string>, nestedKinds: ReadonlyMap<string, string>, containers: ReadonlySet<string> = new Set(),): SymbolInfo[] { const symbols: SymbolInfo[] = []; const outer = declarationSymbol(node, source, kinds); if (outer) symbols.push(outer); collectContainerMembers(node, source, nestedKinds, containers, symbols); return symbols.sort((a, b) => (a.range?.[0] ?? 0) - (b.range?.[0] ?? 0));}
function collectContainerMembers( node: any, source: string, nestedKinds: ReadonlyMap<string, string>, containers: ReadonlySet<string>, output: SymbolInfo[],): void { if (containers.has(node.type)) { collectNested(node, source, nestedKinds, output); return; } for (const child of node.namedChildren ?? []) { collectContainerMembers(child, source, nestedKinds, containers, output); }}
function collectNested( node: any, source: string, nestedKinds: ReadonlyMap<string, string>, output: SymbolInfo[],): void { for (const child of node.namedChildren ?? []) { const symbol = declarationSymbol(child, source, nestedKinds); if (symbol) output.push(symbol); else collectNested(child, source, nestedKinds, output); }}