feat(core): AST-based pattern analysis via tree-sitter queries#16
Merged
Conversation
Replace ast-grep CLI approach with tree-sitter queries using WASM we already bundle. Key changes: PatternMatcher interface for future NAPI swap, PatternRule DSL translated to S-expressions, zero new dependencies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add typescript, tsx, and javascript to TreeSitterLanguage type and SUPPORTED_LANGUAGES. Covers the full Node/frontend ecosystem: .ts, .tsx, .js, .jsx files. Bundle size: +5.3MB WASM (TS 2.3MB + TSX 2.3MB + JS 647KB). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PatternMatcher interface with WasmPatternMatcher implementation: - 5 error handling queries (try-catch, throw, promise.catch, await-in-try, error-class) - 3 import style queries (dynamic-import, re-export, require) - 2 type coverage queries (arrow-return-type, function-return-type) All S-expressions verified against actual tree-sitter-typescript grammar. runQueries() handles parser creation, tree.delete() cleanup, and error recovery. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 positive (exact counts), 10 negative (one per query), 3 language routing (TSX fixture, JSX→javascript, unsupported), 3 edge cases (empty, malformed, invalid query), 1 performance sanity (552 lines + 10 queries in 35ms), 5 resolveLanguage extension tests. 32 tests total. All S-expressions verified against real tree-sitter parsing — no mocks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire PatternMatcher through InspectAdapter to PatternAnalysisService. Three AST-enhanced extractors with regex fallback: - extractErrorHandlingWithAst: detects try/catch, promise.catch, error classes - extractImportStyleWithAst: detects dynamic imports, precise require - extractTypeCoverageWithAst: detects arrow function return types All extractors fall back to regex when PatternMatcher is not configured or file extension is unsupported. Existing 49 tests pass unchanged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Query object WASM leak: call q.delete() in finally after matches() - Fix type coverage ratio inflation: add arrow-total and function-total queries for accurate denominator (was counting only typed functions) - Fix try/catch-alone classification: fall through to regex instead of mapping to 'throw' style (try-catch is a mechanism, not a style) - Add comment explaining AST/regex import count asymmetry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fill the test coverage gaps identified in review: - 3 tests for arrow-total/function-total denominator queries - 7 tests for extractErrorHandlingWithAst merge logic - 4 tests for extractImportStyleWithAst merge logic - 5 tests for extractTypeCoverageWithAst merge logic (accurate denominator) - Fallback tests verifying matcher=undefined produces identical regex output 51 tests total in wasm-matcher.test.ts (was 32). 1628 tests pass overall. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…puted AST Address review findings: 1. runQueries doing too much: extracted runAllAstQueries() that parses once and runs all 12 queries. Extractors now take a pre-computed Map<string, number> instead of matcher+filePath (pure functions). 2. 3x parsing eliminated: analyzeFileFromIndex and analyzeFileWithDocs call runAllAstQueries once, pass results to all 3 extractors. 3. Extractors are now synchronous pure functions — easier to test, no async overhead, no hidden parsing. Tests updated to match new signatures. Same 51 test count, same coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f94c7c3 to
5e36957
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds AST-based pattern detection to
dev_patternsusing tree-sitter queries. Replaces regex-only detection with 12 S-expression queries across 3 categories, covering the full JS/TS ecosystem (.ts,.tsx,.js,.jsx).What it does
Error handling — detects patterns regex can't:
throw new Error(...)Result<T>/{ ok: true }try { } catch { }promise.catch(handler)awaitinside try/catchclass AppError extends BaseErrorImport style — more precise detection:
import()— now counts as ESM (was invisible)require()— AST-precise (regex was fragile)Type coverage — catches what regex misses:
(): Type => ...) — regex is fragile on thesearrow-total+function-totalqueriesArchitecture
Changes
New files
packages/core/src/pattern-matcher/— PatternMatcher interface, 12 rules, WASM implementationpackages/core/src/pattern-matcher/__tests__/wasm-matcher.test.ts— 51 testsModified files
packages/core/src/scanner/tree-sitter.ts— add TS/TSX/JS languages +runQueries()packages/dev-agent/scripts/copy-wasm.js— bundle 3 new WASM grammarspackages/core/src/services/pattern-analysis-service.ts— AST-enhanced extractors +runAllAstQueriespackages/core/src/services/pattern-analysis-types.ts— optionalpatternMatcherin configpackages/mcp-server/— wire PatternMatcher through InspectAdapterBundle size
+5.3MB WASM (TS 2.3MB + TSX 2.3MB + JS 647KB). Acceptable for CLI tool.
Test plan
Automated (51 tests in wasm-matcher.test.ts)
count === 1)count === 0)Manual smoke test
Known test gap
PatternMatcher— AST path is not exercised through the MCP adapter layer. Tracked in.claude/scratchpad.mdfor follow-up.Review findings addressed
q.delete()in finallyarrow-total+function-totaldenominator queriesrunAllAstQueriesparses once, extractors take pre-computed mapResearch that informed this
Generated with Claude Code