refactor: Extract per-language configs and standalone extractors from tree-sitter.ts
Splits the monolithic tree-sitter.ts (3,358 lines) into modular files: - 14 language config files under src/extraction/languages/ - 3 standalone extractors (Liquid, Svelte, DFM) - Shared helpers and types modules to avoid circular imports Also fixes a bug where Java's extractImport hook incorrectly set handledRefs: true, preventing unresolved reference creation and degrading codegraph_explore results for Java codebases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
0d63166f9d
commit
c8407ad007
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Tree-sitter Shared Helpers
|
||||
*
|
||||
* Utility functions used by the core TreeSitterExtractor and per-language extractors.
|
||||
* Extracted to a leaf module to avoid circular imports between tree-sitter.ts and languages/.
|
||||
*/
|
||||
|
||||
import { Node as SyntaxNode } from 'web-tree-sitter';
|
||||
import * as crypto from 'crypto';
|
||||
import { NodeKind } from '../types';
|
||||
|
||||
/**
|
||||
* Generate a unique node ID
|
||||
*
|
||||
* Uses a 32-character (128-bit) hash to avoid collisions when indexing
|
||||
* large codebases with many files containing similar symbols.
|
||||
*/
|
||||
export function generateNodeId(
|
||||
filePath: string,
|
||||
kind: NodeKind,
|
||||
name: string,
|
||||
line: number
|
||||
): string {
|
||||
const hash = crypto
|
||||
.createHash('sha256')
|
||||
.update(`${filePath}:${kind}:${name}:${line}`)
|
||||
.digest('hex')
|
||||
.substring(0, 32);
|
||||
return `${kind}:${hash}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract text from a syntax node
|
||||
*/
|
||||
export function getNodeText(node: SyntaxNode, source: string): string {
|
||||
return source.substring(node.startIndex, node.endIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a child node by field name
|
||||
*/
|
||||
export function getChildByField(node: SyntaxNode, fieldName: string): SyntaxNode | null {
|
||||
return node.childForFieldName(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the docstring/comment preceding a node
|
||||
*/
|
||||
export function getPrecedingDocstring(node: SyntaxNode, source: string): string | undefined {
|
||||
let sibling = node.previousNamedSibling;
|
||||
const comments: string[] = [];
|
||||
|
||||
while (sibling) {
|
||||
if (
|
||||
sibling.type === 'comment' ||
|
||||
sibling.type === 'line_comment' ||
|
||||
sibling.type === 'block_comment' ||
|
||||
sibling.type === 'documentation_comment'
|
||||
) {
|
||||
comments.unshift(getNodeText(sibling, source));
|
||||
sibling = sibling.previousNamedSibling;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (comments.length === 0) return undefined;
|
||||
|
||||
// Clean up comment markers
|
||||
return comments
|
||||
.map((c) =>
|
||||
c
|
||||
.replace(/^\/\*\*?|\*\/$/g, '')
|
||||
.replace(/^\/\/\s?/gm, '')
|
||||
.replace(/^\s*\*\s?/gm, '')
|
||||
.trim()
|
||||
)
|
||||
.join('\n')
|
||||
.trim();
|
||||
}
|
||||
Reference in New Issue
Block a user