@grafema/core 0.1.0-alpha.5 → 0.2.0-beta
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 +31 -2
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +222 -27
- package/dist/config/ConfigLoader.d.ts +90 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +249 -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/FileExplainer.d.ts +101 -0
- package/dist/core/FileExplainer.d.ts.map +1 -0
- package/dist/core/FileExplainer.js +139 -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 +266 -19
- package/dist/core/NodeFactory.d.ts.map +1 -1
- package/dist/core/NodeFactory.js +256 -21
- 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 +43 -0
- package/dist/core/nodes/BranchNode.d.ts +41 -0
- package/dist/core/nodes/BranchNode.d.ts.map +1 -0
- package/dist/core/nodes/BranchNode.js +82 -0
- package/dist/core/nodes/CallSiteNode.d.ts +30 -2
- package/dist/core/nodes/CallSiteNode.d.ts.map +1 -1
- package/dist/core/nodes/CallSiteNode.js +54 -4
- package/dist/core/nodes/CaseNode.d.ts +43 -0
- package/dist/core/nodes/CaseNode.d.ts.map +1 -0
- package/dist/core/nodes/CaseNode.js +81 -0
- package/dist/core/nodes/ClassNode.d.ts +34 -2
- package/dist/core/nodes/ClassNode.d.ts.map +1 -1
- package/dist/core/nodes/ClassNode.js +52 -4
- package/dist/core/nodes/ConstantNode.d.ts +2 -2
- package/dist/core/nodes/ConstantNode.d.ts.map +1 -1
- package/dist/core/nodes/ConstantNode.js +6 -4
- package/dist/core/nodes/ConstructorCallNode.d.ts +51 -0
- package/dist/core/nodes/ConstructorCallNode.d.ts.map +1 -0
- package/dist/core/nodes/ConstructorCallNode.js +171 -0
- package/dist/core/nodes/DatabaseQueryNode.d.ts +3 -2
- package/dist/core/nodes/DatabaseQueryNode.d.ts.map +1 -1
- package/dist/core/nodes/DatabaseQueryNode.js +5 -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 +64 -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 +56 -0
- package/dist/core/nodes/EventListenerNode.d.ts +4 -4
- package/dist/core/nodes/EventListenerNode.d.ts.map +1 -1
- package/dist/core/nodes/EventListenerNode.js +7 -4
- package/dist/core/nodes/ExportNode.d.ts +38 -2
- package/dist/core/nodes/ExportNode.d.ts.map +1 -1
- package/dist/core/nodes/ExportNode.js +54 -4
- 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 +180 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts +32 -0
- package/dist/core/nodes/ExternalModuleNode.d.ts.map +1 -0
- package/dist/core/nodes/ExternalModuleNode.js +49 -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/HttpRequestNode.d.ts +4 -4
- package/dist/core/nodes/HttpRequestNode.d.ts.map +1 -1
- package/dist/core/nodes/HttpRequestNode.js +7 -4
- package/dist/core/nodes/ImportNode.d.ts +28 -6
- package/dist/core/nodes/ImportNode.d.ts.map +1 -1
- package/dist/core/nodes/ImportNode.js +43 -8
- 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 +57 -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/LiteralNode.d.ts +2 -2
- package/dist/core/nodes/LiteralNode.d.ts.map +1 -1
- package/dist/core/nodes/LiteralNode.js +6 -4
- package/dist/core/nodes/MethodCallNode.d.ts +32 -2
- package/dist/core/nodes/MethodCallNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodCallNode.js +57 -4
- package/dist/core/nodes/MethodNode.d.ts +34 -2
- package/dist/core/nodes/MethodNode.d.ts.map +1 -1
- package/dist/core/nodes/MethodNode.js +55 -3
- 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 +43 -0
- package/dist/core/nodes/ParameterNode.d.ts +2 -2
- package/dist/core/nodes/ParameterNode.d.ts.map +1 -1
- package/dist/core/nodes/ParameterNode.js +5 -3
- 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 +55 -0
- package/dist/core/nodes/VariableDeclarationNode.d.ts +29 -2
- package/dist/core/nodes/VariableDeclarationNode.d.ts.map +1 -1
- package/dist/core/nodes/VariableDeclarationNode.js +48 -4
- package/dist/core/nodes/index.d.ts +15 -1
- package/dist/core/nodes/index.d.ts.map +1 -1
- package/dist/core/nodes/index.js +17 -0
- package/dist/data/builtins/BuiltinRegistry.d.ts +78 -0
- package/dist/data/builtins/BuiltinRegistry.d.ts.map +1 -0
- package/dist/data/builtins/BuiltinRegistry.js +110 -0
- package/dist/data/builtins/definitions.d.ts +28 -0
- package/dist/data/builtins/definitions.d.ts.map +1 -0
- package/dist/data/builtins/definitions.js +250 -0
- package/dist/data/builtins/index.d.ts +10 -0
- package/dist/data/builtins/index.d.ts.map +1 -0
- package/dist/data/builtins/index.js +8 -0
- package/dist/data/builtins/jsGlobals.d.ts +18 -0
- package/dist/data/builtins/jsGlobals.d.ts.map +1 -0
- package/dist/data/builtins/jsGlobals.js +26 -0
- package/dist/data/builtins/types.d.ts +34 -0
- package/dist/data/builtins/types.d.ts.map +1 -0
- package/dist/data/builtins/types.js +7 -0
- package/dist/data/globals/definitions.d.ts +27 -0
- package/dist/data/globals/definitions.d.ts.map +1 -0
- package/dist/data/globals/definitions.js +117 -0
- package/dist/data/globals/index.d.ts +36 -0
- package/dist/data/globals/index.d.ts.map +1 -0
- package/dist/data/globals/index.js +52 -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 +100 -0
- package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
- package/dist/diagnostics/DiagnosticReporter.js +247 -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 +161 -0
- package/dist/errors/GrafemaError.d.ts.map +1 -0
- package/dist/errors/GrafemaError.js +181 -0
- package/dist/index.d.ts +73 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -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 +14 -6
- package/dist/plugins/analysis/ExpressAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressAnalyzer.js +29 -19
- package/dist/plugins/analysis/ExpressResponseAnalyzer.d.ts +148 -0
- package/dist/plugins/analysis/ExpressResponseAnalyzer.d.ts.map +1 -0
- package/dist/plugins/analysis/ExpressResponseAnalyzer.js +495 -0
- package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/ExpressRouteAnalyzer.js +71 -29
- package/dist/plugins/analysis/FetchAnalyzer.d.ts +41 -0
- package/dist/plugins/analysis/FetchAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/FetchAnalyzer.js +187 -19
- 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 +313 -19
- package/dist/plugins/analysis/JSASTAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/JSASTAnalyzer.js +3430 -503
- 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 +16 -11
- package/dist/plugins/analysis/SQLiteAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SQLiteAnalyzer.js +11 -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 +9 -0
- package/dist/plugins/analysis/SocketIOAnalyzer.d.ts.map +1 -1
- package/dist/plugins/analysis/SocketIOAnalyzer.js +117 -21
- 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 +207 -4
- package/dist/plugins/analysis/ast/GraphBuilder.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/GraphBuilder.js +1527 -316
- 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 +470 -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 +14 -5
- 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 +100 -9
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.js +674 -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 +14 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/FunctionVisitor.js +190 -63
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts +4 -0
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.js +112 -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 +20 -2
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts.map +1 -1
- package/dist/plugins/analysis/ast/visitors/VariableVisitor.js +243 -45
- 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 +141 -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 +29 -8
- package/dist/plugins/enrichment/ArgumentParameterLinker.d.ts +32 -0
- package/dist/plugins/enrichment/ArgumentParameterLinker.d.ts.map +1 -0
- package/dist/plugins/enrichment/ArgumentParameterLinker.js +175 -0
- package/dist/plugins/enrichment/ClosureCaptureEnricher.d.ts +51 -0
- package/dist/plugins/enrichment/ClosureCaptureEnricher.d.ts.map +1 -0
- package/dist/plugins/enrichment/ClosureCaptureEnricher.js +205 -0
- package/dist/plugins/enrichment/ExternalCallResolver.d.ts +42 -0
- package/dist/plugins/enrichment/ExternalCallResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/ExternalCallResolver.js +213 -0
- package/dist/plugins/enrichment/FunctionCallResolver.d.ts +58 -0
- package/dist/plugins/enrichment/FunctionCallResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/FunctionCallResolver.js +340 -0
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts +16 -3
- package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts.map +1 -1
- package/dist/plugins/enrichment/HTTPConnectionEnricher.js +78 -27
- 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 +33 -13
- package/dist/plugins/enrichment/MountPointResolver.d.ts +14 -12
- package/dist/plugins/enrichment/MountPointResolver.d.ts.map +1 -1
- package/dist/plugins/enrichment/MountPointResolver.js +173 -147
- package/dist/plugins/enrichment/NodejsBuiltinsResolver.d.ts +44 -0
- package/dist/plugins/enrichment/NodejsBuiltinsResolver.d.ts.map +1 -0
- package/dist/plugins/enrichment/NodejsBuiltinsResolver.js +271 -0
- 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 +22 -27
- package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts.map +1 -1
- package/dist/plugins/enrichment/ValueDomainAnalyzer.js +185 -143
- 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 +15 -0
- package/dist/plugins/indexing/JSModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/JSModuleIndexer.js +121 -31
- package/dist/plugins/indexing/RustModuleIndexer.d.ts +1 -1
- package/dist/plugins/indexing/RustModuleIndexer.d.ts.map +1 -1
- package/dist/plugins/indexing/RustModuleIndexer.js +8 -7
- 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/BrokenImportValidator.d.ts +31 -0
- package/dist/plugins/validation/BrokenImportValidator.d.ts.map +1 -0
- package/dist/plugins/validation/BrokenImportValidator.js +249 -0
- package/dist/plugins/validation/CallResolverValidator.d.ts +21 -10
- package/dist/plugins/validation/CallResolverValidator.d.ts.map +1 -1
- package/dist/plugins/validation/CallResolverValidator.js +103 -77
- package/dist/plugins/validation/DataFlowValidator.d.ts.map +1 -1
- package/dist/plugins/validation/DataFlowValidator.js +62 -49
- 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 +44 -24
- 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 +61 -19
- 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/queries/findCallsInFunction.d.ts +52 -0
- package/dist/queries/findCallsInFunction.d.ts.map +1 -0
- package/dist/queries/findCallsInFunction.js +135 -0
- package/dist/queries/findContainingFunction.d.ts +45 -0
- package/dist/queries/findContainingFunction.d.ts.map +1 -0
- package/dist/queries/findContainingFunction.js +54 -0
- package/dist/queries/index.d.ts +14 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +11 -0
- package/dist/queries/traceValues.d.ts +70 -0
- package/dist/queries/traceValues.d.ts.map +1 -0
- package/dist/queries/traceValues.js +299 -0
- package/dist/queries/types.d.ts +163 -0
- package/dist/queries/types.d.ts.map +1 -0
- package/dist/queries/types.js +9 -0
- package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
- package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/GraphSchemaExtractor.js +124 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
- package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
- package/dist/schema/InterfaceSchemaExtractor.js +112 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +2 -0
- package/dist/storage/backends/RFDBServerBackend.d.ts +21 -34
- package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -1
- package/dist/storage/backends/RFDBServerBackend.js +72 -62
- package/dist/storage/backends/typeValidation.d.ts.map +1 -1
- package/dist/storage/backends/typeValidation.js +1 -0
- 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 +272 -27
- package/src/config/ConfigLoader.ts +354 -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/FileExplainer.ts +179 -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 +470 -23
- 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 +66 -0
- package/src/core/nodes/BranchNode.ts +113 -0
- package/src/core/nodes/CallSiteNode.ts +64 -4
- package/src/core/nodes/CaseNode.ts +123 -0
- package/src/core/nodes/ClassNode.ts +67 -4
- package/src/core/nodes/ConstantNode.ts +5 -4
- package/src/core/nodes/ConstructorCallNode.ts +217 -0
- package/src/core/nodes/DatabaseQueryNode.ts +5 -1
- package/src/core/nodes/DecoratorNode.ts +92 -0
- package/src/core/nodes/EnumNode.ts +87 -0
- package/src/core/nodes/EventListenerNode.ts +7 -4
- package/src/core/nodes/ExportNode.ts +74 -4
- package/src/core/nodes/ExpressionNode.ts +232 -0
- package/src/core/nodes/ExternalModuleNode.ts +65 -0
- package/src/core/nodes/ExternalStdioNode.ts +17 -9
- package/src/core/nodes/FunctionNode.ts +101 -1
- package/src/core/nodes/HttpRequestNode.ts +7 -4
- package/src/core/nodes/ImportNode.ts +62 -13
- package/src/core/nodes/InterfaceNode.ts +92 -0
- package/src/core/nodes/IssueNode.ts +177 -0
- package/src/core/nodes/LiteralNode.ts +5 -4
- package/src/core/nodes/MethodCallNode.ts +70 -4
- package/src/core/nodes/MethodNode.ts +68 -3
- package/src/core/nodes/ModuleNode.ts +50 -0
- package/src/core/nodes/NetworkRequestNode.ts +77 -0
- package/src/core/nodes/ObjectLiteralNode.ts +66 -0
- package/src/core/nodes/ParameterNode.ts +4 -3
- package/src/core/nodes/ScopeNode.ts +65 -0
- package/src/core/nodes/TypeNode.ts +79 -0
- package/src/core/nodes/VariableDeclarationNode.ts +58 -4
- package/src/core/nodes/index.ts +21 -1
- package/src/data/builtins/BuiltinRegistry.ts +124 -0
- package/src/data/builtins/definitions.ts +267 -0
- package/src/data/builtins/index.ts +10 -0
- package/src/data/builtins/jsGlobals.ts +28 -0
- package/src/data/builtins/types.ts +36 -0
- package/src/data/globals/definitions.ts +156 -0
- package/src/data/globals/index.ts +66 -0
- package/src/diagnostics/DiagnosticCollector.ts +163 -0
- package/src/diagnostics/DiagnosticReporter.ts +324 -0
- package/src/diagnostics/DiagnosticWriter.ts +50 -0
- package/src/diagnostics/index.ts +16 -0
- package/src/errors/GrafemaError.ts +239 -0
- package/src/index.ts +193 -1
- package/src/logging/Logger.ts +152 -0
- package/src/plugins/Plugin.ts +42 -0
- package/src/plugins/analysis/DatabaseAnalyzer.ts +16 -8
- package/src/plugins/analysis/ExpressAnalyzer.ts +33 -19
- package/src/plugins/analysis/ExpressResponseAnalyzer.ts +636 -0
- package/src/plugins/analysis/ExpressRouteAnalyzer.ts +76 -36
- package/src/plugins/analysis/FetchAnalyzer.ts +232 -21
- package/src/plugins/analysis/IncrementalAnalysisPlugin.ts +84 -101
- package/src/plugins/analysis/JSASTAnalyzer.ts +4265 -587
- package/src/plugins/analysis/ReactAnalyzer.ts +57 -57
- package/src/plugins/analysis/RustAnalyzer.ts +16 -11
- package/src/plugins/analysis/SQLiteAnalyzer.ts +13 -7
- package/src/plugins/analysis/ServiceLayerAnalyzer.ts +22 -16
- package/src/plugins/analysis/SocketIOAnalyzer.ts +151 -28
- package/src/plugins/analysis/SystemDbAnalyzer.ts +16 -11
- package/src/plugins/analysis/ast/GraphBuilder.ts +1947 -327
- package/src/plugins/analysis/ast/IdGenerator.ts +177 -0
- package/src/plugins/analysis/ast/types.ts +596 -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 +19 -8
- package/src/plugins/analysis/ast/visitors/CallExpressionVisitor.ts +924 -83
- package/src/plugins/analysis/ast/visitors/ClassVisitor.ts +97 -44
- package/src/plugins/analysis/ast/visitors/FunctionVisitor.ts +234 -93
- package/src/plugins/analysis/ast/visitors/ImportExportVisitor.ts +124 -9
- package/src/plugins/analysis/ast/visitors/TypeScriptVisitor.ts +41 -14
- package/src/plugins/analysis/ast/visitors/VariableVisitor.ts +294 -49
- package/src/plugins/discovery/MonorepoServiceDiscovery.ts +3 -2
- package/src/plugins/discovery/SimpleProjectDiscovery.ts +6 -1
- package/src/plugins/discovery/WorkspaceDiscovery.ts +184 -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 +35 -8
- package/src/plugins/enrichment/ArgumentParameterLinker.ts +240 -0
- package/src/plugins/enrichment/ClosureCaptureEnricher.ts +267 -0
- package/src/plugins/enrichment/ExternalCallResolver.ts +262 -0
- package/src/plugins/enrichment/FunctionCallResolver.ts +456 -0
- package/src/plugins/enrichment/HTTPConnectionEnricher.ts +84 -27
- package/src/plugins/enrichment/ImportExportLinker.ts +24 -6
- package/src/plugins/enrichment/MethodCallResolver.ts +39 -13
- package/src/plugins/enrichment/MountPointResolver.ts +208 -195
- package/src/plugins/enrichment/NodejsBuiltinsResolver.ts +365 -0
- package/src/plugins/enrichment/PrefixEvaluator.ts +16 -7
- package/src/plugins/enrichment/RustFFIEnricher.ts +6 -5
- package/src/plugins/enrichment/ValueDomainAnalyzer.ts +209 -189
- package/src/plugins/indexing/IncrementalModuleIndexer.ts +23 -14
- package/src/plugins/indexing/JSModuleIndexer.ts +140 -34
- package/src/plugins/indexing/RustModuleIndexer.ts +8 -7
- package/src/plugins/validation/BrokenImportValidator.ts +325 -0
- package/src/plugins/validation/CallResolverValidator.ts +131 -110
- package/src/plugins/validation/DataFlowValidator.ts +88 -67
- package/src/plugins/validation/EvalBanValidator.ts +17 -16
- package/src/plugins/validation/GraphConnectivityValidator.ts +58 -24
- package/src/plugins/validation/NodeCreationValidator.ts +554 -0
- package/src/plugins/validation/SQLInjectionValidator.ts +63 -20
- 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/queries/README.md +46 -0
- package/src/queries/findCallsInFunction.ts +206 -0
- package/src/queries/findContainingFunction.ts +83 -0
- package/src/queries/index.ts +23 -0
- package/src/queries/traceValues.ts +398 -0
- package/src/queries/types.ts +187 -0
- package/src/schema/GraphSchemaExtractor.ts +177 -0
- package/src/schema/InterfaceSchemaExtractor.ts +173 -0
- package/src/schema/index.ts +5 -0
- package/src/storage/backends/RFDBServerBackend.ts +100 -98
- package/src/storage/backends/typeValidation.ts +1 -0
- 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
|
@@ -9,9 +9,22 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { ASTVisitor } from './ASTVisitor.js';
|
|
11
11
|
import { ExpressionEvaluator } from '../ExpressionEvaluator.js';
|
|
12
|
+
import { computeSemanticId } from '../../../../core/SemanticId.js';
|
|
13
|
+
import { IdGenerator } from '../IdGenerator.js';
|
|
14
|
+
import { NodeFactory } from '../../../../core/NodeFactory.js';
|
|
15
|
+
import { ObjectLiteralNode } from '../../../../core/nodes/ObjectLiteralNode.js';
|
|
16
|
+
import { ArrayLiteralNode } from '../../../../core/nodes/ArrayLiteralNode.js';
|
|
17
|
+
import { getLine, getColumn } from '../utils/location.js';
|
|
12
18
|
export class CallExpressionVisitor extends ASTVisitor {
|
|
13
|
-
|
|
19
|
+
scopeTracker;
|
|
20
|
+
/**
|
|
21
|
+
* @param module - Current module being analyzed
|
|
22
|
+
* @param collections - Must contain arrays and counter refs
|
|
23
|
+
* @param scopeTracker - Optional ScopeTracker for semantic ID generation
|
|
24
|
+
*/
|
|
25
|
+
constructor(module, collections, scopeTracker) {
|
|
14
26
|
super(module, collections);
|
|
27
|
+
this.scopeTracker = scopeTracker;
|
|
15
28
|
}
|
|
16
29
|
/**
|
|
17
30
|
* Extract argument information for PASSES_ARGUMENT edges
|
|
@@ -31,104 +44,157 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
31
44
|
argInfo.isSpread = true;
|
|
32
45
|
actualArg = arg.argument; // Get the actual argument
|
|
33
46
|
}
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
argInfo.
|
|
50
|
-
argInfo.targetId = literalId;
|
|
51
|
-
argInfo.literalValue = literalValue;
|
|
52
|
-
}
|
|
53
|
-
// Variable reference
|
|
54
|
-
else if (actualArg.type === 'Identifier') {
|
|
55
|
-
argInfo.targetType = 'VARIABLE';
|
|
56
|
-
argInfo.targetName = actualArg.name; // Will be resolved in GraphBuilder
|
|
57
|
-
}
|
|
58
|
-
// Function expression (callback)
|
|
59
|
-
else if (actualArg.type === 'ArrowFunctionExpression' || actualArg.type === 'FunctionExpression') {
|
|
60
|
-
argInfo.targetType = 'FUNCTION';
|
|
61
|
-
argInfo.functionLine = actualArg.loc?.start.line;
|
|
62
|
-
argInfo.functionColumn = actualArg.loc?.start.column;
|
|
63
|
-
}
|
|
64
|
-
// Call expression (nested call)
|
|
65
|
-
else if (actualArg.type === 'CallExpression') {
|
|
66
|
-
argInfo.targetType = 'CALL';
|
|
67
|
-
// Nested calls will be processed separately, link by position
|
|
68
|
-
argInfo.nestedCallLine = actualArg.loc?.start.line;
|
|
69
|
-
argInfo.nestedCallColumn = actualArg.loc?.start.column;
|
|
70
|
-
}
|
|
71
|
-
// Member expression: obj.prop or obj[x]
|
|
72
|
-
else if (actualArg.type === 'MemberExpression') {
|
|
73
|
-
const memberExpr = actualArg;
|
|
74
|
-
argInfo.targetType = 'EXPRESSION';
|
|
75
|
-
argInfo.expressionType = 'MemberExpression';
|
|
76
|
-
if (memberExpr.object.type === 'Identifier') {
|
|
77
|
-
argInfo.objectName = memberExpr.object.name;
|
|
78
|
-
}
|
|
79
|
-
if (!memberExpr.computed && memberExpr.property.type === 'Identifier') {
|
|
80
|
-
argInfo.propertyName = memberExpr.property.name;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// Binary/Logical expression: a + b, a && b
|
|
84
|
-
else if (actualArg.type === 'BinaryExpression' || actualArg.type === 'LogicalExpression') {
|
|
85
|
-
const expr = actualArg;
|
|
86
|
-
const operator = expr.operator || '?';
|
|
87
|
-
const exprName = `<${actualArg.type}:${operator}>`;
|
|
88
|
-
const expressionId = `EXPRESSION#${exprName}#${module.file}#${argInfo.line}:${argInfo.column}:${literalCounterRef.value++}`;
|
|
89
|
-
// Create EXPRESSION node
|
|
90
|
-
literals.push({
|
|
91
|
-
id: expressionId,
|
|
92
|
-
type: 'EXPRESSION',
|
|
93
|
-
expressionType: actualArg.type,
|
|
94
|
-
operator: operator,
|
|
95
|
-
name: exprName,
|
|
96
|
-
file: module.file,
|
|
97
|
-
line: argInfo.line,
|
|
98
|
-
column: argInfo.column,
|
|
47
|
+
// Object literal - check BEFORE extractLiteralValue to handle object-typed args properly
|
|
48
|
+
if (actualArg.type === 'ObjectExpression') {
|
|
49
|
+
const objectExpr = actualArg;
|
|
50
|
+
// Initialize collections if not exist (must assign back to this.collections!)
|
|
51
|
+
if (!this.collections.objectLiteralCounterRef) {
|
|
52
|
+
this.collections.objectLiteralCounterRef = { value: 0 };
|
|
53
|
+
}
|
|
54
|
+
if (!this.collections.objectLiterals) {
|
|
55
|
+
this.collections.objectLiterals = [];
|
|
56
|
+
}
|
|
57
|
+
if (!this.collections.objectProperties) {
|
|
58
|
+
this.collections.objectProperties = [];
|
|
59
|
+
}
|
|
60
|
+
const objectLiteralCounterRef = this.collections.objectLiteralCounterRef;
|
|
61
|
+
// Use factory to create OBJECT_LITERAL node
|
|
62
|
+
const objectNode = ObjectLiteralNode.create(module.file, argInfo.line, argInfo.column, {
|
|
99
63
|
parentCallId: callId,
|
|
100
|
-
argIndex: index
|
|
64
|
+
argIndex: index,
|
|
65
|
+
counter: objectLiteralCounterRef.value++
|
|
101
66
|
});
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
const { variableAssignments } = this.collections;
|
|
108
|
-
if (variableAssignments) {
|
|
109
|
-
for (const identName of identifiers) {
|
|
110
|
-
variableAssignments.push({
|
|
111
|
-
variableId: expressionId,
|
|
112
|
-
sourceId: null,
|
|
113
|
-
sourceName: identName,
|
|
114
|
-
sourceType: 'DERIVES_FROM_VARIABLE',
|
|
115
|
-
file: module.file
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Object literal
|
|
121
|
-
else if (actualArg.type === 'ObjectExpression') {
|
|
67
|
+
// Factory guarantees line is set, cast to ObjectLiteralInfo
|
|
68
|
+
this.collections.objectLiterals.push(objectNode);
|
|
69
|
+
const objectId = objectNode.id;
|
|
70
|
+
// Extract properties
|
|
71
|
+
this.extractObjectProperties(objectExpr, objectId, module, this.collections.objectProperties, this.collections.objectLiterals, objectLiteralCounterRef, literals, literalCounterRef);
|
|
122
72
|
argInfo.targetType = 'OBJECT_LITERAL';
|
|
73
|
+
argInfo.targetId = objectId;
|
|
123
74
|
}
|
|
124
|
-
// Array literal
|
|
75
|
+
// Array literal - check BEFORE extractLiteralValue to handle array-typed args properly
|
|
125
76
|
else if (actualArg.type === 'ArrayExpression') {
|
|
77
|
+
const arrayExpr = actualArg;
|
|
78
|
+
// Initialize collections if not exist (must assign back to this.collections!)
|
|
79
|
+
if (!this.collections.arrayLiteralCounterRef) {
|
|
80
|
+
this.collections.arrayLiteralCounterRef = { value: 0 };
|
|
81
|
+
}
|
|
82
|
+
if (!this.collections.arrayLiterals) {
|
|
83
|
+
this.collections.arrayLiterals = [];
|
|
84
|
+
}
|
|
85
|
+
if (!this.collections.arrayElements) {
|
|
86
|
+
this.collections.arrayElements = [];
|
|
87
|
+
}
|
|
88
|
+
if (!this.collections.objectLiteralCounterRef) {
|
|
89
|
+
this.collections.objectLiteralCounterRef = { value: 0 };
|
|
90
|
+
}
|
|
91
|
+
if (!this.collections.objectLiterals) {
|
|
92
|
+
this.collections.objectLiterals = [];
|
|
93
|
+
}
|
|
94
|
+
if (!this.collections.objectProperties) {
|
|
95
|
+
this.collections.objectProperties = [];
|
|
96
|
+
}
|
|
97
|
+
const arrayLiteralCounterRef = this.collections.arrayLiteralCounterRef;
|
|
98
|
+
// Use factory to create ARRAY_LITERAL node
|
|
99
|
+
const arrayNode = ArrayLiteralNode.create(module.file, argInfo.line, argInfo.column, {
|
|
100
|
+
parentCallId: callId,
|
|
101
|
+
argIndex: index,
|
|
102
|
+
counter: arrayLiteralCounterRef.value++
|
|
103
|
+
});
|
|
104
|
+
// Factory guarantees line is set, cast to ArrayLiteralInfo
|
|
105
|
+
this.collections.arrayLiterals.push(arrayNode);
|
|
106
|
+
const arrayId = arrayNode.id;
|
|
107
|
+
// Extract elements
|
|
108
|
+
this.extractArrayElements(arrayExpr, arrayId, module, this.collections.arrayElements, this.collections.arrayLiterals, arrayLiteralCounterRef, this.collections.objectLiterals, this.collections.objectLiteralCounterRef, this.collections.objectProperties, literals, literalCounterRef);
|
|
126
109
|
argInfo.targetType = 'ARRAY_LITERAL';
|
|
110
|
+
argInfo.targetId = arrayId;
|
|
127
111
|
}
|
|
128
|
-
//
|
|
112
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
129
113
|
else {
|
|
130
|
-
|
|
131
|
-
|
|
114
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(actualArg);
|
|
115
|
+
if (literalValue !== null) {
|
|
116
|
+
const literalId = `LITERAL#arg${index}#${module.file}#${argInfo.line}:${argInfo.column}:${literalCounterRef.value++}`;
|
|
117
|
+
literals.push({
|
|
118
|
+
id: literalId,
|
|
119
|
+
type: 'LITERAL',
|
|
120
|
+
value: literalValue,
|
|
121
|
+
valueType: typeof literalValue,
|
|
122
|
+
file: module.file,
|
|
123
|
+
line: argInfo.line,
|
|
124
|
+
column: argInfo.column,
|
|
125
|
+
parentCallId: callId,
|
|
126
|
+
argIndex: index
|
|
127
|
+
});
|
|
128
|
+
argInfo.targetType = 'LITERAL';
|
|
129
|
+
argInfo.targetId = literalId;
|
|
130
|
+
argInfo.literalValue = literalValue;
|
|
131
|
+
}
|
|
132
|
+
// Variable reference
|
|
133
|
+
else if (actualArg.type === 'Identifier') {
|
|
134
|
+
argInfo.targetType = 'VARIABLE';
|
|
135
|
+
argInfo.targetName = actualArg.name; // Will be resolved in GraphBuilder
|
|
136
|
+
}
|
|
137
|
+
// Function expression (callback)
|
|
138
|
+
else if (actualArg.type === 'ArrowFunctionExpression' || actualArg.type === 'FunctionExpression') {
|
|
139
|
+
argInfo.targetType = 'FUNCTION';
|
|
140
|
+
argInfo.functionLine = actualArg.loc?.start.line;
|
|
141
|
+
argInfo.functionColumn = actualArg.loc?.start.column;
|
|
142
|
+
}
|
|
143
|
+
// Call expression (nested call)
|
|
144
|
+
else if (actualArg.type === 'CallExpression') {
|
|
145
|
+
argInfo.targetType = 'CALL';
|
|
146
|
+
// Nested calls will be processed separately, link by position
|
|
147
|
+
argInfo.nestedCallLine = actualArg.loc?.start.line;
|
|
148
|
+
argInfo.nestedCallColumn = actualArg.loc?.start.column;
|
|
149
|
+
}
|
|
150
|
+
// Member expression: obj.prop or obj[x]
|
|
151
|
+
else if (actualArg.type === 'MemberExpression') {
|
|
152
|
+
const memberExpr = actualArg;
|
|
153
|
+
argInfo.targetType = 'EXPRESSION';
|
|
154
|
+
argInfo.expressionType = 'MemberExpression';
|
|
155
|
+
if (memberExpr.object.type === 'Identifier') {
|
|
156
|
+
argInfo.objectName = memberExpr.object.name;
|
|
157
|
+
}
|
|
158
|
+
if (!memberExpr.computed && memberExpr.property.type === 'Identifier') {
|
|
159
|
+
argInfo.propertyName = memberExpr.property.name;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Binary/Logical expression: a + b, a && b
|
|
163
|
+
else if (actualArg.type === 'BinaryExpression' || actualArg.type === 'LogicalExpression') {
|
|
164
|
+
const expr = actualArg;
|
|
165
|
+
const operator = expr.operator || '?';
|
|
166
|
+
const counter = literalCounterRef.value++;
|
|
167
|
+
// Create EXPRESSION node via NodeFactory
|
|
168
|
+
const expressionNode = NodeFactory.createArgumentExpression(actualArg.type, module.file, argInfo.line, argInfo.column, {
|
|
169
|
+
parentCallId: callId,
|
|
170
|
+
argIndex: index,
|
|
171
|
+
operator,
|
|
172
|
+
counter
|
|
173
|
+
});
|
|
174
|
+
literals.push(expressionNode);
|
|
175
|
+
argInfo.targetType = 'EXPRESSION';
|
|
176
|
+
argInfo.targetId = expressionNode.id;
|
|
177
|
+
argInfo.expressionType = actualArg.type;
|
|
178
|
+
// Track DERIVES_FROM edges for identifiers in expression
|
|
179
|
+
const identifiers = this.extractIdentifiers(actualArg);
|
|
180
|
+
const { variableAssignments } = this.collections;
|
|
181
|
+
if (variableAssignments) {
|
|
182
|
+
for (const identName of identifiers) {
|
|
183
|
+
variableAssignments.push({
|
|
184
|
+
variableId: expressionNode.id,
|
|
185
|
+
sourceId: null,
|
|
186
|
+
sourceName: identName,
|
|
187
|
+
sourceType: 'DERIVES_FROM_VARIABLE',
|
|
188
|
+
file: module.file
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Other expression types (fallback for unhandled expression types)
|
|
194
|
+
else {
|
|
195
|
+
argInfo.targetType = 'EXPRESSION';
|
|
196
|
+
argInfo.expressionType = actualArg.type;
|
|
197
|
+
}
|
|
132
198
|
}
|
|
133
199
|
callArguments.push(argInfo);
|
|
134
200
|
});
|
|
@@ -186,28 +252,446 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
186
252
|
return Array.from(identifiers);
|
|
187
253
|
}
|
|
188
254
|
/**
|
|
189
|
-
*
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
255
|
+
* Extract object properties and create ObjectPropertyInfo records
|
|
256
|
+
*/
|
|
257
|
+
extractObjectProperties(objectExpr, objectId, module, objectProperties, objectLiterals, objectLiteralCounterRef, literals, literalCounterRef) {
|
|
258
|
+
for (const prop of objectExpr.properties) {
|
|
259
|
+
const propLine = prop.loc?.start.line || 0;
|
|
260
|
+
const propColumn = prop.loc?.start.column || 0;
|
|
261
|
+
// Handle spread properties: { ...other }
|
|
262
|
+
if (prop.type === 'SpreadElement') {
|
|
263
|
+
const spreadArg = prop.argument;
|
|
264
|
+
const propertyInfo = {
|
|
265
|
+
objectId,
|
|
266
|
+
propertyName: '<spread>',
|
|
267
|
+
valueType: 'SPREAD',
|
|
268
|
+
file: module.file,
|
|
269
|
+
line: propLine,
|
|
270
|
+
column: propColumn
|
|
271
|
+
};
|
|
272
|
+
if (spreadArg.type === 'Identifier') {
|
|
273
|
+
propertyInfo.valueName = spreadArg.name;
|
|
274
|
+
propertyInfo.valueType = 'VARIABLE';
|
|
275
|
+
// REG-329: Capture scope path for spread variable resolution
|
|
276
|
+
propertyInfo.valueScopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
277
|
+
}
|
|
278
|
+
objectProperties.push(propertyInfo);
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
// Handle regular properties
|
|
282
|
+
if (prop.type === 'ObjectProperty') {
|
|
283
|
+
const objProp = prop;
|
|
284
|
+
let propertyName;
|
|
285
|
+
// Get property name
|
|
286
|
+
if (objProp.key.type === 'Identifier') {
|
|
287
|
+
propertyName = objProp.key.name;
|
|
288
|
+
}
|
|
289
|
+
else if (objProp.key.type === 'StringLiteral') {
|
|
290
|
+
propertyName = objProp.key.value;
|
|
291
|
+
}
|
|
292
|
+
else if (objProp.key.type === 'NumericLiteral') {
|
|
293
|
+
propertyName = String(objProp.key.value);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
propertyName = '<computed>';
|
|
297
|
+
}
|
|
298
|
+
const propertyInfo = {
|
|
299
|
+
objectId,
|
|
300
|
+
propertyName,
|
|
301
|
+
file: module.file,
|
|
302
|
+
line: propLine,
|
|
303
|
+
column: propColumn,
|
|
304
|
+
valueType: 'EXPRESSION'
|
|
305
|
+
};
|
|
306
|
+
const value = objProp.value;
|
|
307
|
+
// Nested object literal - check BEFORE extractLiteralValue
|
|
308
|
+
if (value.type === 'ObjectExpression') {
|
|
309
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'obj' suffix)
|
|
310
|
+
const nestedObjectNode = ObjectLiteralNode.create(module.file, value.loc?.start.line || 0, value.loc?.start.column || 0, {
|
|
311
|
+
counter: objectLiteralCounterRef.value++
|
|
312
|
+
});
|
|
313
|
+
objectLiterals.push(nestedObjectNode);
|
|
314
|
+
const nestedObjectId = nestedObjectNode.id;
|
|
315
|
+
// Recursively extract nested properties
|
|
316
|
+
this.extractObjectProperties(value, nestedObjectId, module, objectProperties, objectLiterals, objectLiteralCounterRef, literals, literalCounterRef);
|
|
317
|
+
propertyInfo.valueType = 'OBJECT_LITERAL';
|
|
318
|
+
propertyInfo.nestedObjectId = nestedObjectId;
|
|
319
|
+
propertyInfo.valueNodeId = nestedObjectId;
|
|
320
|
+
}
|
|
321
|
+
// Nested array literal - check BEFORE extractLiteralValue
|
|
322
|
+
else if (value.type === 'ArrayExpression') {
|
|
323
|
+
const arrayLiteralCounterRef = (this.collections.arrayLiteralCounterRef ?? { value: 0 });
|
|
324
|
+
const arrayLiterals = this.collections.arrayLiterals ?? [];
|
|
325
|
+
const arrayElements = this.collections.arrayElements ?? [];
|
|
326
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'arr' suffix)
|
|
327
|
+
const nestedArrayNode = ArrayLiteralNode.create(module.file, value.loc?.start.line || 0, value.loc?.start.column || 0, {
|
|
328
|
+
counter: arrayLiteralCounterRef.value++
|
|
329
|
+
});
|
|
330
|
+
arrayLiterals.push(nestedArrayNode);
|
|
331
|
+
const nestedArrayId = nestedArrayNode.id;
|
|
332
|
+
// Recursively extract array elements
|
|
333
|
+
this.extractArrayElements(value, nestedArrayId, module, arrayElements, arrayLiterals, arrayLiteralCounterRef, objectLiterals, objectLiteralCounterRef, objectProperties, literals, literalCounterRef);
|
|
334
|
+
propertyInfo.valueType = 'ARRAY_LITERAL';
|
|
335
|
+
propertyInfo.nestedArrayId = nestedArrayId;
|
|
336
|
+
propertyInfo.valueNodeId = nestedArrayId;
|
|
337
|
+
}
|
|
338
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
339
|
+
else {
|
|
340
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(value);
|
|
341
|
+
// Handle both non-null literals AND explicit null literals (NullLiteral)
|
|
342
|
+
if (literalValue !== null || value.type === 'NullLiteral') {
|
|
343
|
+
const literalId = `LITERAL#${propertyName}#${module.file}#${propLine}:${propColumn}:${literalCounterRef.value++}`;
|
|
344
|
+
literals.push({
|
|
345
|
+
id: literalId,
|
|
346
|
+
type: 'LITERAL',
|
|
347
|
+
value: literalValue,
|
|
348
|
+
valueType: typeof literalValue,
|
|
349
|
+
file: module.file,
|
|
350
|
+
line: propLine,
|
|
351
|
+
column: propColumn,
|
|
352
|
+
parentCallId: objectId,
|
|
353
|
+
argIndex: 0
|
|
354
|
+
});
|
|
355
|
+
propertyInfo.valueType = 'LITERAL';
|
|
356
|
+
propertyInfo.valueNodeId = literalId;
|
|
357
|
+
propertyInfo.literalValue = literalValue;
|
|
358
|
+
}
|
|
359
|
+
// Variable reference
|
|
360
|
+
else if (value.type === 'Identifier') {
|
|
361
|
+
propertyInfo.valueType = 'VARIABLE';
|
|
362
|
+
propertyInfo.valueName = value.name;
|
|
363
|
+
// REG-329: Capture scope path for scope-aware variable resolution
|
|
364
|
+
propertyInfo.valueScopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
365
|
+
}
|
|
366
|
+
// Call expression
|
|
367
|
+
else if (value.type === 'CallExpression') {
|
|
368
|
+
propertyInfo.valueType = 'CALL';
|
|
369
|
+
propertyInfo.callLine = value.loc?.start.line;
|
|
370
|
+
propertyInfo.callColumn = value.loc?.start.column;
|
|
371
|
+
}
|
|
372
|
+
// Other expressions
|
|
373
|
+
else {
|
|
374
|
+
propertyInfo.valueType = 'EXPRESSION';
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
objectProperties.push(propertyInfo);
|
|
378
|
+
}
|
|
379
|
+
// Handle object methods: { foo() {} }
|
|
380
|
+
else if (prop.type === 'ObjectMethod') {
|
|
381
|
+
const propertyName = prop.key.type === 'Identifier' ? prop.key.name : '<computed>';
|
|
382
|
+
objectProperties.push({
|
|
383
|
+
objectId,
|
|
384
|
+
propertyName,
|
|
385
|
+
valueType: 'EXPRESSION',
|
|
386
|
+
file: module.file,
|
|
387
|
+
line: propLine,
|
|
388
|
+
column: propColumn
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Extract array elements and create ArrayElementInfo records
|
|
395
|
+
*/
|
|
396
|
+
extractArrayElements(arrayExpr, arrayId, module, arrayElements, arrayLiterals, arrayLiteralCounterRef, objectLiterals, objectLiteralCounterRef, objectProperties, literals, literalCounterRef) {
|
|
397
|
+
arrayExpr.elements.forEach((element, index) => {
|
|
398
|
+
if (!element)
|
|
399
|
+
return; // Skip holes in arrays
|
|
400
|
+
const elemLine = element.loc?.start.line || 0;
|
|
401
|
+
const elemColumn = element.loc?.start.column || 0;
|
|
402
|
+
const elementInfo = {
|
|
403
|
+
arrayId,
|
|
404
|
+
index,
|
|
405
|
+
file: module.file,
|
|
406
|
+
line: elemLine,
|
|
407
|
+
column: elemColumn,
|
|
408
|
+
valueType: 'EXPRESSION'
|
|
409
|
+
};
|
|
410
|
+
// Handle spread elements: [...arr]
|
|
411
|
+
if (element.type === 'SpreadElement') {
|
|
412
|
+
const spreadArg = element.argument;
|
|
413
|
+
elementInfo.valueType = 'SPREAD';
|
|
414
|
+
if (spreadArg.type === 'Identifier') {
|
|
415
|
+
elementInfo.valueName = spreadArg.name;
|
|
416
|
+
}
|
|
417
|
+
arrayElements.push(elementInfo);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
// Nested object literal - check BEFORE extractLiteralValue
|
|
421
|
+
if (element.type === 'ObjectExpression') {
|
|
422
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'obj' suffix)
|
|
423
|
+
const nestedObjectNode = ObjectLiteralNode.create(module.file, elemLine, elemColumn, {
|
|
424
|
+
counter: objectLiteralCounterRef.value++
|
|
425
|
+
});
|
|
426
|
+
objectLiterals.push(nestedObjectNode);
|
|
427
|
+
const nestedObjectId = nestedObjectNode.id;
|
|
428
|
+
// Recursively extract properties
|
|
429
|
+
this.extractObjectProperties(element, nestedObjectId, module, objectProperties, objectLiterals, objectLiteralCounterRef, literals, literalCounterRef);
|
|
430
|
+
elementInfo.valueType = 'OBJECT_LITERAL';
|
|
431
|
+
elementInfo.nestedObjectId = nestedObjectId;
|
|
432
|
+
elementInfo.valueNodeId = nestedObjectId;
|
|
433
|
+
}
|
|
434
|
+
// Nested array literal - check BEFORE extractLiteralValue
|
|
435
|
+
else if (element.type === 'ArrayExpression') {
|
|
436
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'arr' suffix)
|
|
437
|
+
const nestedArrayNode = ArrayLiteralNode.create(module.file, elemLine, elemColumn, {
|
|
438
|
+
counter: arrayLiteralCounterRef.value++
|
|
439
|
+
});
|
|
440
|
+
arrayLiterals.push(nestedArrayNode);
|
|
441
|
+
const nestedArrayId = nestedArrayNode.id;
|
|
442
|
+
// Recursively extract elements
|
|
443
|
+
this.extractArrayElements(element, nestedArrayId, module, arrayElements, arrayLiterals, arrayLiteralCounterRef, objectLiterals, objectLiteralCounterRef, objectProperties, literals, literalCounterRef);
|
|
444
|
+
elementInfo.valueType = 'ARRAY_LITERAL';
|
|
445
|
+
elementInfo.nestedArrayId = nestedArrayId;
|
|
446
|
+
elementInfo.valueNodeId = nestedArrayId;
|
|
447
|
+
}
|
|
448
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
449
|
+
else {
|
|
450
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(element);
|
|
451
|
+
if (literalValue !== null) {
|
|
452
|
+
const literalId = `LITERAL#elem${index}#${module.file}#${elemLine}:${elemColumn}:${literalCounterRef.value++}`;
|
|
453
|
+
literals.push({
|
|
454
|
+
id: literalId,
|
|
455
|
+
type: 'LITERAL',
|
|
456
|
+
value: literalValue,
|
|
457
|
+
valueType: typeof literalValue,
|
|
458
|
+
file: module.file,
|
|
459
|
+
line: elemLine,
|
|
460
|
+
column: elemColumn,
|
|
461
|
+
parentCallId: arrayId,
|
|
462
|
+
argIndex: index
|
|
463
|
+
});
|
|
464
|
+
elementInfo.valueType = 'LITERAL';
|
|
465
|
+
elementInfo.valueNodeId = literalId;
|
|
466
|
+
elementInfo.literalValue = literalValue;
|
|
467
|
+
}
|
|
468
|
+
// Variable reference
|
|
469
|
+
else if (element.type === 'Identifier') {
|
|
470
|
+
elementInfo.valueType = 'VARIABLE';
|
|
471
|
+
elementInfo.valueName = element.name;
|
|
472
|
+
}
|
|
473
|
+
// Call expression
|
|
474
|
+
else if (element.type === 'CallExpression') {
|
|
475
|
+
elementInfo.valueType = 'CALL';
|
|
476
|
+
elementInfo.callLine = element.loc?.start.line;
|
|
477
|
+
elementInfo.callColumn = element.loc?.start.column;
|
|
478
|
+
}
|
|
479
|
+
// Other expressions
|
|
480
|
+
else {
|
|
481
|
+
elementInfo.valueType = 'EXPRESSION';
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
arrayElements.push(elementInfo);
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Detect array mutation calls (push, unshift, splice) and collect mutation info
|
|
489
|
+
* for later FLOWS_INTO edge creation in GraphBuilder
|
|
490
|
+
*
|
|
491
|
+
* REG-117: Added isNested, baseObjectName, propertyName for nested mutations
|
|
492
|
+
*/
|
|
493
|
+
detectArrayMutation(callNode, arrayName, method, module, isNested, baseObjectName, propertyName) {
|
|
494
|
+
// Initialize collection if not exists
|
|
495
|
+
if (!this.collections.arrayMutations) {
|
|
496
|
+
this.collections.arrayMutations = [];
|
|
497
|
+
}
|
|
498
|
+
const arrayMutations = this.collections.arrayMutations;
|
|
499
|
+
const mutationArgs = [];
|
|
500
|
+
// For splice, only arguments from index 2 onwards are insertions
|
|
501
|
+
// splice(start, deleteCount, item1, item2, ...)
|
|
502
|
+
callNode.arguments.forEach((arg, index) => {
|
|
503
|
+
// Skip start and deleteCount for splice
|
|
504
|
+
if (method === 'splice' && index < 2)
|
|
505
|
+
return;
|
|
506
|
+
const argInfo = {
|
|
507
|
+
argIndex: method === 'splice' ? index - 2 : index,
|
|
508
|
+
isSpread: arg.type === 'SpreadElement',
|
|
509
|
+
valueType: 'EXPRESSION' // Default
|
|
510
|
+
};
|
|
511
|
+
let actualArg = arg;
|
|
512
|
+
if (arg.type === 'SpreadElement') {
|
|
513
|
+
actualArg = arg.argument;
|
|
514
|
+
}
|
|
515
|
+
// Determine value type
|
|
516
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(actualArg);
|
|
517
|
+
if (literalValue !== null) {
|
|
518
|
+
argInfo.valueType = 'LITERAL';
|
|
519
|
+
argInfo.literalValue = literalValue;
|
|
520
|
+
}
|
|
521
|
+
else if (actualArg.type === 'Identifier') {
|
|
522
|
+
argInfo.valueType = 'VARIABLE';
|
|
523
|
+
argInfo.valueName = actualArg.name;
|
|
524
|
+
}
|
|
525
|
+
else if (actualArg.type === 'ObjectExpression') {
|
|
526
|
+
argInfo.valueType = 'OBJECT_LITERAL';
|
|
527
|
+
}
|
|
528
|
+
else if (actualArg.type === 'ArrayExpression') {
|
|
529
|
+
argInfo.valueType = 'ARRAY_LITERAL';
|
|
530
|
+
}
|
|
531
|
+
else if (actualArg.type === 'CallExpression') {
|
|
532
|
+
argInfo.valueType = 'CALL';
|
|
533
|
+
argInfo.callLine = actualArg.loc?.start.line;
|
|
534
|
+
argInfo.callColumn = actualArg.loc?.start.column;
|
|
535
|
+
}
|
|
536
|
+
mutationArgs.push(argInfo);
|
|
537
|
+
});
|
|
538
|
+
// Only record if there are actual insertions
|
|
539
|
+
if (mutationArgs.length > 0) {
|
|
540
|
+
const line = callNode.loc?.start.line ?? 0;
|
|
541
|
+
const column = callNode.loc?.start.column ?? 0;
|
|
542
|
+
// Generate semantic ID for array mutation if scopeTracker available
|
|
543
|
+
const scopeTracker = this.scopeTracker;
|
|
544
|
+
let mutationId;
|
|
545
|
+
// Capture scope path for scope-aware lookup (REG-309)
|
|
546
|
+
const scopePath = scopeTracker?.getContext().scopePath ?? [];
|
|
547
|
+
if (scopeTracker) {
|
|
548
|
+
const discriminator = scopeTracker.getItemCounter(`ARRAY_MUTATION:${arrayName}.${method}`);
|
|
549
|
+
mutationId = computeSemanticId('ARRAY_MUTATION', `${arrayName}.${method}`, scopeTracker.getContext(), { discriminator });
|
|
550
|
+
}
|
|
551
|
+
arrayMutations.push({
|
|
552
|
+
id: mutationId,
|
|
553
|
+
arrayName,
|
|
554
|
+
mutationScopePath: scopePath,
|
|
555
|
+
mutationMethod: method,
|
|
556
|
+
file: module.file,
|
|
557
|
+
line,
|
|
558
|
+
column,
|
|
559
|
+
insertedValues: mutationArgs,
|
|
560
|
+
// REG-117: Nested mutation fields
|
|
561
|
+
isNested,
|
|
562
|
+
baseObjectName,
|
|
563
|
+
propertyName
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Detect Object.assign(target, source1, source2, ...) calls
|
|
569
|
+
* Creates ObjectMutationInfo for FLOWS_INTO edge generation in GraphBuilder
|
|
570
|
+
*
|
|
571
|
+
* @param callNode - The call expression node
|
|
572
|
+
* @param module - Current module being analyzed
|
|
573
|
+
*/
|
|
574
|
+
detectObjectAssign(callNode, module) {
|
|
575
|
+
// Need at least 2 arguments: target and at least one source
|
|
576
|
+
if (callNode.arguments.length < 2)
|
|
577
|
+
return;
|
|
578
|
+
// Initialize object mutations collection if not exists
|
|
579
|
+
if (!this.collections.objectMutations) {
|
|
580
|
+
this.collections.objectMutations = [];
|
|
581
|
+
}
|
|
582
|
+
const objectMutations = this.collections.objectMutations;
|
|
583
|
+
// First argument is target
|
|
584
|
+
const targetArg = callNode.arguments[0];
|
|
585
|
+
let targetName;
|
|
586
|
+
if (targetArg.type === 'Identifier') {
|
|
587
|
+
targetName = targetArg.name;
|
|
588
|
+
}
|
|
589
|
+
else if (targetArg.type === 'ObjectExpression') {
|
|
590
|
+
targetName = '<anonymous>';
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const line = callNode.loc?.start.line ?? 0;
|
|
596
|
+
const column = callNode.loc?.start.column ?? 0;
|
|
597
|
+
for (let i = 1; i < callNode.arguments.length; i++) {
|
|
598
|
+
let arg = callNode.arguments[i];
|
|
599
|
+
let isSpread = false;
|
|
600
|
+
if (arg.type === 'SpreadElement') {
|
|
601
|
+
isSpread = true;
|
|
602
|
+
arg = arg.argument;
|
|
603
|
+
}
|
|
604
|
+
const valueInfo = {
|
|
605
|
+
valueType: 'EXPRESSION',
|
|
606
|
+
argIndex: i - 1,
|
|
607
|
+
isSpread
|
|
608
|
+
};
|
|
609
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(arg);
|
|
610
|
+
if (literalValue !== null) {
|
|
611
|
+
valueInfo.valueType = 'LITERAL';
|
|
612
|
+
valueInfo.literalValue = literalValue;
|
|
613
|
+
}
|
|
614
|
+
else if (arg.type === 'Identifier') {
|
|
615
|
+
valueInfo.valueType = 'VARIABLE';
|
|
616
|
+
valueInfo.valueName = arg.name;
|
|
617
|
+
}
|
|
618
|
+
else if (arg.type === 'ObjectExpression') {
|
|
619
|
+
valueInfo.valueType = 'OBJECT_LITERAL';
|
|
620
|
+
}
|
|
621
|
+
else if (arg.type === 'ArrayExpression') {
|
|
622
|
+
valueInfo.valueType = 'ARRAY_LITERAL';
|
|
623
|
+
}
|
|
624
|
+
else if (arg.type === 'CallExpression') {
|
|
625
|
+
valueInfo.valueType = 'CALL';
|
|
626
|
+
valueInfo.callLine = arg.loc?.start.line;
|
|
627
|
+
valueInfo.callColumn = arg.loc?.start.column;
|
|
628
|
+
}
|
|
629
|
+
// Capture scope path for scope-aware lookup (REG-309)
|
|
630
|
+
const scopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
631
|
+
let mutationId;
|
|
632
|
+
if (this.scopeTracker) {
|
|
633
|
+
const discriminator = this.scopeTracker.getItemCounter(`OBJECT_MUTATION:Object.assign:${targetName}`);
|
|
634
|
+
mutationId = computeSemanticId('OBJECT_MUTATION', `Object.assign:${targetName}`, this.scopeTracker.getContext(), { discriminator });
|
|
635
|
+
}
|
|
636
|
+
objectMutations.push({
|
|
637
|
+
id: mutationId,
|
|
638
|
+
objectName: targetName,
|
|
639
|
+
mutationScopePath: scopePath,
|
|
640
|
+
propertyName: '<assign>',
|
|
641
|
+
mutationType: 'assign',
|
|
642
|
+
file: module.file,
|
|
643
|
+
line,
|
|
644
|
+
column,
|
|
645
|
+
value: valueInfo
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Get a stable scope ID for a function parent.
|
|
651
|
+
*
|
|
652
|
+
* Format must match what FunctionVisitor/ClassVisitor creates (semantic ID):
|
|
653
|
+
* - Module-level function: {file}->global->FUNCTION->{name}
|
|
654
|
+
* - Class method: {file}->{className}->FUNCTION->{methodName}
|
|
193
655
|
*
|
|
194
|
-
*
|
|
195
|
-
* we try to match by name+file+line:col. This may not always work for
|
|
196
|
-
* multiple arrow functions on the same line.
|
|
656
|
+
* Reconstructs scope path by walking up the AST.
|
|
197
657
|
*/
|
|
198
658
|
getFunctionScopeId(functionParent, module) {
|
|
199
659
|
const funcNode = functionParent.node;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// FunctionDeclaration with name
|
|
660
|
+
// Get function name
|
|
661
|
+
let funcName;
|
|
203
662
|
if (funcNode.type === 'FunctionDeclaration' && funcNode.id?.name) {
|
|
204
|
-
|
|
663
|
+
funcName = funcNode.id.name;
|
|
664
|
+
}
|
|
665
|
+
else if (funcNode.type === 'ClassMethod' && funcNode.key?.type === 'Identifier') {
|
|
666
|
+
funcName = funcNode.key.name;
|
|
667
|
+
}
|
|
668
|
+
if (!funcName) {
|
|
669
|
+
// Anonymous function - fall back to module scope
|
|
670
|
+
return module.id;
|
|
671
|
+
}
|
|
672
|
+
// Build scope path by walking up the AST
|
|
673
|
+
const scopePath = [];
|
|
674
|
+
let current = functionParent.parentPath;
|
|
675
|
+
while (current) {
|
|
676
|
+
const node = current.node;
|
|
677
|
+
if (node.type === 'ClassDeclaration' && node.id?.name) {
|
|
678
|
+
scopePath.unshift(node.id.name);
|
|
679
|
+
break; // Class is the outermost scope we need
|
|
680
|
+
}
|
|
681
|
+
else if (node.type === 'ClassBody') {
|
|
682
|
+
// Continue up to ClassDeclaration
|
|
683
|
+
}
|
|
684
|
+
else if (node.type === 'Program') {
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
current = current.parentPath;
|
|
688
|
+
}
|
|
689
|
+
// If no class found, it's at module level (global scope)
|
|
690
|
+
if (scopePath.length === 0) {
|
|
691
|
+
scopePath.push('global');
|
|
205
692
|
}
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
// to avoid creating invalid edges. The CALL node will be connected to MODULE
|
|
209
|
-
// instead of the specific function.
|
|
210
|
-
return module.id;
|
|
693
|
+
// Compute semantic ID: {file}->{scopePath}->FUNCTION->{name}
|
|
694
|
+
return `${module.file}->${scopePath.join('->')}->FUNCTION->${funcName}`;
|
|
211
695
|
}
|
|
212
696
|
getHandlers() {
|
|
213
697
|
const { module } = this;
|
|
@@ -220,6 +704,7 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
220
704
|
const callSiteCounterRef = (this.collections.callSiteCounterRef ?? { value: 0 });
|
|
221
705
|
const literalCounterRef = (this.collections.literalCounterRef ?? { value: 0 });
|
|
222
706
|
const processedNodes = this.collections.processedNodes ?? { callSites: new Set(), methodCalls: new Set(), eventListeners: new Set() };
|
|
707
|
+
const scopeTracker = this.scopeTracker;
|
|
223
708
|
return {
|
|
224
709
|
CallExpression: (path) => {
|
|
225
710
|
const callNode = path.node;
|
|
@@ -227,16 +712,24 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
227
712
|
// Determine parent scope - if inside a function, use function's scope, otherwise module
|
|
228
713
|
const parentScopeId = functionParent ? this.getFunctionScopeId(functionParent, module) : module.id;
|
|
229
714
|
// Identifier calls (direct function calls)
|
|
715
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
230
716
|
if (callNode.callee.type === 'Identifier') {
|
|
717
|
+
if (functionParent) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
231
720
|
const callee = callNode.callee;
|
|
232
|
-
const
|
|
721
|
+
const line = getLine(callNode);
|
|
722
|
+
const column = getColumn(callNode);
|
|
723
|
+
// Generate ID using centralized IdGenerator
|
|
724
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
725
|
+
const callId = idGenerator.generate('CALL', callee.name, module.file, line, column, callSiteCounterRef, { useDiscriminator: true, discriminatorKey: `CALL:${callee.name}` });
|
|
233
726
|
callSites.push({
|
|
234
727
|
id: callId,
|
|
235
728
|
type: 'CALL',
|
|
236
729
|
name: callee.name,
|
|
237
730
|
file: module.file,
|
|
238
|
-
line
|
|
239
|
-
column
|
|
731
|
+
line,
|
|
732
|
+
column,
|
|
240
733
|
parentScopeId,
|
|
241
734
|
targetFunctionName: callee.name
|
|
242
735
|
});
|
|
@@ -245,8 +738,12 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
245
738
|
this.extractArguments(callNode.arguments, callId, module, callArguments, literals, literalCounterRef);
|
|
246
739
|
}
|
|
247
740
|
}
|
|
248
|
-
// MemberExpression calls (method calls
|
|
741
|
+
// MemberExpression calls (method calls)
|
|
742
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
249
743
|
else if (callNode.callee.type === 'MemberExpression') {
|
|
744
|
+
if (functionParent) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
250
747
|
const memberCallee = callNode.callee;
|
|
251
748
|
const object = memberCallee.object;
|
|
252
749
|
const property = memberCallee.property;
|
|
@@ -268,13 +765,15 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
268
765
|
return;
|
|
269
766
|
}
|
|
270
767
|
processedNodes.eventListeners.add(nodeKey);
|
|
768
|
+
const eventLine = getLine(callNode);
|
|
769
|
+
const eventColumn = getColumn(callNode);
|
|
271
770
|
eventListeners.push({
|
|
272
|
-
id: `event:listener#${eventName}#${module.file}#${
|
|
771
|
+
id: `event:listener#${eventName}#${module.file}#${eventLine}:${eventColumn}:${callSiteCounterRef.value++}`,
|
|
273
772
|
type: 'event:listener',
|
|
274
773
|
name: eventName,
|
|
275
774
|
object: objectName,
|
|
276
775
|
file: module.file,
|
|
277
|
-
line:
|
|
776
|
+
line: eventLine,
|
|
278
777
|
parentScopeId,
|
|
279
778
|
callbackArg: secondArg
|
|
280
779
|
});
|
|
@@ -288,7 +787,11 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
288
787
|
}
|
|
289
788
|
processedNodes.methodCalls.add(nodeKey);
|
|
290
789
|
const fullName = `${objectName}.${methodName}`;
|
|
291
|
-
const
|
|
790
|
+
const methodLine = getLine(callNode);
|
|
791
|
+
const methodColumn = getColumn(callNode);
|
|
792
|
+
// Generate ID using centralized IdGenerator
|
|
793
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
794
|
+
const methodCallId = idGenerator.generate('CALL', fullName, module.file, methodLine, methodColumn, callSiteCounterRef, { useDiscriminator: true, discriminatorKey: `CALL:${fullName}` });
|
|
292
795
|
methodCalls.push({
|
|
293
796
|
id: methodCallId,
|
|
294
797
|
type: 'CALL',
|
|
@@ -298,10 +801,19 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
298
801
|
computed: isComputed,
|
|
299
802
|
computedPropertyVar, // Variable name used in obj[x]() calls
|
|
300
803
|
file: module.file,
|
|
301
|
-
line:
|
|
302
|
-
column:
|
|
804
|
+
line: methodLine,
|
|
805
|
+
column: methodColumn,
|
|
303
806
|
parentScopeId
|
|
304
807
|
});
|
|
808
|
+
// Check for array mutation methods (push, unshift, splice)
|
|
809
|
+
const ARRAY_MUTATION_METHODS = ['push', 'unshift', 'splice'];
|
|
810
|
+
if (ARRAY_MUTATION_METHODS.includes(methodName)) {
|
|
811
|
+
this.detectArrayMutation(callNode, objectName, methodName, module);
|
|
812
|
+
}
|
|
813
|
+
// Check for Object.assign() calls
|
|
814
|
+
if (objectName === 'Object' && methodName === 'assign') {
|
|
815
|
+
this.detectObjectAssign(callNode, module);
|
|
816
|
+
}
|
|
305
817
|
// Extract arguments for PASSES_ARGUMENT edges
|
|
306
818
|
if (callNode.arguments.length > 0) {
|
|
307
819
|
this.extractArguments(callNode.arguments, methodCallId, module, callArguments, literals, literalCounterRef);
|
|
@@ -310,8 +822,8 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
310
822
|
if (arg.type === 'ArrowFunctionExpression' || arg.type === 'FunctionExpression') {
|
|
311
823
|
methodCallbacks.push({
|
|
312
824
|
methodCallId,
|
|
313
|
-
callbackLine: arg
|
|
314
|
-
callbackColumn: arg
|
|
825
|
+
callbackLine: getLine(arg),
|
|
826
|
+
callbackColumn: getColumn(arg),
|
|
315
827
|
callbackType: arg.type
|
|
316
828
|
});
|
|
317
829
|
}
|
|
@@ -319,13 +831,40 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
319
831
|
}
|
|
320
832
|
}
|
|
321
833
|
}
|
|
834
|
+
// REG-117: Nested array mutations like obj.arr.push(item)
|
|
835
|
+
// object is MemberExpression, property is the method name
|
|
836
|
+
else if (object.type === 'MemberExpression' && property.type === 'Identifier') {
|
|
837
|
+
const nestedMember = object;
|
|
838
|
+
const methodName = property.name;
|
|
839
|
+
const ARRAY_MUTATION_METHODS = ['push', 'unshift', 'splice'];
|
|
840
|
+
if (ARRAY_MUTATION_METHODS.includes(methodName)) {
|
|
841
|
+
// Extract base object and property from nested MemberExpression
|
|
842
|
+
const base = nestedMember.object;
|
|
843
|
+
const prop = nestedMember.property;
|
|
844
|
+
// Only handle single-level nesting: obj.arr.push() or this.items.push()
|
|
845
|
+
if ((base.type === 'Identifier' || base.type === 'ThisExpression') &&
|
|
846
|
+
!nestedMember.computed &&
|
|
847
|
+
prop.type === 'Identifier') {
|
|
848
|
+
const baseObjectName = base.type === 'Identifier' ? base.name : 'this';
|
|
849
|
+
const propertyName = prop.name;
|
|
850
|
+
this.detectArrayMutation(callNode, `${baseObjectName}.${propertyName}`, // arrayName for ID purposes
|
|
851
|
+
methodName, module, true, // isNested
|
|
852
|
+
baseObjectName, propertyName);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
322
856
|
}
|
|
323
857
|
},
|
|
324
858
|
// NewExpression: new Foo(), new Function(), new Map(), etc.
|
|
859
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
325
860
|
NewExpression: (path) => {
|
|
326
861
|
const newNode = path.node;
|
|
327
862
|
const functionParent = path.getFunctionParent();
|
|
328
|
-
|
|
863
|
+
// Skip if inside function - handled by analyzeFunctionBody
|
|
864
|
+
if (functionParent) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const parentScopeId = module.id;
|
|
329
868
|
// Dedup check
|
|
330
869
|
const nodeKey = `new:${newNode.start}:${newNode.end}`;
|
|
331
870
|
if (processedNodes.methodCalls.has(nodeKey)) {
|
|
@@ -336,13 +875,18 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
336
875
|
if (newNode.callee.type === 'Identifier') {
|
|
337
876
|
const callee = newNode.callee;
|
|
338
877
|
const constructorName = callee.name;
|
|
878
|
+
const newLine = getLine(newNode);
|
|
879
|
+
const newColumn = getColumn(newNode);
|
|
880
|
+
// Generate ID using centralized IdGenerator
|
|
881
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
882
|
+
const newCallId = idGenerator.generate('CALL', `new:${constructorName}`, module.file, newLine, newColumn, callSiteCounterRef, { useDiscriminator: true, discriminatorKey: `CALL:new:${constructorName}` });
|
|
339
883
|
callSites.push({
|
|
340
|
-
id:
|
|
884
|
+
id: newCallId,
|
|
341
885
|
type: 'CALL',
|
|
342
886
|
name: constructorName,
|
|
343
887
|
file: module.file,
|
|
344
|
-
line:
|
|
345
|
-
column:
|
|
888
|
+
line: newLine,
|
|
889
|
+
column: newColumn,
|
|
346
890
|
parentScopeId,
|
|
347
891
|
targetFunctionName: constructorName,
|
|
348
892
|
isNew: true // Mark as constructor call
|
|
@@ -357,15 +901,20 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
357
901
|
const objectName = object.name;
|
|
358
902
|
const constructorName = property.name;
|
|
359
903
|
const fullName = `${objectName}.${constructorName}`;
|
|
904
|
+
const memberNewLine = getLine(newNode);
|
|
905
|
+
const memberNewColumn = getColumn(newNode);
|
|
906
|
+
// Generate ID using centralized IdGenerator
|
|
907
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
908
|
+
const newMethodCallId = idGenerator.generate('CALL', `new:${fullName}`, module.file, memberNewLine, memberNewColumn, callSiteCounterRef, { useDiscriminator: true, discriminatorKey: `CALL:new:${fullName}` });
|
|
360
909
|
methodCalls.push({
|
|
361
|
-
id:
|
|
910
|
+
id: newMethodCallId,
|
|
362
911
|
type: 'CALL',
|
|
363
912
|
name: fullName,
|
|
364
913
|
object: objectName,
|
|
365
914
|
method: constructorName,
|
|
366
915
|
file: module.file,
|
|
367
|
-
line:
|
|
368
|
-
column:
|
|
916
|
+
line: memberNewLine,
|
|
917
|
+
column: memberNewColumn,
|
|
369
918
|
parentScopeId,
|
|
370
919
|
isNew: true // Mark as constructor call
|
|
371
920
|
});
|