agentic-qe 3.8.6 → 3.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/n8n/n8n-base-agent.md +4 -35
- package/.claude/agents/n8n/n8n-bdd-scenario-tester.md +4 -25
- package/.claude/agents/n8n/n8n-chaos-tester.md +4 -26
- package/.claude/agents/n8n/n8n-ci-orchestrator.md +4 -27
- package/.claude/agents/n8n/n8n-compliance-validator.md +4 -25
- package/.claude/agents/n8n/n8n-expression-validator.md +4 -25
- package/.claude/agents/n8n/n8n-integration-test.md +4 -27
- package/.claude/agents/n8n/n8n-monitoring-validator.md +4 -26
- package/.claude/agents/n8n/n8n-node-validator.md +4 -25
- package/.claude/agents/n8n/n8n-performance-tester.md +4 -29
- package/.claude/agents/n8n/n8n-security-auditor.md +4 -26
- package/.claude/agents/n8n/n8n-trigger-test.md +4 -27
- package/.claude/agents/n8n/n8n-unit-tester.md +4 -25
- package/.claude/agents/n8n/n8n-version-comparator.md +4 -26
- package/.claude/agents/n8n/n8n-workflow-executor.md +4 -26
- package/.claude/agents/v3/qe-accessibility-auditor.md +21 -55
- package/.claude/agents/v3/qe-bdd-generator.md +23 -58
- package/.claude/agents/v3/qe-chaos-engineer.md +21 -54
- package/.claude/agents/v3/qe-code-complexity.md +21 -54
- package/.claude/agents/v3/qe-code-intelligence.md +21 -54
- package/.claude/agents/v3/qe-contract-validator.md +21 -53
- package/.claude/agents/v3/qe-coverage-specialist.md +23 -79
- package/.claude/agents/v3/qe-defect-predictor.md +23 -76
- package/.claude/agents/v3/qe-dependency-mapper.md +21 -53
- package/.claude/agents/v3/qe-deployment-advisor.md +21 -54
- package/.claude/agents/v3/qe-devils-advocate.md +212 -238
- package/.claude/agents/v3/qe-flaky-hunter.md +21 -53
- package/.claude/agents/v3/qe-fleet-commander.md +21 -54
- package/.claude/agents/v3/qe-gap-detector.md +23 -79
- package/.claude/agents/v3/qe-graphql-tester.md +21 -54
- package/.claude/agents/v3/qe-impact-analyzer.md +21 -53
- package/.claude/agents/v3/qe-integration-architect.md +2 -2
- package/.claude/agents/v3/qe-integration-tester.md +15 -36
- package/.claude/agents/v3/qe-kg-builder.md +21 -53
- package/.claude/agents/v3/qe-learning-coordinator.md +21 -51
- package/.claude/agents/v3/qe-load-tester.md +21 -55
- package/.claude/agents/v3/qe-message-broker-tester.md +345 -385
- package/.claude/agents/v3/qe-metrics-optimizer.md +21 -54
- package/.claude/agents/v3/qe-middleware-validator.md +389 -428
- package/.claude/agents/v3/qe-mutation-tester.md +21 -54
- package/.claude/agents/v3/qe-odata-contract-tester.md +443 -489
- package/.claude/agents/v3/qe-parallel-executor.md +21 -52
- package/.claude/agents/v3/qe-pattern-learner.md +23 -70
- package/.claude/agents/v3/qe-pentest-validator.md +322 -359
- package/.claude/agents/v3/qe-performance-tester.md +21 -54
- package/.claude/agents/v3/qe-product-factors-assessor.md +339 -376
- package/.claude/agents/v3/qe-property-tester.md +21 -53
- package/.claude/agents/v3/qe-quality-criteria-recommender.md +379 -410
- package/.claude/agents/v3/qe-quality-gate.md +17 -64
- package/.claude/agents/v3/qe-queen-coordinator.md +71 -121
- package/.claude/agents/v3/qe-qx-partner.md +23 -64
- package/.claude/agents/v3/qe-regression-analyzer.md +21 -54
- package/.claude/agents/v3/qe-requirements-validator.md +23 -66
- package/.claude/agents/v3/qe-responsive-tester.md +21 -54
- package/.claude/agents/v3/qe-retry-handler.md +21 -53
- package/.claude/agents/v3/qe-risk-assessor.md +23 -58
- package/.claude/agents/v3/qe-root-cause-analyzer.md +21 -53
- package/.claude/agents/v3/qe-sap-idoc-tester.md +371 -412
- package/.claude/agents/v3/qe-sap-rfc-tester.md +323 -362
- package/.claude/agents/v3/qe-security-auditor.md +21 -54
- package/.claude/agents/v3/qe-security-scanner.md +21 -58
- package/.claude/agents/v3/qe-soap-tester.md +307 -345
- package/.claude/agents/v3/qe-sod-analyzer.md +486 -533
- package/.claude/agents/v3/qe-tdd-specialist.md +17 -42
- package/.claude/agents/v3/qe-test-architect.md +23 -58
- package/.claude/agents/v3/qe-test-idea-rewriter.md +351 -375
- package/.claude/agents/v3/qe-transfer-specialist.md +21 -55
- package/.claude/agents/v3/qe-visual-tester.md +15 -37
- package/.claude/agents/v3/subagents/qe-code-reviewer.md +21 -54
- package/.claude/agents/v3/subagents/qe-integration-reviewer.md +21 -54
- package/.claude/agents/v3/subagents/qe-performance-reviewer.md +21 -54
- package/.claude/agents/v3/subagents/qe-security-reviewer.md +21 -54
- package/.claude/agents/v3/subagents/qe-tdd-green.md +21 -53
- package/.claude/agents/v3/subagents/qe-tdd-red.md +21 -53
- package/.claude/agents/v3/subagents/qe-tdd-refactor.md +21 -53
- package/.claude/skills/.validation/schemas/skill-eval.schema.json +5 -5
- package/.claude/skills/.validation/skill-validation-mcp-integration.md +32 -81
- package/.claude/skills/agentic-quality-engineering/SKILL.md +31 -60
- package/.claude/skills/iterative-loop/SKILL.md +2 -2
- package/.claude/skills/pair-programming/SKILL.md +2 -2
- package/.claude/skills/performance-testing/SKILL.md +1 -1
- package/.claude/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +2 -2
- package/.claude/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +6 -6
- package/.claude/skills/qcsd-development-swarm/steps/01-flag-detection.md +2 -2
- package/.claude/skills/qcsd-development-swarm/steps/07-learning-persistence.md +6 -6
- package/.claude/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +6 -6
- package/.claude/skills/qcsd-production-swarm/steps/01-flag-detection.md +202 -206
- package/.claude/skills/qcsd-production-swarm/steps/07-learning-persistence.md +157 -185
- package/.claude/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +87 -91
- package/.claude/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +49 -53
- package/.claude/skills/qe-chaos-resilience/SKILL.md +2 -2
- package/.claude/skills/qe-code-intelligence/SKILL.md +2 -2
- package/.claude/skills/qe-coverage-analysis/SKILL.md +2 -2
- package/.claude/skills/qe-defect-intelligence/SKILL.md +2 -2
- package/.claude/skills/qe-iterative-loop/SKILL.md +12 -12
- package/.claude/skills/qe-learning-optimization/SKILL.md +2 -2
- package/.claude/skills/qe-quality-assessment/SKILL.md +2 -2
- package/.claude/skills/qe-requirements-validation/SKILL.md +2 -2
- package/.claude/skills/qe-test-execution/SKILL.md +2 -2
- package/.claude/skills/qe-test-generation/SKILL.md +2 -2
- package/.claude/skills/qe-visual-accessibility/SKILL.md +2 -2
- package/.claude/skills/quality-metrics/SKILL.md +1 -1
- package/.claude/skills/security-testing/SKILL.md +1 -1
- package/.claude/skills/skills-manifest.json +1 -1
- package/.claude/skills/validation-pipeline/SKILL.md +2 -2
- package/.claude/skills/verification-quality/SKILL.md +2 -2
- package/CHANGELOG.md +41 -0
- package/assets/agents/v3/qe-accessibility-auditor.md +21 -55
- package/assets/agents/v3/qe-bdd-generator.md +23 -58
- package/assets/agents/v3/qe-chaos-engineer.md +21 -54
- package/assets/agents/v3/qe-code-complexity.md +21 -54
- package/assets/agents/v3/qe-code-intelligence.md +21 -54
- package/assets/agents/v3/qe-contract-validator.md +21 -53
- package/assets/agents/v3/qe-coverage-specialist.md +23 -79
- package/assets/agents/v3/qe-defect-predictor.md +23 -76
- package/assets/agents/v3/qe-dependency-mapper.md +21 -53
- package/assets/agents/v3/qe-deployment-advisor.md +21 -54
- package/assets/agents/v3/qe-devils-advocate.md +212 -238
- package/assets/agents/v3/qe-flaky-hunter.md +21 -53
- package/assets/agents/v3/qe-fleet-commander.md +21 -54
- package/assets/agents/v3/qe-gap-detector.md +23 -79
- package/assets/agents/v3/qe-graphql-tester.md +21 -54
- package/assets/agents/v3/qe-impact-analyzer.md +21 -53
- package/assets/agents/v3/qe-integration-architect.md +2 -2
- package/assets/agents/v3/qe-integration-tester.md +15 -36
- package/assets/agents/v3/qe-kg-builder.md +21 -53
- package/assets/agents/v3/qe-learning-coordinator.md +21 -51
- package/assets/agents/v3/qe-load-tester.md +21 -55
- package/assets/agents/v3/qe-message-broker-tester.md +345 -385
- package/assets/agents/v3/qe-metrics-optimizer.md +21 -54
- package/assets/agents/v3/qe-middleware-validator.md +389 -428
- package/assets/agents/v3/qe-mutation-tester.md +21 -54
- package/assets/agents/v3/qe-odata-contract-tester.md +443 -489
- package/assets/agents/v3/qe-parallel-executor.md +21 -52
- package/assets/agents/v3/qe-pattern-learner.md +23 -70
- package/assets/agents/v3/qe-pentest-validator.md +322 -359
- package/assets/agents/v3/qe-performance-tester.md +21 -54
- package/assets/agents/v3/qe-product-factors-assessor.md +339 -376
- package/assets/agents/v3/qe-property-tester.md +21 -53
- package/assets/agents/v3/qe-quality-criteria-recommender.md +379 -410
- package/assets/agents/v3/qe-quality-gate.md +17 -64
- package/assets/agents/v3/qe-queen-coordinator.md +71 -121
- package/assets/agents/v3/qe-qx-partner.md +23 -64
- package/assets/agents/v3/qe-regression-analyzer.md +21 -54
- package/assets/agents/v3/qe-requirements-validator.md +23 -66
- package/assets/agents/v3/qe-responsive-tester.md +21 -54
- package/assets/agents/v3/qe-retry-handler.md +21 -53
- package/assets/agents/v3/qe-risk-assessor.md +23 -58
- package/assets/agents/v3/qe-root-cause-analyzer.md +21 -53
- package/assets/agents/v3/qe-sap-idoc-tester.md +371 -412
- package/assets/agents/v3/qe-sap-rfc-tester.md +323 -362
- package/assets/agents/v3/qe-security-auditor.md +21 -54
- package/assets/agents/v3/qe-security-scanner.md +21 -58
- package/assets/agents/v3/qe-soap-tester.md +307 -345
- package/assets/agents/v3/qe-sod-analyzer.md +486 -533
- package/assets/agents/v3/qe-tdd-specialist.md +17 -42
- package/assets/agents/v3/qe-test-architect.md +23 -58
- package/assets/agents/v3/qe-test-idea-rewriter.md +351 -375
- package/assets/agents/v3/qe-transfer-specialist.md +21 -55
- package/assets/agents/v3/qe-visual-tester.md +15 -37
- package/assets/agents/v3/subagents/qe-code-reviewer.md +21 -54
- package/assets/agents/v3/subagents/qe-integration-reviewer.md +21 -54
- package/assets/agents/v3/subagents/qe-performance-reviewer.md +21 -54
- package/assets/agents/v3/subagents/qe-security-reviewer.md +21 -54
- package/assets/agents/v3/subagents/qe-tdd-green.md +21 -53
- package/assets/agents/v3/subagents/qe-tdd-red.md +21 -53
- package/assets/agents/v3/subagents/qe-tdd-refactor.md +21 -53
- package/assets/governance/constitution.md +1 -1
- package/assets/governance/shards/chaos-resilience.shard.md +1 -1
- package/assets/governance/shards/code-intelligence.shard.md +1 -1
- package/assets/governance/shards/contract-testing.shard.md +1 -1
- package/assets/governance/shards/coverage-analysis.shard.md +1 -1
- package/assets/governance/shards/defect-intelligence.shard.md +1 -1
- package/assets/governance/shards/learning-optimization.shard.md +1 -1
- package/assets/governance/shards/quality-assessment.shard.md +1 -1
- package/assets/governance/shards/requirements-validation.shard.md +1 -1
- package/assets/governance/shards/security-compliance.shard.md +1 -1
- package/assets/governance/shards/test-execution.shard.md +1 -1
- package/assets/governance/shards/test-generation.shard.md +1 -1
- package/assets/governance/shards/visual-accessibility.shard.md +1 -1
- package/assets/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/assets/grammars/tree-sitter-java.wasm +0 -0
- package/assets/grammars/tree-sitter-python.wasm +0 -0
- package/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/assets/grammars/tree-sitter-swift.wasm +0 -0
- package/assets/skills/.validation/schemas/skill-eval.schema.json +5 -5
- package/assets/skills/.validation/skill-validation-mcp-integration.md +32 -81
- package/assets/skills/agentic-quality-engineering/SKILL.md +31 -60
- package/assets/skills/pair-programming/SKILL.md +2 -2
- package/assets/skills/performance-testing/SKILL.md +1 -1
- package/assets/skills/qcsd-cicd-swarm/steps/01-flag-detection.md +2 -2
- package/assets/skills/qcsd-cicd-swarm/steps/07-learning-persistence.md +6 -6
- package/assets/skills/qcsd-development-swarm/steps/01-flag-detection.md +2 -2
- package/assets/skills/qcsd-development-swarm/steps/07-learning-persistence.md +6 -6
- package/assets/skills/qcsd-ideation-swarm/steps/07-learning-persistence.md +6 -6
- package/assets/skills/qcsd-production-swarm/steps/01-flag-detection.md +202 -206
- package/assets/skills/qcsd-production-swarm/steps/07-learning-persistence.md +157 -185
- package/assets/skills/qcsd-refinement-swarm/steps/01-flag-detection.md +87 -91
- package/assets/skills/qcsd-refinement-swarm/steps/07-learning-persistence.md +49 -53
- package/assets/skills/qe-chaos-resilience/SKILL.md +2 -2
- package/assets/skills/qe-code-intelligence/SKILL.md +2 -2
- package/assets/skills/qe-coverage-analysis/SKILL.md +2 -2
- package/assets/skills/qe-defect-intelligence/SKILL.md +2 -2
- package/assets/skills/qe-iterative-loop/SKILL.md +12 -12
- package/assets/skills/qe-learning-optimization/SKILL.md +2 -2
- package/assets/skills/qe-quality-assessment/SKILL.md +2 -2
- package/assets/skills/qe-requirements-validation/SKILL.md +2 -2
- package/assets/skills/qe-test-execution/SKILL.md +2 -2
- package/assets/skills/qe-test-generation/SKILL.md +2 -2
- package/assets/skills/qe-visual-accessibility/SKILL.md +2 -2
- package/assets/skills/quality-metrics/SKILL.md +1 -1
- package/assets/skills/security-testing/SKILL.md +1 -1
- package/assets/skills/validation-pipeline/SKILL.md +2 -2
- package/assets/skills/verification-quality/SKILL.md +2 -2
- package/dist/cli/bundle.js +5240 -4631
- package/dist/cli/command-registry.js +3 -1
- package/dist/cli/commands/init.js +2 -0
- package/dist/cli/commands/memory.d.ts +11 -0
- package/dist/cli/commands/memory.js +333 -0
- package/dist/cli/completions/index.d.ts +17 -0
- package/dist/cli/completions/index.js +49 -1
- package/dist/cli/handlers/hypergraph-handler.d.ts +27 -0
- package/dist/cli/handlers/hypergraph-handler.js +248 -0
- package/dist/cli/handlers/index.d.ts +1 -0
- package/dist/cli/handlers/index.js +1 -0
- package/dist/cli/handlers/init-handler.d.ts +1 -0
- package/dist/cli/handlers/init-handler.js +18 -6
- package/dist/cli/index.js +2 -0
- package/dist/coordination/protocols/code-intelligence-index.js +2 -11
- package/dist/domains/code-intelligence/coordinator-hypergraph.js +1 -1
- package/dist/domains/code-intelligence/coordinator.d.ts +5 -0
- package/dist/domains/code-intelligence/coordinator.js +35 -3
- package/dist/init/phases/06-code-intelligence.d.ts +8 -3
- package/dist/init/phases/06-code-intelligence.js +70 -32
- package/dist/init/phases/08-mcp.js +10 -0
- package/dist/init/phases/phase-interface.d.ts +2 -0
- package/dist/mcp/bundle.js +1507 -1506
- package/dist/mcp/handlers/hypergraph-handler.d.ts +27 -0
- package/dist/mcp/handlers/hypergraph-handler.js +140 -0
- package/dist/mcp/handlers/index.d.ts +1 -0
- package/dist/mcp/handlers/index.js +2 -0
- package/dist/mcp/server.js +19 -0
- package/dist/mcp/tool-scoping.js +5 -0
- package/dist/shared/code-index-extractor.d.ts +23 -0
- package/dist/shared/code-index-extractor.js +101 -0
- package/dist/shared/parsers/multi-language-parser.d.ts +4 -1
- package/dist/shared/parsers/multi-language-parser.js +73 -1
- package/dist/shared/parsers/tree-sitter-wasm-parser.d.ts +32 -0
- package/dist/shared/parsers/tree-sitter-wasm-parser.js +1034 -0
- package/package.json +2 -1
|
@@ -0,0 +1,1034 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree-sitter WASM Parser (ADR-076 Amendment 2026-03-24)
|
|
3
|
+
*
|
|
4
|
+
* Provides AST-based parsing for Python, Java, C#, Rust, Swift using
|
|
5
|
+
* web-tree-sitter WASM grammars. Achieves ~100% accuracy for identifying
|
|
6
|
+
* functions, classes, imports, properties, and complexity — eliminating
|
|
7
|
+
* the ~2-3% edge cases (code in strings, complex generics) that regex misses.
|
|
8
|
+
*
|
|
9
|
+
* Lazy-loads WASM grammars on first parse per language.
|
|
10
|
+
* Falls back to regex parsers with user-facing log warnings when WASM
|
|
11
|
+
* initialization fails (missing dependency, incompatible Node version, etc.).
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import Module from 'node:module';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { createLogger } from '../../logging/logger-factory.js';
|
|
18
|
+
const logger = createLogger('TreeSitterWASM');
|
|
19
|
+
const GRAMMAR_CONFIG = {
|
|
20
|
+
python: {
|
|
21
|
+
wasmFile: 'tree-sitter-python.wasm',
|
|
22
|
+
nodeTypes: {
|
|
23
|
+
functionDecl: ['function_definition'],
|
|
24
|
+
classDecl: ['class_definition'],
|
|
25
|
+
importDecl: ['import_statement', 'import_from_statement'],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
java: {
|
|
29
|
+
wasmFile: 'tree-sitter-java.wasm',
|
|
30
|
+
nodeTypes: {
|
|
31
|
+
functionDecl: ['method_declaration', 'constructor_declaration'],
|
|
32
|
+
classDecl: ['class_declaration', 'interface_declaration'],
|
|
33
|
+
importDecl: ['import_declaration'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
csharp: {
|
|
37
|
+
wasmFile: 'tree-sitter-c_sharp.wasm',
|
|
38
|
+
nodeTypes: {
|
|
39
|
+
functionDecl: ['method_declaration', 'constructor_declaration'],
|
|
40
|
+
classDecl: ['class_declaration', 'interface_declaration'],
|
|
41
|
+
importDecl: ['using_directive'],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
rust: {
|
|
45
|
+
wasmFile: 'tree-sitter-rust.wasm',
|
|
46
|
+
nodeTypes: {
|
|
47
|
+
functionDecl: ['function_item'],
|
|
48
|
+
classDecl: [],
|
|
49
|
+
importDecl: ['use_declaration'],
|
|
50
|
+
implBlock: 'impl_item',
|
|
51
|
+
structDecl: 'struct_item',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
swift: {
|
|
55
|
+
wasmFile: 'tree-sitter-swift.wasm',
|
|
56
|
+
nodeTypes: {
|
|
57
|
+
functionDecl: ['function_declaration'],
|
|
58
|
+
classDecl: ['class_declaration'],
|
|
59
|
+
importDecl: ['import_declaration'],
|
|
60
|
+
structDecl: 'struct_declaration',
|
|
61
|
+
protocolDecl: 'protocol_declaration',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Shared WASM Initialization (singleton)
|
|
67
|
+
// ============================================================================
|
|
68
|
+
let treeSitterModule = null;
|
|
69
|
+
let initPromise = null;
|
|
70
|
+
let initFailCount = 0;
|
|
71
|
+
const MAX_INIT_RETRIES = 3;
|
|
72
|
+
const loadedLanguages = new Map();
|
|
73
|
+
/**
|
|
74
|
+
* Resolve grammar WASM file path. Tries multiple locations to handle:
|
|
75
|
+
* - Source: src/shared/parsers/ -> ../../../assets/grammars/
|
|
76
|
+
* - CLI bundle: dist/cli/bundle.js -> ../../assets/grammars/
|
|
77
|
+
* - MCP bundle: dist/mcp/bundle.js -> ../../assets/grammars/
|
|
78
|
+
* - Installed package: node_modules/agentic-qe/ -> assets/grammars/
|
|
79
|
+
*/
|
|
80
|
+
function resolveGrammarPath(wasmFile) {
|
|
81
|
+
const thisDir = fileURLToPath(new URL('.', import.meta.url));
|
|
82
|
+
const candidates = [
|
|
83
|
+
// From source (src/shared/parsers/)
|
|
84
|
+
path.resolve(thisDir, '..', '..', '..', 'assets', 'grammars', wasmFile),
|
|
85
|
+
// From dist bundle (dist/cli/ or dist/mcp/)
|
|
86
|
+
path.resolve(thisDir, '..', '..', 'assets', 'grammars', wasmFile),
|
|
87
|
+
// From package root via cwd (fallback)
|
|
88
|
+
path.resolve(process.cwd(), 'assets', 'grammars', wasmFile),
|
|
89
|
+
// From dist root (dist/)
|
|
90
|
+
path.resolve(thisDir, '..', 'assets', 'grammars', wasmFile),
|
|
91
|
+
];
|
|
92
|
+
for (const candidate of candidates) {
|
|
93
|
+
if (fs.existsSync(candidate))
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
throw new Error(`Grammar file ${wasmFile} not found. Searched: ${candidates.join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
async function ensureTreeSitterInit() {
|
|
99
|
+
if (initFailCount >= MAX_INIT_RETRIES) {
|
|
100
|
+
throw new Error(`web-tree-sitter failed to initialize after ${MAX_INIT_RETRIES} attempts`);
|
|
101
|
+
}
|
|
102
|
+
if (treeSitterModule)
|
|
103
|
+
return;
|
|
104
|
+
if (!initPromise) {
|
|
105
|
+
initPromise = (async () => {
|
|
106
|
+
try {
|
|
107
|
+
const mod = await import('web-tree-sitter');
|
|
108
|
+
const TreeSitter = mod.default || mod;
|
|
109
|
+
await TreeSitter.init();
|
|
110
|
+
treeSitterModule = TreeSitter;
|
|
111
|
+
initFailCount = 0; // Reset on success
|
|
112
|
+
logger.info('web-tree-sitter WASM runtime initialized');
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
initFailCount++;
|
|
116
|
+
initPromise = null; // Allow retry on next call
|
|
117
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
118
|
+
logger.warn(`web-tree-sitter WASM init failed (attempt ${initFailCount}/${MAX_INIT_RETRIES}): ${msg}. ` +
|
|
119
|
+
(initFailCount < MAX_INIT_RETRIES ? 'Will retry on next parse.' : 'Falling back to regex permanently.'));
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
})();
|
|
123
|
+
}
|
|
124
|
+
return initPromise;
|
|
125
|
+
}
|
|
126
|
+
async function loadLanguage(lang) {
|
|
127
|
+
const cached = loadedLanguages.get(lang);
|
|
128
|
+
if (cached)
|
|
129
|
+
return cached;
|
|
130
|
+
await ensureTreeSitterInit();
|
|
131
|
+
const config = GRAMMAR_CONFIG[lang];
|
|
132
|
+
if (!config)
|
|
133
|
+
throw new Error(`No WASM grammar config for ${lang}`);
|
|
134
|
+
try {
|
|
135
|
+
// Resolve WASM file from bundled assets/grammars/ (shipped with the package)
|
|
136
|
+
const wasmPath = resolveGrammarPath(config.wasmFile);
|
|
137
|
+
const language = await treeSitterModule.Language.load(wasmPath);
|
|
138
|
+
loadedLanguages.set(lang, language);
|
|
139
|
+
logger.info(`Loaded tree-sitter WASM grammar for ${lang}`);
|
|
140
|
+
return language;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
144
|
+
logger.warn(`Failed to load WASM grammar for ${lang}: ${msg}. Falling back to regex parser.`);
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// AST Node Helpers
|
|
150
|
+
// ============================================================================
|
|
151
|
+
function findChildren(node, types) {
|
|
152
|
+
const results = [];
|
|
153
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
154
|
+
const child = node.child(i);
|
|
155
|
+
if (types.includes(child.type)) {
|
|
156
|
+
results.push(child);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return results;
|
|
160
|
+
}
|
|
161
|
+
function findDescendants(node, types, maxDepth = 10) {
|
|
162
|
+
const results = [];
|
|
163
|
+
function walk(n, depth) {
|
|
164
|
+
if (depth > maxDepth)
|
|
165
|
+
return;
|
|
166
|
+
for (let i = 0; i < n.childCount; i++) {
|
|
167
|
+
const child = n.child(i);
|
|
168
|
+
if (types.includes(child.type)) {
|
|
169
|
+
results.push(child);
|
|
170
|
+
}
|
|
171
|
+
walk(child, depth + 1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
walk(node, 0);
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
function getModifiers(node) {
|
|
178
|
+
const mods = [];
|
|
179
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
180
|
+
const child = node.child(i);
|
|
181
|
+
if (child.type === 'modifiers' || child.type === 'modifier' || child.type === 'visibility_modifier') {
|
|
182
|
+
mods.push(child.text.trim());
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return mods;
|
|
186
|
+
}
|
|
187
|
+
function hasModifier(node, mod) {
|
|
188
|
+
return getModifiers(node).some(m => m.includes(mod));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Compute cyclomatic complexity by counting branching AST nodes in a function body.
|
|
192
|
+
* Baseline of 1 + count of (if, while, for, for_in, match/switch, case, &&, ||, catch, ?:).
|
|
193
|
+
*/
|
|
194
|
+
const COMPLEXITY_NODE_TYPES = new Set([
|
|
195
|
+
// Branching
|
|
196
|
+
'if_statement', 'if_expression', 'if_let_statement',
|
|
197
|
+
'while_statement', 'while_expression',
|
|
198
|
+
'for_statement', 'for_in_statement', 'for_expression', 'enhanced_for_statement',
|
|
199
|
+
'match_expression', 'switch_statement', 'switch_expression',
|
|
200
|
+
'case_clause', 'match_arm', 'switch_entry',
|
|
201
|
+
// Exception handling
|
|
202
|
+
'catch_clause', 'except_clause', 'catch_block',
|
|
203
|
+
// Short-circuit operators
|
|
204
|
+
'binary_expression', // checked for && / || below
|
|
205
|
+
// Ternary
|
|
206
|
+
'conditional_expression', 'ternary_expression',
|
|
207
|
+
]);
|
|
208
|
+
const SHORT_CIRCUIT_OPS = new Set(['&&', '||', 'and', 'or']);
|
|
209
|
+
function computeComplexity(bodyNode) {
|
|
210
|
+
if (!bodyNode)
|
|
211
|
+
return 1;
|
|
212
|
+
let complexity = 1;
|
|
213
|
+
function walk(node) {
|
|
214
|
+
if (COMPLEXITY_NODE_TYPES.has(node.type)) {
|
|
215
|
+
if (node.type === 'binary_expression') {
|
|
216
|
+
// Only count && and || operators
|
|
217
|
+
const op = node.childForFieldName('operator');
|
|
218
|
+
if (op && SHORT_CIRCUIT_OPS.has(op.text)) {
|
|
219
|
+
complexity++;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
complexity++;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
227
|
+
walk(node.child(i));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
walk(bodyNode);
|
|
231
|
+
return complexity;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Extract properties/fields from a class body AST node.
|
|
235
|
+
*/
|
|
236
|
+
function extractProperties(bodyNode, language) {
|
|
237
|
+
if (!bodyNode)
|
|
238
|
+
return [];
|
|
239
|
+
const props = [];
|
|
240
|
+
for (let i = 0; i < bodyNode.childCount; i++) {
|
|
241
|
+
const child = bodyNode.child(i);
|
|
242
|
+
switch (language) {
|
|
243
|
+
case 'java':
|
|
244
|
+
if (child.type === 'field_declaration') {
|
|
245
|
+
const mods = getModifiers(child);
|
|
246
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
247
|
+
const declarator = child.childForFieldName('declarator');
|
|
248
|
+
const name = declarator?.childForFieldName('name')?.text ?? declarator?.text?.split(/[=;]/)[0]?.trim() ?? '';
|
|
249
|
+
if (name) {
|
|
250
|
+
props.push({
|
|
251
|
+
name,
|
|
252
|
+
type: type || undefined,
|
|
253
|
+
isPublic: mods.some(m => m.includes('public')),
|
|
254
|
+
isReadonly: mods.some(m => m.includes('final')),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
case 'csharp':
|
|
260
|
+
if (child.type === 'field_declaration' || child.type === 'property_declaration') {
|
|
261
|
+
const mods = getModifiers(child);
|
|
262
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
263
|
+
const name = child.childForFieldName('name')?.text ?? '';
|
|
264
|
+
if (name) {
|
|
265
|
+
props.push({
|
|
266
|
+
name,
|
|
267
|
+
type: type || undefined,
|
|
268
|
+
isPublic: mods.some(m => m.includes('public')),
|
|
269
|
+
isReadonly: mods.some(m => m.includes('readonly')),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
case 'rust':
|
|
275
|
+
if (child.type === 'field_declaration') {
|
|
276
|
+
const name = child.childForFieldName('name')?.text ?? '';
|
|
277
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
278
|
+
const isPub = hasModifier(child, 'pub');
|
|
279
|
+
if (name) {
|
|
280
|
+
props.push({ name, type: type || undefined, isPublic: isPub, isReadonly: false });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
case 'swift':
|
|
285
|
+
if (child.type === 'property_declaration') {
|
|
286
|
+
const mods = getSwiftModifiers(child);
|
|
287
|
+
const name = child.childForFieldName('name')?.text ?? '';
|
|
288
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
289
|
+
const isPublic = mods.includes('public') || mods.includes('open');
|
|
290
|
+
const isReadonly = child.text.includes('let ');
|
|
291
|
+
if (name) {
|
|
292
|
+
props.push({ name, type: type || undefined, isPublic, isReadonly });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
case 'python':
|
|
297
|
+
// Python class attributes from assignment in __init__ or class body
|
|
298
|
+
if (child.type === 'expression_statement') {
|
|
299
|
+
const expr = child.child(0);
|
|
300
|
+
if (expr?.type === 'assignment') {
|
|
301
|
+
const left = expr.childForFieldName('left');
|
|
302
|
+
if (left?.type === 'attribute' || left?.type === 'identifier') {
|
|
303
|
+
const name = left.text.replace('self.', '');
|
|
304
|
+
props.push({ name, type: undefined, isPublic: !name.startsWith('_'), isReadonly: false });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return props;
|
|
312
|
+
}
|
|
313
|
+
// ============================================================================
|
|
314
|
+
// Language-Specific Extractors
|
|
315
|
+
// ============================================================================
|
|
316
|
+
// --- Python ---
|
|
317
|
+
function extractPythonFunctions(nodes) {
|
|
318
|
+
return nodes.map(node => {
|
|
319
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
320
|
+
const paramsNode = node.childForFieldName('parameters');
|
|
321
|
+
const returnTypeNode = node.childForFieldName('return_type');
|
|
322
|
+
const bodyNode = node.childForFieldName('body');
|
|
323
|
+
const isAsync = node.text.trimStart().startsWith('async');
|
|
324
|
+
const decorators = collectPythonDecorators(node);
|
|
325
|
+
return {
|
|
326
|
+
name,
|
|
327
|
+
parameters: parsePythonParams(paramsNode),
|
|
328
|
+
returnType: returnTypeNode?.text?.trim() || undefined,
|
|
329
|
+
isAsync,
|
|
330
|
+
isPublic: !name.startsWith('_'),
|
|
331
|
+
complexity: computeComplexity(bodyNode),
|
|
332
|
+
decorators,
|
|
333
|
+
genericParams: [],
|
|
334
|
+
startLine: node.startPosition.row + 1,
|
|
335
|
+
endLine: node.endPosition.row + 1,
|
|
336
|
+
};
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
function parsePythonParams(paramsNode) {
|
|
340
|
+
if (!paramsNode)
|
|
341
|
+
return [];
|
|
342
|
+
const params = [];
|
|
343
|
+
for (let i = 0; i < paramsNode.childCount; i++) {
|
|
344
|
+
const child = paramsNode.child(i);
|
|
345
|
+
if (child.type === 'identifier') {
|
|
346
|
+
const name = child.text;
|
|
347
|
+
if (name === 'self' || name === 'cls')
|
|
348
|
+
continue;
|
|
349
|
+
params.push({ name, type: undefined, isOptional: false, defaultValue: undefined });
|
|
350
|
+
}
|
|
351
|
+
else if (child.type === 'typed_parameter') {
|
|
352
|
+
const name = child.child(0)?.text ?? '';
|
|
353
|
+
if (name === 'self' || name === 'cls')
|
|
354
|
+
continue;
|
|
355
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
356
|
+
params.push({ name, type: type || undefined, isOptional: false, defaultValue: undefined });
|
|
357
|
+
}
|
|
358
|
+
else if (child.type === 'default_parameter' || child.type === 'typed_default_parameter') {
|
|
359
|
+
const name = child.childForFieldName('name')?.text ?? child.child(0)?.text ?? '';
|
|
360
|
+
if (name === 'self' || name === 'cls')
|
|
361
|
+
continue;
|
|
362
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
363
|
+
const defaultValue = child.childForFieldName('value')?.text?.trim();
|
|
364
|
+
params.push({ name, type: type || undefined, isOptional: true, defaultValue: defaultValue || undefined });
|
|
365
|
+
}
|
|
366
|
+
else if (child.type === 'list_splat_pattern' || child.type === 'dictionary_splat_pattern') {
|
|
367
|
+
const name = child.text;
|
|
368
|
+
params.push({ name, type: undefined, isOptional: true, defaultValue: undefined });
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return params;
|
|
372
|
+
}
|
|
373
|
+
function collectPythonDecorators(funcNode) {
|
|
374
|
+
const decorators = [];
|
|
375
|
+
const parent = funcNode.parent;
|
|
376
|
+
if (!parent)
|
|
377
|
+
return decorators;
|
|
378
|
+
// Decorated definitions wrap the function node
|
|
379
|
+
if (parent.type === 'decorated_definition') {
|
|
380
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
381
|
+
const child = parent.child(i);
|
|
382
|
+
if (child.type === 'decorator') {
|
|
383
|
+
decorators.push(child.text.trim());
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return decorators;
|
|
388
|
+
}
|
|
389
|
+
function extractPythonClasses(nodes) {
|
|
390
|
+
return nodes.map(node => {
|
|
391
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
392
|
+
const body = node.childForFieldName('body');
|
|
393
|
+
// Extract base classes from superclasses (argument_list)
|
|
394
|
+
const superclasses = node.childForFieldName('superclasses');
|
|
395
|
+
const bases = [];
|
|
396
|
+
if (superclasses) {
|
|
397
|
+
for (let i = 0; i < superclasses.childCount; i++) {
|
|
398
|
+
const child = superclasses.child(i);
|
|
399
|
+
if (child.isNamed)
|
|
400
|
+
bases.push(child.text);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Extract methods from body
|
|
404
|
+
const methodNodes = body ? findDescendants(body, ['function_definition'], 2) : [];
|
|
405
|
+
const methods = extractPythonFunctions(methodNodes);
|
|
406
|
+
const decorators = collectPythonDecorators(node);
|
|
407
|
+
return {
|
|
408
|
+
name,
|
|
409
|
+
methods,
|
|
410
|
+
properties: extractProperties(body, 'python'),
|
|
411
|
+
isPublic: !name.startsWith('_'),
|
|
412
|
+
implements: [],
|
|
413
|
+
extends: bases[0] || undefined,
|
|
414
|
+
decorators,
|
|
415
|
+
startLine: node.startPosition.row + 1,
|
|
416
|
+
endLine: node.endPosition.row + 1,
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
function extractPythonImports(nodes) {
|
|
421
|
+
return nodes.map(node => {
|
|
422
|
+
if (node.type === 'import_from_statement') {
|
|
423
|
+
const module = node.childForFieldName('module_name')?.text ?? '';
|
|
424
|
+
const namedImports = [];
|
|
425
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
426
|
+
const child = node.child(i);
|
|
427
|
+
const fieldName = node.fieldNameForChild(i);
|
|
428
|
+
if (fieldName === 'name' && child.isNamed) {
|
|
429
|
+
namedImports.push(child.text);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return { module, namedImports, isTypeOnly: false };
|
|
433
|
+
}
|
|
434
|
+
// import_statement
|
|
435
|
+
const nameNode = node.childForFieldName('name');
|
|
436
|
+
return {
|
|
437
|
+
module: nameNode?.text ?? '',
|
|
438
|
+
namedImports: [],
|
|
439
|
+
isTypeOnly: false,
|
|
440
|
+
};
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
// --- Java ---
|
|
444
|
+
function extractJavaFunctions(nodes) {
|
|
445
|
+
return nodes.map(node => {
|
|
446
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
447
|
+
const returnTypeNode = node.childForFieldName('type');
|
|
448
|
+
const paramsNode = node.childForFieldName('parameters');
|
|
449
|
+
const bodyNode = node.childForFieldName('body');
|
|
450
|
+
const modifiers = getModifiers(node);
|
|
451
|
+
const isPublic = modifiers.some(m => m.includes('public'));
|
|
452
|
+
const isAsync = returnTypeNode?.text?.includes('CompletableFuture') ?? false;
|
|
453
|
+
const decorators = extractJavaAnnotations(node);
|
|
454
|
+
return {
|
|
455
|
+
name,
|
|
456
|
+
parameters: parseJavaParams(paramsNode),
|
|
457
|
+
returnType: returnTypeNode?.text === 'void' ? undefined : returnTypeNode?.text?.trim(),
|
|
458
|
+
isAsync,
|
|
459
|
+
isPublic,
|
|
460
|
+
complexity: computeComplexity(bodyNode),
|
|
461
|
+
decorators,
|
|
462
|
+
genericParams: [],
|
|
463
|
+
startLine: node.startPosition.row + 1,
|
|
464
|
+
endLine: node.endPosition.row + 1,
|
|
465
|
+
};
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
function parseJavaParams(paramsNode) {
|
|
469
|
+
if (!paramsNode)
|
|
470
|
+
return [];
|
|
471
|
+
const params = [];
|
|
472
|
+
for (let i = 0; i < paramsNode.childCount; i++) {
|
|
473
|
+
const child = paramsNode.child(i);
|
|
474
|
+
if (child.type === 'formal_parameter' || child.type === 'spread_parameter') {
|
|
475
|
+
const name = child.childForFieldName('name')?.text ?? '';
|
|
476
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
477
|
+
params.push({ name, type: type || undefined, isOptional: false, defaultValue: undefined });
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return params;
|
|
481
|
+
}
|
|
482
|
+
function extractJavaAnnotations(node) {
|
|
483
|
+
const annotations = [];
|
|
484
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
485
|
+
const child = node.child(i);
|
|
486
|
+
if (child.type === 'modifiers') {
|
|
487
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
488
|
+
const mod = child.child(j);
|
|
489
|
+
if (mod.type === 'marker_annotation' || mod.type === 'annotation') {
|
|
490
|
+
annotations.push(mod.text.trim());
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return annotations;
|
|
496
|
+
}
|
|
497
|
+
function extractJavaClasses(nodes) {
|
|
498
|
+
return nodes.map(node => {
|
|
499
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
500
|
+
const body = node.childForFieldName('body');
|
|
501
|
+
const modifiers = getModifiers(node);
|
|
502
|
+
const isPublic = modifiers.some(m => m.includes('public'));
|
|
503
|
+
// Extract extends/implements
|
|
504
|
+
const superclass = node.childForFieldName('superclass')?.text;
|
|
505
|
+
const interfaces = node.childForFieldName('interfaces');
|
|
506
|
+
const implementsList = [];
|
|
507
|
+
if (interfaces) {
|
|
508
|
+
for (let i = 0; i < interfaces.childCount; i++) {
|
|
509
|
+
const child = interfaces.child(i);
|
|
510
|
+
if (child.isNamed)
|
|
511
|
+
implementsList.push(child.text);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
const methodNodes = body ? findChildren(body, ['method_declaration', 'constructor_declaration']) : [];
|
|
515
|
+
const methods = extractJavaFunctions(methodNodes);
|
|
516
|
+
const decorators = extractJavaAnnotations(node);
|
|
517
|
+
return {
|
|
518
|
+
name,
|
|
519
|
+
methods,
|
|
520
|
+
properties: extractProperties(body, 'java'),
|
|
521
|
+
isPublic,
|
|
522
|
+
implements: implementsList,
|
|
523
|
+
extends: superclass || undefined,
|
|
524
|
+
decorators,
|
|
525
|
+
startLine: node.startPosition.row + 1,
|
|
526
|
+
endLine: node.endPosition.row + 1,
|
|
527
|
+
};
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function extractJavaImports(nodes) {
|
|
531
|
+
return nodes.map(node => {
|
|
532
|
+
const text = node.text.replace(/^\s*import\s+(static\s+)?/, '').replace(/;\s*$/, '').trim();
|
|
533
|
+
const parts = text.split('.');
|
|
534
|
+
const name = parts[parts.length - 1];
|
|
535
|
+
return {
|
|
536
|
+
module: text,
|
|
537
|
+
namedImports: name === '*' ? [] : [name],
|
|
538
|
+
isTypeOnly: false,
|
|
539
|
+
};
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
// --- C# ---
|
|
543
|
+
function extractCSharpFunctions(root) {
|
|
544
|
+
const methods = findDescendants(root, ['method_declaration', 'constructor_declaration']);
|
|
545
|
+
return methods.map(node => {
|
|
546
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
547
|
+
const returnTypeNode = node.childForFieldName('type');
|
|
548
|
+
const paramsNode = node.childForFieldName('parameters');
|
|
549
|
+
const modifiers = getModifiers(node);
|
|
550
|
+
const isPublic = modifiers.some(m => m.includes('public'));
|
|
551
|
+
const isAsync = modifiers.some(m => m.includes('async')) || returnTypeNode?.text?.includes('Task') || false;
|
|
552
|
+
const decorators = extractCSharpAttributes(node);
|
|
553
|
+
return {
|
|
554
|
+
name,
|
|
555
|
+
parameters: parseCSharpParams(paramsNode),
|
|
556
|
+
returnType: returnTypeNode?.text === 'void' ? undefined : returnTypeNode?.text?.trim(),
|
|
557
|
+
isAsync,
|
|
558
|
+
isPublic,
|
|
559
|
+
complexity: computeComplexity(node.childForFieldName('body')),
|
|
560
|
+
decorators,
|
|
561
|
+
genericParams: [],
|
|
562
|
+
startLine: node.startPosition.row + 1,
|
|
563
|
+
endLine: node.endPosition.row + 1,
|
|
564
|
+
};
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
function parseCSharpParams(paramsNode) {
|
|
568
|
+
if (!paramsNode)
|
|
569
|
+
return [];
|
|
570
|
+
const params = [];
|
|
571
|
+
for (let i = 0; i < paramsNode.childCount; i++) {
|
|
572
|
+
const child = paramsNode.child(i);
|
|
573
|
+
if (child.type === 'parameter') {
|
|
574
|
+
const name = child.childForFieldName('name')?.text ?? '';
|
|
575
|
+
const type = child.childForFieldName('type')?.text?.trim();
|
|
576
|
+
params.push({
|
|
577
|
+
name,
|
|
578
|
+
type: type || undefined,
|
|
579
|
+
isOptional: type?.endsWith('?') || false,
|
|
580
|
+
defaultValue: undefined,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return params;
|
|
585
|
+
}
|
|
586
|
+
function extractCSharpAttributes(node) {
|
|
587
|
+
const attrs = [];
|
|
588
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
589
|
+
const child = node.child(i);
|
|
590
|
+
if (child.type === 'attribute_list') {
|
|
591
|
+
attrs.push(child.text.trim());
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return attrs;
|
|
595
|
+
}
|
|
596
|
+
function extractCSharpClasses(root) {
|
|
597
|
+
const classes = findDescendants(root, ['class_declaration', 'interface_declaration']);
|
|
598
|
+
return classes.map(node => {
|
|
599
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
600
|
+
const body = node.childForFieldName('body');
|
|
601
|
+
const modifiers = getModifiers(node);
|
|
602
|
+
const isPublic = modifiers.some(m => m.includes('public'));
|
|
603
|
+
// Extract base list (extends/implements combined in C#)
|
|
604
|
+
const baseList = node.childForFieldName('bases');
|
|
605
|
+
const bases = [];
|
|
606
|
+
if (baseList) {
|
|
607
|
+
for (let i = 0; i < baseList.childCount; i++) {
|
|
608
|
+
const child = baseList.child(i);
|
|
609
|
+
if (child.isNamed)
|
|
610
|
+
bases.push(child.text);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
const methodNodes = body ? findChildren(body, ['method_declaration', 'constructor_declaration']) : [];
|
|
614
|
+
const methods = extractJavaFunctions(methodNodes); // Same structure as Java
|
|
615
|
+
const decorators = extractCSharpAttributes(node);
|
|
616
|
+
return {
|
|
617
|
+
name,
|
|
618
|
+
methods,
|
|
619
|
+
properties: extractProperties(body, 'csharp'),
|
|
620
|
+
isPublic,
|
|
621
|
+
implements: bases.slice(1),
|
|
622
|
+
extends: bases[0] || undefined,
|
|
623
|
+
decorators,
|
|
624
|
+
startLine: node.startPosition.row + 1,
|
|
625
|
+
endLine: node.endPosition.row + 1,
|
|
626
|
+
};
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
function extractCSharpImports(root) {
|
|
630
|
+
const usings = findDescendants(root, ['using_directive']);
|
|
631
|
+
return usings.map(node => {
|
|
632
|
+
const text = node.text.replace(/^\s*using\s+(static\s+)?/, '').replace(/;\s*$/, '').trim();
|
|
633
|
+
return { module: text, namedImports: [], isTypeOnly: false };
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
// --- Rust ---
|
|
637
|
+
function extractRustFunctions(root, config) {
|
|
638
|
+
const functions = [];
|
|
639
|
+
// Top-level functions
|
|
640
|
+
const topFns = findChildren(root, config.nodeTypes.functionDecl);
|
|
641
|
+
functions.push(...topFns.map(parseRustFunction));
|
|
642
|
+
// Functions inside impl blocks
|
|
643
|
+
if (config.nodeTypes.implBlock) {
|
|
644
|
+
const implBlocks = findChildren(root, [config.nodeTypes.implBlock]);
|
|
645
|
+
for (const impl of implBlocks) {
|
|
646
|
+
const body = impl.childForFieldName('body');
|
|
647
|
+
if (body) {
|
|
648
|
+
const methods = findChildren(body, config.nodeTypes.functionDecl);
|
|
649
|
+
functions.push(...methods.map(parseRustFunction));
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return functions;
|
|
654
|
+
}
|
|
655
|
+
function parseRustFunction(node) {
|
|
656
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
657
|
+
const paramsNode = node.childForFieldName('parameters');
|
|
658
|
+
const returnTypeNode = node.childForFieldName('return_type');
|
|
659
|
+
const bodyNode = node.childForFieldName('body');
|
|
660
|
+
const isPub = hasModifier(node, 'pub');
|
|
661
|
+
const isAsync = node.text.trimStart().startsWith('pub async') || node.text.trimStart().startsWith('async');
|
|
662
|
+
const decorators = collectRustAttributes(node);
|
|
663
|
+
return {
|
|
664
|
+
name,
|
|
665
|
+
parameters: parseRustParams(paramsNode),
|
|
666
|
+
returnType: returnTypeNode?.text?.trim() || undefined,
|
|
667
|
+
isAsync,
|
|
668
|
+
isPublic: isPub,
|
|
669
|
+
complexity: computeComplexity(bodyNode),
|
|
670
|
+
decorators,
|
|
671
|
+
genericParams: [],
|
|
672
|
+
startLine: node.startPosition.row + 1,
|
|
673
|
+
endLine: node.endPosition.row + 1,
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function parseRustParams(paramsNode) {
|
|
677
|
+
if (!paramsNode)
|
|
678
|
+
return [];
|
|
679
|
+
const params = [];
|
|
680
|
+
for (let i = 0; i < paramsNode.childCount; i++) {
|
|
681
|
+
const child = paramsNode.child(i);
|
|
682
|
+
if (child.type === 'parameter') {
|
|
683
|
+
const patternNode = child.childForFieldName('pattern');
|
|
684
|
+
const typeNode = child.childForFieldName('type');
|
|
685
|
+
const name = patternNode?.text ?? '';
|
|
686
|
+
const type = typeNode?.text?.trim();
|
|
687
|
+
params.push({ name, type: type || undefined, isOptional: false, defaultValue: undefined });
|
|
688
|
+
}
|
|
689
|
+
else if (child.type === 'self_parameter') {
|
|
690
|
+
// Skip &self, &mut self, self
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return params;
|
|
695
|
+
}
|
|
696
|
+
function collectRustAttributes(node) {
|
|
697
|
+
const attrs = [];
|
|
698
|
+
// Attributes precede the function as siblings
|
|
699
|
+
let prev = node.previousNamedSibling;
|
|
700
|
+
while (prev && prev.type === 'attribute_item') {
|
|
701
|
+
attrs.unshift(prev.text.trim());
|
|
702
|
+
prev = prev.previousNamedSibling;
|
|
703
|
+
}
|
|
704
|
+
return attrs;
|
|
705
|
+
}
|
|
706
|
+
function extractRustStructs(root) {
|
|
707
|
+
const structs = [];
|
|
708
|
+
// Extract structs, enums, and traits as class-like entities
|
|
709
|
+
const structNodes = findChildren(root, ['struct_item', 'enum_item', 'trait_item']);
|
|
710
|
+
for (const node of structNodes) {
|
|
711
|
+
const name = node.childForFieldName('name')?.text ?? '';
|
|
712
|
+
const isPub = hasModifier(node, 'pub');
|
|
713
|
+
const decorators = collectRustAttributes(node);
|
|
714
|
+
const bodyNode = node.childForFieldName('body');
|
|
715
|
+
structs.push({
|
|
716
|
+
name,
|
|
717
|
+
methods: [],
|
|
718
|
+
properties: extractProperties(bodyNode, 'rust'),
|
|
719
|
+
isPublic: isPub,
|
|
720
|
+
implements: [],
|
|
721
|
+
extends: undefined,
|
|
722
|
+
decorators,
|
|
723
|
+
startLine: node.startPosition.row + 1,
|
|
724
|
+
endLine: node.endPosition.row + 1,
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
return structs;
|
|
728
|
+
}
|
|
729
|
+
function extractRustImports(root) {
|
|
730
|
+
const uses = findChildren(root, ['use_declaration']);
|
|
731
|
+
return uses.map(node => {
|
|
732
|
+
const arg = node.childForFieldName('argument');
|
|
733
|
+
const module = arg?.text ?? node.text.replace(/^\s*use\s+/, '').replace(/;\s*$/, '').trim();
|
|
734
|
+
return { module, namedImports: [], isTypeOnly: false };
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
// --- Swift ---
|
|
738
|
+
function extractSwiftFunctions(nodes) {
|
|
739
|
+
return nodes.map(node => {
|
|
740
|
+
// Swift uses 'name' field for the function identifier (simple_identifier)
|
|
741
|
+
let name = '';
|
|
742
|
+
const params = [];
|
|
743
|
+
let returnType;
|
|
744
|
+
const modifiers = getSwiftModifiers(node);
|
|
745
|
+
const isPublic = modifiers.includes('public') || modifiers.includes('open');
|
|
746
|
+
let isAsync = false;
|
|
747
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
748
|
+
const child = node.child(i);
|
|
749
|
+
const fieldName = node.fieldNameForChild(i);
|
|
750
|
+
if (fieldName === 'name') {
|
|
751
|
+
if (child.type === 'simple_identifier') {
|
|
752
|
+
name = child.text;
|
|
753
|
+
}
|
|
754
|
+
else if (!name) {
|
|
755
|
+
// Return type may also use 'name' field in some tree-sitter-swift versions
|
|
756
|
+
returnType = child.text;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (child.type === 'parameter') {
|
|
760
|
+
params.push(child);
|
|
761
|
+
}
|
|
762
|
+
if (child.type === 'async' || child.text === 'async') {
|
|
763
|
+
isAsync = true;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// If name was overwritten by return type, try first simple_identifier
|
|
767
|
+
if (!name) {
|
|
768
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
769
|
+
if (node.child(i).type === 'simple_identifier') {
|
|
770
|
+
name = node.child(i).text;
|
|
771
|
+
break;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
// Find body node for complexity
|
|
776
|
+
let bodyNode = null;
|
|
777
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
778
|
+
if (node.child(i).type === 'function_body') {
|
|
779
|
+
bodyNode = node.child(i);
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
name,
|
|
785
|
+
parameters: parseSwiftParams(params),
|
|
786
|
+
returnType,
|
|
787
|
+
isAsync,
|
|
788
|
+
isPublic,
|
|
789
|
+
complexity: computeComplexity(bodyNode),
|
|
790
|
+
decorators: [],
|
|
791
|
+
genericParams: [],
|
|
792
|
+
startLine: node.startPosition.row + 1,
|
|
793
|
+
endLine: node.endPosition.row + 1,
|
|
794
|
+
};
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
function getSwiftModifiers(node) {
|
|
798
|
+
const mods = [];
|
|
799
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
800
|
+
const child = node.child(i);
|
|
801
|
+
if (child.type === 'modifiers') {
|
|
802
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
803
|
+
mods.push(child.child(j).text.trim());
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
return mods;
|
|
808
|
+
}
|
|
809
|
+
function parseSwiftParams(paramNodes) {
|
|
810
|
+
return paramNodes.map(p => {
|
|
811
|
+
const text = p.text;
|
|
812
|
+
const parts = text.split(':');
|
|
813
|
+
const labelAndName = parts[0]?.trim().split(/\s+/) ?? [];
|
|
814
|
+
const name = labelAndName[labelAndName.length - 1] || '';
|
|
815
|
+
const type = parts.slice(1).join(':').trim() || undefined;
|
|
816
|
+
return {
|
|
817
|
+
name,
|
|
818
|
+
type,
|
|
819
|
+
isOptional: type?.endsWith('?') || false,
|
|
820
|
+
defaultValue: undefined,
|
|
821
|
+
};
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
function extractSwiftClasses(root) {
|
|
825
|
+
const classTypes = ['class_declaration', 'struct_declaration', 'protocol_declaration'];
|
|
826
|
+
const classNodes = findChildren(root, classTypes);
|
|
827
|
+
return classNodes.map(node => {
|
|
828
|
+
const nameNode = node.childForFieldName('name');
|
|
829
|
+
const name = nameNode?.text ?? '';
|
|
830
|
+
const modifiers = getSwiftModifiers(node);
|
|
831
|
+
const isPublic = modifiers.includes('public') || modifiers.includes('open');
|
|
832
|
+
// Extract conformances from inheritance clause
|
|
833
|
+
const conformances = [];
|
|
834
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
835
|
+
const child = node.child(i);
|
|
836
|
+
if (child.type === 'type_identifier' && child !== nameNode) {
|
|
837
|
+
conformances.push(child.text);
|
|
838
|
+
}
|
|
839
|
+
if (child.type === 'inheritance_specifier' || child.type === 'user_type') {
|
|
840
|
+
conformances.push(child.text);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
// Extract methods from class body
|
|
844
|
+
const body = node.childForFieldName('body');
|
|
845
|
+
const methodNodes = body ? findDescendants(body, ['function_declaration'], 2) : [];
|
|
846
|
+
const methods = extractSwiftFunctions(methodNodes);
|
|
847
|
+
return {
|
|
848
|
+
name,
|
|
849
|
+
methods,
|
|
850
|
+
properties: extractProperties(body, 'swift'),
|
|
851
|
+
isPublic,
|
|
852
|
+
implements: conformances.slice(1),
|
|
853
|
+
extends: conformances[0] || undefined,
|
|
854
|
+
decorators: [],
|
|
855
|
+
startLine: node.startPosition.row + 1,
|
|
856
|
+
endLine: node.endPosition.row + 1,
|
|
857
|
+
};
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
function extractSwiftImports(root) {
|
|
861
|
+
const imports = findChildren(root, ['import_declaration']);
|
|
862
|
+
return imports.map(node => {
|
|
863
|
+
let module = '';
|
|
864
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
865
|
+
const child = node.child(i);
|
|
866
|
+
if (child.type === 'identifier' || child.type === 'simple_identifier') {
|
|
867
|
+
module = child.text;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return { module, namedImports: [], isTypeOnly: false };
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
// ============================================================================
|
|
874
|
+
// TreeSitterWASMParser — ILanguageParser implementation
|
|
875
|
+
// ============================================================================
|
|
876
|
+
export class TreeSitterWASMParser {
|
|
877
|
+
language;
|
|
878
|
+
supportedExtensions;
|
|
879
|
+
constructor(language, extensions) {
|
|
880
|
+
this.language = language;
|
|
881
|
+
this.supportedExtensions = extensions;
|
|
882
|
+
}
|
|
883
|
+
async parseFile(content, filePath) {
|
|
884
|
+
const lang = await loadLanguage(this.language);
|
|
885
|
+
// Create a parser per call to avoid TOCTOU race conditions.
|
|
886
|
+
// Two concurrent parseFile() calls for different languages could otherwise
|
|
887
|
+
// corrupt each other via setLanguage() on a shared instance across await boundaries.
|
|
888
|
+
// Parser creation is ~μs; grammar loading (the expensive part) is already cached.
|
|
889
|
+
const parser = new treeSitterModule();
|
|
890
|
+
parser.setLanguage(lang);
|
|
891
|
+
const tree = parser.parse(content);
|
|
892
|
+
const root = tree.rootNode;
|
|
893
|
+
try {
|
|
894
|
+
const result = this.extractFromAST(root);
|
|
895
|
+
return {
|
|
896
|
+
...result,
|
|
897
|
+
language: this.language,
|
|
898
|
+
filePath,
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
finally {
|
|
902
|
+
tree.delete();
|
|
903
|
+
parser.delete();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
extractFromAST(root) {
|
|
907
|
+
const config = GRAMMAR_CONFIG[this.language];
|
|
908
|
+
switch (this.language) {
|
|
909
|
+
case 'python': {
|
|
910
|
+
// Collect top-level functions (not inside classes)
|
|
911
|
+
const allFuncNodes = findChildren(root, config.nodeTypes.functionDecl);
|
|
912
|
+
// Also check decorated definitions
|
|
913
|
+
const decoratedFuncs = findChildren(root, ['decorated_definition'])
|
|
914
|
+
.map(d => {
|
|
915
|
+
for (let i = 0; i < d.childCount; i++) {
|
|
916
|
+
if (config.nodeTypes.functionDecl.includes(d.child(i).type))
|
|
917
|
+
return d.child(i);
|
|
918
|
+
}
|
|
919
|
+
return null;
|
|
920
|
+
})
|
|
921
|
+
.filter(Boolean);
|
|
922
|
+
const funcNodes = [...allFuncNodes, ...decoratedFuncs];
|
|
923
|
+
const allClassNodes = findChildren(root, config.nodeTypes.classDecl);
|
|
924
|
+
const decoratedClasses = findChildren(root, ['decorated_definition'])
|
|
925
|
+
.map(d => {
|
|
926
|
+
for (let i = 0; i < d.childCount; i++) {
|
|
927
|
+
if (config.nodeTypes.classDecl.includes(d.child(i).type))
|
|
928
|
+
return d.child(i);
|
|
929
|
+
}
|
|
930
|
+
return null;
|
|
931
|
+
})
|
|
932
|
+
.filter(Boolean);
|
|
933
|
+
const classNodes = [...allClassNodes, ...decoratedClasses];
|
|
934
|
+
const importNodes = findChildren(root, config.nodeTypes.importDecl);
|
|
935
|
+
return {
|
|
936
|
+
functions: extractPythonFunctions(funcNodes),
|
|
937
|
+
classes: extractPythonClasses(classNodes),
|
|
938
|
+
imports: extractPythonImports(importNodes),
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
case 'java': {
|
|
942
|
+
const classNodes = findDescendants(root, config.nodeTypes.classDecl);
|
|
943
|
+
const importNodes = findChildren(root, config.nodeTypes.importDecl);
|
|
944
|
+
// Top-level method declarations (outside classes are rare in Java, but extract them)
|
|
945
|
+
const topFuncNodes = findChildren(root, config.nodeTypes.functionDecl);
|
|
946
|
+
// Also extract methods from all classes for flat function list
|
|
947
|
+
const allMethods = [...topFuncNodes];
|
|
948
|
+
for (const cls of classNodes) {
|
|
949
|
+
const body = cls.childForFieldName('body');
|
|
950
|
+
if (body) {
|
|
951
|
+
allMethods.push(...findChildren(body, config.nodeTypes.functionDecl));
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return {
|
|
955
|
+
functions: extractJavaFunctions(allMethods),
|
|
956
|
+
classes: extractJavaClasses(classNodes),
|
|
957
|
+
imports: extractJavaImports(importNodes),
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
case 'csharp':
|
|
961
|
+
return {
|
|
962
|
+
functions: extractCSharpFunctions(root),
|
|
963
|
+
classes: extractCSharpClasses(root),
|
|
964
|
+
imports: extractCSharpImports(root),
|
|
965
|
+
};
|
|
966
|
+
case 'rust':
|
|
967
|
+
return {
|
|
968
|
+
functions: extractRustFunctions(root, config),
|
|
969
|
+
classes: extractRustStructs(root),
|
|
970
|
+
imports: extractRustImports(root),
|
|
971
|
+
};
|
|
972
|
+
case 'swift': {
|
|
973
|
+
// All function declarations at any depth (matching regex parser behavior)
|
|
974
|
+
const allFuncNodes = findDescendants(root, config.nodeTypes.functionDecl);
|
|
975
|
+
return {
|
|
976
|
+
functions: extractSwiftFunctions(allFuncNodes),
|
|
977
|
+
classes: extractSwiftClasses(root),
|
|
978
|
+
imports: extractSwiftImports(root),
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
default:
|
|
982
|
+
return { functions: [], classes: [], imports: [] };
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
// ============================================================================
|
|
987
|
+
// Factory: Create WASM parsers for supported languages
|
|
988
|
+
// ============================================================================
|
|
989
|
+
const WASM_LANGUAGE_EXTENSIONS = {
|
|
990
|
+
python: ['.py'],
|
|
991
|
+
java: ['.java'],
|
|
992
|
+
csharp: ['.cs'],
|
|
993
|
+
rust: ['.rs'],
|
|
994
|
+
swift: ['.swift'],
|
|
995
|
+
};
|
|
996
|
+
export function createWasmParsers() {
|
|
997
|
+
const parsers = new Map();
|
|
998
|
+
for (const [lang, exts] of Object.entries(WASM_LANGUAGE_EXTENSIONS)) {
|
|
999
|
+
parsers.set(lang, new TreeSitterWASMParser(lang, exts));
|
|
1000
|
+
}
|
|
1001
|
+
return parsers;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Check if web-tree-sitter WASM is available in this environment.
|
|
1005
|
+
* Returns true if the dependency is installed; does NOT initialize WASM.
|
|
1006
|
+
*/
|
|
1007
|
+
export function isWasmAvailable() {
|
|
1008
|
+
// Opt-out: set AQE_PARSER_REGEX_ONLY=1 to force regex parsers
|
|
1009
|
+
if (process.env.AQE_PARSER_REGEX_ONLY === '1' || process.env.AQE_PARSER_REGEX_ONLY === 'true') {
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
try {
|
|
1013
|
+
// Check that web-tree-sitter runtime is installed
|
|
1014
|
+
const { createRequire } = Module;
|
|
1015
|
+
const req = createRequire(import.meta.url);
|
|
1016
|
+
req.resolve('web-tree-sitter');
|
|
1017
|
+
// Check that at least one bundled grammar exists
|
|
1018
|
+
resolveGrammarPath('tree-sitter-python.wasm');
|
|
1019
|
+
return true;
|
|
1020
|
+
}
|
|
1021
|
+
catch {
|
|
1022
|
+
return false;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Reset internal state — for testing only.
|
|
1027
|
+
*/
|
|
1028
|
+
export function _resetWasmState() {
|
|
1029
|
+
treeSitterModule = null;
|
|
1030
|
+
initPromise = null;
|
|
1031
|
+
initFailCount = 0;
|
|
1032
|
+
loadedLanguages.clear();
|
|
1033
|
+
}
|
|
1034
|
+
//# sourceMappingURL=tree-sitter-wasm-parser.js.map
|