@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
|
@@ -8,10 +8,85 @@
|
|
|
8
8
|
* - Constructor calls: new Foo(), new Function()
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { Node, CallExpression, NewExpression, Identifier, MemberExpression } from '@babel/types';
|
|
11
|
+
import type { Node, CallExpression, NewExpression, Identifier, MemberExpression, ObjectExpression, ArrayExpression, ObjectProperty, SpreadElement } from '@babel/types';
|
|
12
12
|
import type { NodePath } from '@babel/traverse';
|
|
13
13
|
import { ASTVisitor, type VisitorModule, type VisitorCollections, type VisitorHandlers, type CounterRef } from './ASTVisitor.js';
|
|
14
14
|
import { ExpressionEvaluator } from '../ExpressionEvaluator.js';
|
|
15
|
+
import type { ArrayMutationInfo, ArrayMutationArgument, ObjectMutationInfo, ObjectMutationValue } from '../types.js';
|
|
16
|
+
import { ScopeTracker } from '../../../../core/ScopeTracker.js';
|
|
17
|
+
import { computeSemanticId } from '../../../../core/SemanticId.js';
|
|
18
|
+
import { IdGenerator } from '../IdGenerator.js';
|
|
19
|
+
import { NodeFactory } from '../../../../core/NodeFactory.js';
|
|
20
|
+
import { ObjectLiteralNode } from '../../../../core/nodes/ObjectLiteralNode.js';
|
|
21
|
+
import { ArrayLiteralNode } from '../../../../core/nodes/ArrayLiteralNode.js';
|
|
22
|
+
import { getLine, getColumn } from '../utils/location.js';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Object literal info for OBJECT_LITERAL nodes
|
|
26
|
+
*/
|
|
27
|
+
interface ObjectLiteralInfo {
|
|
28
|
+
id: string;
|
|
29
|
+
type: 'OBJECT_LITERAL';
|
|
30
|
+
file: string;
|
|
31
|
+
line: number;
|
|
32
|
+
column: number;
|
|
33
|
+
parentCallId?: string;
|
|
34
|
+
argIndex?: number;
|
|
35
|
+
isSpread?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Object property info for HAS_PROPERTY edges
|
|
40
|
+
*/
|
|
41
|
+
interface ObjectPropertyInfo {
|
|
42
|
+
objectId: string;
|
|
43
|
+
propertyName: string;
|
|
44
|
+
valueNodeId?: string;
|
|
45
|
+
valueType: 'LITERAL' | 'VARIABLE' | 'CALL' | 'EXPRESSION' | 'OBJECT_LITERAL' | 'ARRAY_LITERAL' | 'SPREAD';
|
|
46
|
+
valueName?: string;
|
|
47
|
+
literalValue?: unknown;
|
|
48
|
+
file: string;
|
|
49
|
+
line: number;
|
|
50
|
+
column: number;
|
|
51
|
+
callLine?: number;
|
|
52
|
+
callColumn?: number;
|
|
53
|
+
nestedObjectId?: string;
|
|
54
|
+
nestedArrayId?: string;
|
|
55
|
+
// REG-329: Scope path for variable resolution
|
|
56
|
+
valueScopePath?: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Array literal info for ARRAY_LITERAL nodes
|
|
61
|
+
*/
|
|
62
|
+
interface ArrayLiteralInfo {
|
|
63
|
+
id: string;
|
|
64
|
+
type: 'ARRAY_LITERAL';
|
|
65
|
+
file: string;
|
|
66
|
+
line: number;
|
|
67
|
+
column: number;
|
|
68
|
+
parentCallId?: string;
|
|
69
|
+
argIndex?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Array element info for HAS_ELEMENT edges
|
|
74
|
+
*/
|
|
75
|
+
interface ArrayElementInfo {
|
|
76
|
+
arrayId: string;
|
|
77
|
+
index: number;
|
|
78
|
+
valueNodeId?: string;
|
|
79
|
+
valueType: 'LITERAL' | 'VARIABLE' | 'CALL' | 'EXPRESSION' | 'OBJECT_LITERAL' | 'ARRAY_LITERAL' | 'SPREAD';
|
|
80
|
+
valueName?: string;
|
|
81
|
+
literalValue?: unknown;
|
|
82
|
+
file: string;
|
|
83
|
+
line: number;
|
|
84
|
+
column: number;
|
|
85
|
+
callLine?: number;
|
|
86
|
+
callColumn?: number;
|
|
87
|
+
nestedObjectId?: string;
|
|
88
|
+
nestedArrayId?: string;
|
|
89
|
+
}
|
|
15
90
|
|
|
16
91
|
/**
|
|
17
92
|
* Argument info for PASSES_ARGUMENT edges
|
|
@@ -112,8 +187,16 @@ interface LiteralInfo {
|
|
|
112
187
|
}
|
|
113
188
|
|
|
114
189
|
export class CallExpressionVisitor extends ASTVisitor {
|
|
115
|
-
|
|
190
|
+
private scopeTracker?: ScopeTracker;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @param module - Current module being analyzed
|
|
194
|
+
* @param collections - Must contain arrays and counter refs
|
|
195
|
+
* @param scopeTracker - Optional ScopeTracker for semantic ID generation
|
|
196
|
+
*/
|
|
197
|
+
constructor(module: VisitorModule, collections: VisitorCollections, scopeTracker?: ScopeTracker) {
|
|
116
198
|
super(module, collections);
|
|
199
|
+
this.scopeTracker = scopeTracker;
|
|
117
200
|
}
|
|
118
201
|
|
|
119
202
|
/**
|
|
@@ -143,27 +226,130 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
143
226
|
actualArg = arg.argument; // Get the actual argument
|
|
144
227
|
}
|
|
145
228
|
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
229
|
+
// Object literal - check BEFORE extractLiteralValue to handle object-typed args properly
|
|
230
|
+
if (actualArg.type === 'ObjectExpression') {
|
|
231
|
+
const objectExpr = actualArg as ObjectExpression;
|
|
232
|
+
// Initialize collections if not exist (must assign back to this.collections!)
|
|
233
|
+
if (!this.collections.objectLiteralCounterRef) {
|
|
234
|
+
this.collections.objectLiteralCounterRef = { value: 0 };
|
|
235
|
+
}
|
|
236
|
+
if (!this.collections.objectLiterals) {
|
|
237
|
+
this.collections.objectLiterals = [];
|
|
238
|
+
}
|
|
239
|
+
if (!this.collections.objectProperties) {
|
|
240
|
+
this.collections.objectProperties = [];
|
|
241
|
+
}
|
|
242
|
+
const objectLiteralCounterRef = this.collections.objectLiteralCounterRef as CounterRef;
|
|
243
|
+
|
|
244
|
+
// Use factory to create OBJECT_LITERAL node
|
|
245
|
+
const objectNode = ObjectLiteralNode.create(
|
|
246
|
+
module.file,
|
|
247
|
+
argInfo.line,
|
|
248
|
+
argInfo.column,
|
|
249
|
+
{
|
|
250
|
+
parentCallId: callId,
|
|
251
|
+
argIndex: index,
|
|
252
|
+
counter: objectLiteralCounterRef.value++
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
// Factory guarantees line is set, cast to ObjectLiteralInfo
|
|
256
|
+
(this.collections.objectLiterals as ObjectLiteralInfo[]).push(objectNode as unknown as ObjectLiteralInfo);
|
|
257
|
+
const objectId = objectNode.id;
|
|
258
|
+
|
|
259
|
+
// Extract properties
|
|
260
|
+
this.extractObjectProperties(
|
|
261
|
+
objectExpr,
|
|
262
|
+
objectId,
|
|
263
|
+
module,
|
|
264
|
+
this.collections.objectProperties as ObjectPropertyInfo[],
|
|
265
|
+
this.collections.objectLiterals as ObjectLiteralInfo[],
|
|
266
|
+
objectLiteralCounterRef,
|
|
267
|
+
literals as LiteralInfo[],
|
|
268
|
+
literalCounterRef
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
argInfo.targetType = 'OBJECT_LITERAL';
|
|
272
|
+
argInfo.targetId = objectId;
|
|
164
273
|
}
|
|
165
|
-
//
|
|
166
|
-
else if (actualArg.type === '
|
|
274
|
+
// Array literal - check BEFORE extractLiteralValue to handle array-typed args properly
|
|
275
|
+
else if (actualArg.type === 'ArrayExpression') {
|
|
276
|
+
const arrayExpr = actualArg as ArrayExpression;
|
|
277
|
+
// Initialize collections if not exist (must assign back to this.collections!)
|
|
278
|
+
if (!this.collections.arrayLiteralCounterRef) {
|
|
279
|
+
this.collections.arrayLiteralCounterRef = { value: 0 };
|
|
280
|
+
}
|
|
281
|
+
if (!this.collections.arrayLiterals) {
|
|
282
|
+
this.collections.arrayLiterals = [];
|
|
283
|
+
}
|
|
284
|
+
if (!this.collections.arrayElements) {
|
|
285
|
+
this.collections.arrayElements = [];
|
|
286
|
+
}
|
|
287
|
+
if (!this.collections.objectLiteralCounterRef) {
|
|
288
|
+
this.collections.objectLiteralCounterRef = { value: 0 };
|
|
289
|
+
}
|
|
290
|
+
if (!this.collections.objectLiterals) {
|
|
291
|
+
this.collections.objectLiterals = [];
|
|
292
|
+
}
|
|
293
|
+
if (!this.collections.objectProperties) {
|
|
294
|
+
this.collections.objectProperties = [];
|
|
295
|
+
}
|
|
296
|
+
const arrayLiteralCounterRef = this.collections.arrayLiteralCounterRef as CounterRef;
|
|
297
|
+
|
|
298
|
+
// Use factory to create ARRAY_LITERAL node
|
|
299
|
+
const arrayNode = ArrayLiteralNode.create(
|
|
300
|
+
module.file,
|
|
301
|
+
argInfo.line,
|
|
302
|
+
argInfo.column,
|
|
303
|
+
{
|
|
304
|
+
parentCallId: callId,
|
|
305
|
+
argIndex: index,
|
|
306
|
+
counter: arrayLiteralCounterRef.value++
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
// Factory guarantees line is set, cast to ArrayLiteralInfo
|
|
310
|
+
(this.collections.arrayLiterals as ArrayLiteralInfo[]).push(arrayNode as unknown as ArrayLiteralInfo);
|
|
311
|
+
const arrayId = arrayNode.id;
|
|
312
|
+
|
|
313
|
+
// Extract elements
|
|
314
|
+
this.extractArrayElements(
|
|
315
|
+
arrayExpr,
|
|
316
|
+
arrayId,
|
|
317
|
+
module,
|
|
318
|
+
this.collections.arrayElements as ArrayElementInfo[],
|
|
319
|
+
this.collections.arrayLiterals as ArrayLiteralInfo[],
|
|
320
|
+
arrayLiteralCounterRef,
|
|
321
|
+
this.collections.objectLiterals as ObjectLiteralInfo[],
|
|
322
|
+
this.collections.objectLiteralCounterRef as CounterRef,
|
|
323
|
+
this.collections.objectProperties as ObjectPropertyInfo[],
|
|
324
|
+
literals as LiteralInfo[],
|
|
325
|
+
literalCounterRef
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
argInfo.targetType = 'ARRAY_LITERAL';
|
|
329
|
+
argInfo.targetId = arrayId;
|
|
330
|
+
}
|
|
331
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
332
|
+
else {
|
|
333
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(actualArg);
|
|
334
|
+
if (literalValue !== null) {
|
|
335
|
+
const literalId = `LITERAL#arg${index}#${module.file}#${argInfo.line}:${argInfo.column}:${literalCounterRef.value++}`;
|
|
336
|
+
literals.push({
|
|
337
|
+
id: literalId,
|
|
338
|
+
type: 'LITERAL',
|
|
339
|
+
value: literalValue,
|
|
340
|
+
valueType: typeof literalValue,
|
|
341
|
+
file: module.file,
|
|
342
|
+
line: argInfo.line,
|
|
343
|
+
column: argInfo.column,
|
|
344
|
+
parentCallId: callId,
|
|
345
|
+
argIndex: index
|
|
346
|
+
});
|
|
347
|
+
argInfo.targetType = 'LITERAL';
|
|
348
|
+
argInfo.targetId = literalId;
|
|
349
|
+
argInfo.literalValue = literalValue;
|
|
350
|
+
}
|
|
351
|
+
// Variable reference
|
|
352
|
+
else if (actualArg.type === 'Identifier') {
|
|
167
353
|
argInfo.targetType = 'VARIABLE';
|
|
168
354
|
argInfo.targetName = (actualArg as Identifier).name; // Will be resolved in GraphBuilder
|
|
169
355
|
}
|
|
@@ -196,25 +382,26 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
196
382
|
else if (actualArg.type === 'BinaryExpression' || actualArg.type === 'LogicalExpression') {
|
|
197
383
|
const expr = actualArg as { operator?: string; type: string };
|
|
198
384
|
const operator = expr.operator || '?';
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
385
|
+
const counter = literalCounterRef.value++;
|
|
386
|
+
|
|
387
|
+
// Create EXPRESSION node via NodeFactory
|
|
388
|
+
const expressionNode = NodeFactory.createArgumentExpression(
|
|
389
|
+
actualArg.type,
|
|
390
|
+
module.file,
|
|
391
|
+
argInfo.line,
|
|
392
|
+
argInfo.column,
|
|
393
|
+
{
|
|
394
|
+
parentCallId: callId,
|
|
395
|
+
argIndex: index,
|
|
396
|
+
operator,
|
|
397
|
+
counter
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
literals.push(expressionNode as LiteralInfo);
|
|
215
402
|
|
|
216
403
|
argInfo.targetType = 'EXPRESSION';
|
|
217
|
-
argInfo.targetId =
|
|
404
|
+
argInfo.targetId = expressionNode.id;
|
|
218
405
|
argInfo.expressionType = actualArg.type;
|
|
219
406
|
|
|
220
407
|
// Track DERIVES_FROM edges for identifiers in expression
|
|
@@ -223,7 +410,7 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
223
410
|
if (variableAssignments) {
|
|
224
411
|
for (const identName of identifiers) {
|
|
225
412
|
variableAssignments.push({
|
|
226
|
-
variableId:
|
|
413
|
+
variableId: expressionNode.id,
|
|
227
414
|
sourceId: null,
|
|
228
415
|
sourceName: identName,
|
|
229
416
|
sourceType: 'DERIVES_FROM_VARIABLE',
|
|
@@ -232,19 +419,12 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
232
419
|
}
|
|
233
420
|
}
|
|
234
421
|
}
|
|
235
|
-
//
|
|
236
|
-
else if (actualArg.type === 'ObjectExpression') {
|
|
237
|
-
argInfo.targetType = 'OBJECT_LITERAL';
|
|
238
|
-
}
|
|
239
|
-
// Array literal
|
|
240
|
-
else if (actualArg.type === 'ArrayExpression') {
|
|
241
|
-
argInfo.targetType = 'ARRAY_LITERAL';
|
|
242
|
-
}
|
|
243
|
-
// Other expression types
|
|
422
|
+
// Other expression types (fallback for unhandled expression types)
|
|
244
423
|
else {
|
|
245
424
|
argInfo.targetType = 'EXPRESSION';
|
|
246
425
|
argInfo.expressionType = actualArg.type;
|
|
247
426
|
}
|
|
427
|
+
}
|
|
248
428
|
|
|
249
429
|
callArguments.push(argInfo);
|
|
250
430
|
});
|
|
@@ -298,34 +478,585 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
298
478
|
}
|
|
299
479
|
|
|
300
480
|
/**
|
|
301
|
-
*
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
481
|
+
* Extract object properties and create ObjectPropertyInfo records
|
|
482
|
+
*/
|
|
483
|
+
extractObjectProperties(
|
|
484
|
+
objectExpr: ObjectExpression,
|
|
485
|
+
objectId: string,
|
|
486
|
+
module: VisitorModule,
|
|
487
|
+
objectProperties: ObjectPropertyInfo[],
|
|
488
|
+
objectLiterals: ObjectLiteralInfo[],
|
|
489
|
+
objectLiteralCounterRef: CounterRef,
|
|
490
|
+
literals: LiteralInfo[],
|
|
491
|
+
literalCounterRef: CounterRef
|
|
492
|
+
): void {
|
|
493
|
+
for (const prop of objectExpr.properties) {
|
|
494
|
+
const propLine = prop.loc?.start.line || 0;
|
|
495
|
+
const propColumn = prop.loc?.start.column || 0;
|
|
496
|
+
|
|
497
|
+
// Handle spread properties: { ...other }
|
|
498
|
+
if (prop.type === 'SpreadElement') {
|
|
499
|
+
const spreadArg = prop.argument;
|
|
500
|
+
const propertyInfo: ObjectPropertyInfo = {
|
|
501
|
+
objectId,
|
|
502
|
+
propertyName: '<spread>',
|
|
503
|
+
valueType: 'SPREAD',
|
|
504
|
+
file: module.file,
|
|
505
|
+
line: propLine,
|
|
506
|
+
column: propColumn
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
if (spreadArg.type === 'Identifier') {
|
|
510
|
+
propertyInfo.valueName = spreadArg.name;
|
|
511
|
+
propertyInfo.valueType = 'VARIABLE';
|
|
512
|
+
// REG-329: Capture scope path for spread variable resolution
|
|
513
|
+
propertyInfo.valueScopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
objectProperties.push(propertyInfo);
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Handle regular properties
|
|
521
|
+
if (prop.type === 'ObjectProperty') {
|
|
522
|
+
const objProp = prop as ObjectProperty;
|
|
523
|
+
let propertyName: string;
|
|
524
|
+
|
|
525
|
+
// Get property name
|
|
526
|
+
if (objProp.key.type === 'Identifier') {
|
|
527
|
+
propertyName = objProp.key.name;
|
|
528
|
+
} else if (objProp.key.type === 'StringLiteral') {
|
|
529
|
+
propertyName = objProp.key.value;
|
|
530
|
+
} else if (objProp.key.type === 'NumericLiteral') {
|
|
531
|
+
propertyName = String(objProp.key.value);
|
|
532
|
+
} else {
|
|
533
|
+
propertyName = '<computed>';
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const propertyInfo: ObjectPropertyInfo = {
|
|
537
|
+
objectId,
|
|
538
|
+
propertyName,
|
|
539
|
+
file: module.file,
|
|
540
|
+
line: propLine,
|
|
541
|
+
column: propColumn,
|
|
542
|
+
valueType: 'EXPRESSION'
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const value = objProp.value;
|
|
546
|
+
|
|
547
|
+
// Nested object literal - check BEFORE extractLiteralValue
|
|
548
|
+
if (value.type === 'ObjectExpression') {
|
|
549
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'obj' suffix)
|
|
550
|
+
const nestedObjectNode = ObjectLiteralNode.create(
|
|
551
|
+
module.file,
|
|
552
|
+
value.loc?.start.line || 0,
|
|
553
|
+
value.loc?.start.column || 0,
|
|
554
|
+
{
|
|
555
|
+
counter: objectLiteralCounterRef.value++
|
|
556
|
+
}
|
|
557
|
+
);
|
|
558
|
+
objectLiterals.push(nestedObjectNode as unknown as ObjectLiteralInfo);
|
|
559
|
+
const nestedObjectId = nestedObjectNode.id;
|
|
560
|
+
|
|
561
|
+
// Recursively extract nested properties
|
|
562
|
+
this.extractObjectProperties(
|
|
563
|
+
value,
|
|
564
|
+
nestedObjectId,
|
|
565
|
+
module,
|
|
566
|
+
objectProperties,
|
|
567
|
+
objectLiterals,
|
|
568
|
+
objectLiteralCounterRef,
|
|
569
|
+
literals,
|
|
570
|
+
literalCounterRef
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
propertyInfo.valueType = 'OBJECT_LITERAL';
|
|
574
|
+
propertyInfo.nestedObjectId = nestedObjectId;
|
|
575
|
+
propertyInfo.valueNodeId = nestedObjectId;
|
|
576
|
+
}
|
|
577
|
+
// Nested array literal - check BEFORE extractLiteralValue
|
|
578
|
+
else if (value.type === 'ArrayExpression') {
|
|
579
|
+
const arrayLiteralCounterRef = (this.collections.arrayLiteralCounterRef ?? { value: 0 }) as CounterRef;
|
|
580
|
+
const arrayLiterals = this.collections.arrayLiterals ?? [];
|
|
581
|
+
const arrayElements = this.collections.arrayElements ?? [];
|
|
582
|
+
|
|
583
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'arr' suffix)
|
|
584
|
+
const nestedArrayNode = ArrayLiteralNode.create(
|
|
585
|
+
module.file,
|
|
586
|
+
value.loc?.start.line || 0,
|
|
587
|
+
value.loc?.start.column || 0,
|
|
588
|
+
{
|
|
589
|
+
counter: arrayLiteralCounterRef.value++
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
(arrayLiterals as ArrayLiteralInfo[]).push(nestedArrayNode as unknown as ArrayLiteralInfo);
|
|
593
|
+
const nestedArrayId = nestedArrayNode.id;
|
|
594
|
+
|
|
595
|
+
// Recursively extract array elements
|
|
596
|
+
this.extractArrayElements(
|
|
597
|
+
value,
|
|
598
|
+
nestedArrayId,
|
|
599
|
+
module,
|
|
600
|
+
arrayElements as ArrayElementInfo[],
|
|
601
|
+
arrayLiterals as ArrayLiteralInfo[],
|
|
602
|
+
arrayLiteralCounterRef,
|
|
603
|
+
objectLiterals,
|
|
604
|
+
objectLiteralCounterRef,
|
|
605
|
+
objectProperties,
|
|
606
|
+
literals,
|
|
607
|
+
literalCounterRef
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
propertyInfo.valueType = 'ARRAY_LITERAL';
|
|
611
|
+
propertyInfo.nestedArrayId = nestedArrayId;
|
|
612
|
+
propertyInfo.valueNodeId = nestedArrayId;
|
|
613
|
+
}
|
|
614
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
615
|
+
else {
|
|
616
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(value);
|
|
617
|
+
// Handle both non-null literals AND explicit null literals (NullLiteral)
|
|
618
|
+
if (literalValue !== null || value.type === 'NullLiteral') {
|
|
619
|
+
const literalId = `LITERAL#${propertyName}#${module.file}#${propLine}:${propColumn}:${literalCounterRef.value++}`;
|
|
620
|
+
literals.push({
|
|
621
|
+
id: literalId,
|
|
622
|
+
type: 'LITERAL',
|
|
623
|
+
value: literalValue,
|
|
624
|
+
valueType: typeof literalValue,
|
|
625
|
+
file: module.file,
|
|
626
|
+
line: propLine,
|
|
627
|
+
column: propColumn,
|
|
628
|
+
parentCallId: objectId,
|
|
629
|
+
argIndex: 0
|
|
630
|
+
});
|
|
631
|
+
propertyInfo.valueType = 'LITERAL';
|
|
632
|
+
propertyInfo.valueNodeId = literalId;
|
|
633
|
+
propertyInfo.literalValue = literalValue;
|
|
634
|
+
}
|
|
635
|
+
// Variable reference
|
|
636
|
+
else if (value.type === 'Identifier') {
|
|
637
|
+
propertyInfo.valueType = 'VARIABLE';
|
|
638
|
+
propertyInfo.valueName = value.name;
|
|
639
|
+
// REG-329: Capture scope path for scope-aware variable resolution
|
|
640
|
+
propertyInfo.valueScopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
641
|
+
}
|
|
642
|
+
// Call expression
|
|
643
|
+
else if (value.type === 'CallExpression') {
|
|
644
|
+
propertyInfo.valueType = 'CALL';
|
|
645
|
+
propertyInfo.callLine = value.loc?.start.line;
|
|
646
|
+
propertyInfo.callColumn = value.loc?.start.column;
|
|
647
|
+
}
|
|
648
|
+
// Other expressions
|
|
649
|
+
else {
|
|
650
|
+
propertyInfo.valueType = 'EXPRESSION';
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
objectProperties.push(propertyInfo);
|
|
655
|
+
}
|
|
656
|
+
// Handle object methods: { foo() {} }
|
|
657
|
+
else if (prop.type === 'ObjectMethod') {
|
|
658
|
+
const propertyName = prop.key.type === 'Identifier' ? prop.key.name : '<computed>';
|
|
659
|
+
objectProperties.push({
|
|
660
|
+
objectId,
|
|
661
|
+
propertyName,
|
|
662
|
+
valueType: 'EXPRESSION',
|
|
663
|
+
file: module.file,
|
|
664
|
+
line: propLine,
|
|
665
|
+
column: propColumn
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Extract array elements and create ArrayElementInfo records
|
|
673
|
+
*/
|
|
674
|
+
extractArrayElements(
|
|
675
|
+
arrayExpr: ArrayExpression,
|
|
676
|
+
arrayId: string,
|
|
677
|
+
module: VisitorModule,
|
|
678
|
+
arrayElements: ArrayElementInfo[],
|
|
679
|
+
arrayLiterals: ArrayLiteralInfo[],
|
|
680
|
+
arrayLiteralCounterRef: CounterRef,
|
|
681
|
+
objectLiterals: ObjectLiteralInfo[],
|
|
682
|
+
objectLiteralCounterRef: CounterRef,
|
|
683
|
+
objectProperties: ObjectPropertyInfo[],
|
|
684
|
+
literals: LiteralInfo[],
|
|
685
|
+
literalCounterRef: CounterRef
|
|
686
|
+
): void {
|
|
687
|
+
arrayExpr.elements.forEach((element, index) => {
|
|
688
|
+
if (!element) return; // Skip holes in arrays
|
|
689
|
+
|
|
690
|
+
const elemLine = element.loc?.start.line || 0;
|
|
691
|
+
const elemColumn = element.loc?.start.column || 0;
|
|
692
|
+
|
|
693
|
+
const elementInfo: ArrayElementInfo = {
|
|
694
|
+
arrayId,
|
|
695
|
+
index,
|
|
696
|
+
file: module.file,
|
|
697
|
+
line: elemLine,
|
|
698
|
+
column: elemColumn,
|
|
699
|
+
valueType: 'EXPRESSION'
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// Handle spread elements: [...arr]
|
|
703
|
+
if (element.type === 'SpreadElement') {
|
|
704
|
+
const spreadArg = element.argument;
|
|
705
|
+
elementInfo.valueType = 'SPREAD';
|
|
706
|
+
if (spreadArg.type === 'Identifier') {
|
|
707
|
+
elementInfo.valueName = spreadArg.name;
|
|
708
|
+
}
|
|
709
|
+
arrayElements.push(elementInfo);
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Nested object literal - check BEFORE extractLiteralValue
|
|
714
|
+
if (element.type === 'ObjectExpression') {
|
|
715
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'obj' suffix)
|
|
716
|
+
const nestedObjectNode = ObjectLiteralNode.create(
|
|
717
|
+
module.file,
|
|
718
|
+
elemLine,
|
|
719
|
+
elemColumn,
|
|
720
|
+
{
|
|
721
|
+
counter: objectLiteralCounterRef.value++
|
|
722
|
+
}
|
|
723
|
+
);
|
|
724
|
+
objectLiterals.push(nestedObjectNode as unknown as ObjectLiteralInfo);
|
|
725
|
+
const nestedObjectId = nestedObjectNode.id;
|
|
726
|
+
|
|
727
|
+
// Recursively extract properties
|
|
728
|
+
this.extractObjectProperties(
|
|
729
|
+
element,
|
|
730
|
+
nestedObjectId,
|
|
731
|
+
module,
|
|
732
|
+
objectProperties,
|
|
733
|
+
objectLiterals,
|
|
734
|
+
objectLiteralCounterRef,
|
|
735
|
+
literals,
|
|
736
|
+
literalCounterRef
|
|
737
|
+
);
|
|
738
|
+
|
|
739
|
+
elementInfo.valueType = 'OBJECT_LITERAL';
|
|
740
|
+
elementInfo.nestedObjectId = nestedObjectId;
|
|
741
|
+
elementInfo.valueNodeId = nestedObjectId;
|
|
742
|
+
}
|
|
743
|
+
// Nested array literal - check BEFORE extractLiteralValue
|
|
744
|
+
else if (element.type === 'ArrayExpression') {
|
|
745
|
+
// Use factory - do NOT pass argIndex for nested literals (uses 'arr' suffix)
|
|
746
|
+
const nestedArrayNode = ArrayLiteralNode.create(
|
|
747
|
+
module.file,
|
|
748
|
+
elemLine,
|
|
749
|
+
elemColumn,
|
|
750
|
+
{
|
|
751
|
+
counter: arrayLiteralCounterRef.value++
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
arrayLiterals.push(nestedArrayNode as unknown as ArrayLiteralInfo);
|
|
755
|
+
const nestedArrayId = nestedArrayNode.id;
|
|
756
|
+
|
|
757
|
+
// Recursively extract elements
|
|
758
|
+
this.extractArrayElements(
|
|
759
|
+
element,
|
|
760
|
+
nestedArrayId,
|
|
761
|
+
module,
|
|
762
|
+
arrayElements,
|
|
763
|
+
arrayLiterals,
|
|
764
|
+
arrayLiteralCounterRef,
|
|
765
|
+
objectLiterals,
|
|
766
|
+
objectLiteralCounterRef,
|
|
767
|
+
objectProperties,
|
|
768
|
+
literals,
|
|
769
|
+
literalCounterRef
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
elementInfo.valueType = 'ARRAY_LITERAL';
|
|
773
|
+
elementInfo.nestedArrayId = nestedArrayId;
|
|
774
|
+
elementInfo.valueNodeId = nestedArrayId;
|
|
775
|
+
}
|
|
776
|
+
// Literal value (primitives only - objects/arrays handled above)
|
|
777
|
+
else {
|
|
778
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(element);
|
|
779
|
+
if (literalValue !== null) {
|
|
780
|
+
const literalId = `LITERAL#elem${index}#${module.file}#${elemLine}:${elemColumn}:${literalCounterRef.value++}`;
|
|
781
|
+
literals.push({
|
|
782
|
+
id: literalId,
|
|
783
|
+
type: 'LITERAL',
|
|
784
|
+
value: literalValue,
|
|
785
|
+
valueType: typeof literalValue,
|
|
786
|
+
file: module.file,
|
|
787
|
+
line: elemLine,
|
|
788
|
+
column: elemColumn,
|
|
789
|
+
parentCallId: arrayId,
|
|
790
|
+
argIndex: index
|
|
791
|
+
});
|
|
792
|
+
elementInfo.valueType = 'LITERAL';
|
|
793
|
+
elementInfo.valueNodeId = literalId;
|
|
794
|
+
elementInfo.literalValue = literalValue;
|
|
795
|
+
}
|
|
796
|
+
// Variable reference
|
|
797
|
+
else if (element.type === 'Identifier') {
|
|
798
|
+
elementInfo.valueType = 'VARIABLE';
|
|
799
|
+
elementInfo.valueName = element.name;
|
|
800
|
+
}
|
|
801
|
+
// Call expression
|
|
802
|
+
else if (element.type === 'CallExpression') {
|
|
803
|
+
elementInfo.valueType = 'CALL';
|
|
804
|
+
elementInfo.callLine = element.loc?.start.line;
|
|
805
|
+
elementInfo.callColumn = element.loc?.start.column;
|
|
806
|
+
}
|
|
807
|
+
// Other expressions
|
|
808
|
+
else {
|
|
809
|
+
elementInfo.valueType = 'EXPRESSION';
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
arrayElements.push(elementInfo);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Detect array mutation calls (push, unshift, splice) and collect mutation info
|
|
819
|
+
* for later FLOWS_INTO edge creation in GraphBuilder
|
|
305
820
|
*
|
|
306
|
-
*
|
|
307
|
-
|
|
308
|
-
|
|
821
|
+
* REG-117: Added isNested, baseObjectName, propertyName for nested mutations
|
|
822
|
+
*/
|
|
823
|
+
private detectArrayMutation(
|
|
824
|
+
callNode: CallExpression,
|
|
825
|
+
arrayName: string,
|
|
826
|
+
method: 'push' | 'unshift' | 'splice',
|
|
827
|
+
module: VisitorModule,
|
|
828
|
+
isNested?: boolean,
|
|
829
|
+
baseObjectName?: string,
|
|
830
|
+
propertyName?: string
|
|
831
|
+
): void {
|
|
832
|
+
// Initialize collection if not exists
|
|
833
|
+
if (!this.collections.arrayMutations) {
|
|
834
|
+
this.collections.arrayMutations = [];
|
|
835
|
+
}
|
|
836
|
+
const arrayMutations = this.collections.arrayMutations as ArrayMutationInfo[];
|
|
837
|
+
|
|
838
|
+
const mutationArgs: ArrayMutationArgument[] = [];
|
|
839
|
+
|
|
840
|
+
// For splice, only arguments from index 2 onwards are insertions
|
|
841
|
+
// splice(start, deleteCount, item1, item2, ...)
|
|
842
|
+
callNode.arguments.forEach((arg, index) => {
|
|
843
|
+
// Skip start and deleteCount for splice
|
|
844
|
+
if (method === 'splice' && index < 2) return;
|
|
845
|
+
|
|
846
|
+
const argInfo: ArrayMutationArgument = {
|
|
847
|
+
argIndex: method === 'splice' ? index - 2 : index,
|
|
848
|
+
isSpread: arg.type === 'SpreadElement',
|
|
849
|
+
valueType: 'EXPRESSION' // Default
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
let actualArg = arg;
|
|
853
|
+
if (arg.type === 'SpreadElement') {
|
|
854
|
+
actualArg = arg.argument;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Determine value type
|
|
858
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(actualArg);
|
|
859
|
+
if (literalValue !== null) {
|
|
860
|
+
argInfo.valueType = 'LITERAL';
|
|
861
|
+
argInfo.literalValue = literalValue;
|
|
862
|
+
} else if (actualArg.type === 'Identifier') {
|
|
863
|
+
argInfo.valueType = 'VARIABLE';
|
|
864
|
+
argInfo.valueName = actualArg.name;
|
|
865
|
+
} else if (actualArg.type === 'ObjectExpression') {
|
|
866
|
+
argInfo.valueType = 'OBJECT_LITERAL';
|
|
867
|
+
} else if (actualArg.type === 'ArrayExpression') {
|
|
868
|
+
argInfo.valueType = 'ARRAY_LITERAL';
|
|
869
|
+
} else if (actualArg.type === 'CallExpression') {
|
|
870
|
+
argInfo.valueType = 'CALL';
|
|
871
|
+
argInfo.callLine = actualArg.loc?.start.line;
|
|
872
|
+
argInfo.callColumn = actualArg.loc?.start.column;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
mutationArgs.push(argInfo);
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
// Only record if there are actual insertions
|
|
879
|
+
if (mutationArgs.length > 0) {
|
|
880
|
+
const line = callNode.loc?.start.line ?? 0;
|
|
881
|
+
const column = callNode.loc?.start.column ?? 0;
|
|
882
|
+
|
|
883
|
+
// Generate semantic ID for array mutation if scopeTracker available
|
|
884
|
+
const scopeTracker = this.scopeTracker;
|
|
885
|
+
let mutationId: string | undefined;
|
|
886
|
+
// Capture scope path for scope-aware lookup (REG-309)
|
|
887
|
+
const scopePath = scopeTracker?.getContext().scopePath ?? [];
|
|
888
|
+
|
|
889
|
+
if (scopeTracker) {
|
|
890
|
+
const discriminator = scopeTracker.getItemCounter(`ARRAY_MUTATION:${arrayName}.${method}`);
|
|
891
|
+
mutationId = computeSemanticId('ARRAY_MUTATION', `${arrayName}.${method}`, scopeTracker.getContext(), { discriminator });
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
arrayMutations.push({
|
|
895
|
+
id: mutationId,
|
|
896
|
+
arrayName,
|
|
897
|
+
mutationScopePath: scopePath,
|
|
898
|
+
mutationMethod: method,
|
|
899
|
+
file: module.file,
|
|
900
|
+
line,
|
|
901
|
+
column,
|
|
902
|
+
insertedValues: mutationArgs,
|
|
903
|
+
// REG-117: Nested mutation fields
|
|
904
|
+
isNested,
|
|
905
|
+
baseObjectName,
|
|
906
|
+
propertyName
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Detect Object.assign(target, source1, source2, ...) calls
|
|
913
|
+
* Creates ObjectMutationInfo for FLOWS_INTO edge generation in GraphBuilder
|
|
914
|
+
*
|
|
915
|
+
* @param callNode - The call expression node
|
|
916
|
+
* @param module - Current module being analyzed
|
|
917
|
+
*/
|
|
918
|
+
private detectObjectAssign(
|
|
919
|
+
callNode: CallExpression,
|
|
920
|
+
module: VisitorModule
|
|
921
|
+
): void {
|
|
922
|
+
// Need at least 2 arguments: target and at least one source
|
|
923
|
+
if (callNode.arguments.length < 2) return;
|
|
924
|
+
|
|
925
|
+
// Initialize object mutations collection if not exists
|
|
926
|
+
if (!this.collections.objectMutations) {
|
|
927
|
+
this.collections.objectMutations = [];
|
|
928
|
+
}
|
|
929
|
+
const objectMutations = this.collections.objectMutations as ObjectMutationInfo[];
|
|
930
|
+
|
|
931
|
+
// First argument is target
|
|
932
|
+
const targetArg = callNode.arguments[0];
|
|
933
|
+
let targetName: string;
|
|
934
|
+
|
|
935
|
+
if (targetArg.type === 'Identifier') {
|
|
936
|
+
targetName = targetArg.name;
|
|
937
|
+
} else if (targetArg.type === 'ObjectExpression') {
|
|
938
|
+
targetName = '<anonymous>';
|
|
939
|
+
} else {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
const line = callNode.loc?.start.line ?? 0;
|
|
944
|
+
const column = callNode.loc?.start.column ?? 0;
|
|
945
|
+
|
|
946
|
+
for (let i = 1; i < callNode.arguments.length; i++) {
|
|
947
|
+
let arg = callNode.arguments[i];
|
|
948
|
+
let isSpread = false;
|
|
949
|
+
|
|
950
|
+
if (arg.type === 'SpreadElement') {
|
|
951
|
+
isSpread = true;
|
|
952
|
+
arg = arg.argument;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const valueInfo: ObjectMutationValue = {
|
|
956
|
+
valueType: 'EXPRESSION',
|
|
957
|
+
argIndex: i - 1,
|
|
958
|
+
isSpread
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
const literalValue = ExpressionEvaluator.extractLiteralValue(arg);
|
|
962
|
+
if (literalValue !== null) {
|
|
963
|
+
valueInfo.valueType = 'LITERAL';
|
|
964
|
+
valueInfo.literalValue = literalValue;
|
|
965
|
+
} else if (arg.type === 'Identifier') {
|
|
966
|
+
valueInfo.valueType = 'VARIABLE';
|
|
967
|
+
valueInfo.valueName = arg.name;
|
|
968
|
+
} else if (arg.type === 'ObjectExpression') {
|
|
969
|
+
valueInfo.valueType = 'OBJECT_LITERAL';
|
|
970
|
+
} else if (arg.type === 'ArrayExpression') {
|
|
971
|
+
valueInfo.valueType = 'ARRAY_LITERAL';
|
|
972
|
+
} else if (arg.type === 'CallExpression') {
|
|
973
|
+
valueInfo.valueType = 'CALL';
|
|
974
|
+
valueInfo.callLine = arg.loc?.start.line;
|
|
975
|
+
valueInfo.callColumn = arg.loc?.start.column;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// Capture scope path for scope-aware lookup (REG-309)
|
|
979
|
+
const scopePath = this.scopeTracker?.getContext().scopePath ?? [];
|
|
980
|
+
|
|
981
|
+
let mutationId: string | undefined;
|
|
982
|
+
if (this.scopeTracker) {
|
|
983
|
+
const discriminator = this.scopeTracker.getItemCounter(`OBJECT_MUTATION:Object.assign:${targetName}`);
|
|
984
|
+
mutationId = computeSemanticId('OBJECT_MUTATION', `Object.assign:${targetName}`, this.scopeTracker.getContext(), { discriminator });
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
objectMutations.push({
|
|
988
|
+
id: mutationId,
|
|
989
|
+
objectName: targetName,
|
|
990
|
+
mutationScopePath: scopePath,
|
|
991
|
+
propertyName: '<assign>',
|
|
992
|
+
mutationType: 'assign',
|
|
993
|
+
file: module.file,
|
|
994
|
+
line,
|
|
995
|
+
column,
|
|
996
|
+
value: valueInfo
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Get a stable scope ID for a function parent.
|
|
1003
|
+
*
|
|
1004
|
+
* Format must match what FunctionVisitor/ClassVisitor creates (semantic ID):
|
|
1005
|
+
* - Module-level function: {file}->global->FUNCTION->{name}
|
|
1006
|
+
* - Class method: {file}->{className}->FUNCTION->{methodName}
|
|
1007
|
+
*
|
|
1008
|
+
* Reconstructs scope path by walking up the AST.
|
|
309
1009
|
*/
|
|
310
1010
|
getFunctionScopeId(functionParent: NodePath, module: VisitorModule): string {
|
|
311
1011
|
const funcNode = functionParent.node as Node & {
|
|
312
1012
|
id?: { name: string } | null;
|
|
1013
|
+
key?: { name?: string; type: string };
|
|
313
1014
|
loc?: { start: { line: number; column: number } };
|
|
314
1015
|
type: string;
|
|
315
1016
|
};
|
|
316
|
-
const line = funcNode.loc?.start.line || 0;
|
|
317
|
-
const col = funcNode.loc?.start.column || 0;
|
|
318
1017
|
|
|
319
|
-
//
|
|
1018
|
+
// Get function name
|
|
1019
|
+
let funcName: string | undefined;
|
|
320
1020
|
if (funcNode.type === 'FunctionDeclaration' && funcNode.id?.name) {
|
|
321
|
-
|
|
1021
|
+
funcName = funcNode.id.name;
|
|
1022
|
+
} else if (funcNode.type === 'ClassMethod' && funcNode.key?.type === 'Identifier') {
|
|
1023
|
+
funcName = funcNode.key.name;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
if (!funcName) {
|
|
1027
|
+
// Anonymous function - fall back to module scope
|
|
1028
|
+
return module.id;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Build scope path by walking up the AST
|
|
1032
|
+
const scopePath: string[] = [];
|
|
1033
|
+
let current: NodePath | null = functionParent.parentPath;
|
|
1034
|
+
|
|
1035
|
+
while (current) {
|
|
1036
|
+
const node = current.node as Node & {
|
|
1037
|
+
id?: { name: string } | null;
|
|
1038
|
+
type: string;
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
if (node.type === 'ClassDeclaration' && node.id?.name) {
|
|
1042
|
+
scopePath.unshift(node.id.name);
|
|
1043
|
+
break; // Class is the outermost scope we need
|
|
1044
|
+
} else if (node.type === 'ClassBody') {
|
|
1045
|
+
// Continue up to ClassDeclaration
|
|
1046
|
+
} else if (node.type === 'Program') {
|
|
1047
|
+
break;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
current = current.parentPath;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// If no class found, it's at module level (global scope)
|
|
1054
|
+
if (scopePath.length === 0) {
|
|
1055
|
+
scopePath.push('global');
|
|
322
1056
|
}
|
|
323
1057
|
|
|
324
|
-
//
|
|
325
|
-
|
|
326
|
-
// to avoid creating invalid edges. The CALL node will be connected to MODULE
|
|
327
|
-
// instead of the specific function.
|
|
328
|
-
return module.id;
|
|
1058
|
+
// Compute semantic ID: {file}->{scopePath}->FUNCTION->{name}
|
|
1059
|
+
return `${module.file}->${scopePath.join('->')}->FUNCTION->${funcName}`;
|
|
329
1060
|
}
|
|
330
1061
|
|
|
331
1062
|
getHandlers(): VisitorHandlers {
|
|
@@ -339,26 +1070,43 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
339
1070
|
const callSiteCounterRef = (this.collections.callSiteCounterRef ?? { value: 0 }) as CounterRef;
|
|
340
1071
|
const literalCounterRef = (this.collections.literalCounterRef ?? { value: 0 }) as CounterRef;
|
|
341
1072
|
const processedNodes = this.collections.processedNodes ?? { callSites: new Set(), methodCalls: new Set(), eventListeners: new Set() };
|
|
1073
|
+
const scopeTracker = this.scopeTracker;
|
|
342
1074
|
|
|
343
1075
|
return {
|
|
344
1076
|
CallExpression: (path: NodePath) => {
|
|
345
1077
|
const callNode = path.node as CallExpression;
|
|
346
1078
|
const functionParent = path.getFunctionParent();
|
|
1079
|
+
|
|
347
1080
|
// Determine parent scope - if inside a function, use function's scope, otherwise module
|
|
348
1081
|
const parentScopeId = functionParent ? this.getFunctionScopeId(functionParent, module) : module.id;
|
|
349
1082
|
|
|
350
1083
|
// Identifier calls (direct function calls)
|
|
1084
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
351
1085
|
if (callNode.callee.type === 'Identifier') {
|
|
1086
|
+
if (functionParent) {
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
352
1089
|
const callee = callNode.callee as Identifier;
|
|
353
|
-
|
|
1090
|
+
|
|
1091
|
+
const line = getLine(callNode);
|
|
1092
|
+
const column = getColumn(callNode);
|
|
1093
|
+
|
|
1094
|
+
// Generate ID using centralized IdGenerator
|
|
1095
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
1096
|
+
const callId = idGenerator.generate(
|
|
1097
|
+
'CALL', callee.name, module.file,
|
|
1098
|
+
line, column,
|
|
1099
|
+
callSiteCounterRef,
|
|
1100
|
+
{ useDiscriminator: true, discriminatorKey: `CALL:${callee.name}` }
|
|
1101
|
+
);
|
|
354
1102
|
|
|
355
1103
|
(callSites as CallSiteInfo[]).push({
|
|
356
1104
|
id: callId,
|
|
357
1105
|
type: 'CALL',
|
|
358
1106
|
name: callee.name,
|
|
359
1107
|
file: module.file,
|
|
360
|
-
line
|
|
361
|
-
column
|
|
1108
|
+
line,
|
|
1109
|
+
column,
|
|
362
1110
|
parentScopeId,
|
|
363
1111
|
targetFunctionName: callee.name
|
|
364
1112
|
});
|
|
@@ -375,8 +1123,12 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
375
1123
|
);
|
|
376
1124
|
}
|
|
377
1125
|
}
|
|
378
|
-
// MemberExpression calls (method calls
|
|
1126
|
+
// MemberExpression calls (method calls)
|
|
1127
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
379
1128
|
else if (callNode.callee.type === 'MemberExpression') {
|
|
1129
|
+
if (functionParent) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
380
1132
|
const memberCallee = callNode.callee as MemberExpression;
|
|
381
1133
|
const object = memberCallee.object;
|
|
382
1134
|
const property = memberCallee.property;
|
|
@@ -403,13 +1155,16 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
403
1155
|
}
|
|
404
1156
|
processedNodes.eventListeners.add(nodeKey);
|
|
405
1157
|
|
|
1158
|
+
const eventLine = getLine(callNode);
|
|
1159
|
+
const eventColumn = getColumn(callNode);
|
|
1160
|
+
|
|
406
1161
|
(eventListeners as EventListenerInfo[]).push({
|
|
407
|
-
id: `event:listener#${eventName}#${module.file}#${
|
|
1162
|
+
id: `event:listener#${eventName}#${module.file}#${eventLine}:${eventColumn}:${callSiteCounterRef.value++}`,
|
|
408
1163
|
type: 'event:listener',
|
|
409
1164
|
name: eventName,
|
|
410
1165
|
object: objectName,
|
|
411
1166
|
file: module.file,
|
|
412
|
-
line:
|
|
1167
|
+
line: eventLine,
|
|
413
1168
|
parentScopeId,
|
|
414
1169
|
callbackArg: secondArg
|
|
415
1170
|
});
|
|
@@ -423,7 +1178,17 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
423
1178
|
processedNodes.methodCalls.add(nodeKey);
|
|
424
1179
|
|
|
425
1180
|
const fullName = `${objectName}.${methodName}`;
|
|
426
|
-
const
|
|
1181
|
+
const methodLine = getLine(callNode);
|
|
1182
|
+
const methodColumn = getColumn(callNode);
|
|
1183
|
+
|
|
1184
|
+
// Generate ID using centralized IdGenerator
|
|
1185
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
1186
|
+
const methodCallId = idGenerator.generate(
|
|
1187
|
+
'CALL', fullName, module.file,
|
|
1188
|
+
methodLine, methodColumn,
|
|
1189
|
+
callSiteCounterRef,
|
|
1190
|
+
{ useDiscriminator: true, discriminatorKey: `CALL:${fullName}` }
|
|
1191
|
+
);
|
|
427
1192
|
|
|
428
1193
|
(methodCalls as MethodCallInfo[]).push({
|
|
429
1194
|
id: methodCallId,
|
|
@@ -434,11 +1199,27 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
434
1199
|
computed: isComputed,
|
|
435
1200
|
computedPropertyVar, // Variable name used in obj[x]() calls
|
|
436
1201
|
file: module.file,
|
|
437
|
-
line:
|
|
438
|
-
column:
|
|
1202
|
+
line: methodLine,
|
|
1203
|
+
column: methodColumn,
|
|
439
1204
|
parentScopeId
|
|
440
1205
|
});
|
|
441
1206
|
|
|
1207
|
+
// Check for array mutation methods (push, unshift, splice)
|
|
1208
|
+
const ARRAY_MUTATION_METHODS = ['push', 'unshift', 'splice'];
|
|
1209
|
+
if (ARRAY_MUTATION_METHODS.includes(methodName)) {
|
|
1210
|
+
this.detectArrayMutation(
|
|
1211
|
+
callNode,
|
|
1212
|
+
objectName,
|
|
1213
|
+
methodName as 'push' | 'unshift' | 'splice',
|
|
1214
|
+
module
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// Check for Object.assign() calls
|
|
1219
|
+
if (objectName === 'Object' && methodName === 'assign') {
|
|
1220
|
+
this.detectObjectAssign(callNode, module);
|
|
1221
|
+
}
|
|
1222
|
+
|
|
442
1223
|
// Extract arguments for PASSES_ARGUMENT edges
|
|
443
1224
|
if (callNode.arguments.length > 0) {
|
|
444
1225
|
this.extractArguments(
|
|
@@ -455,8 +1236,8 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
455
1236
|
if (arg.type === 'ArrowFunctionExpression' || arg.type === 'FunctionExpression') {
|
|
456
1237
|
(methodCallbacks as MethodCallbackInfo[]).push({
|
|
457
1238
|
methodCallId,
|
|
458
|
-
callbackLine: arg
|
|
459
|
-
callbackColumn: arg
|
|
1239
|
+
callbackLine: getLine(arg),
|
|
1240
|
+
callbackColumn: getColumn(arg),
|
|
460
1241
|
callbackType: arg.type
|
|
461
1242
|
});
|
|
462
1243
|
}
|
|
@@ -464,14 +1245,52 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
464
1245
|
}
|
|
465
1246
|
}
|
|
466
1247
|
}
|
|
1248
|
+
// REG-117: Nested array mutations like obj.arr.push(item)
|
|
1249
|
+
// object is MemberExpression, property is the method name
|
|
1250
|
+
else if (object.type === 'MemberExpression' && property.type === 'Identifier') {
|
|
1251
|
+
const nestedMember = object as MemberExpression;
|
|
1252
|
+
const methodName = (property as Identifier).name;
|
|
1253
|
+
const ARRAY_MUTATION_METHODS = ['push', 'unshift', 'splice'];
|
|
1254
|
+
|
|
1255
|
+
if (ARRAY_MUTATION_METHODS.includes(methodName)) {
|
|
1256
|
+
// Extract base object and property from nested MemberExpression
|
|
1257
|
+
const base = nestedMember.object;
|
|
1258
|
+
const prop = nestedMember.property;
|
|
1259
|
+
|
|
1260
|
+
// Only handle single-level nesting: obj.arr.push() or this.items.push()
|
|
1261
|
+
if ((base.type === 'Identifier' || base.type === 'ThisExpression') &&
|
|
1262
|
+
!nestedMember.computed &&
|
|
1263
|
+
prop.type === 'Identifier') {
|
|
1264
|
+
const baseObjectName = base.type === 'Identifier' ? (base as Identifier).name : 'this';
|
|
1265
|
+
const propertyName = (prop as Identifier).name;
|
|
1266
|
+
|
|
1267
|
+
this.detectArrayMutation(
|
|
1268
|
+
callNode,
|
|
1269
|
+
`${baseObjectName}.${propertyName}`, // arrayName for ID purposes
|
|
1270
|
+
methodName as 'push' | 'unshift' | 'splice',
|
|
1271
|
+
module,
|
|
1272
|
+
true, // isNested
|
|
1273
|
+
baseObjectName,
|
|
1274
|
+
propertyName
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
467
1279
|
}
|
|
468
1280
|
},
|
|
469
1281
|
|
|
470
1282
|
// NewExpression: new Foo(), new Function(), new Map(), etc.
|
|
1283
|
+
// Skip if inside function - they will be processed by analyzeFunctionBody with proper scope tracking
|
|
471
1284
|
NewExpression: (path: NodePath) => {
|
|
472
1285
|
const newNode = path.node as NewExpression;
|
|
473
1286
|
const functionParent = path.getFunctionParent();
|
|
474
|
-
|
|
1287
|
+
|
|
1288
|
+
// Skip if inside function - handled by analyzeFunctionBody
|
|
1289
|
+
if (functionParent) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
const parentScopeId = module.id;
|
|
475
1294
|
|
|
476
1295
|
// Dedup check
|
|
477
1296
|
const nodeKey = `new:${newNode.start}:${newNode.end}`;
|
|
@@ -484,14 +1303,25 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
484
1303
|
if (newNode.callee.type === 'Identifier') {
|
|
485
1304
|
const callee = newNode.callee as Identifier;
|
|
486
1305
|
const constructorName = callee.name;
|
|
1306
|
+
const newLine = getLine(newNode);
|
|
1307
|
+
const newColumn = getColumn(newNode);
|
|
1308
|
+
|
|
1309
|
+
// Generate ID using centralized IdGenerator
|
|
1310
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
1311
|
+
const newCallId = idGenerator.generate(
|
|
1312
|
+
'CALL', `new:${constructorName}`, module.file,
|
|
1313
|
+
newLine, newColumn,
|
|
1314
|
+
callSiteCounterRef,
|
|
1315
|
+
{ useDiscriminator: true, discriminatorKey: `CALL:new:${constructorName}` }
|
|
1316
|
+
);
|
|
487
1317
|
|
|
488
1318
|
(callSites as CallSiteInfo[]).push({
|
|
489
|
-
id:
|
|
1319
|
+
id: newCallId,
|
|
490
1320
|
type: 'CALL',
|
|
491
1321
|
name: constructorName,
|
|
492
1322
|
file: module.file,
|
|
493
|
-
line:
|
|
494
|
-
column:
|
|
1323
|
+
line: newLine,
|
|
1324
|
+
column: newColumn,
|
|
495
1325
|
parentScopeId,
|
|
496
1326
|
targetFunctionName: constructorName,
|
|
497
1327
|
isNew: true // Mark as constructor call
|
|
@@ -507,16 +1337,27 @@ export class CallExpressionVisitor extends ASTVisitor {
|
|
|
507
1337
|
const objectName = (object as Identifier).name;
|
|
508
1338
|
const constructorName = (property as Identifier).name;
|
|
509
1339
|
const fullName = `${objectName}.${constructorName}`;
|
|
1340
|
+
const memberNewLine = getLine(newNode);
|
|
1341
|
+
const memberNewColumn = getColumn(newNode);
|
|
1342
|
+
|
|
1343
|
+
// Generate ID using centralized IdGenerator
|
|
1344
|
+
const idGenerator = new IdGenerator(scopeTracker);
|
|
1345
|
+
const newMethodCallId = idGenerator.generate(
|
|
1346
|
+
'CALL', `new:${fullName}`, module.file,
|
|
1347
|
+
memberNewLine, memberNewColumn,
|
|
1348
|
+
callSiteCounterRef,
|
|
1349
|
+
{ useDiscriminator: true, discriminatorKey: `CALL:new:${fullName}` }
|
|
1350
|
+
);
|
|
510
1351
|
|
|
511
1352
|
(methodCalls as MethodCallInfo[]).push({
|
|
512
|
-
id:
|
|
1353
|
+
id: newMethodCallId,
|
|
513
1354
|
type: 'CALL',
|
|
514
1355
|
name: fullName,
|
|
515
1356
|
object: objectName,
|
|
516
1357
|
method: constructorName,
|
|
517
1358
|
file: module.file,
|
|
518
|
-
line:
|
|
519
|
-
column:
|
|
1359
|
+
line: memberNewLine,
|
|
1360
|
+
column: memberNewColumn,
|
|
520
1361
|
parentScopeId,
|
|
521
1362
|
isNew: true // Mark as constructor call
|
|
522
1363
|
});
|