@grafema/core 0.1.0-alpha.5 → 0.1.1-alpha
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/README.md +0 -1
- package/dist/Orchestrator.d.ts +24 -2
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +197 -24
- package/dist/config/ConfigLoader.d.ts +72 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +187 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/core/ASTWorker.d.ts +11 -36
- package/dist/core/ASTWorker.d.ts.map +1 -1
- package/dist/core/ASTWorker.js +93 -99
- package/dist/core/CoverageAnalyzer.d.ts +65 -0
- package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
- package/dist/core/CoverageAnalyzer.js +198 -0
- package/dist/core/FileNodeManager.d.ts +40 -0
- package/dist/core/FileNodeManager.d.ts.map +1 -0
- package/dist/core/FileNodeManager.js +84 -0
- package/dist/core/GraphFreshnessChecker.d.ts +33 -0
- package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
- package/dist/core/GraphFreshnessChecker.js +101 -0
- package/dist/core/HashUtils.d.ts +24 -0
- package/dist/core/HashUtils.d.ts.map +1 -0
- package/dist/core/HashUtils.js +45 -0
- package/dist/core/IncrementalReanalyzer.d.ts +36 -0
- package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
- package/dist/core/IncrementalReanalyzer.js +132 -0
- package/dist/core/NodeFactory.d.ts +225 -17
- package/dist/core/NodeFactory.d.ts.map +1 -1
- package/dist/core/NodeFactory.js +208 -18
- package/dist/core/ScopeTracker.d.ts +84 -0
- package/dist/core/ScopeTracker.d.ts.map +1 -0
- package/dist/core/ScopeTracker.js +116 -0
- package/dist/core/SemanticId.d.ts +90 -0
- package/dist/core/SemanticId.d.ts.map +1 -0
- package/dist/core/SemanticId.js +115 -0
- package/dist/core/VersionManager.d.ts.map +1 -1
- package/dist/core/VersionManager.js +3 -2
- package/dist/core/nodes/ArgumentExpressionNode.d.ts +43 -0
- package/dist/core/nodes/ArgumentExpressionNode.d.ts.map +1 -0
- package/dist/core/nodes/ArgumentExpressionNode.js +60 -0
- package/dist/core/nodes/ArrayLiteralNode.d.ts +27 -0
- package/dist/core/nodes/ArrayLiteralNode.d.ts.map +1 -0
- package/dist/core/nodes/ArrayLiteralNode.js +41 -0
- package/dist/core/nodes/CallSiteNode.d.ts +28 -0
- package/dist/core/nodes/CallSiteNode.d.ts.map +1 -1
- package/dist/core/nodes/CallSiteNode.js +46 -0
- package/dist/core/nodes/ClassNode.d.ts +33 -1
- package/dist/core/nodes/ClassNode.d.ts.map +1 -1
- package/dist/core/nodes/ClassNode.js +46 -2
- package/dist/core/nodes/DecoratorNode.d.ts +42 -0
- package/dist/core/nodes/DecoratorNode.d.ts.map +1 -0
- package/dist/core/nodes/DecoratorNode.js +62 -0
- package/dist/core/nodes/EnumNode.d.ts +42 -0
- package/dist/core/nodes/EnumNode.d.ts.map +1 -0
- package/dist/core/nodes/EnumNode.js +54 -0
- package/dist/core/nodes/ExportNode.d.ts +37 -1
- package/dist/core/nodes/ExportNode.d.ts.map +1 -1
- package/dist/core/nodes/ExportNode.js +48 -2
- package/dist/core/nodes/ExpressionNode.d.ts +97 -0
- package/dist/core/nodes/ExpressionNode.d.ts.map +1 -0
- package/dist/core/nodes/ExpressionNode.js +178 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts +28 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts.map +1 -0
- package/dist/core/nodes/ExternalModuleNode.js +41 -0
- package/dist/core/nodes/ExternalStdioNode.d.ts +13 -6
- package/dist/core/nodes/ExternalStdioNode.d.ts.map +1 -1
- package/dist/core/nodes/ExternalStdioNode.js +15 -8
- package/dist/core/nodes/FunctionNode.d.ts +36 -0
- package/dist/core/nodes/FunctionNode.d.ts.map +1 -1
- package/dist/core/nodes/FunctionNode.js +80 -1
- package/dist/core/nodes/ImportNode.d.ts +19 -5
- package/dist/core/nodes/ImportNode.d.ts.map +1 -1
- package/dist/core/nodes/ImportNode.js +23 -5
- package/dist/core/nodes/InterfaceNode.d.ts +46 -0
- package/dist/core/nodes/InterfaceNode.d.ts.map +1 -0
- package/dist/core/nodes/InterfaceNode.js +55 -0
- package/dist/core/nodes/IssueNode.d.ts +73 -0
- package/dist/core/nodes/IssueNode.d.ts.map +1 -0
- package/dist/core/nodes/IssueNode.js +129 -0
- package/dist/core/nodes/MethodCallNode.d.ts +30 -0
- package/dist/core/nodes/MethodCallNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodCallNode.js +49 -0
- package/dist/core/nodes/MethodNode.d.ts +32 -0
- package/dist/core/nodes/MethodNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodNode.js +48 -0
- package/dist/core/nodes/ModuleNode.d.ts +31 -0
- package/dist/core/nodes/ModuleNode.d.ts.map +1 -1
- package/dist/core/nodes/ModuleNode.js +37 -0
- package/dist/core/nodes/NetworkRequestNode.d.ts +54 -0
- package/dist/core/nodes/NetworkRequestNode.d.ts.map +1 -0
- package/dist/core/nodes/NetworkRequestNode.js +65 -0
- package/dist/core/nodes/ObjectLiteralNode.d.ts +27 -0
- package/dist/core/nodes/ObjectLiteralNode.d.ts.map +1 -0
- package/dist/core/nodes/ObjectLiteralNode.js +41 -0
- package/dist/core/nodes/ScopeNode.d.ts +31 -0
- package/dist/core/nodes/ScopeNode.d.ts.map +1 -1
- package/dist/core/nodes/ScopeNode.js +49 -0
- package/dist/core/nodes/TypeNode.d.ts +36 -0
- package/dist/core/nodes/TypeNode.d.ts.map +1 -0
- package/dist/core/nodes/TypeNode.js +53 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts +27 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts.map +1 -1
- package/dist/core/nodes/VariableDeclarationNode.js +40 -0
- package/dist/core/nodes/index.d.ts +12 -1
- package/dist/core/nodes/index.d.ts.map +1 -1
- package/dist/core/nodes/index.js +14 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts +98 -0
- package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticCollector.js +129 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts +77 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.js +159 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
- package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticWriter.js +43 -0
- package/dist/diagnostics/index.d.ts +14 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +11 -0
- package/dist/errors/GrafemaError.d.ts +118 -0
- package/dist/errors/GrafemaError.d.ts.map +1 -0
- package/dist/errors/GrafemaError.js +131 -0
- package/dist/index.d.ts +57 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -1
- package/dist/logging/Logger.d.ts +48 -0
- package/dist/logging/Logger.d.ts.map +1 -0
- package/dist/logging/Logger.js +134 -0
- package/dist/plugins/Plugin.d.ts +5 -1
- package/dist/plugins/Plugin.d.ts.map +1 -1
- package/dist/plugins/Plugin.js +33 -0
- package/dist/plugins/analysis/DatabaseAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/DatabaseAnalyzer.js +13 -6
- package/dist/plugins/analysis/ExpressAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressAnalyzer.js +27 -19
- package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressRouteAnalyzer.js +21 -14
- package/dist/plugins/analysis/FetchAnalyzer.d.ts +1 -0
- package/dist/plugins/analysis/FetchAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/FetchAnalyzer.js +34 -14
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts +6 -3
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.d.ts.map +1 -1
- package/dist/plugins/analysis/IncrementalAnalysisPlugin.js +76 -80
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts +180 -17
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/JSASTAnalyzer.js +1171 -471
- package/dist/plugins/analysis/ReactAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ReactAnalyzer.js +56 -57
- package/dist/plugins/analysis/RustAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/RustAnalyzer.js +15 -10
- package/dist/plugins/analysis/SQLiteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SQLiteAnalyzer.js +9 -7
- package/dist/plugins/analysis/ServiceLayerAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ServiceLayerAnalyzer.js +21 -9
- package/dist/plugins/analysis/SocketIOAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SocketIOAnalyzer.js +27 -15
- package/dist/plugins/analysis/SystemDbAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SystemDbAnalyzer.js +15 -5
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts +34 -4
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/GraphBuilder.js +318 -298
- package/dist/plugins/analysis/ast/IdGenerator.d.ts +105 -0
- package/dist/plugins/analysis/ast/IdGenerator.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/IdGenerator.js +116 -0
- package/dist/plugins/analysis/ast/types.d.ts +176 -5
- package/dist/plugins/analysis/ast/types.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/utils/createParameterNodes.d.ts +33 -0
- package/dist/plugins/analysis/ast/utils/createParameterNodes.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/createParameterNodes.js +89 -0
- package/dist/plugins/analysis/ast/utils/index.d.ts +6 -0
- package/dist/plugins/analysis/ast/utils/index.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/index.js +5 -0
- package/dist/plugins/analysis/ast/utils/location.d.ts +87 -0
- package/dist/plugins/analysis/ast/utils/location.d.ts.map +1 -0
- package/dist/plugins/analysis/ast/utils/location.js +78 -0
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts +9 -4
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ASTVisitor.js +6 -5
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts +99 -9
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.js +663 -125
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ClassVisitor.js +72 -32
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.js +128 -63
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.js +11 -8
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts +12 -1
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/TypeScriptVisitor.js +36 -14
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts +4 -1
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.js +17 -13
- package/dist/plugins/discovery/MonorepoServiceDiscovery.d.ts.map +1 -1
- package/dist/plugins/discovery/MonorepoServiceDiscovery.js +3 -2
- package/dist/plugins/discovery/SimpleProjectDiscovery.d.ts.map +1 -1
- package/dist/plugins/discovery/SimpleProjectDiscovery.js +5 -1
- package/dist/plugins/discovery/WorkspaceDiscovery.d.ts +22 -0
- package/dist/plugins/discovery/WorkspaceDiscovery.d.ts.map +1 -0
- package/dist/plugins/discovery/WorkspaceDiscovery.js +136 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.d.ts +46 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.d.ts.map +1 -0
- package/dist/plugins/discovery/resolveSourceEntrypoint.js +86 -0
- package/dist/plugins/discovery/workspaces/detector.d.ts +21 -0
- package/dist/plugins/discovery/workspaces/detector.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/detector.js +49 -0
- package/dist/plugins/discovery/workspaces/globResolver.d.ts +35 -0
- package/dist/plugins/discovery/workspaces/globResolver.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/globResolver.js +184 -0
- package/dist/plugins/discovery/workspaces/index.d.ts +9 -0
- package/dist/plugins/discovery/workspaces/index.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/index.js +8 -0
- package/dist/plugins/discovery/workspaces/parsers.d.ts +38 -0
- package/dist/plugins/discovery/workspaces/parsers.d.ts.map +1 -0
- package/dist/plugins/discovery/workspaces/parsers.js +80 -0
- package/dist/plugins/enrichment/AliasTracker.d.ts.map +1 -1
- package/dist/plugins/enrichment/AliasTracker.js +14 -8
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts.map +1 -1
- package/dist/plugins/enrichment/HTTPConnectionEnricher.js +14 -7
- package/dist/plugins/enrichment/ImportExportLinker.d.ts.map +1 -1
- package/dist/plugins/enrichment/ImportExportLinker.js +23 -6
- package/dist/plugins/enrichment/MethodCallResolver.d.ts.map +1 -1
- package/dist/plugins/enrichment/MethodCallResolver.js +18 -12
- package/dist/plugins/enrichment/MountPointResolver.d.ts.map +1 -1
- package/dist/plugins/enrichment/MountPointResolver.js +8 -3
- package/dist/plugins/enrichment/PrefixEvaluator.d.ts.map +1 -1
- package/dist/plugins/enrichment/PrefixEvaluator.js +16 -7
- package/dist/plugins/enrichment/RustFFIEnricher.d.ts.map +1 -1
- package/dist/plugins/enrichment/RustFFIEnricher.js +6 -5
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts +17 -0
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts.map +1 -1
- package/dist/plugins/enrichment/ValueDomainAnalyzer.js +129 -10
- package/dist/plugins/indexing/IncrementalModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/IncrementalModuleIndexer.js +23 -14
- package/dist/plugins/indexing/JSModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/JSModuleIndexer.js +63 -31
- package/dist/plugins/indexing/RustModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/RustModuleIndexer.js +5 -4
- package/dist/plugins/indexing/ServiceDetector.d.ts +10 -0
- package/dist/plugins/indexing/ServiceDetector.d.ts.map +1 -1
- package/dist/plugins/indexing/ServiceDetector.js +28 -15
- package/dist/plugins/validation/CallResolverValidator.d.ts.map +1 -1
- package/dist/plugins/validation/CallResolverValidator.js +8 -7
- package/dist/plugins/validation/DataFlowValidator.d.ts.map +1 -1
- package/dist/plugins/validation/DataFlowValidator.js +17 -12
- package/dist/plugins/validation/EvalBanValidator.d.ts.map +1 -1
- package/dist/plugins/validation/EvalBanValidator.js +17 -16
- package/dist/plugins/validation/GraphConnectivityValidator.d.ts.map +1 -1
- package/dist/plugins/validation/GraphConnectivityValidator.js +19 -23
- package/dist/plugins/validation/NodeCreationValidator.d.ts +85 -0
- package/dist/plugins/validation/NodeCreationValidator.d.ts.map +1 -0
- package/dist/plugins/validation/NodeCreationValidator.js +415 -0
- package/dist/plugins/validation/SQLInjectionValidator.d.ts.map +1 -1
- package/dist/plugins/validation/SQLInjectionValidator.js +59 -16
- package/dist/plugins/validation/ShadowingDetector.d.ts.map +1 -1
- package/dist/plugins/validation/ShadowingDetector.js +6 -5
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.d.ts.map +1 -1
- package/dist/plugins/validation/TypeScriptDeadCodeValidator.js +12 -11
- package/dist/plugins/vcs/GitPlugin.d.ts.map +1 -1
- package/dist/plugins/vcs/GitPlugin.js +10 -12
- package/dist/plugins/vcs/VCSPlugin.d.ts +3 -2
- package/dist/plugins/vcs/VCSPlugin.d.ts.map +1 -1
- package/dist/plugins/vcs/VCSPlugin.js +5 -5
- package/dist/storage/backends/RFDBServerBackend.d.ts +10 -17
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -1
- package/dist/storage/backends/RFDBServerBackend.js +31 -10
- package/dist/validation/PathValidator.d.ts +1 -2
- package/dist/validation/PathValidator.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/Orchestrator.ts +237 -24
- package/src/config/ConfigLoader.ts +263 -0
- package/src/config/index.ts +5 -0
- package/src/core/ASTWorker.ts +143 -139
- package/src/core/CoverageAnalyzer.ts +243 -0
- package/src/core/FileNodeManager.ts +100 -0
- package/src/core/GraphFreshnessChecker.ts +143 -0
- package/src/core/HashUtils.ts +48 -0
- package/src/core/IncrementalReanalyzer.ts +192 -0
- package/src/core/NodeFactory.ts +401 -18
- package/src/core/ScopeTracker.ts +154 -0
- package/src/core/SemanticId.ts +192 -0
- package/src/core/VersionManager.ts +3 -2
- package/src/core/nodes/ArgumentExpressionNode.ts +89 -0
- package/src/core/nodes/ArrayLiteralNode.ts +65 -0
- package/src/core/nodes/CallSiteNode.ts +58 -0
- package/src/core/nodes/ClassNode.ts +63 -2
- package/src/core/nodes/DecoratorNode.ts +91 -0
- package/src/core/nodes/EnumNode.ts +86 -0
- package/src/core/nodes/ExportNode.ts +70 -2
- package/src/core/nodes/ExpressionNode.ts +231 -0
- package/src/core/nodes/ExternalModuleNode.ts +56 -0
- package/src/core/nodes/ExternalStdioNode.ts +17 -9
- package/src/core/nodes/FunctionNode.ts +101 -1
- package/src/core/nodes/ImportNode.ts +32 -10
- package/src/core/nodes/InterfaceNode.ts +91 -0
- package/src/core/nodes/IssueNode.ts +177 -0
- package/src/core/nodes/MethodCallNode.ts +64 -0
- package/src/core/nodes/MethodNode.ts +63 -0
- package/src/core/nodes/ModuleNode.ts +50 -0
- package/src/core/nodes/NetworkRequestNode.ts +77 -0
- package/src/core/nodes/ObjectLiteralNode.ts +65 -0
- package/src/core/nodes/ScopeNode.ts +65 -0
- package/src/core/nodes/TypeNode.ts +78 -0
- package/src/core/nodes/VariableDeclarationNode.ts +52 -0
- package/src/core/nodes/index.ts +18 -1
- package/src/diagnostics/DiagnosticCollector.ts +163 -0
- package/src/diagnostics/DiagnosticReporter.ts +204 -0
- package/src/diagnostics/DiagnosticWriter.ts +50 -0
- package/src/diagnostics/index.ts +16 -0
- package/src/errors/GrafemaError.ts +174 -0
- package/src/index.ts +148 -1
- package/src/logging/Logger.ts +152 -0
- package/src/plugins/Plugin.ts +42 -0
- package/src/plugins/analysis/DatabaseAnalyzer.ts +14 -8
- package/src/plugins/analysis/ExpressAnalyzer.ts +29 -19
- package/src/plugins/analysis/ExpressRouteAnalyzer.ts +22 -21
- package/src/plugins/analysis/FetchAnalyzer.ts +39 -16
- package/src/plugins/analysis/IncrementalAnalysisPlugin.ts +84 -101
- package/src/plugins/analysis/JSASTAnalyzer.ts +1483 -503
- package/src/plugins/analysis/ReactAnalyzer.ts +57 -57
- package/src/plugins/analysis/RustAnalyzer.ts +15 -10
- package/src/plugins/analysis/SQLiteAnalyzer.ts +10 -7
- package/src/plugins/analysis/ServiceLayerAnalyzer.ts +22 -16
- package/src/plugins/analysis/SocketIOAnalyzer.ts +31 -22
- package/src/plugins/analysis/SystemDbAnalyzer.ts +16 -11
- package/src/plugins/analysis/ast/GraphBuilder.ts +439 -327
- package/src/plugins/analysis/ast/IdGenerator.ts +177 -0
- package/src/plugins/analysis/ast/types.ts +209 -6
- package/src/plugins/analysis/ast/utils/createParameterNodes.ts +104 -0
- package/src/plugins/analysis/ast/utils/index.ts +12 -0
- package/src/plugins/analysis/ast/utils/location.ts +103 -0
- package/src/plugins/analysis/ast/visitors/ASTVisitor.ts +11 -8
- package/src/plugins/analysis/ast/visitors/CallExpressionVisitor.ts +909 -83
- package/src/plugins/analysis/ast/visitors/ClassVisitor.ts +97 -44
- package/src/plugins/analysis/ast/visitors/FunctionVisitor.ts +159 -93
- package/src/plugins/analysis/ast/visitors/ImportExportVisitor.ts +12 -8
- package/src/plugins/analysis/ast/visitors/TypeScriptVisitor.ts +41 -14
- package/src/plugins/analysis/ast/visitors/VariableVisitor.ts +37 -17
- package/src/plugins/discovery/MonorepoServiceDiscovery.ts +3 -2
- package/src/plugins/discovery/SimpleProjectDiscovery.ts +6 -1
- package/src/plugins/discovery/WorkspaceDiscovery.ts +177 -0
- package/src/plugins/discovery/resolveSourceEntrypoint.ts +103 -0
- package/src/plugins/discovery/workspaces/detector.ts +63 -0
- package/src/plugins/discovery/workspaces/globResolver.ts +229 -0
- package/src/plugins/discovery/workspaces/index.ts +23 -0
- package/src/plugins/discovery/workspaces/parsers.ts +99 -0
- package/src/plugins/enrichment/AliasTracker.ts +14 -8
- package/src/plugins/enrichment/HTTPConnectionEnricher.ts +14 -7
- package/src/plugins/enrichment/ImportExportLinker.ts +24 -6
- package/src/plugins/enrichment/MethodCallResolver.ts +18 -12
- package/src/plugins/enrichment/MountPointResolver.ts +8 -3
- package/src/plugins/enrichment/PrefixEvaluator.ts +16 -7
- package/src/plugins/enrichment/RustFFIEnricher.ts +6 -5
- package/src/plugins/enrichment/ValueDomainAnalyzer.ts +149 -12
- package/src/plugins/indexing/IncrementalModuleIndexer.ts +23 -14
- package/src/plugins/indexing/JSModuleIndexer.ts +74 -34
- package/src/plugins/indexing/RustModuleIndexer.ts +5 -4
- package/src/plugins/validation/CallResolverValidator.ts +8 -7
- package/src/plugins/validation/DataFlowValidator.ts +16 -12
- package/src/plugins/validation/EvalBanValidator.ts +17 -16
- package/src/plugins/validation/GraphConnectivityValidator.ts +19 -23
- package/src/plugins/validation/NodeCreationValidator.ts +554 -0
- package/src/plugins/validation/SQLInjectionValidator.ts +61 -15
- package/src/plugins/validation/ShadowingDetector.ts +6 -5
- package/src/plugins/validation/TypeScriptDeadCodeValidator.ts +12 -11
- package/src/plugins/vcs/GitPlugin.ts +40 -12
- package/src/plugins/vcs/VCSPlugin.ts +7 -5
- package/src/storage/backends/RFDBServerBackend.ts +43 -29
- package/src/validation/PathValidator.ts +1 -1
- package/dist/core/AnalysisWorker.d.ts +0 -14
- package/dist/core/AnalysisWorker.d.ts.map +0 -1
- package/dist/core/AnalysisWorker.js +0 -307
- package/dist/core/ParallelAnalyzer.d.ts +0 -120
- package/dist/core/ParallelAnalyzer.d.ts.map +0 -1
- package/dist/core/ParallelAnalyzer.js +0 -331
- package/dist/core/QueueWorker.d.ts +0 -12
- package/dist/core/QueueWorker.d.ts.map +0 -1
- package/dist/core/QueueWorker.js +0 -567
- package/dist/core/RFDBClient.d.ts +0 -179
- package/dist/core/RFDBClient.d.ts.map +0 -1
- package/dist/core/RFDBClient.js +0 -429
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts +0 -19
- package/dist/plugins/discovery/ZonServiceDiscovery.d.ts.map +0 -1
- package/dist/plugins/discovery/ZonServiceDiscovery.js +0 -204
- package/src/core/AnalysisWorker.ts +0 -410
- package/src/core/ParallelAnalyzer.ts +0 -476
- package/src/core/QueueWorker.ts +0 -780
- package/src/plugins/indexing/ServiceDetector.ts +0 -230
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
* OPTIMIZED: Uses batched writes to reduce FFI overhead
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { dirname, resolve } from 'path';
|
|
6
|
+
import { dirname, resolve, basename } from 'path';
|
|
7
7
|
import type { GraphBackend } from '@grafema/types';
|
|
8
|
+
import { ImportNode } from '../../../core/nodes/ImportNode.js';
|
|
9
|
+
import { InterfaceNode, type InterfaceNodeRecord } from '../../../core/nodes/InterfaceNode.js';
|
|
10
|
+
import { EnumNode, type EnumNodeRecord } from '../../../core/nodes/EnumNode.js';
|
|
11
|
+
import { DecoratorNode } from '../../../core/nodes/DecoratorNode.js';
|
|
12
|
+
import { NetworkRequestNode } from '../../../core/nodes/NetworkRequestNode.js';
|
|
13
|
+
import { NodeFactory } from '../../../core/NodeFactory.js';
|
|
8
14
|
import type {
|
|
9
15
|
ModuleNode,
|
|
10
16
|
FunctionInfo,
|
|
@@ -27,6 +33,10 @@ import type {
|
|
|
27
33
|
TypeAliasInfo,
|
|
28
34
|
EnumDeclarationInfo,
|
|
29
35
|
DecoratorInfo,
|
|
36
|
+
ArrayMutationInfo,
|
|
37
|
+
ObjectMutationInfo,
|
|
38
|
+
ObjectLiteralInfo,
|
|
39
|
+
ArrayLiteralInfo,
|
|
30
40
|
ASTCollections,
|
|
31
41
|
GraphNode,
|
|
32
42
|
GraphEdge,
|
|
@@ -108,7 +118,14 @@ export class GraphBuilder {
|
|
|
108
118
|
interfaces = [],
|
|
109
119
|
typeAliases = [],
|
|
110
120
|
enums = [],
|
|
111
|
-
decorators = []
|
|
121
|
+
decorators = [],
|
|
122
|
+
// Array mutation tracking for FLOWS_INTO edges
|
|
123
|
+
arrayMutations = [],
|
|
124
|
+
// Object mutation tracking for FLOWS_INTO edges
|
|
125
|
+
objectMutations = [],
|
|
126
|
+
// Object/Array literal tracking
|
|
127
|
+
objectLiterals = [],
|
|
128
|
+
arrayLiterals = []
|
|
112
129
|
} = data;
|
|
113
130
|
|
|
114
131
|
// Reset buffers for this build
|
|
@@ -218,17 +235,27 @@ export class GraphBuilder {
|
|
|
218
235
|
// 25. Buffer IMPLEMENTS edges (CLASS -> INTERFACE)
|
|
219
236
|
this.bufferImplementsEdges(classDeclarations, interfaces);
|
|
220
237
|
|
|
238
|
+
// 26. Buffer FLOWS_INTO edges for array mutations (push, unshift, splice, indexed assignment)
|
|
239
|
+
this.bufferArrayMutationEdges(arrayMutations, variableDeclarations, parameters);
|
|
240
|
+
|
|
241
|
+
// 27. Buffer FLOWS_INTO edges for object mutations (property assignment, Object.assign)
|
|
242
|
+
// REG-152: Now includes classDeclarations for this.prop = value patterns
|
|
243
|
+
this.bufferObjectMutationEdges(objectMutations, variableDeclarations, parameters, functions, classDeclarations);
|
|
244
|
+
|
|
245
|
+
// 28. Buffer OBJECT_LITERAL nodes
|
|
246
|
+
this.bufferObjectLiteralNodes(objectLiterals);
|
|
247
|
+
|
|
248
|
+
// 29. Buffer ARRAY_LITERAL nodes
|
|
249
|
+
this.bufferArrayLiteralNodes(arrayLiterals);
|
|
250
|
+
|
|
221
251
|
// FLUSH: Write all nodes first, then edges in single batch calls
|
|
222
252
|
const nodesCreated = await this._flushNodes(graph);
|
|
223
253
|
const edgesCreated = await this._flushEdges(graph);
|
|
224
254
|
|
|
225
|
-
// Handle async operations that need graph queries (IMPORTS_FROM edges)
|
|
226
|
-
const importExportEdges = await this.createImportExportEdges(module, imports, exports, graph, projectPath);
|
|
227
|
-
|
|
228
255
|
// Handle async operations for ASSIGNED_FROM with CLASS lookups
|
|
229
256
|
const classAssignmentEdges = await this.createClassAssignmentEdges(variableAssignments, graph);
|
|
230
257
|
|
|
231
|
-
return { nodes: nodesCreated, edges: edgesCreated +
|
|
258
|
+
return { nodes: nodesCreated, edges: edgesCreated + classAssignmentEdges };
|
|
232
259
|
}
|
|
233
260
|
|
|
234
261
|
// ============= BUFFERED METHODS (synchronous, no awaits) =============
|
|
@@ -360,16 +387,12 @@ export class GraphBuilder {
|
|
|
360
387
|
);
|
|
361
388
|
|
|
362
389
|
if (consoleIOMethods.length > 0) {
|
|
363
|
-
const
|
|
390
|
+
const stdioNode = NodeFactory.createExternalStdio();
|
|
391
|
+
|
|
364
392
|
// Buffer net:stdio node only once (singleton)
|
|
365
|
-
if (!this._createdSingletons.has(
|
|
366
|
-
this._bufferNode(
|
|
367
|
-
|
|
368
|
-
type: 'net:stdio',
|
|
369
|
-
name: '__stdio__',
|
|
370
|
-
description: 'Standard input/output stream'
|
|
371
|
-
});
|
|
372
|
-
this._createdSingletons.add(stdioId);
|
|
393
|
+
if (!this._createdSingletons.has(stdioNode.id)) {
|
|
394
|
+
this._bufferNode(stdioNode as unknown as GraphNode);
|
|
395
|
+
this._createdSingletons.add(stdioNode.id);
|
|
373
396
|
}
|
|
374
397
|
|
|
375
398
|
// Buffer WRITES_TO edges for console.log/error
|
|
@@ -377,7 +400,7 @@ export class GraphBuilder {
|
|
|
377
400
|
this._bufferEdge({
|
|
378
401
|
type: 'WRITES_TO',
|
|
379
402
|
src: methodCall.id,
|
|
380
|
-
dst:
|
|
403
|
+
dst: stdioNode.id
|
|
381
404
|
});
|
|
382
405
|
}
|
|
383
406
|
}
|
|
@@ -407,9 +430,13 @@ export class GraphBuilder {
|
|
|
407
430
|
});
|
|
408
431
|
}
|
|
409
432
|
|
|
410
|
-
// If superClass, buffer DERIVES_FROM edge
|
|
433
|
+
// If superClass, buffer DERIVES_FROM edge with computed ID
|
|
411
434
|
if (superClass) {
|
|
412
|
-
|
|
435
|
+
// Compute superclass ID using same format as ClassNode (line 0 = unknown location)
|
|
436
|
+
// Assume superclass is in same file (most common case)
|
|
437
|
+
// When superclass is in different file, edge will be dangling until that file analyzed
|
|
438
|
+
const superClassId = `${file}:CLASS:${superClass}:0`;
|
|
439
|
+
|
|
413
440
|
this._bufferEdge({
|
|
414
441
|
type: 'DERIVES_FROM',
|
|
415
442
|
src: id,
|
|
@@ -434,16 +461,12 @@ export class GraphBuilder {
|
|
|
434
461
|
let classId = declarationMap.get(className);
|
|
435
462
|
|
|
436
463
|
if (!classId) {
|
|
437
|
-
// External class -
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
file: module.file,
|
|
444
|
-
line,
|
|
445
|
-
isInstantiationRef: true
|
|
446
|
-
});
|
|
464
|
+
// External class - compute ID using ClassNode format (line 0 = unknown location)
|
|
465
|
+
// Assume class is in same file (most common case)
|
|
466
|
+
// When class is in different file, edge will be dangling until that file analyzed
|
|
467
|
+
classId = `${module.file}:CLASS:${className}:0`;
|
|
468
|
+
|
|
469
|
+
// NO node creation - node will exist when class file analyzed
|
|
447
470
|
}
|
|
448
471
|
|
|
449
472
|
// Buffer INSTANCE_OF edge
|
|
@@ -475,49 +498,47 @@ export class GraphBuilder {
|
|
|
475
498
|
|
|
476
499
|
private bufferImportNodes(module: ModuleNode, imports: ImportInfo[]): void {
|
|
477
500
|
for (const imp of imports) {
|
|
478
|
-
const { source, specifiers, line } = imp;
|
|
501
|
+
const { source, specifiers, line, column } = imp;
|
|
479
502
|
|
|
480
503
|
for (const spec of specifiers) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
504
|
+
// Use ImportNode factory for proper semantic IDs and field population
|
|
505
|
+
const importNode = ImportNode.create(
|
|
506
|
+
spec.local, // name = local binding
|
|
507
|
+
module.file, // file
|
|
508
|
+
line, // line (stored as field, not in ID)
|
|
509
|
+
column || 0, // column
|
|
510
|
+
source, // source module
|
|
511
|
+
{
|
|
512
|
+
imported: spec.imported,
|
|
513
|
+
local: spec.local
|
|
514
|
+
// importType is auto-detected from imported field
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
this._bufferNode(importNode as unknown as GraphNode);
|
|
496
519
|
|
|
497
520
|
// MODULE -> CONTAINS -> IMPORT
|
|
498
521
|
this._bufferEdge({
|
|
499
522
|
type: 'CONTAINS',
|
|
500
523
|
src: module.id,
|
|
501
|
-
dst:
|
|
524
|
+
dst: importNode.id
|
|
502
525
|
});
|
|
503
526
|
|
|
504
527
|
// Create EXTERNAL_MODULE node for external modules
|
|
505
528
|
const isRelative = source.startsWith('./') || source.startsWith('../');
|
|
506
529
|
if (!isRelative) {
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
line: line
|
|
515
|
-
});
|
|
530
|
+
const externalModule = NodeFactory.createExternalModule(source);
|
|
531
|
+
|
|
532
|
+
// Avoid duplicate EXTERNAL_MODULE nodes
|
|
533
|
+
if (!this._createdSingletons.has(externalModule.id)) {
|
|
534
|
+
this._bufferNode(externalModule as unknown as GraphNode);
|
|
535
|
+
this._createdSingletons.add(externalModule.id);
|
|
536
|
+
}
|
|
516
537
|
|
|
517
538
|
this._bufferEdge({
|
|
518
539
|
type: 'IMPORTS',
|
|
519
540
|
src: module.id,
|
|
520
|
-
dst:
|
|
541
|
+
dst: externalModule.id
|
|
521
542
|
});
|
|
522
543
|
}
|
|
523
544
|
}
|
|
@@ -529,79 +550,79 @@ export class GraphBuilder {
|
|
|
529
550
|
const { type, line, name, specifiers, source } = exp;
|
|
530
551
|
|
|
531
552
|
if (type === 'default') {
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
exportType: 'default'
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
});
|
|
553
|
+
const exportNode = NodeFactory.createExport(
|
|
554
|
+
'default',
|
|
555
|
+
module.file,
|
|
556
|
+
line,
|
|
557
|
+
0,
|
|
558
|
+
{ default: true, exportType: 'default' }
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
this._bufferNode(exportNode as unknown as GraphNode);
|
|
542
562
|
|
|
543
563
|
this._bufferEdge({
|
|
544
564
|
type: 'CONTAINS',
|
|
545
565
|
src: module.id,
|
|
546
|
-
dst:
|
|
566
|
+
dst: exportNode.id
|
|
547
567
|
});
|
|
548
568
|
} else if (type === 'named') {
|
|
549
569
|
if (specifiers) {
|
|
550
570
|
for (const spec of specifiers) {
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
571
|
+
const exportNode = NodeFactory.createExport(
|
|
572
|
+
spec.exported,
|
|
573
|
+
module.file,
|
|
574
|
+
line,
|
|
575
|
+
0,
|
|
576
|
+
{
|
|
577
|
+
local: spec.local,
|
|
578
|
+
source: source,
|
|
579
|
+
exportType: 'named'
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
this._bufferNode(exportNode as unknown as GraphNode);
|
|
563
584
|
|
|
564
585
|
this._bufferEdge({
|
|
565
586
|
type: 'CONTAINS',
|
|
566
587
|
src: module.id,
|
|
567
|
-
dst:
|
|
588
|
+
dst: exportNode.id
|
|
568
589
|
});
|
|
569
590
|
}
|
|
570
591
|
} else if (name) {
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
exportType: 'named'
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
});
|
|
592
|
+
const exportNode = NodeFactory.createExport(
|
|
593
|
+
name,
|
|
594
|
+
module.file,
|
|
595
|
+
line,
|
|
596
|
+
0,
|
|
597
|
+
{ exportType: 'named' }
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
this._bufferNode(exportNode as unknown as GraphNode);
|
|
581
601
|
|
|
582
602
|
this._bufferEdge({
|
|
583
603
|
type: 'CONTAINS',
|
|
584
604
|
src: module.id,
|
|
585
|
-
dst:
|
|
605
|
+
dst: exportNode.id
|
|
586
606
|
});
|
|
587
607
|
}
|
|
588
608
|
} else if (type === 'all') {
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
609
|
+
const exportNode = NodeFactory.createExport(
|
|
610
|
+
'*',
|
|
611
|
+
module.file,
|
|
612
|
+
line,
|
|
613
|
+
0,
|
|
614
|
+
{
|
|
615
|
+
source: source,
|
|
616
|
+
exportType: 'all'
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
this._bufferNode(exportNode as unknown as GraphNode);
|
|
600
621
|
|
|
601
622
|
this._bufferEdge({
|
|
602
623
|
type: 'CONTAINS',
|
|
603
624
|
src: module.id,
|
|
604
|
-
dst:
|
|
625
|
+
dst: exportNode.id
|
|
605
626
|
});
|
|
606
627
|
}
|
|
607
628
|
}
|
|
@@ -638,15 +659,12 @@ export class GraphBuilder {
|
|
|
638
659
|
|
|
639
660
|
private bufferHttpRequests(httpRequests: HttpRequestInfo[], functions: FunctionInfo[]): void {
|
|
640
661
|
if (httpRequests.length > 0) {
|
|
641
|
-
|
|
662
|
+
// Create net:request singleton using factory
|
|
663
|
+
const networkNode = NetworkRequestNode.create();
|
|
642
664
|
|
|
643
|
-
if (!this._createdSingletons.has(
|
|
644
|
-
this._bufferNode(
|
|
645
|
-
|
|
646
|
-
type: 'net:request',
|
|
647
|
-
name: '__network__'
|
|
648
|
-
});
|
|
649
|
-
this._createdSingletons.add(networkId);
|
|
665
|
+
if (!this._createdSingletons.has(networkNode.id)) {
|
|
666
|
+
this._bufferNode(networkNode as unknown as GraphNode);
|
|
667
|
+
this._createdSingletons.add(networkNode.id);
|
|
650
668
|
}
|
|
651
669
|
|
|
652
670
|
for (const request of httpRequests) {
|
|
@@ -657,7 +675,7 @@ export class GraphBuilder {
|
|
|
657
675
|
this._bufferEdge({
|
|
658
676
|
type: 'CALLS',
|
|
659
677
|
src: request.id,
|
|
660
|
-
dst:
|
|
678
|
+
dst: networkNode.id
|
|
661
679
|
});
|
|
662
680
|
|
|
663
681
|
if (parentScopeId) {
|
|
@@ -766,8 +784,10 @@ export class GraphBuilder {
|
|
|
766
784
|
}
|
|
767
785
|
// VARIABLE by name
|
|
768
786
|
else if (sourceType === 'VARIABLE' && sourceName) {
|
|
769
|
-
|
|
770
|
-
|
|
787
|
+
// Find the current variable's file by looking it up in variableDeclarations
|
|
788
|
+
// (semantic IDs don't have predictable file positions like old hash-based IDs)
|
|
789
|
+
const currentVar = variableDeclarations.find(v => v.id === variableId);
|
|
790
|
+
const varFile = currentVar?.file ?? null;
|
|
771
791
|
const sourceVariable = variableDeclarations.find(v =>
|
|
772
792
|
v.name === sourceName && v.file === varFile
|
|
773
793
|
);
|
|
@@ -806,7 +826,7 @@ export class GraphBuilder {
|
|
|
806
826
|
});
|
|
807
827
|
}
|
|
808
828
|
}
|
|
809
|
-
// EXPRESSION node creation
|
|
829
|
+
// EXPRESSION node creation using NodeFactory
|
|
810
830
|
else if (sourceType === 'EXPRESSION' && sourceId) {
|
|
811
831
|
const {
|
|
812
832
|
expressionType,
|
|
@@ -821,33 +841,25 @@ export class GraphBuilder {
|
|
|
821
841
|
consequentSourceName,
|
|
822
842
|
alternateSourceName,
|
|
823
843
|
file: exprFile,
|
|
824
|
-
line: exprLine
|
|
844
|
+
line: exprLine,
|
|
845
|
+
column: exprColumn
|
|
825
846
|
} = assignment;
|
|
826
847
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
expressionNode.computedPropertyVar = computedPropertyVar;
|
|
848
|
+
// Create node from upstream metadata using factory
|
|
849
|
+
const expressionNode = NodeFactory.createExpressionFromMetadata(
|
|
850
|
+
expressionType || 'Unknown',
|
|
851
|
+
exprFile || '',
|
|
852
|
+
exprLine || 0,
|
|
853
|
+
exprColumn || 0,
|
|
854
|
+
{
|
|
855
|
+
id: sourceId, // ID from JSASTAnalyzer
|
|
856
|
+
object,
|
|
857
|
+
property,
|
|
858
|
+
computed,
|
|
859
|
+
computedPropertyVar: computedPropertyVar ?? undefined,
|
|
860
|
+
operator
|
|
841
861
|
}
|
|
842
|
-
|
|
843
|
-
} else if (expressionType === 'BinaryExpression' || expressionType === 'LogicalExpression') {
|
|
844
|
-
expressionNode.operator = operator;
|
|
845
|
-
expressionNode.name = `<${expressionType}>`;
|
|
846
|
-
} else if (expressionType === 'ConditionalExpression') {
|
|
847
|
-
expressionNode.name = '<ternary>';
|
|
848
|
-
} else if (expressionType === 'TemplateLiteral') {
|
|
849
|
-
expressionNode.name = '<template>';
|
|
850
|
-
}
|
|
862
|
+
);
|
|
851
863
|
|
|
852
864
|
this._bufferNode(expressionNode);
|
|
853
865
|
|
|
@@ -1051,54 +1063,66 @@ export class GraphBuilder {
|
|
|
1051
1063
|
|
|
1052
1064
|
/**
|
|
1053
1065
|
* Buffer INTERFACE nodes and EXTENDS edges
|
|
1066
|
+
*
|
|
1067
|
+
* Uses two-pass approach:
|
|
1068
|
+
* 1. First pass: create all interface nodes, store in Map
|
|
1069
|
+
* 2. Second pass: create EXTENDS edges using stored node IDs
|
|
1054
1070
|
*/
|
|
1055
1071
|
private bufferInterfaceNodes(module: ModuleNode, interfaces: InterfaceDeclarationInfo[]): void {
|
|
1072
|
+
// First pass: create all interface nodes and store them
|
|
1073
|
+
const interfaceNodes = new Map<string, InterfaceNodeRecord>();
|
|
1074
|
+
|
|
1056
1075
|
for (const iface of interfaces) {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1076
|
+
const interfaceNode = InterfaceNode.create(
|
|
1077
|
+
iface.name,
|
|
1078
|
+
iface.file,
|
|
1079
|
+
iface.line,
|
|
1080
|
+
iface.column || 0,
|
|
1081
|
+
{
|
|
1082
|
+
extends: iface.extends,
|
|
1083
|
+
properties: iface.properties
|
|
1084
|
+
}
|
|
1085
|
+
);
|
|
1086
|
+
interfaceNodes.set(iface.name, interfaceNode);
|
|
1087
|
+
this._bufferNode(interfaceNode as unknown as GraphNode);
|
|
1068
1088
|
|
|
1069
1089
|
// MODULE -> CONTAINS -> INTERFACE
|
|
1070
1090
|
this._bufferEdge({
|
|
1071
1091
|
type: 'CONTAINS',
|
|
1072
1092
|
src: module.id,
|
|
1073
|
-
dst:
|
|
1093
|
+
dst: interfaceNode.id
|
|
1074
1094
|
});
|
|
1095
|
+
}
|
|
1075
1096
|
|
|
1076
|
-
|
|
1097
|
+
// Second pass: create EXTENDS edges
|
|
1098
|
+
for (const iface of interfaces) {
|
|
1077
1099
|
if (iface.extends && iface.extends.length > 0) {
|
|
1100
|
+
const srcNode = interfaceNodes.get(iface.name)!;
|
|
1101
|
+
|
|
1078
1102
|
for (const parentName of iface.extends) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
if (
|
|
1103
|
+
const parentNode = interfaceNodes.get(parentName);
|
|
1104
|
+
|
|
1105
|
+
if (parentNode) {
|
|
1106
|
+
// Same-file interface
|
|
1082
1107
|
this._bufferEdge({
|
|
1083
1108
|
type: 'EXTENDS',
|
|
1084
|
-
src:
|
|
1085
|
-
dst:
|
|
1109
|
+
src: srcNode.id,
|
|
1110
|
+
dst: parentNode.id
|
|
1086
1111
|
});
|
|
1087
1112
|
} else {
|
|
1088
1113
|
// External interface - create a reference node
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
});
|
|
1114
|
+
const externalInterface = NodeFactory.createInterface(
|
|
1115
|
+
parentName,
|
|
1116
|
+
iface.file,
|
|
1117
|
+
iface.line,
|
|
1118
|
+
0,
|
|
1119
|
+
{ isExternal: true }
|
|
1120
|
+
);
|
|
1121
|
+
this._bufferNode(externalInterface as unknown as GraphNode);
|
|
1098
1122
|
this._bufferEdge({
|
|
1099
1123
|
type: 'EXTENDS',
|
|
1100
|
-
src:
|
|
1101
|
-
dst:
|
|
1124
|
+
src: srcNode.id,
|
|
1125
|
+
dst: externalInterface.id
|
|
1102
1126
|
});
|
|
1103
1127
|
}
|
|
1104
1128
|
}
|
|
@@ -1111,48 +1135,51 @@ export class GraphBuilder {
|
|
|
1111
1135
|
*/
|
|
1112
1136
|
private bufferTypeAliasNodes(module: ModuleNode, typeAliases: TypeAliasInfo[]): void {
|
|
1113
1137
|
for (const typeAlias of typeAliases) {
|
|
1114
|
-
//
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
});
|
|
1138
|
+
// Create TYPE node using factory
|
|
1139
|
+
const typeNode = NodeFactory.createType(
|
|
1140
|
+
typeAlias.name,
|
|
1141
|
+
typeAlias.file,
|
|
1142
|
+
typeAlias.line,
|
|
1143
|
+
typeAlias.column || 0,
|
|
1144
|
+
{ aliasOf: typeAlias.aliasOf }
|
|
1145
|
+
);
|
|
1146
|
+
this._bufferNode(typeNode as unknown as GraphNode);
|
|
1124
1147
|
|
|
1125
1148
|
// MODULE -> CONTAINS -> TYPE
|
|
1126
1149
|
this._bufferEdge({
|
|
1127
1150
|
type: 'CONTAINS',
|
|
1128
1151
|
src: module.id,
|
|
1129
|
-
dst:
|
|
1152
|
+
dst: typeNode.id
|
|
1130
1153
|
});
|
|
1131
1154
|
}
|
|
1132
1155
|
}
|
|
1133
1156
|
|
|
1134
1157
|
/**
|
|
1135
1158
|
* Buffer ENUM nodes
|
|
1159
|
+
* Uses EnumNode.create() to ensure consistent ID format (colon separator)
|
|
1136
1160
|
*/
|
|
1137
1161
|
private bufferEnumNodes(module: ModuleNode, enums: EnumDeclarationInfo[]): void {
|
|
1138
1162
|
for (const enumDecl of enums) {
|
|
1139
|
-
//
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1163
|
+
// Use EnumNode.create() to generate proper ID (colon format)
|
|
1164
|
+
// Do NOT use enumDecl.id which has legacy # format from TypeScriptVisitor
|
|
1165
|
+
const enumNode = EnumNode.create(
|
|
1166
|
+
enumDecl.name,
|
|
1167
|
+
enumDecl.file,
|
|
1168
|
+
enumDecl.line,
|
|
1169
|
+
enumDecl.column || 0,
|
|
1170
|
+
{
|
|
1171
|
+
isConst: enumDecl.isConst || false,
|
|
1172
|
+
members: enumDecl.members || []
|
|
1173
|
+
}
|
|
1174
|
+
);
|
|
1175
|
+
|
|
1176
|
+
this._bufferNode(enumNode as unknown as GraphNode);
|
|
1150
1177
|
|
|
1151
1178
|
// MODULE -> CONTAINS -> ENUM
|
|
1152
1179
|
this._bufferEdge({
|
|
1153
1180
|
type: 'CONTAINS',
|
|
1154
1181
|
src: module.id,
|
|
1155
|
-
dst:
|
|
1182
|
+
dst: enumNode.id // Use factory-generated ID (colon format)
|
|
1156
1183
|
});
|
|
1157
1184
|
}
|
|
1158
1185
|
}
|
|
@@ -1162,23 +1189,24 @@ export class GraphBuilder {
|
|
|
1162
1189
|
*/
|
|
1163
1190
|
private bufferDecoratorNodes(decorators: DecoratorInfo[]): void {
|
|
1164
1191
|
for (const decorator of decorators) {
|
|
1165
|
-
//
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
arguments: decorator.arguments
|
|
1174
|
-
|
|
1175
|
-
|
|
1192
|
+
// Create DECORATOR node using factory (generates colon-format ID)
|
|
1193
|
+
const decoratorNode = DecoratorNode.create(
|
|
1194
|
+
decorator.name,
|
|
1195
|
+
decorator.file,
|
|
1196
|
+
decorator.line,
|
|
1197
|
+
decorator.column || 0,
|
|
1198
|
+
decorator.targetId, // Now included in the node!
|
|
1199
|
+
decorator.targetType,
|
|
1200
|
+
{ arguments: decorator.arguments }
|
|
1201
|
+
);
|
|
1202
|
+
|
|
1203
|
+
this._bufferNode(decoratorNode as unknown as GraphNode);
|
|
1176
1204
|
|
|
1177
1205
|
// TARGET -> DECORATED_BY -> DECORATOR
|
|
1178
1206
|
this._bufferEdge({
|
|
1179
1207
|
type: 'DECORATED_BY',
|
|
1180
1208
|
src: decorator.targetId,
|
|
1181
|
-
dst:
|
|
1209
|
+
dst: decoratorNode.id // Use factory-generated ID (colon format)
|
|
1182
1210
|
});
|
|
1183
1211
|
}
|
|
1184
1212
|
}
|
|
@@ -1193,26 +1221,28 @@ export class GraphBuilder {
|
|
|
1193
1221
|
// Try to find the interface in the same file
|
|
1194
1222
|
const iface = interfaces.find(i => i.name === ifaceName);
|
|
1195
1223
|
if (iface) {
|
|
1224
|
+
// Compute interface ID using same formula as InterfaceNode.create()
|
|
1225
|
+
// Format: {file}:INTERFACE:{name}:{line}
|
|
1226
|
+
const interfaceId = `${iface.file}:INTERFACE:${iface.name}:${iface.line}`;
|
|
1196
1227
|
this._bufferEdge({
|
|
1197
1228
|
type: 'IMPLEMENTS',
|
|
1198
1229
|
src: classDecl.id,
|
|
1199
|
-
dst:
|
|
1230
|
+
dst: interfaceId
|
|
1200
1231
|
});
|
|
1201
1232
|
} else {
|
|
1202
1233
|
// External interface - create a reference node
|
|
1203
|
-
const
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
});
|
|
1234
|
+
const externalInterface = NodeFactory.createInterface(
|
|
1235
|
+
ifaceName,
|
|
1236
|
+
classDecl.file,
|
|
1237
|
+
classDecl.line,
|
|
1238
|
+
0,
|
|
1239
|
+
{ isExternal: true }
|
|
1240
|
+
);
|
|
1241
|
+
this._bufferNode(externalInterface as unknown as GraphNode);
|
|
1212
1242
|
this._bufferEdge({
|
|
1213
1243
|
type: 'IMPLEMENTS',
|
|
1214
1244
|
src: classDecl.id,
|
|
1215
|
-
dst:
|
|
1245
|
+
dst: externalInterface.id
|
|
1216
1246
|
});
|
|
1217
1247
|
}
|
|
1218
1248
|
}
|
|
@@ -1220,6 +1250,202 @@ export class GraphBuilder {
|
|
|
1220
1250
|
}
|
|
1221
1251
|
}
|
|
1222
1252
|
|
|
1253
|
+
/**
|
|
1254
|
+
* Buffer FLOWS_INTO edges for array mutations (push, unshift, splice, indexed assignment)
|
|
1255
|
+
* Creates edges from inserted values to the array variable
|
|
1256
|
+
*
|
|
1257
|
+
* REG-117: Now handles nested mutations like obj.arr.push(item):
|
|
1258
|
+
* - For nested mutations, falls back to base object if array property not found
|
|
1259
|
+
* - Adds nestedProperty metadata for tracking
|
|
1260
|
+
*
|
|
1261
|
+
* OPTIMIZED: Uses Map-based lookup cache for O(1) variable lookups instead of O(n) find()
|
|
1262
|
+
*/
|
|
1263
|
+
private bufferArrayMutationEdges(
|
|
1264
|
+
arrayMutations: ArrayMutationInfo[],
|
|
1265
|
+
variableDeclarations: VariableDeclarationInfo[],
|
|
1266
|
+
parameters: ParameterInfo[]
|
|
1267
|
+
): void {
|
|
1268
|
+
// Build lookup cache once: O(n) instead of O(n*m) with find() per mutation
|
|
1269
|
+
const varLookup = new Map<string, VariableDeclarationInfo>();
|
|
1270
|
+
for (const v of variableDeclarations) {
|
|
1271
|
+
varLookup.set(`${v.file}:${v.name}`, v);
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// Build parameter lookup cache for function-level mutations
|
|
1275
|
+
const paramLookup = new Map<string, ParameterInfo>();
|
|
1276
|
+
for (const p of parameters) {
|
|
1277
|
+
paramLookup.set(`${p.file}:${p.name}`, p);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
for (const mutation of arrayMutations) {
|
|
1281
|
+
const { arrayName, mutationMethod, insertedValues, file, isNested, baseObjectName, propertyName } = mutation;
|
|
1282
|
+
|
|
1283
|
+
// REG-117: For nested mutations (obj.arr.push), resolve target node
|
|
1284
|
+
// First try direct lookup, then fallback to base object
|
|
1285
|
+
let targetNodeId: string | null = null;
|
|
1286
|
+
let nestedProperty: string | undefined;
|
|
1287
|
+
|
|
1288
|
+
if (isNested && baseObjectName) {
|
|
1289
|
+
// Skip 'this.items.push' - 'this' is not a variable node
|
|
1290
|
+
if (baseObjectName === 'this') continue;
|
|
1291
|
+
|
|
1292
|
+
// Nested mutation: try base object lookup
|
|
1293
|
+
const baseVar = varLookup.get(`${file}:${baseObjectName}`);
|
|
1294
|
+
const baseParam = !baseVar ? paramLookup.get(`${file}:${baseObjectName}`) : null;
|
|
1295
|
+
targetNodeId = baseVar?.id ?? baseParam?.id ?? null;
|
|
1296
|
+
nestedProperty = propertyName;
|
|
1297
|
+
} else {
|
|
1298
|
+
// Direct mutation: arr.push()
|
|
1299
|
+
const arrayVar = varLookup.get(`${file}:${arrayName}`);
|
|
1300
|
+
const arrayParam = !arrayVar ? paramLookup.get(`${file}:${arrayName}`) : null;
|
|
1301
|
+
targetNodeId = arrayVar?.id ?? arrayParam?.id ?? null;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
if (!targetNodeId) continue;
|
|
1305
|
+
|
|
1306
|
+
// Create FLOWS_INTO edges for each inserted value
|
|
1307
|
+
for (const arg of insertedValues) {
|
|
1308
|
+
if (arg.valueType === 'VARIABLE' && arg.valueName) {
|
|
1309
|
+
// O(1) lookup instead of O(n) find
|
|
1310
|
+
const sourceVar = varLookup.get(`${file}:${arg.valueName}`);
|
|
1311
|
+
const sourceParam = !sourceVar ? paramLookup.get(`${file}:${arg.valueName}`) : null;
|
|
1312
|
+
const sourceNodeId = sourceVar?.id ?? sourceParam?.id;
|
|
1313
|
+
|
|
1314
|
+
if (sourceNodeId) {
|
|
1315
|
+
const edgeData: GraphEdge = {
|
|
1316
|
+
type: 'FLOWS_INTO',
|
|
1317
|
+
src: sourceNodeId,
|
|
1318
|
+
dst: targetNodeId,
|
|
1319
|
+
mutationMethod,
|
|
1320
|
+
argIndex: arg.argIndex
|
|
1321
|
+
};
|
|
1322
|
+
if (arg.isSpread) {
|
|
1323
|
+
edgeData.isSpread = true;
|
|
1324
|
+
}
|
|
1325
|
+
// REG-117: Add nested property metadata
|
|
1326
|
+
if (nestedProperty) {
|
|
1327
|
+
edgeData.nestedProperty = nestedProperty;
|
|
1328
|
+
}
|
|
1329
|
+
this._bufferEdge(edgeData);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
// For literals, object literals, etc. - we could create edges from LITERAL nodes
|
|
1333
|
+
// but for now we just track variable -> array flows
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* Buffer FLOWS_INTO edges for object mutations (property assignment, Object.assign)
|
|
1340
|
+
* Creates edges from source values to the object variable being mutated.
|
|
1341
|
+
*
|
|
1342
|
+
* REG-152: For 'this.prop = value' patterns inside classes, creates edges
|
|
1343
|
+
* to the CLASS node with mutationType: 'this_property'.
|
|
1344
|
+
*/
|
|
1345
|
+
private bufferObjectMutationEdges(
|
|
1346
|
+
objectMutations: ObjectMutationInfo[],
|
|
1347
|
+
variableDeclarations: VariableDeclarationInfo[],
|
|
1348
|
+
parameters: ParameterInfo[],
|
|
1349
|
+
functions: FunctionInfo[],
|
|
1350
|
+
classDeclarations: ClassDeclarationInfo[]
|
|
1351
|
+
): void {
|
|
1352
|
+
for (const mutation of objectMutations) {
|
|
1353
|
+
const { objectName, propertyName, mutationType, computedPropertyVar, value, file, enclosingClassName } = mutation;
|
|
1354
|
+
|
|
1355
|
+
// Find the target node (object variable, parameter, or class for 'this')
|
|
1356
|
+
let objectNodeId: string | null = null;
|
|
1357
|
+
let effectiveMutationType: 'property' | 'computed' | 'assign' | 'spread' | 'this_property' = mutationType;
|
|
1358
|
+
|
|
1359
|
+
if (objectName !== 'this') {
|
|
1360
|
+
// Regular object - find variable or parameter
|
|
1361
|
+
const objectVar = variableDeclarations.find(v => v.name === objectName && v.file === file);
|
|
1362
|
+
const objectParam = !objectVar ? parameters.find(p => p.name === objectName && p.file === file) : null;
|
|
1363
|
+
objectNodeId = objectVar?.id ?? objectParam?.id ?? null;
|
|
1364
|
+
if (!objectNodeId) continue;
|
|
1365
|
+
} else {
|
|
1366
|
+
// REG-152: 'this' mutations - find the CLASS node
|
|
1367
|
+
if (!enclosingClassName) continue; // Skip if no class context (e.g., standalone function)
|
|
1368
|
+
|
|
1369
|
+
// Compare using basename since classes use scopeTracker.file (basename)
|
|
1370
|
+
// but mutations use module.file (full path)
|
|
1371
|
+
const fileBasename = basename(file);
|
|
1372
|
+
const classDecl = classDeclarations.find(c => c.name === enclosingClassName && c.file === fileBasename);
|
|
1373
|
+
objectNodeId = classDecl?.id ?? null;
|
|
1374
|
+
|
|
1375
|
+
if (!objectNodeId) continue; // Skip if class not found
|
|
1376
|
+
|
|
1377
|
+
// Use special mutation type to distinguish from regular property mutations
|
|
1378
|
+
effectiveMutationType = 'this_property';
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
// Create FLOWS_INTO edge for VARIABLE value type
|
|
1382
|
+
if (value.valueType === 'VARIABLE' && value.valueName) {
|
|
1383
|
+
// Find the source: can be variable, parameter, or function (arrow functions assigned to const)
|
|
1384
|
+
const sourceVar = variableDeclarations.find(v => v.name === value.valueName && v.file === file);
|
|
1385
|
+
const sourceParam = !sourceVar ? parameters.find(p => p.name === value.valueName && p.file === file) : null;
|
|
1386
|
+
const sourceFunc = !sourceVar && !sourceParam ? functions.find(f => f.name === value.valueName && f.file === file) : null;
|
|
1387
|
+
const sourceNodeId = sourceVar?.id ?? sourceParam?.id ?? sourceFunc?.id;
|
|
1388
|
+
|
|
1389
|
+
if (sourceNodeId && objectNodeId) {
|
|
1390
|
+
const edgeData: GraphEdge = {
|
|
1391
|
+
type: 'FLOWS_INTO',
|
|
1392
|
+
src: sourceNodeId,
|
|
1393
|
+
dst: objectNodeId,
|
|
1394
|
+
mutationType: effectiveMutationType,
|
|
1395
|
+
propertyName,
|
|
1396
|
+
computedPropertyVar // For enrichment phase resolution
|
|
1397
|
+
};
|
|
1398
|
+
if (value.argIndex !== undefined) {
|
|
1399
|
+
edgeData.argIndex = value.argIndex;
|
|
1400
|
+
}
|
|
1401
|
+
if (value.isSpread) {
|
|
1402
|
+
edgeData.isSpread = true;
|
|
1403
|
+
}
|
|
1404
|
+
this._bufferEdge(edgeData);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
// For literals, object literals, etc. - we just track variable -> object flows for now
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/**
|
|
1412
|
+
* Buffer OBJECT_LITERAL nodes to the graph.
|
|
1413
|
+
* These are object literals passed as function arguments or nested in other literals.
|
|
1414
|
+
*/
|
|
1415
|
+
private bufferObjectLiteralNodes(objectLiterals: ObjectLiteralInfo[]): void {
|
|
1416
|
+
for (const obj of objectLiterals) {
|
|
1417
|
+
this._bufferNode({
|
|
1418
|
+
id: obj.id,
|
|
1419
|
+
type: obj.type,
|
|
1420
|
+
name: '<object>',
|
|
1421
|
+
file: obj.file,
|
|
1422
|
+
line: obj.line,
|
|
1423
|
+
column: obj.column,
|
|
1424
|
+
parentCallId: obj.parentCallId,
|
|
1425
|
+
argIndex: obj.argIndex
|
|
1426
|
+
} as GraphNode);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
/**
|
|
1431
|
+
* Buffer ARRAY_LITERAL nodes to the graph.
|
|
1432
|
+
* These are array literals passed as function arguments or nested in other literals.
|
|
1433
|
+
*/
|
|
1434
|
+
private bufferArrayLiteralNodes(arrayLiterals: ArrayLiteralInfo[]): void {
|
|
1435
|
+
for (const arr of arrayLiterals) {
|
|
1436
|
+
this._bufferNode({
|
|
1437
|
+
id: arr.id,
|
|
1438
|
+
type: arr.type,
|
|
1439
|
+
name: '<array>',
|
|
1440
|
+
file: arr.file,
|
|
1441
|
+
line: arr.line,
|
|
1442
|
+
column: arr.column,
|
|
1443
|
+
parentCallId: arr.parentCallId,
|
|
1444
|
+
argIndex: arr.argIndex
|
|
1445
|
+
} as GraphNode);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1223
1449
|
/**
|
|
1224
1450
|
* Handle CLASS ASSIGNED_FROM edges asynchronously (needs graph queries)
|
|
1225
1451
|
*/
|
|
@@ -1254,118 +1480,4 @@ export class GraphBuilder {
|
|
|
1254
1480
|
|
|
1255
1481
|
return edgesCreated;
|
|
1256
1482
|
}
|
|
1257
|
-
|
|
1258
|
-
/**
|
|
1259
|
-
* Create IMPORTS_FROM edges linking imports to their target exports
|
|
1260
|
-
*/
|
|
1261
|
-
private async createImportExportEdges(
|
|
1262
|
-
module: ModuleNode,
|
|
1263
|
-
imports: ImportInfo[],
|
|
1264
|
-
_exports: ExportInfo[],
|
|
1265
|
-
graph: GraphBackend,
|
|
1266
|
-
_projectPath: string
|
|
1267
|
-
): Promise<number> {
|
|
1268
|
-
let edgesCreated = 0;
|
|
1269
|
-
|
|
1270
|
-
for (const imp of imports) {
|
|
1271
|
-
const { source, specifiers, line } = imp;
|
|
1272
|
-
|
|
1273
|
-
// Только для относительных импортов
|
|
1274
|
-
const isRelative = source.startsWith('./') || source.startsWith('../');
|
|
1275
|
-
if (!isRelative) {
|
|
1276
|
-
continue;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
// Резолвим целевой модуль
|
|
1280
|
-
const currentDir = dirname(module.file);
|
|
1281
|
-
let targetPath = resolve(currentDir, source);
|
|
1282
|
-
|
|
1283
|
-
// Пытаемся найти файл с расширениями .js, .ts, .jsx, .tsx
|
|
1284
|
-
const extensions = ['', '.js', '.ts', '.jsx', '.tsx', '/index.js', '/index.ts'];
|
|
1285
|
-
let targetModule: { id: string; file: string } | null = null;
|
|
1286
|
-
|
|
1287
|
-
// Ищем MODULE ноду по file атрибуту (не по ID, т.к. формат ID изменился)
|
|
1288
|
-
for (const ext of extensions) {
|
|
1289
|
-
const testPath = targetPath + ext;
|
|
1290
|
-
|
|
1291
|
-
// Ищем MODULE с этим file path
|
|
1292
|
-
for await (const node of graph.queryNodes({ type: 'MODULE' })) {
|
|
1293
|
-
if (node.file === testPath) {
|
|
1294
|
-
targetModule = node as { id: string; file: string };
|
|
1295
|
-
targetPath = testPath;
|
|
1296
|
-
break;
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
if (targetModule) break;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
if (!targetModule) {
|
|
1303
|
-
// Целевой модуль не найден в графе
|
|
1304
|
-
continue;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
// Создаём IMPORTS edge от MODULE к MODULE (для совместимости с тестами)
|
|
1308
|
-
await graph.addEdge({
|
|
1309
|
-
type: 'IMPORTS',
|
|
1310
|
-
src: module.id,
|
|
1311
|
-
dst: targetModule.id
|
|
1312
|
-
});
|
|
1313
|
-
edgesCreated++;
|
|
1314
|
-
|
|
1315
|
-
// Для каждого импортированного идентификатора создаём ребро к соответствующему EXPORT
|
|
1316
|
-
for (const spec of specifiers) {
|
|
1317
|
-
const importId = `${module.file}:IMPORT:${source}:${spec.local}:${line}`;
|
|
1318
|
-
const importType = spec.imported === 'default' ? 'default' :
|
|
1319
|
-
spec.imported === '*' ? 'namespace' : 'named';
|
|
1320
|
-
|
|
1321
|
-
if (importType === 'namespace') {
|
|
1322
|
-
// import * as foo - связываем со всем модулем
|
|
1323
|
-
await graph.addEdge({
|
|
1324
|
-
type: 'IMPORTS_FROM',
|
|
1325
|
-
src: importId,
|
|
1326
|
-
dst: targetModule.id
|
|
1327
|
-
});
|
|
1328
|
-
edgesCreated++;
|
|
1329
|
-
} else if (importType === 'default') {
|
|
1330
|
-
// Находим EXPORT default в целевом модуле
|
|
1331
|
-
const targetExports: { id: string }[] = [];
|
|
1332
|
-
for await (const node of graph.queryNodes({ type: 'EXPORT' })) {
|
|
1333
|
-
const exportNode = node as { id: string; file?: string; exportType?: string };
|
|
1334
|
-
if (exportNode.file === targetPath && exportNode.exportType === 'default') {
|
|
1335
|
-
targetExports.push(exportNode);
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
if (targetExports.length > 0) {
|
|
1340
|
-
await graph.addEdge({
|
|
1341
|
-
type: 'IMPORTS_FROM',
|
|
1342
|
-
src: importId,
|
|
1343
|
-
dst: targetExports[0].id
|
|
1344
|
-
});
|
|
1345
|
-
edgesCreated++;
|
|
1346
|
-
}
|
|
1347
|
-
} else {
|
|
1348
|
-
// Named import - находим соответствующий named export
|
|
1349
|
-
const targetExports: { id: string }[] = [];
|
|
1350
|
-
for await (const node of graph.queryNodes({ type: 'EXPORT' })) {
|
|
1351
|
-
const exportNode = node as { id: string; file?: string; exportType?: string; name?: string };
|
|
1352
|
-
if (exportNode.file === targetPath && exportNode.exportType === 'named' && exportNode.name === spec.imported) {
|
|
1353
|
-
targetExports.push(exportNode);
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
if (targetExports.length > 0) {
|
|
1358
|
-
await graph.addEdge({
|
|
1359
|
-
type: 'IMPORTS_FROM',
|
|
1360
|
-
src: importId,
|
|
1361
|
-
dst: targetExports[0].id
|
|
1362
|
-
});
|
|
1363
|
-
edgesCreated++;
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
return edgesCreated;
|
|
1370
|
-
}
|
|
1371
1483
|
}
|