diff --git a/understand-anything-plugin/packages/core/src/plugins/extractors/base-extractor.ts b/understand-anything-plugin/packages/core/src/plugins/extractors/base-extractor.ts new file mode 100644 index 0000000..814462f --- /dev/null +++ b/understand-anything-plugin/packages/core/src/plugins/extractors/base-extractor.ts @@ -0,0 +1,52 @@ +import type { TreeSitterNode } from "./types.js"; + +/** Recursively traverse an AST tree, calling the visitor for each node. */ +export function traverse( + node: TreeSitterNode, + visitor: (node: TreeSitterNode) => void, +): void { + visitor(node); + for (let i = 0; i < node.childCount; i++) { + const child = node.child(i); + if (child) traverse(child, visitor); + } +} + +/** Extract the unquoted string value from a string-like node. */ +export function getStringValue(node: TreeSitterNode): string { + for (let i = 0; i < node.childCount; i++) { + const child = node.child(i); + if (child && child.type === "string_fragment") { + return child.text; + } + } + return node.text.replace(/^['"`]|['"`]$/g, ""); +} + +/** Find the first child matching a type. */ +export function findChild(node: TreeSitterNode, type: string): TreeSitterNode | null { + for (let i = 0; i < node.childCount; i++) { + const child = node.child(i); + if (child && child.type === type) return child; + } + return null; +} + +/** Find all children matching a type. */ +export function findChildren(node: TreeSitterNode, type: string): TreeSitterNode[] { + const result: TreeSitterNode[] = []; + for (let i = 0; i < node.childCount; i++) { + const child = node.child(i); + if (child && child.type === type) result.push(child); + } + return result; +} + +/** Check if a node has a child of the given type (used for export/visibility checks). */ +export function hasChildOfType(node: TreeSitterNode, type: string): boolean { + for (let i = 0; i < node.childCount; i++) { + const child = node.child(i); + if (child && child.type === type) return true; + } + return false; +} diff --git a/understand-anything-plugin/packages/core/src/plugins/extractors/types.ts b/understand-anything-plugin/packages/core/src/plugins/extractors/types.ts new file mode 100644 index 0000000..2370ebe --- /dev/null +++ b/understand-anything-plugin/packages/core/src/plugins/extractors/types.ts @@ -0,0 +1,19 @@ +import type { StructuralAnalysis, CallGraphEntry } from "../../types.js"; + +// Re-export the tree-sitter Node type for use by extractors +export type TreeSitterNode = import("web-tree-sitter").Node; + +/** + * Language-specific extractor that maps a tree-sitter AST + * to the common StructuralAnalysis / CallGraphEntry types. + */ +export interface LanguageExtractor { + /** Language IDs this extractor handles (must match LanguageConfig.id) */ + languageIds: string[]; + + /** Extract functions, classes, imports, exports from the root AST node */ + extractStructure(rootNode: TreeSitterNode): StructuralAnalysis; + + /** Extract caller→callee relationships from the root AST node */ + extractCallGraph(rootNode: TreeSitterNode): CallGraphEntry[]; +}