TreeSitterPlugin is the built-in implementation of AnalyzerPlugin for JavaScript and TypeScript. It uses web-tree-sitter — a WebAssembly build of the tree-sitter parsing library — to parse source files into concrete syntax trees and extract structural information without spawning any native processes.
Why web-tree-sitter (WASM) instead of native bindings
The nativetree-sitter npm package relies on N-API native addons that must be compiled for the specific platform, Node.js version, and CPU architecture at install time. On darwin/arm64 with Node.js 24 this compilation fails consistently.
web-tree-sitter ships pre-compiled .wasm files that run inside Node.js’s built-in WebAssembly runtime with no native compilation step, making it portable across all platforms and Node.js versions.
Class: TreeSitterPlugin
init
Loads the WASM runtime and all language grammars. Must be called and awaited before any other method.init() a second time is safe — it returns immediately if already initialized.
During initialization the plugin:
- Imports
web-tree-sitterand callsParser.init()to boot the WASM runtime. - Resolves the
.wasmgrammar files for TypeScript (.ts), TSX (.tsx), and JavaScript (.js/.mjs/.cjs/.jsx) viacreateRequire. - Loads all three grammars in parallel with
Promise.all.
Language support
| File extension | Language key | Grammar |
|---|---|---|
.ts | typescript | tree-sitter-typescript/tree-sitter-typescript.wasm |
.tsx | tsx | tree-sitter-typescript/tree-sitter-tsx.wasm |
.js, .mjs, .cjs, .jsx | javascript | tree-sitter-javascript/tree-sitter-javascript.wasm |
PluginRegistry, the plugin’s languages array (["typescript", "javascript"]) is used for routing. Both typescript and tsx files are handled through the "typescript" language mapping; the correct WASM grammar is selected internally based on the actual file extension.
analyzeFile
Parses a file and extracts all structural declarations.Path to the source file. Used to select the correct grammar (
.ts → TypeScript, .tsx → TSX, .js/.mjs/.cjs/.jsx → JavaScript).Full source code of the file as a string.
StructuralAnalysis. If tree-sitter fails to produce a tree, an empty analysis { functions: [], classes: [], imports: [], exports: [] } is returned.
The parser and tree are explicitly deleted after use to avoid WASM memory leaks.
What is extracted
- Functions —
functiondeclarations, arrow functions, and function expressions assigned to variables. Captures name, line range, parameter names (including rest params), and return type annotation. - Classes — Class declarations with name, line range, method names, and property names.
- Imports — All
importstatements: named imports, default imports, and namespace imports (* as name). - Exports — All
exportstatements: named exports, default exports, and re-exports.
resolveImports
Parses import statements and resolves relative specifiers to absolute paths.Path to the source file. Used as the base directory for resolving relative imports (
./, ../).Full source code of the file.
analyzeFile and maps the imports array:
- Specifiers starting with
./or../are resolved withnode:path’sresolve(dir, source). - All other specifiers (package imports) are passed through unchanged.
extractCallGraph
Extracts caller→callee relationships by walking the AST and tracking function scope.Path to the source file.
Full source code of the file.
CallGraphEntry. Returns an empty array if the file cannot be parsed.
How scope tracking works
The method performs a recursive AST walk maintaining afunctionStack:
- When entering a
function_declaration,method_definition,arrow_function, orfunction_expressionnode, the function’s name is pushed onto the stack. - When a
call_expressionis encountered and the stack is non-empty, aCallGraphEntryis emitted withcaller = stack.top,callee = callee expression text, and the line number. - When leaving the function node, its name is popped from the stack.
variable_declarator node.