codeguardian-mcp 1.0.0
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/LICENSE +21 -0
- package/README.md +348 -0
- package/dist/agent/agentTools.d.ts +26 -0
- package/dist/agent/agentTools.d.ts.map +1 -0
- package/dist/agent/agentTools.js +699 -0
- package/dist/agent/agentTools.js.map +1 -0
- package/dist/agent/autoValidator.d.ts +110 -0
- package/dist/agent/autoValidator.d.ts.map +1 -0
- package/dist/agent/autoValidator.js +964 -0
- package/dist/agent/autoValidator.js.map +1 -0
- package/dist/agent/fileWatcher.d.ts +28 -0
- package/dist/agent/fileWatcher.d.ts.map +1 -0
- package/dist/agent/fileWatcher.js +88 -0
- package/dist/agent/fileWatcher.js.map +1 -0
- package/dist/agent/guardianPersistence.d.ts +98 -0
- package/dist/agent/guardianPersistence.d.ts.map +1 -0
- package/dist/agent/guardianPersistence.js +296 -0
- package/dist/agent/guardianPersistence.js.map +1 -0
- package/dist/agent/mcpNotifications.d.ts +38 -0
- package/dist/agent/mcpNotifications.d.ts.map +1 -0
- package/dist/agent/mcpNotifications.js +81 -0
- package/dist/agent/mcpNotifications.js.map +1 -0
- package/dist/analyzers/aiPatterns.d.ts +16 -0
- package/dist/analyzers/aiPatterns.d.ts.map +1 -0
- package/dist/analyzers/aiPatterns.js +103 -0
- package/dist/analyzers/aiPatterns.js.map +1 -0
- package/dist/analyzers/antiPatterns.d.ts +60 -0
- package/dist/analyzers/antiPatterns.d.ts.map +1 -0
- package/dist/analyzers/antiPatterns.js +198 -0
- package/dist/analyzers/antiPatterns.js.map +1 -0
- package/dist/analyzers/builtinTypes.d.ts +18 -0
- package/dist/analyzers/builtinTypes.d.ts.map +1 -0
- package/dist/analyzers/builtinTypes.js +1275 -0
- package/dist/analyzers/builtinTypes.js.map +1 -0
- package/dist/analyzers/complexity.d.ts +14 -0
- package/dist/analyzers/complexity.d.ts.map +1 -0
- package/dist/analyzers/complexity.js +610 -0
- package/dist/analyzers/complexity.js.map +1 -0
- package/dist/analyzers/findingVerifier.d.ts +59 -0
- package/dist/analyzers/findingVerifier.d.ts.map +1 -0
- package/dist/analyzers/findingVerifier.js +1169 -0
- package/dist/analyzers/findingVerifier.js.map +1 -0
- package/dist/analyzers/impactAnalyzer.d.ts +53 -0
- package/dist/analyzers/impactAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/impactAnalyzer.js +152 -0
- package/dist/analyzers/impactAnalyzer.js.map +1 -0
- package/dist/analyzers/languageDetector.d.ts +48 -0
- package/dist/analyzers/languageDetector.d.ts.map +1 -0
- package/dist/analyzers/languageDetector.js +404 -0
- package/dist/analyzers/languageDetector.js.map +1 -0
- package/dist/analyzers/parsers/incrementalParser.d.ts +53 -0
- package/dist/analyzers/parsers/incrementalParser.d.ts.map +1 -0
- package/dist/analyzers/parsers/incrementalParser.js +193 -0
- package/dist/analyzers/parsers/incrementalParser.js.map +1 -0
- package/dist/analyzers/parsers/scopeResolver.d.ts +92 -0
- package/dist/analyzers/parsers/scopeResolver.d.ts.map +1 -0
- package/dist/analyzers/parsers/scopeResolver.js +324 -0
- package/dist/analyzers/parsers/scopeResolver.js.map +1 -0
- package/dist/analyzers/parsers/semanticIndex.d.ts +127 -0
- package/dist/analyzers/parsers/semanticIndex.d.ts.map +1 -0
- package/dist/analyzers/parsers/semanticIndex.js +429 -0
- package/dist/analyzers/parsers/semanticIndex.js.map +1 -0
- package/dist/analyzers/parsers/sessionDiffAnalyzer.d.ts +42 -0
- package/dist/analyzers/parsers/sessionDiffAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/parsers/sessionDiffAnalyzer.js +233 -0
- package/dist/analyzers/parsers/sessionDiffAnalyzer.js.map +1 -0
- package/dist/analyzers/parsers/treeSitterParser.d.ts +76 -0
- package/dist/analyzers/parsers/treeSitterParser.d.ts.map +1 -0
- package/dist/analyzers/parsers/treeSitterParser.js +709 -0
- package/dist/analyzers/parsers/treeSitterParser.js.map +1 -0
- package/dist/analyzers/relevanceScorer.d.ts +43 -0
- package/dist/analyzers/relevanceScorer.d.ts.map +1 -0
- package/dist/analyzers/relevanceScorer.js +200 -0
- package/dist/analyzers/relevanceScorer.js.map +1 -0
- package/dist/analyzers/standardLibrary.d.ts +22 -0
- package/dist/analyzers/standardLibrary.d.ts.map +1 -0
- package/dist/analyzers/standardLibrary.js +211 -0
- package/dist/analyzers/standardLibrary.js.map +1 -0
- package/dist/analyzers/symbolGraph.d.ts +30 -0
- package/dist/analyzers/symbolGraph.d.ts.map +1 -0
- package/dist/analyzers/symbolGraph.js +380 -0
- package/dist/analyzers/symbolGraph.js.map +1 -0
- package/dist/analyzers/symbolTable.d.ts +18 -0
- package/dist/analyzers/symbolTable.d.ts.map +1 -0
- package/dist/analyzers/symbolTable.js +176 -0
- package/dist/analyzers/symbolTable.js.map +1 -0
- package/dist/analyzers/typeChecker.d.ts +13 -0
- package/dist/analyzers/typeChecker.d.ts.map +1 -0
- package/dist/analyzers/typeChecker.js +580 -0
- package/dist/analyzers/typeChecker.js.map +1 -0
- package/dist/analyzers/usagePatterns.d.ts +42 -0
- package/dist/analyzers/usagePatterns.d.ts.map +1 -0
- package/dist/analyzers/usagePatterns.js +75 -0
- package/dist/analyzers/usagePatterns.js.map +1 -0
- package/dist/api-contract/context/backend.d.ts +19 -0
- package/dist/api-contract/context/backend.d.ts.map +1 -0
- package/dist/api-contract/context/backend.js +64 -0
- package/dist/api-contract/context/backend.js.map +1 -0
- package/dist/api-contract/context/contract.d.ts +34 -0
- package/dist/api-contract/context/contract.d.ts.map +1 -0
- package/dist/api-contract/context/contract.js +306 -0
- package/dist/api-contract/context/contract.js.map +1 -0
- package/dist/api-contract/context/frontend.d.ts +19 -0
- package/dist/api-contract/context/frontend.d.ts.map +1 -0
- package/dist/api-contract/context/frontend.js +64 -0
- package/dist/api-contract/context/frontend.js.map +1 -0
- package/dist/api-contract/detector.d.ts +28 -0
- package/dist/api-contract/detector.d.ts.map +1 -0
- package/dist/api-contract/detector.js +393 -0
- package/dist/api-contract/detector.js.map +1 -0
- package/dist/api-contract/extractors/python.d.ts +32 -0
- package/dist/api-contract/extractors/python.d.ts.map +1 -0
- package/dist/api-contract/extractors/python.js +521 -0
- package/dist/api-contract/extractors/python.js.map +1 -0
- package/dist/api-contract/extractors/pythonAstUtils.d.ts +44 -0
- package/dist/api-contract/extractors/pythonAstUtils.d.ts.map +1 -0
- package/dist/api-contract/extractors/pythonAstUtils.js +489 -0
- package/dist/api-contract/extractors/pythonAstUtils.js.map +1 -0
- package/dist/api-contract/extractors/tsAstUtils.d.ts +47 -0
- package/dist/api-contract/extractors/tsAstUtils.d.ts.map +1 -0
- package/dist/api-contract/extractors/tsAstUtils.js +173 -0
- package/dist/api-contract/extractors/tsAstUtils.js.map +1 -0
- package/dist/api-contract/extractors/typescript.d.ts +32 -0
- package/dist/api-contract/extractors/typescript.d.ts.map +1 -0
- package/dist/api-contract/extractors/typescript.js +666 -0
- package/dist/api-contract/extractors/typescript.js.map +1 -0
- package/dist/api-contract/index.d.ts +104 -0
- package/dist/api-contract/index.d.ts.map +1 -0
- package/dist/api-contract/index.js +232 -0
- package/dist/api-contract/index.js.map +1 -0
- package/dist/api-contract/types.d.ts +151 -0
- package/dist/api-contract/types.d.ts.map +1 -0
- package/dist/api-contract/types.js +19 -0
- package/dist/api-contract/types.js.map +1 -0
- package/dist/api-contract/validators/endpoint.d.ts +21 -0
- package/dist/api-contract/validators/endpoint.d.ts.map +1 -0
- package/dist/api-contract/validators/endpoint.js +224 -0
- package/dist/api-contract/validators/endpoint.js.map +1 -0
- package/dist/api-contract/validators/index.d.ts +40 -0
- package/dist/api-contract/validators/index.d.ts.map +1 -0
- package/dist/api-contract/validators/index.js +875 -0
- package/dist/api-contract/validators/index.js.map +1 -0
- package/dist/api-contract/validators/parameter.d.ts +17 -0
- package/dist/api-contract/validators/parameter.d.ts.map +1 -0
- package/dist/api-contract/validators/parameter.js +250 -0
- package/dist/api-contract/validators/parameter.js.map +1 -0
- package/dist/api-contract/validators/type.d.ts +38 -0
- package/dist/api-contract/validators/type.d.ts.map +1 -0
- package/dist/api-contract/validators/type.js +244 -0
- package/dist/api-contract/validators/type.js.map +1 -0
- package/dist/context/apiContract/complexTypeSupport.d.ts +83 -0
- package/dist/context/apiContract/complexTypeSupport.d.ts.map +1 -0
- package/dist/context/apiContract/complexTypeSupport.js +665 -0
- package/dist/context/apiContract/complexTypeSupport.js.map +1 -0
- package/dist/context/apiContract/graphqlSupport.d.ts +105 -0
- package/dist/context/apiContract/graphqlSupport.d.ts.map +1 -0
- package/dist/context/apiContract/graphqlSupport.js +671 -0
- package/dist/context/apiContract/graphqlSupport.js.map +1 -0
- package/dist/context/apiContract/index.d.ts +14 -0
- package/dist/context/apiContract/index.d.ts.map +1 -0
- package/dist/context/apiContract/index.js +17 -0
- package/dist/context/apiContract/index.js.map +1 -0
- package/dist/context/apiContract/webSocketSupport.d.ts +104 -0
- package/dist/context/apiContract/webSocketSupport.d.ts.map +1 -0
- package/dist/context/apiContract/webSocketSupport.js +465 -0
- package/dist/context/apiContract/webSocketSupport.js.map +1 -0
- package/dist/context/apiContractContext.d.ts +15 -0
- package/dist/context/apiContractContext.d.ts.map +1 -0
- package/dist/context/apiContractContext.js +979 -0
- package/dist/context/apiContractContext.js.map +1 -0
- package/dist/context/apiContractExtraction.d.ts +52 -0
- package/dist/context/apiContractExtraction.d.ts.map +1 -0
- package/dist/context/apiContractExtraction.js +438 -0
- package/dist/context/apiContractExtraction.js.map +1 -0
- package/dist/context/contextLineage.d.ts +79 -0
- package/dist/context/contextLineage.d.ts.map +1 -0
- package/dist/context/contextLineage.js +259 -0
- package/dist/context/contextLineage.js.map +1 -0
- package/dist/context/contextOrchestrator.d.ts +57 -0
- package/dist/context/contextOrchestrator.d.ts.map +1 -0
- package/dist/context/contextOrchestrator.js +162 -0
- package/dist/context/contextOrchestrator.js.map +1 -0
- package/dist/context/intentTracker.d.ts +73 -0
- package/dist/context/intentTracker.d.ts.map +1 -0
- package/dist/context/intentTracker.js +168 -0
- package/dist/context/intentTracker.js.map +1 -0
- package/dist/context/projectContext.d.ts +219 -0
- package/dist/context/projectContext.d.ts.map +1 -0
- package/dist/context/projectContext.js +1984 -0
- package/dist/context/projectContext.js.map +1 -0
- package/dist/prompts/index.d.ts +17 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +260 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/library.d.ts +51 -0
- package/dist/prompts/library.d.ts.map +1 -0
- package/dist/prompts/library.js +65 -0
- package/dist/prompts/library.js.map +1 -0
- package/dist/prompts/templates.d.ts +44 -0
- package/dist/prompts/templates.d.ts.map +1 -0
- package/dist/prompts/templates.js +97 -0
- package/dist/prompts/templates.js.map +1 -0
- package/dist/queue/jobPersistence.d.ts +46 -0
- package/dist/queue/jobPersistence.d.ts.map +1 -0
- package/dist/queue/jobPersistence.js +158 -0
- package/dist/queue/jobPersistence.js.map +1 -0
- package/dist/queue/jobQueue.d.ts +116 -0
- package/dist/queue/jobQueue.d.ts.map +1 -0
- package/dist/queue/jobQueue.js +275 -0
- package/dist/queue/jobQueue.js.map +1 -0
- package/dist/queue/validationJob.d.ts +69 -0
- package/dist/queue/validationJob.d.ts.map +1 -0
- package/dist/queue/validationJob.js +435 -0
- package/dist/queue/validationJob.js.map +1 -0
- package/dist/resources/index.d.ts +15 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +328 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/validationReportStore.d.ts +170 -0
- package/dist/resources/validationReportStore.d.ts.map +1 -0
- package/dist/resources/validationReportStore.js +515 -0
- package/dist/resources/validationReportStore.js.map +1 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +102 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/asyncValidation.d.ts +19 -0
- package/dist/tools/asyncValidation.d.ts.map +1 -0
- package/dist/tools/asyncValidation.js +346 -0
- package/dist/tools/asyncValidation.js.map +1 -0
- package/dist/tools/buildContext.d.ts +17 -0
- package/dist/tools/buildContext.d.ts.map +1 -0
- package/dist/tools/buildContext.js +188 -0
- package/dist/tools/buildContext.js.map +1 -0
- package/dist/tools/getDependencyGraph.d.ts +16 -0
- package/dist/tools/getDependencyGraph.d.ts.map +1 -0
- package/dist/tools/getDependencyGraph.js +436 -0
- package/dist/tools/getDependencyGraph.js.map +1 -0
- package/dist/tools/incrementalValidation.d.ts +71 -0
- package/dist/tools/incrementalValidation.d.ts.map +1 -0
- package/dist/tools/incrementalValidation.js +203 -0
- package/dist/tools/incrementalValidation.js.map +1 -0
- package/dist/tools/index.d.ts +24 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +106 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/validateCode.d.ts +17 -0
- package/dist/tools/validateCode.d.ts.map +1 -0
- package/dist/tools/validateCode.js +368 -0
- package/dist/tools/validateCode.js.map +1 -0
- package/dist/tools/validateCodeLite.d.ts +2 -0
- package/dist/tools/validateCodeLite.d.ts.map +1 -0
- package/dist/tools/validateCodeLite.js +2 -0
- package/dist/tools/validateCodeLite.js.map +1 -0
- package/dist/tools/validation/builtins.d.ts +92 -0
- package/dist/tools/validation/builtins.d.ts.map +1 -0
- package/dist/tools/validation/builtins.js +2184 -0
- package/dist/tools/validation/builtins.js.map +1 -0
- package/dist/tools/validation/contextualNaming.d.ts +99 -0
- package/dist/tools/validation/contextualNaming.d.ts.map +1 -0
- package/dist/tools/validation/contextualNaming.js +959 -0
- package/dist/tools/validation/contextualNaming.js.map +1 -0
- package/dist/tools/validation/deadCode.d.ts +115 -0
- package/dist/tools/validation/deadCode.d.ts.map +1 -0
- package/dist/tools/validation/deadCode.js +861 -0
- package/dist/tools/validation/deadCode.js.map +1 -0
- package/dist/tools/validation/extractors/index.d.ts +131 -0
- package/dist/tools/validation/extractors/index.d.ts.map +1 -0
- package/dist/tools/validation/extractors/index.js +233 -0
- package/dist/tools/validation/extractors/index.js.map +1 -0
- package/dist/tools/validation/extractors/javascript.d.ts +73 -0
- package/dist/tools/validation/extractors/javascript.d.ts.map +1 -0
- package/dist/tools/validation/extractors/javascript.js +1841 -0
- package/dist/tools/validation/extractors/javascript.js.map +1 -0
- package/dist/tools/validation/extractors/python.d.ts +93 -0
- package/dist/tools/validation/extractors/python.d.ts.map +1 -0
- package/dist/tools/validation/extractors/python.js +799 -0
- package/dist/tools/validation/extractors/python.js.map +1 -0
- package/dist/tools/validation/manifest.d.ts +45 -0
- package/dist/tools/validation/manifest.d.ts.map +1 -0
- package/dist/tools/validation/manifest.js +719 -0
- package/dist/tools/validation/manifest.js.map +1 -0
- package/dist/tools/validation/parser.d.ts +58 -0
- package/dist/tools/validation/parser.d.ts.map +1 -0
- package/dist/tools/validation/parser.js +232 -0
- package/dist/tools/validation/parser.js.map +1 -0
- package/dist/tools/validation/registry.d.ts +15 -0
- package/dist/tools/validation/registry.d.ts.map +1 -0
- package/dist/tools/validation/registry.js +169 -0
- package/dist/tools/validation/registry.js.map +1 -0
- package/dist/tools/validation/scoring.d.ts +54 -0
- package/dist/tools/validation/scoring.d.ts.map +1 -0
- package/dist/tools/validation/scoring.js +242 -0
- package/dist/tools/validation/scoring.js.map +1 -0
- package/dist/tools/validation/types.d.ts +120 -0
- package/dist/tools/validation/types.d.ts.map +1 -0
- package/dist/tools/validation/types.js +11 -0
- package/dist/tools/validation/types.js.map +1 -0
- package/dist/tools/validation/unusedLocals.d.ts +36 -0
- package/dist/tools/validation/unusedLocals.d.ts.map +1 -0
- package/dist/tools/validation/unusedLocals.js +333 -0
- package/dist/tools/validation/unusedLocals.js.map +1 -0
- package/dist/tools/validation/validation.d.ts +98 -0
- package/dist/tools/validation/validation.d.ts.map +1 -0
- package/dist/tools/validation/validation.js +1837 -0
- package/dist/tools/validation/validation.js.map +1 -0
- package/dist/types/codeGraph.d.ts +163 -0
- package/dist/types/codeGraph.d.ts.map +1 -0
- package/dist/types/codeGraph.js +9 -0
- package/dist/types/codeGraph.js.map +1 -0
- package/dist/types/symbolGraph.d.ts +68 -0
- package/dist/types/symbolGraph.d.ts.map +1 -0
- package/dist/types/symbolGraph.js +10 -0
- package/dist/types/symbolGraph.js.map +1 -0
- package/dist/types/tools.d.ts +43 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +7 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/utils/fileFilter.d.ts +37 -0
- package/dist/utils/fileFilter.d.ts.map +1 -0
- package/dist/utils/fileFilter.js +91 -0
- package/dist/utils/fileFilter.js.map +1 -0
- package/dist/utils/gitUtils.d.ts +28 -0
- package/dist/utils/gitUtils.d.ts.map +1 -0
- package/dist/utils/gitUtils.js +81 -0
- package/dist/utils/gitUtils.js.map +1 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +38 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/serialization.d.ts +25 -0
- package/dist/utils/serialization.d.ts.map +1 -0
- package/dist/utils/serialization.js +53 -0
- package/dist/utils/serialization.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree-sitter Based Parser
|
|
3
|
+
*
|
|
4
|
+
* Accurate, fast parsing using Tree-sitter for multiple languages.
|
|
5
|
+
* Handles edge cases, nested scopes, and complex syntax correctly.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
*/
|
|
9
|
+
import { createRequire } from "module";
|
|
10
|
+
import { logger } from "../../utils/logger.js";
|
|
11
|
+
import * as crypto from "crypto";
|
|
12
|
+
export class TreeSitterParser {
|
|
13
|
+
parsers = new Map();
|
|
14
|
+
config;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = {
|
|
17
|
+
language: "typescript",
|
|
18
|
+
enableIncremental: true,
|
|
19
|
+
resolveTypes: true,
|
|
20
|
+
buildCallGraph: true,
|
|
21
|
+
maxFileSize: 1024 * 1024 * 5, // 5MB default
|
|
22
|
+
parallelParsing: false,
|
|
23
|
+
cacheResults: true,
|
|
24
|
+
...config,
|
|
25
|
+
};
|
|
26
|
+
this.initializeParsers();
|
|
27
|
+
}
|
|
28
|
+
initializeParsers() {
|
|
29
|
+
try {
|
|
30
|
+
const require = createRequire(import.meta.url);
|
|
31
|
+
const ParserRuntime = require("tree-sitter");
|
|
32
|
+
const TypeScriptLangs = require("tree-sitter-typescript");
|
|
33
|
+
const JavaScriptLang = require("tree-sitter-javascript");
|
|
34
|
+
const PythonLang = require("tree-sitter-python");
|
|
35
|
+
// TypeScript parser
|
|
36
|
+
const tsParser = new ParserRuntime();
|
|
37
|
+
tsParser.setLanguage((TypeScriptLangs.tsx ?? TypeScriptLangs.typescript ?? TypeScriptLangs));
|
|
38
|
+
this.parsers.set("typescript", tsParser);
|
|
39
|
+
// JavaScript parser
|
|
40
|
+
const jsParser = new ParserRuntime();
|
|
41
|
+
jsParser.setLanguage(JavaScriptLang);
|
|
42
|
+
this.parsers.set("javascript", jsParser);
|
|
43
|
+
// Python parser
|
|
44
|
+
const pyParser = new ParserRuntime();
|
|
45
|
+
pyParser.setLanguage(PythonLang);
|
|
46
|
+
this.parsers.set("python", pyParser);
|
|
47
|
+
logger.debug("Tree-sitter parsers initialized");
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
logger.error("Failed to initialize tree-sitter parsers", e);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse code and build complete CodeGraph
|
|
55
|
+
*/
|
|
56
|
+
async parse(code, filePath, language) {
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
const errors = [];
|
|
59
|
+
try {
|
|
60
|
+
const parser = this.parsers.get(language);
|
|
61
|
+
if (!parser) {
|
|
62
|
+
throw new Error(`No parser available for language: ${language}`);
|
|
63
|
+
}
|
|
64
|
+
// Parse to AST
|
|
65
|
+
const tree = parser.parse(code);
|
|
66
|
+
if (!tree.rootNode) {
|
|
67
|
+
throw new Error("Failed to parse code - no root node");
|
|
68
|
+
}
|
|
69
|
+
// Build CodeGraph from AST
|
|
70
|
+
const graph = await this.buildCodeGraph(tree, code, filePath, language);
|
|
71
|
+
const parseTime = Date.now() - startTime;
|
|
72
|
+
logger.debug(`Parsed ${filePath} in ${parseTime}ms`);
|
|
73
|
+
return {
|
|
74
|
+
graph,
|
|
75
|
+
errors,
|
|
76
|
+
parseTime,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
logger.error("Parse error:", error);
|
|
81
|
+
errors.push({
|
|
82
|
+
message: error instanceof Error ? error.message : "Unknown parse error",
|
|
83
|
+
location: { file: filePath, line: 0, column: 0 },
|
|
84
|
+
severity: "error",
|
|
85
|
+
});
|
|
86
|
+
// Return empty graph on error
|
|
87
|
+
return {
|
|
88
|
+
graph: this.createEmptyGraph(),
|
|
89
|
+
errors,
|
|
90
|
+
parseTime: Date.now() - startTime,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build CodeGraph from Tree-sitter AST
|
|
96
|
+
*/
|
|
97
|
+
async buildCodeGraph(tree, code, filePath, language) {
|
|
98
|
+
const graph = this.createEmptyGraph();
|
|
99
|
+
const fileHash = this.computeHash(code);
|
|
100
|
+
graph.fileHashes.set(filePath, fileHash);
|
|
101
|
+
graph.lastUpdated = new Date();
|
|
102
|
+
// Initialize global scope
|
|
103
|
+
graph.globalScope = {
|
|
104
|
+
name: "global",
|
|
105
|
+
type: "global",
|
|
106
|
+
symbols: new Map(),
|
|
107
|
+
children: [],
|
|
108
|
+
};
|
|
109
|
+
// Create file scope
|
|
110
|
+
const fileScope = {
|
|
111
|
+
name: filePath,
|
|
112
|
+
type: "module",
|
|
113
|
+
parent: graph.globalScope,
|
|
114
|
+
symbols: new Map(),
|
|
115
|
+
children: [],
|
|
116
|
+
location: { file: filePath, line: 0, column: 0 },
|
|
117
|
+
};
|
|
118
|
+
graph.globalScope.children.push(fileScope);
|
|
119
|
+
graph.scopes.set(filePath, fileScope);
|
|
120
|
+
// Traverse AST and extract symbols
|
|
121
|
+
const cursor = tree.walk();
|
|
122
|
+
switch (language) {
|
|
123
|
+
case "typescript":
|
|
124
|
+
case "javascript":
|
|
125
|
+
await this.extractJavaScriptSymbols(cursor, code, filePath, graph, fileScope);
|
|
126
|
+
break;
|
|
127
|
+
case "python":
|
|
128
|
+
await this.extractPythonSymbols(cursor, code, filePath, graph, fileScope);
|
|
129
|
+
break;
|
|
130
|
+
default:
|
|
131
|
+
logger.warn(`Symbol extraction not implemented for ${language}`);
|
|
132
|
+
}
|
|
133
|
+
return graph;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Extract symbols from JavaScript/TypeScript AST
|
|
137
|
+
*/
|
|
138
|
+
async extractJavaScriptSymbols(cursor, code, filePath, graph, currentScope) {
|
|
139
|
+
const visited = new Set();
|
|
140
|
+
const traverse = (node, scope) => {
|
|
141
|
+
if (visited.has(node.id))
|
|
142
|
+
return;
|
|
143
|
+
visited.add(node.id);
|
|
144
|
+
const nodeType = node.type;
|
|
145
|
+
const location = {
|
|
146
|
+
file: filePath,
|
|
147
|
+
line: node.startPosition.row + 1,
|
|
148
|
+
column: node.startPosition.column,
|
|
149
|
+
endLine: node.endPosition.row + 1,
|
|
150
|
+
endColumn: node.endPosition.column,
|
|
151
|
+
};
|
|
152
|
+
// Function declarations
|
|
153
|
+
if (nodeType === "function_declaration" || nodeType === "function") {
|
|
154
|
+
const nameNode = node.childForFieldName("name");
|
|
155
|
+
if (nameNode) {
|
|
156
|
+
const funcName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
157
|
+
const symbol = this.createFunctionSymbol(funcName, location, node, code, scope);
|
|
158
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
159
|
+
// Create function scope
|
|
160
|
+
const funcScope = {
|
|
161
|
+
name: funcName,
|
|
162
|
+
type: "function",
|
|
163
|
+
parent: scope,
|
|
164
|
+
symbols: new Map(),
|
|
165
|
+
children: [],
|
|
166
|
+
location,
|
|
167
|
+
};
|
|
168
|
+
scope.children.push(funcScope);
|
|
169
|
+
// Process function body
|
|
170
|
+
const bodyNode = node.childForFieldName("body");
|
|
171
|
+
if (bodyNode) {
|
|
172
|
+
for (const child of bodyNode.children) {
|
|
173
|
+
traverse(child, funcScope);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Arrow functions
|
|
180
|
+
if (nodeType === "arrow_function") {
|
|
181
|
+
const parent = node.parent;
|
|
182
|
+
if (parent && parent.type === "variable_declarator") {
|
|
183
|
+
const nameNode = parent.childForFieldName("name");
|
|
184
|
+
if (nameNode) {
|
|
185
|
+
const funcName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
186
|
+
const symbol = this.createFunctionSymbol(funcName, location, node, code, scope);
|
|
187
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Method definitions
|
|
192
|
+
if (nodeType === "method_definition") {
|
|
193
|
+
const nameNode = node.childForFieldName("name");
|
|
194
|
+
if (nameNode) {
|
|
195
|
+
const methodName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
196
|
+
const symbol = this.createFunctionSymbol(methodName, location, node, code, scope);
|
|
197
|
+
symbol.type = "method";
|
|
198
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
199
|
+
// Create method scope
|
|
200
|
+
const methodScope = {
|
|
201
|
+
name: methodName,
|
|
202
|
+
type: "function",
|
|
203
|
+
parent: scope,
|
|
204
|
+
symbols: new Map(),
|
|
205
|
+
children: [],
|
|
206
|
+
location,
|
|
207
|
+
};
|
|
208
|
+
scope.children.push(methodScope);
|
|
209
|
+
// Process method body
|
|
210
|
+
const bodyNode = node.childForFieldName("body");
|
|
211
|
+
if (bodyNode) {
|
|
212
|
+
for (const child of bodyNode.children) {
|
|
213
|
+
traverse(child, methodScope);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Class declarations
|
|
220
|
+
if (nodeType === "class_declaration" || nodeType === "class") {
|
|
221
|
+
const nameNode = node.childForFieldName("name");
|
|
222
|
+
if (nameNode) {
|
|
223
|
+
const className = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
224
|
+
const symbol = {
|
|
225
|
+
name: className,
|
|
226
|
+
type: "class",
|
|
227
|
+
location,
|
|
228
|
+
usages: [],
|
|
229
|
+
definedIn: scope.name,
|
|
230
|
+
properties: new Map(),
|
|
231
|
+
methods: new Map(),
|
|
232
|
+
};
|
|
233
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
234
|
+
// Create class scope
|
|
235
|
+
const classScope = {
|
|
236
|
+
name: className,
|
|
237
|
+
type: "class",
|
|
238
|
+
parent: scope,
|
|
239
|
+
symbols: new Map(),
|
|
240
|
+
children: [],
|
|
241
|
+
location,
|
|
242
|
+
};
|
|
243
|
+
scope.children.push(classScope);
|
|
244
|
+
// Process class body
|
|
245
|
+
const bodyNode = node.childForFieldName("body");
|
|
246
|
+
if (bodyNode) {
|
|
247
|
+
for (const child of bodyNode.children) {
|
|
248
|
+
traverse(child, classScope);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Variable declarations
|
|
255
|
+
if (nodeType === "variable_declarator") {
|
|
256
|
+
const nameNode = node.childForFieldName("name");
|
|
257
|
+
if (nameNode) {
|
|
258
|
+
const varName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
259
|
+
const symbol = {
|
|
260
|
+
name: varName,
|
|
261
|
+
type: "variable",
|
|
262
|
+
location,
|
|
263
|
+
usages: [],
|
|
264
|
+
definedIn: scope.name,
|
|
265
|
+
};
|
|
266
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Import statements
|
|
270
|
+
if (nodeType === "import_statement") {
|
|
271
|
+
this.extractImport(node, code, filePath, graph);
|
|
272
|
+
}
|
|
273
|
+
// Export statements
|
|
274
|
+
if (nodeType === "export_statement") {
|
|
275
|
+
this.extractExport(node, code, filePath, graph);
|
|
276
|
+
}
|
|
277
|
+
// Call expressions (for call graph)
|
|
278
|
+
if (nodeType === "call_expression") {
|
|
279
|
+
this.extractCallExpression(node, code, graph, scope);
|
|
280
|
+
}
|
|
281
|
+
// Identifier references
|
|
282
|
+
if (nodeType === "identifier") {
|
|
283
|
+
const name = code.substring(node.startIndex, node.endIndex);
|
|
284
|
+
const ref = {
|
|
285
|
+
name,
|
|
286
|
+
location,
|
|
287
|
+
type: "usage",
|
|
288
|
+
scope: scope.name,
|
|
289
|
+
};
|
|
290
|
+
const refs = graph.references.get(name) || [];
|
|
291
|
+
refs.push(ref);
|
|
292
|
+
graph.references.set(name, refs);
|
|
293
|
+
}
|
|
294
|
+
// Traverse children
|
|
295
|
+
for (const child of node.children) {
|
|
296
|
+
traverse(child, scope);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
traverse(cursor.currentNode, currentScope);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Extract symbols from Python AST
|
|
303
|
+
*/
|
|
304
|
+
async extractPythonSymbols(cursor, code, filePath, graph, currentScope) {
|
|
305
|
+
const visited = new Set();
|
|
306
|
+
const traverse = (node, scope) => {
|
|
307
|
+
if (visited.has(node.id))
|
|
308
|
+
return;
|
|
309
|
+
visited.add(node.id);
|
|
310
|
+
const nodeType = node.type;
|
|
311
|
+
const location = {
|
|
312
|
+
file: filePath,
|
|
313
|
+
line: node.startPosition.row + 1,
|
|
314
|
+
column: node.startPosition.column,
|
|
315
|
+
endLine: node.endPosition.row + 1,
|
|
316
|
+
endColumn: node.endPosition.column,
|
|
317
|
+
};
|
|
318
|
+
// Function definitions
|
|
319
|
+
if (nodeType === "function_definition") {
|
|
320
|
+
const nameNode = node.childForFieldName("name");
|
|
321
|
+
if (nameNode) {
|
|
322
|
+
const funcName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
323
|
+
const symbol = this.createPythonFunctionSymbol(funcName, location, node, code, scope);
|
|
324
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
325
|
+
// Create function scope
|
|
326
|
+
const funcScope = {
|
|
327
|
+
name: funcName,
|
|
328
|
+
type: "function",
|
|
329
|
+
parent: scope,
|
|
330
|
+
symbols: new Map(),
|
|
331
|
+
children: [],
|
|
332
|
+
location,
|
|
333
|
+
};
|
|
334
|
+
scope.children.push(funcScope);
|
|
335
|
+
// Process function body
|
|
336
|
+
const bodyNode = node.childForFieldName("body");
|
|
337
|
+
if (bodyNode) {
|
|
338
|
+
for (const child of bodyNode.children) {
|
|
339
|
+
traverse(child, funcScope);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Class definitions
|
|
346
|
+
if (nodeType === "class_definition") {
|
|
347
|
+
const nameNode = node.childForFieldName("name");
|
|
348
|
+
if (nameNode) {
|
|
349
|
+
const className = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
350
|
+
const symbol = {
|
|
351
|
+
name: className,
|
|
352
|
+
type: "class",
|
|
353
|
+
location,
|
|
354
|
+
usages: [],
|
|
355
|
+
definedIn: scope.name,
|
|
356
|
+
properties: new Map(),
|
|
357
|
+
methods: new Map(),
|
|
358
|
+
};
|
|
359
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
360
|
+
// Create class scope
|
|
361
|
+
const classScope = {
|
|
362
|
+
name: className,
|
|
363
|
+
type: "class",
|
|
364
|
+
parent: scope,
|
|
365
|
+
symbols: new Map(),
|
|
366
|
+
children: [],
|
|
367
|
+
location,
|
|
368
|
+
};
|
|
369
|
+
scope.children.push(classScope);
|
|
370
|
+
// Process class body
|
|
371
|
+
const bodyNode = node.childForFieldName("body");
|
|
372
|
+
if (bodyNode) {
|
|
373
|
+
for (const child of bodyNode.children) {
|
|
374
|
+
traverse(child, classScope);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// Assignment (variables)
|
|
381
|
+
if (nodeType === "assignment") {
|
|
382
|
+
const leftNode = node.childForFieldName("left");
|
|
383
|
+
if (leftNode && leftNode.type === "identifier") {
|
|
384
|
+
const varName = code.substring(leftNode.startIndex, leftNode.endIndex);
|
|
385
|
+
const symbol = {
|
|
386
|
+
name: varName,
|
|
387
|
+
type: "variable",
|
|
388
|
+
location,
|
|
389
|
+
usages: [],
|
|
390
|
+
definedIn: scope.name,
|
|
391
|
+
};
|
|
392
|
+
this.addSymbol(graph, symbol, scope, filePath);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Import statements
|
|
396
|
+
if (nodeType === "import_statement" ||
|
|
397
|
+
nodeType === "import_from_statement") {
|
|
398
|
+
this.extractPythonImport(node, code, filePath, graph);
|
|
399
|
+
}
|
|
400
|
+
// Call expressions (for call graph)
|
|
401
|
+
if (nodeType === "call") {
|
|
402
|
+
this.extractPythonCallExpression(node, code, graph, scope);
|
|
403
|
+
}
|
|
404
|
+
// Identifier references
|
|
405
|
+
if (nodeType === "identifier") {
|
|
406
|
+
const name = code.substring(node.startIndex, node.endIndex);
|
|
407
|
+
const ref = {
|
|
408
|
+
name,
|
|
409
|
+
location,
|
|
410
|
+
type: "usage",
|
|
411
|
+
scope: scope.name,
|
|
412
|
+
};
|
|
413
|
+
const refs = graph.references.get(name) || [];
|
|
414
|
+
refs.push(ref);
|
|
415
|
+
graph.references.set(name, refs);
|
|
416
|
+
}
|
|
417
|
+
// Traverse children
|
|
418
|
+
for (const child of node.children) {
|
|
419
|
+
traverse(child, scope);
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
traverse(cursor.currentNode, currentScope);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Create function symbol with signature
|
|
426
|
+
*/
|
|
427
|
+
createFunctionSymbol(name, location, node, code, scope) {
|
|
428
|
+
const paramsNode = node.childForFieldName("parameters");
|
|
429
|
+
const parameters = [];
|
|
430
|
+
if (paramsNode) {
|
|
431
|
+
for (const param of paramsNode.children) {
|
|
432
|
+
if (param.type === "identifier" ||
|
|
433
|
+
param.type === "required_parameter") {
|
|
434
|
+
const paramName = code.substring(param.startIndex, param.endIndex);
|
|
435
|
+
parameters.push(paramName);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// Check if async
|
|
440
|
+
const isAsync = node.children.some((c) => c.type === "async");
|
|
441
|
+
return {
|
|
442
|
+
name,
|
|
443
|
+
type: "function",
|
|
444
|
+
location,
|
|
445
|
+
usages: [],
|
|
446
|
+
definedIn: scope.name,
|
|
447
|
+
parameters,
|
|
448
|
+
isAsync,
|
|
449
|
+
signature: this.buildSignature(parameters, node, code),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Create Python function symbol
|
|
454
|
+
*/
|
|
455
|
+
createPythonFunctionSymbol(name, location, node, code, scope) {
|
|
456
|
+
const paramsNode = node.childForFieldName("parameters");
|
|
457
|
+
const parameters = [];
|
|
458
|
+
if (paramsNode) {
|
|
459
|
+
for (const param of paramsNode.children) {
|
|
460
|
+
if (param.type === "identifier" || param.type === "typed_parameter") {
|
|
461
|
+
const nameNode = param.type === "typed_parameter" ?
|
|
462
|
+
param.childForFieldName("name")
|
|
463
|
+
: param;
|
|
464
|
+
if (nameNode) {
|
|
465
|
+
const paramName = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
466
|
+
if (paramName !== "self" && paramName !== "cls") {
|
|
467
|
+
parameters.push(paramName);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
// Check if async
|
|
474
|
+
const isAsync = node.parent?.type === "decorated_definition" ||
|
|
475
|
+
code.substring(node.startIndex, node.startIndex + 10).includes("async");
|
|
476
|
+
return {
|
|
477
|
+
name,
|
|
478
|
+
type: "function",
|
|
479
|
+
location,
|
|
480
|
+
usages: [],
|
|
481
|
+
definedIn: scope.name,
|
|
482
|
+
parameters,
|
|
483
|
+
isAsync,
|
|
484
|
+
signature: `def ${name}(${parameters.join(", ")})`,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Build function signature
|
|
489
|
+
*/
|
|
490
|
+
buildSignature(parameters, node, code) {
|
|
491
|
+
const params = parameters.join(", ");
|
|
492
|
+
// Try to get return type if available (TypeScript)
|
|
493
|
+
const returnTypeNode = node.childForFieldName("return_type");
|
|
494
|
+
if (returnTypeNode) {
|
|
495
|
+
const returnType = code.substring(returnTypeNode.startIndex, returnTypeNode.endIndex);
|
|
496
|
+
return `(${params}) => ${returnType}`;
|
|
497
|
+
}
|
|
498
|
+
return `(${params})`;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Extract import statement
|
|
502
|
+
*/
|
|
503
|
+
extractImport(node, code, filePath, graph) {
|
|
504
|
+
const sourceNode = node.childForFieldName("source");
|
|
505
|
+
if (!sourceNode)
|
|
506
|
+
return;
|
|
507
|
+
const module = code.substring(sourceNode.startIndex + 1, sourceNode.endIndex - 1); // Remove quotes
|
|
508
|
+
const location = {
|
|
509
|
+
file: filePath,
|
|
510
|
+
line: node.startPosition.row + 1,
|
|
511
|
+
column: node.startPosition.column,
|
|
512
|
+
};
|
|
513
|
+
const importNode = {
|
|
514
|
+
module,
|
|
515
|
+
location,
|
|
516
|
+
names: [],
|
|
517
|
+
};
|
|
518
|
+
// Extract imported names
|
|
519
|
+
for (const child of node.children) {
|
|
520
|
+
if (child.type === "import_clause") {
|
|
521
|
+
for (const nameChild of child.children) {
|
|
522
|
+
if (nameChild.type === "identifier") {
|
|
523
|
+
const name = code.substring(nameChild.startIndex, nameChild.endIndex);
|
|
524
|
+
importNode.names.push({
|
|
525
|
+
imported: name,
|
|
526
|
+
local: name,
|
|
527
|
+
type: "default",
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
else if (nameChild.type === "named_imports") {
|
|
531
|
+
for (const specifier of nameChild.children) {
|
|
532
|
+
if (specifier.type === "import_specifier") {
|
|
533
|
+
const nameNode = specifier.childForFieldName("name");
|
|
534
|
+
const aliasNode = specifier.childForFieldName("alias");
|
|
535
|
+
if (nameNode) {
|
|
536
|
+
const imported = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
537
|
+
const local = aliasNode ?
|
|
538
|
+
code.substring(aliasNode.startIndex, aliasNode.endIndex)
|
|
539
|
+
: imported;
|
|
540
|
+
importNode.names.push({
|
|
541
|
+
imported,
|
|
542
|
+
local,
|
|
543
|
+
type: "named",
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
graph.imports.set(filePath, importNode);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Extract Python import statement
|
|
556
|
+
*/
|
|
557
|
+
extractPythonImport(node, code, filePath, graph) {
|
|
558
|
+
const location = {
|
|
559
|
+
file: filePath,
|
|
560
|
+
line: node.startPosition.row + 1,
|
|
561
|
+
column: node.startPosition.column,
|
|
562
|
+
};
|
|
563
|
+
if (node.type === "import_statement") {
|
|
564
|
+
const nameNode = node.childForFieldName("name");
|
|
565
|
+
if (nameNode) {
|
|
566
|
+
const module = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
567
|
+
const importNode = {
|
|
568
|
+
module,
|
|
569
|
+
location,
|
|
570
|
+
names: [
|
|
571
|
+
{
|
|
572
|
+
imported: module,
|
|
573
|
+
local: module,
|
|
574
|
+
type: "default",
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
};
|
|
578
|
+
graph.imports.set(filePath, importNode);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else if (node.type === "import_from_statement") {
|
|
582
|
+
const moduleNode = node.childForFieldName("module_name");
|
|
583
|
+
if (moduleNode) {
|
|
584
|
+
const module = code.substring(moduleNode.startIndex, moduleNode.endIndex);
|
|
585
|
+
const importNode = {
|
|
586
|
+
module,
|
|
587
|
+
location,
|
|
588
|
+
names: [],
|
|
589
|
+
};
|
|
590
|
+
// Extract names
|
|
591
|
+
for (const child of node.children) {
|
|
592
|
+
if (child.type === "dotted_name" || child.type === "identifier") {
|
|
593
|
+
const name = code.substring(child.startIndex, child.endIndex);
|
|
594
|
+
importNode.names.push({
|
|
595
|
+
imported: name,
|
|
596
|
+
local: name,
|
|
597
|
+
type: "named",
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
graph.imports.set(filePath, importNode);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Extract export statement
|
|
607
|
+
*/
|
|
608
|
+
extractExport(node, code, filePath, graph) {
|
|
609
|
+
// Implementation for exports
|
|
610
|
+
const location = {
|
|
611
|
+
file: filePath,
|
|
612
|
+
line: node.startPosition.row + 1,
|
|
613
|
+
column: node.startPosition.column,
|
|
614
|
+
};
|
|
615
|
+
// Handle various export types
|
|
616
|
+
for (const child of node.children) {
|
|
617
|
+
if (child.type === "function_declaration" ||
|
|
618
|
+
child.type === "class_declaration") {
|
|
619
|
+
const nameNode = child.childForFieldName("name");
|
|
620
|
+
if (nameNode) {
|
|
621
|
+
const name = code.substring(nameNode.startIndex, nameNode.endIndex);
|
|
622
|
+
const exportNode = {
|
|
623
|
+
name,
|
|
624
|
+
location,
|
|
625
|
+
type: "named",
|
|
626
|
+
};
|
|
627
|
+
const exports = graph.exports.get(filePath) || [];
|
|
628
|
+
exports.push(exportNode);
|
|
629
|
+
graph.exports.set(filePath, exports);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Extract call expression for call graph
|
|
636
|
+
*/
|
|
637
|
+
extractCallExpression(node, code, graph, scope) {
|
|
638
|
+
const functionNode = node.childForFieldName("function");
|
|
639
|
+
if (functionNode) {
|
|
640
|
+
const calleeName = code.substring(functionNode.startIndex, functionNode.endIndex);
|
|
641
|
+
// Add to call graph
|
|
642
|
+
const callerName = scope.name;
|
|
643
|
+
const callees = graph.callGraph.get(callerName) || [];
|
|
644
|
+
if (!callees.includes(calleeName)) {
|
|
645
|
+
callees.push(calleeName);
|
|
646
|
+
graph.callGraph.set(callerName, callees);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Extract Python call expression
|
|
652
|
+
*/
|
|
653
|
+
extractPythonCallExpression(node, code, graph, scope) {
|
|
654
|
+
const functionNode = node.childForFieldName("function");
|
|
655
|
+
if (functionNode) {
|
|
656
|
+
const calleeName = code.substring(functionNode.startIndex, functionNode.endIndex);
|
|
657
|
+
const callerName = scope.name;
|
|
658
|
+
const callees = graph.callGraph.get(callerName) || [];
|
|
659
|
+
if (!callees.includes(calleeName)) {
|
|
660
|
+
callees.push(calleeName);
|
|
661
|
+
graph.callGraph.set(callerName, callees);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Add symbol to graph
|
|
667
|
+
*/
|
|
668
|
+
addSymbol(graph, symbol, scope, filePath) {
|
|
669
|
+
const qualifiedName = scope.type === "global" ? symbol.name : `${scope.name}.${symbol.name}`;
|
|
670
|
+
graph.symbols.set(qualifiedName, symbol);
|
|
671
|
+
scope.symbols.set(symbol.name, symbol);
|
|
672
|
+
// Track file symbols
|
|
673
|
+
const fileSymbols = graph.fileSymbols.get(filePath) || new Set();
|
|
674
|
+
fileSymbols.add(qualifiedName);
|
|
675
|
+
graph.fileSymbols.set(filePath, fileSymbols);
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Create empty CodeGraph
|
|
679
|
+
*/
|
|
680
|
+
createEmptyGraph() {
|
|
681
|
+
return {
|
|
682
|
+
symbols: new Map(),
|
|
683
|
+
references: new Map(),
|
|
684
|
+
imports: new Map(),
|
|
685
|
+
exports: new Map(),
|
|
686
|
+
callGraph: new Map(),
|
|
687
|
+
typeGraph: new Map(),
|
|
688
|
+
scopes: new Map(),
|
|
689
|
+
globalScope: {
|
|
690
|
+
name: "global",
|
|
691
|
+
type: "global",
|
|
692
|
+
symbols: new Map(),
|
|
693
|
+
children: [],
|
|
694
|
+
},
|
|
695
|
+
dependencies: [],
|
|
696
|
+
fileSymbols: new Map(),
|
|
697
|
+
fileHashes: new Map(),
|
|
698
|
+
lastUpdated: new Date(),
|
|
699
|
+
version: "1.0.0",
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Compute file hash for change detection
|
|
704
|
+
*/
|
|
705
|
+
computeHash(content) {
|
|
706
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
//# sourceMappingURL=treeSitterParser.js.map
|