@grafema/core 0.1.1-alpha → 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.
Files changed (319) hide show
  1. package/dist/Orchestrator.d.ts +7 -0
  2. package/dist/Orchestrator.d.ts.map +1 -1
  3. package/dist/Orchestrator.js +25 -3
  4. package/dist/config/ConfigLoader.d.ts +18 -0
  5. package/dist/config/ConfigLoader.d.ts.map +1 -1
  6. package/dist/config/ConfigLoader.js +65 -3
  7. package/dist/core/FileExplainer.d.ts +101 -0
  8. package/dist/core/FileExplainer.d.ts.map +1 -0
  9. package/dist/core/FileExplainer.js +139 -0
  10. package/dist/core/NodeFactory.d.ts +44 -5
  11. package/dist/core/NodeFactory.d.ts.map +1 -1
  12. package/dist/core/NodeFactory.js +52 -7
  13. package/dist/core/nodes/ArrayLiteralNode.d.ts.map +1 -1
  14. package/dist/core/nodes/ArrayLiteralNode.js +4 -2
  15. package/dist/core/nodes/BranchNode.d.ts +41 -0
  16. package/dist/core/nodes/BranchNode.d.ts.map +1 -0
  17. package/dist/core/nodes/BranchNode.js +82 -0
  18. package/dist/core/nodes/CallSiteNode.d.ts +2 -2
  19. package/dist/core/nodes/CallSiteNode.d.ts.map +1 -1
  20. package/dist/core/nodes/CallSiteNode.js +9 -5
  21. package/dist/core/nodes/CaseNode.d.ts +43 -0
  22. package/dist/core/nodes/CaseNode.d.ts.map +1 -0
  23. package/dist/core/nodes/CaseNode.js +81 -0
  24. package/dist/core/nodes/ClassNode.d.ts +2 -2
  25. package/dist/core/nodes/ClassNode.d.ts.map +1 -1
  26. package/dist/core/nodes/ClassNode.js +8 -4
  27. package/dist/core/nodes/ConstantNode.d.ts +2 -2
  28. package/dist/core/nodes/ConstantNode.d.ts.map +1 -1
  29. package/dist/core/nodes/ConstantNode.js +6 -4
  30. package/dist/core/nodes/ConstructorCallNode.d.ts +51 -0
  31. package/dist/core/nodes/ConstructorCallNode.d.ts.map +1 -0
  32. package/dist/core/nodes/ConstructorCallNode.js +171 -0
  33. package/dist/core/nodes/DatabaseQueryNode.d.ts +3 -2
  34. package/dist/core/nodes/DatabaseQueryNode.d.ts.map +1 -1
  35. package/dist/core/nodes/DatabaseQueryNode.js +5 -2
  36. package/dist/core/nodes/DecoratorNode.d.ts +2 -2
  37. package/dist/core/nodes/DecoratorNode.d.ts.map +1 -1
  38. package/dist/core/nodes/DecoratorNode.js +5 -3
  39. package/dist/core/nodes/EnumNode.d.ts +2 -2
  40. package/dist/core/nodes/EnumNode.d.ts.map +1 -1
  41. package/dist/core/nodes/EnumNode.js +5 -3
  42. package/dist/core/nodes/EventListenerNode.d.ts +4 -4
  43. package/dist/core/nodes/EventListenerNode.d.ts.map +1 -1
  44. package/dist/core/nodes/EventListenerNode.js +7 -4
  45. package/dist/core/nodes/ExportNode.d.ts +2 -2
  46. package/dist/core/nodes/ExportNode.d.ts.map +1 -1
  47. package/dist/core/nodes/ExportNode.js +8 -4
  48. package/dist/core/nodes/ExpressionNode.d.ts +2 -2
  49. package/dist/core/nodes/ExpressionNode.d.ts.map +1 -1
  50. package/dist/core/nodes/ExpressionNode.js +6 -4
  51. package/dist/core/nodes/ExternalModuleNode.d.ts +4 -0
  52. package/dist/core/nodes/ExternalModuleNode.d.ts.map +1 -1
  53. package/dist/core/nodes/ExternalModuleNode.js +10 -2
  54. package/dist/core/nodes/HttpRequestNode.d.ts +4 -4
  55. package/dist/core/nodes/HttpRequestNode.d.ts.map +1 -1
  56. package/dist/core/nodes/HttpRequestNode.js +7 -4
  57. package/dist/core/nodes/ImportNode.d.ts +10 -2
  58. package/dist/core/nodes/ImportNode.d.ts.map +1 -1
  59. package/dist/core/nodes/ImportNode.js +21 -4
  60. package/dist/core/nodes/InterfaceNode.d.ts +2 -2
  61. package/dist/core/nodes/InterfaceNode.d.ts.map +1 -1
  62. package/dist/core/nodes/InterfaceNode.js +5 -3
  63. package/dist/core/nodes/LiteralNode.d.ts +2 -2
  64. package/dist/core/nodes/LiteralNode.d.ts.map +1 -1
  65. package/dist/core/nodes/LiteralNode.js +6 -4
  66. package/dist/core/nodes/MethodCallNode.d.ts +2 -2
  67. package/dist/core/nodes/MethodCallNode.d.ts.map +1 -1
  68. package/dist/core/nodes/MethodCallNode.js +9 -5
  69. package/dist/core/nodes/MethodNode.d.ts +2 -2
  70. package/dist/core/nodes/MethodNode.d.ts.map +1 -1
  71. package/dist/core/nodes/MethodNode.js +8 -4
  72. package/dist/core/nodes/ObjectLiteralNode.d.ts.map +1 -1
  73. package/dist/core/nodes/ObjectLiteralNode.js +4 -2
  74. package/dist/core/nodes/ParameterNode.d.ts +2 -2
  75. package/dist/core/nodes/ParameterNode.d.ts.map +1 -1
  76. package/dist/core/nodes/ParameterNode.js +5 -3
  77. package/dist/core/nodes/TypeNode.d.ts +2 -2
  78. package/dist/core/nodes/TypeNode.d.ts.map +1 -1
  79. package/dist/core/nodes/TypeNode.js +5 -3
  80. package/dist/core/nodes/VariableDeclarationNode.d.ts +2 -2
  81. package/dist/core/nodes/VariableDeclarationNode.d.ts.map +1 -1
  82. package/dist/core/nodes/VariableDeclarationNode.js +9 -5
  83. package/dist/core/nodes/index.d.ts +3 -0
  84. package/dist/core/nodes/index.d.ts.map +1 -1
  85. package/dist/core/nodes/index.js +3 -0
  86. package/dist/data/builtins/BuiltinRegistry.d.ts +78 -0
  87. package/dist/data/builtins/BuiltinRegistry.d.ts.map +1 -0
  88. package/dist/data/builtins/BuiltinRegistry.js +110 -0
  89. package/dist/data/builtins/definitions.d.ts +28 -0
  90. package/dist/data/builtins/definitions.d.ts.map +1 -0
  91. package/dist/data/builtins/definitions.js +250 -0
  92. package/dist/data/builtins/index.d.ts +10 -0
  93. package/dist/data/builtins/index.d.ts.map +1 -0
  94. package/dist/data/builtins/index.js +8 -0
  95. package/dist/data/builtins/jsGlobals.d.ts +18 -0
  96. package/dist/data/builtins/jsGlobals.d.ts.map +1 -0
  97. package/dist/data/builtins/jsGlobals.js +26 -0
  98. package/dist/data/builtins/types.d.ts +34 -0
  99. package/dist/data/builtins/types.d.ts.map +1 -0
  100. package/dist/data/builtins/types.js +7 -0
  101. package/dist/data/globals/definitions.d.ts +27 -0
  102. package/dist/data/globals/definitions.d.ts.map +1 -0
  103. package/dist/data/globals/definitions.js +117 -0
  104. package/dist/data/globals/index.d.ts +36 -0
  105. package/dist/data/globals/index.d.ts.map +1 -0
  106. package/dist/data/globals/index.js +52 -0
  107. package/dist/diagnostics/DiagnosticReporter.d.ts +23 -0
  108. package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -1
  109. package/dist/diagnostics/DiagnosticReporter.js +88 -0
  110. package/dist/diagnostics/index.d.ts +1 -1
  111. package/dist/diagnostics/index.d.ts.map +1 -1
  112. package/dist/errors/GrafemaError.d.ts +43 -0
  113. package/dist/errors/GrafemaError.d.ts.map +1 -1
  114. package/dist/errors/GrafemaError.js +50 -0
  115. package/dist/index.d.ts +17 -1
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +17 -1
  118. package/dist/plugins/analysis/DatabaseAnalyzer.d.ts.map +1 -1
  119. package/dist/plugins/analysis/DatabaseAnalyzer.js +3 -2
  120. package/dist/plugins/analysis/ExpressAnalyzer.d.ts.map +1 -1
  121. package/dist/plugins/analysis/ExpressAnalyzer.js +3 -1
  122. package/dist/plugins/analysis/ExpressResponseAnalyzer.d.ts +148 -0
  123. package/dist/plugins/analysis/ExpressResponseAnalyzer.d.ts.map +1 -0
  124. package/dist/plugins/analysis/ExpressResponseAnalyzer.js +495 -0
  125. package/dist/plugins/analysis/ExpressRouteAnalyzer.d.ts.map +1 -1
  126. package/dist/plugins/analysis/ExpressRouteAnalyzer.js +53 -18
  127. package/dist/plugins/analysis/FetchAnalyzer.d.ts +40 -0
  128. package/dist/plugins/analysis/FetchAnalyzer.d.ts.map +1 -1
  129. package/dist/plugins/analysis/FetchAnalyzer.js +163 -15
  130. package/dist/plugins/analysis/JSASTAnalyzer.d.ts +157 -26
  131. package/dist/plugins/analysis/JSASTAnalyzer.d.ts.map +1 -1
  132. package/dist/plugins/analysis/JSASTAnalyzer.js +2418 -191
  133. package/dist/plugins/analysis/RustAnalyzer.js +4 -4
  134. package/dist/plugins/analysis/SQLiteAnalyzer.d.ts.map +1 -1
  135. package/dist/plugins/analysis/SQLiteAnalyzer.js +4 -2
  136. package/dist/plugins/analysis/SocketIOAnalyzer.d.ts +9 -0
  137. package/dist/plugins/analysis/SocketIOAnalyzer.d.ts.map +1 -1
  138. package/dist/plugins/analysis/SocketIOAnalyzer.js +91 -7
  139. package/dist/plugins/analysis/ast/GraphBuilder.d.ts +173 -0
  140. package/dist/plugins/analysis/ast/GraphBuilder.d.ts.map +1 -1
  141. package/dist/plugins/analysis/ast/GraphBuilder.js +1256 -65
  142. package/dist/plugins/analysis/ast/types.d.ts +294 -0
  143. package/dist/plugins/analysis/ast/types.d.ts.map +1 -1
  144. package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts +5 -1
  145. package/dist/plugins/analysis/ast/visitors/ASTVisitor.d.ts.map +1 -1
  146. package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts +1 -0
  147. package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.d.ts.map +1 -1
  148. package/dist/plugins/analysis/ast/visitors/CallExpressionVisitor.js +12 -1
  149. package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts +10 -0
  150. package/dist/plugins/analysis/ast/visitors/FunctionVisitor.d.ts.map +1 -1
  151. package/dist/plugins/analysis/ast/visitors/FunctionVisitor.js +62 -0
  152. package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts +4 -0
  153. package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.d.ts.map +1 -1
  154. package/dist/plugins/analysis/ast/visitors/ImportExportVisitor.js +101 -0
  155. package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts +16 -1
  156. package/dist/plugins/analysis/ast/visitors/VariableVisitor.d.ts.map +1 -1
  157. package/dist/plugins/analysis/ast/visitors/VariableVisitor.js +233 -39
  158. package/dist/plugins/discovery/WorkspaceDiscovery.d.ts.map +1 -1
  159. package/dist/plugins/discovery/WorkspaceDiscovery.js +9 -4
  160. package/dist/plugins/enrichment/AliasTracker.d.ts.map +1 -1
  161. package/dist/plugins/enrichment/AliasTracker.js +16 -1
  162. package/dist/plugins/enrichment/ArgumentParameterLinker.d.ts +32 -0
  163. package/dist/plugins/enrichment/ArgumentParameterLinker.d.ts.map +1 -0
  164. package/dist/plugins/enrichment/ArgumentParameterLinker.js +175 -0
  165. package/dist/plugins/enrichment/ClosureCaptureEnricher.d.ts +51 -0
  166. package/dist/plugins/enrichment/ClosureCaptureEnricher.d.ts.map +1 -0
  167. package/dist/plugins/enrichment/ClosureCaptureEnricher.js +205 -0
  168. package/dist/plugins/enrichment/ExternalCallResolver.d.ts +42 -0
  169. package/dist/plugins/enrichment/ExternalCallResolver.d.ts.map +1 -0
  170. package/dist/plugins/enrichment/ExternalCallResolver.js +213 -0
  171. package/dist/plugins/enrichment/FunctionCallResolver.d.ts +58 -0
  172. package/dist/plugins/enrichment/FunctionCallResolver.d.ts.map +1 -0
  173. package/dist/plugins/enrichment/FunctionCallResolver.js +340 -0
  174. package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts +16 -3
  175. package/dist/plugins/enrichment/HTTPConnectionEnricher.d.ts.map +1 -1
  176. package/dist/plugins/enrichment/HTTPConnectionEnricher.js +64 -20
  177. package/dist/plugins/enrichment/MethodCallResolver.d.ts.map +1 -1
  178. package/dist/plugins/enrichment/MethodCallResolver.js +15 -1
  179. package/dist/plugins/enrichment/MountPointResolver.d.ts +14 -12
  180. package/dist/plugins/enrichment/MountPointResolver.d.ts.map +1 -1
  181. package/dist/plugins/enrichment/MountPointResolver.js +172 -151
  182. package/dist/plugins/enrichment/NodejsBuiltinsResolver.d.ts +44 -0
  183. package/dist/plugins/enrichment/NodejsBuiltinsResolver.d.ts.map +1 -0
  184. package/dist/plugins/enrichment/NodejsBuiltinsResolver.js +271 -0
  185. package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts +5 -27
  186. package/dist/plugins/enrichment/ValueDomainAnalyzer.d.ts.map +1 -1
  187. package/dist/plugins/enrichment/ValueDomainAnalyzer.js +62 -139
  188. package/dist/plugins/indexing/JSModuleIndexer.d.ts +15 -0
  189. package/dist/plugins/indexing/JSModuleIndexer.d.ts.map +1 -1
  190. package/dist/plugins/indexing/JSModuleIndexer.js +58 -0
  191. package/dist/plugins/indexing/RustModuleIndexer.d.ts +1 -1
  192. package/dist/plugins/indexing/RustModuleIndexer.js +4 -4
  193. package/dist/plugins/validation/BrokenImportValidator.d.ts +31 -0
  194. package/dist/plugins/validation/BrokenImportValidator.d.ts.map +1 -0
  195. package/dist/plugins/validation/BrokenImportValidator.js +249 -0
  196. package/dist/plugins/validation/CallResolverValidator.d.ts +21 -10
  197. package/dist/plugins/validation/CallResolverValidator.d.ts.map +1 -1
  198. package/dist/plugins/validation/CallResolverValidator.js +101 -76
  199. package/dist/plugins/validation/DataFlowValidator.d.ts.map +1 -1
  200. package/dist/plugins/validation/DataFlowValidator.js +49 -41
  201. package/dist/plugins/validation/GraphConnectivityValidator.d.ts.map +1 -1
  202. package/dist/plugins/validation/GraphConnectivityValidator.js +25 -1
  203. package/dist/plugins/validation/SQLInjectionValidator.d.ts.map +1 -1
  204. package/dist/plugins/validation/SQLInjectionValidator.js +2 -3
  205. package/dist/queries/findCallsInFunction.d.ts +52 -0
  206. package/dist/queries/findCallsInFunction.d.ts.map +1 -0
  207. package/dist/queries/findCallsInFunction.js +135 -0
  208. package/dist/queries/findContainingFunction.d.ts +45 -0
  209. package/dist/queries/findContainingFunction.d.ts.map +1 -0
  210. package/dist/queries/findContainingFunction.js +54 -0
  211. package/dist/queries/index.d.ts +14 -0
  212. package/dist/queries/index.d.ts.map +1 -0
  213. package/dist/queries/index.js +11 -0
  214. package/dist/queries/traceValues.d.ts +70 -0
  215. package/dist/queries/traceValues.d.ts.map +1 -0
  216. package/dist/queries/traceValues.js +299 -0
  217. package/dist/queries/types.d.ts +163 -0
  218. package/dist/queries/types.d.ts.map +1 -0
  219. package/dist/queries/types.js +9 -0
  220. package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
  221. package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
  222. package/dist/schema/GraphSchemaExtractor.js +124 -0
  223. package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
  224. package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
  225. package/dist/schema/InterfaceSchemaExtractor.js +112 -0
  226. package/dist/schema/index.d.ts +5 -0
  227. package/dist/schema/index.d.ts.map +1 -0
  228. package/dist/schema/index.js +2 -0
  229. package/dist/storage/backends/RFDBServerBackend.d.ts +12 -18
  230. package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -1
  231. package/dist/storage/backends/RFDBServerBackend.js +41 -52
  232. package/dist/storage/backends/typeValidation.d.ts.map +1 -1
  233. package/dist/storage/backends/typeValidation.js +1 -0
  234. package/package.json +3 -3
  235. package/src/Orchestrator.ts +35 -3
  236. package/src/config/ConfigLoader.ts +94 -3
  237. package/src/core/FileExplainer.ts +179 -0
  238. package/src/core/NodeFactory.ts +72 -8
  239. package/src/core/nodes/ArrayLiteralNode.ts +3 -2
  240. package/src/core/nodes/BranchNode.ts +113 -0
  241. package/src/core/nodes/CallSiteNode.ts +7 -5
  242. package/src/core/nodes/CaseNode.ts +123 -0
  243. package/src/core/nodes/ClassNode.ts +6 -4
  244. package/src/core/nodes/ConstantNode.ts +5 -4
  245. package/src/core/nodes/ConstructorCallNode.ts +217 -0
  246. package/src/core/nodes/DatabaseQueryNode.ts +5 -1
  247. package/src/core/nodes/DecoratorNode.ts +4 -3
  248. package/src/core/nodes/EnumNode.ts +4 -3
  249. package/src/core/nodes/EventListenerNode.ts +7 -4
  250. package/src/core/nodes/ExportNode.ts +6 -4
  251. package/src/core/nodes/ExpressionNode.ts +5 -4
  252. package/src/core/nodes/ExternalModuleNode.ts +11 -2
  253. package/src/core/nodes/HttpRequestNode.ts +7 -4
  254. package/src/core/nodes/ImportNode.ts +31 -4
  255. package/src/core/nodes/InterfaceNode.ts +4 -3
  256. package/src/core/nodes/LiteralNode.ts +5 -4
  257. package/src/core/nodes/MethodCallNode.ts +7 -5
  258. package/src/core/nodes/MethodNode.ts +6 -4
  259. package/src/core/nodes/ObjectLiteralNode.ts +3 -2
  260. package/src/core/nodes/ParameterNode.ts +4 -3
  261. package/src/core/nodes/TypeNode.ts +4 -3
  262. package/src/core/nodes/VariableDeclarationNode.ts +7 -5
  263. package/src/core/nodes/index.ts +3 -0
  264. package/src/data/builtins/BuiltinRegistry.ts +124 -0
  265. package/src/data/builtins/definitions.ts +267 -0
  266. package/src/data/builtins/index.ts +10 -0
  267. package/src/data/builtins/jsGlobals.ts +28 -0
  268. package/src/data/builtins/types.ts +36 -0
  269. package/src/data/globals/definitions.ts +156 -0
  270. package/src/data/globals/index.ts +66 -0
  271. package/src/diagnostics/DiagnosticReporter.ts +120 -0
  272. package/src/diagnostics/index.ts +1 -1
  273. package/src/errors/GrafemaError.ts +65 -0
  274. package/src/index.ts +45 -0
  275. package/src/plugins/analysis/DatabaseAnalyzer.ts +4 -2
  276. package/src/plugins/analysis/ExpressAnalyzer.ts +5 -1
  277. package/src/plugins/analysis/ExpressResponseAnalyzer.ts +636 -0
  278. package/src/plugins/analysis/ExpressRouteAnalyzer.ts +57 -18
  279. package/src/plugins/analysis/FetchAnalyzer.ts +204 -16
  280. package/src/plugins/analysis/JSASTAnalyzer.ts +2958 -260
  281. package/src/plugins/analysis/RustAnalyzer.ts +4 -4
  282. package/src/plugins/analysis/SQLiteAnalyzer.ts +5 -2
  283. package/src/plugins/analysis/SocketIOAnalyzer.ts +121 -7
  284. package/src/plugins/analysis/ast/GraphBuilder.ts +1578 -70
  285. package/src/plugins/analysis/ast/types.ts +387 -0
  286. package/src/plugins/analysis/ast/visitors/ASTVisitor.ts +8 -0
  287. package/src/plugins/analysis/ast/visitors/CallExpressionVisitor.ts +16 -1
  288. package/src/plugins/analysis/ast/visitors/FunctionVisitor.ts +77 -2
  289. package/src/plugins/analysis/ast/visitors/ImportExportVisitor.ts +112 -1
  290. package/src/plugins/analysis/ast/visitors/VariableVisitor.ts +272 -47
  291. package/src/plugins/discovery/WorkspaceDiscovery.ts +11 -4
  292. package/src/plugins/enrichment/AliasTracker.ts +22 -1
  293. package/src/plugins/enrichment/ArgumentParameterLinker.ts +240 -0
  294. package/src/plugins/enrichment/ClosureCaptureEnricher.ts +267 -0
  295. package/src/plugins/enrichment/ExternalCallResolver.ts +262 -0
  296. package/src/plugins/enrichment/FunctionCallResolver.ts +456 -0
  297. package/src/plugins/enrichment/HTTPConnectionEnricher.ts +70 -20
  298. package/src/plugins/enrichment/MethodCallResolver.ts +21 -1
  299. package/src/plugins/enrichment/MountPointResolver.ts +206 -198
  300. package/src/plugins/enrichment/NodejsBuiltinsResolver.ts +365 -0
  301. package/src/plugins/enrichment/ValueDomainAnalyzer.ts +67 -184
  302. package/src/plugins/indexing/JSModuleIndexer.ts +66 -0
  303. package/src/plugins/indexing/RustModuleIndexer.ts +4 -4
  304. package/src/plugins/validation/BrokenImportValidator.ts +325 -0
  305. package/src/plugins/validation/CallResolverValidator.ts +129 -109
  306. package/src/plugins/validation/DataFlowValidator.ts +75 -58
  307. package/src/plugins/validation/GraphConnectivityValidator.ts +39 -1
  308. package/src/plugins/validation/SQLInjectionValidator.ts +2 -5
  309. package/src/queries/README.md +46 -0
  310. package/src/queries/findCallsInFunction.ts +206 -0
  311. package/src/queries/findContainingFunction.ts +83 -0
  312. package/src/queries/index.ts +23 -0
  313. package/src/queries/traceValues.ts +398 -0
  314. package/src/queries/types.ts +187 -0
  315. package/src/schema/GraphSchemaExtractor.ts +177 -0
  316. package/src/schema/InterfaceSchemaExtractor.ts +173 -0
  317. package/src/schema/index.ts +5 -0
  318. package/src/storage/backends/RFDBServerBackend.ts +58 -70
  319. package/src/storage/backends/typeValidation.ts +1 -0
@@ -1,16 +1,18 @@
1
1
  /**
2
- * CallResolverValidator - проверяет что все вызовы функций ссылаются на определения
2
+ * CallResolverValidator - validates function call resolution (REG-227)
3
3
  *
4
- * Использует Datalog для декларативной проверки гарантии:
5
- * "Все внутренние вызовы функций (CALL_SITE) должны иметь CALLS ребро к FUNCTION"
4
+ * Checks that all function calls are properly resolved:
5
+ * - Internal calls: CALLS edge to FUNCTION node
6
+ * - External calls: CALLS edge to EXTERNAL_MODULE node
7
+ * - Builtin calls: recognized by name (no edge needed)
8
+ * - Unresolved: no edge, not builtin -> WARNING
6
9
  *
7
- * ПРАВИЛО (Datalog):
8
- * violation(X) :- node(X, "CALL"), \+ attr(X, "object", _), \+ edge(X, _, "CALLS").
9
- *
10
- * Это находит CALL узлы без "object" метаданных (т.е. CALL_SITE, не METHOD_CALL),
11
- * которые не имеют CALLS ребра к определению функции.
10
+ * This validator runs AFTER FunctionCallResolver and ExternalCallResolver
11
+ * to verify resolution quality and report issues.
12
12
  */
13
13
  import { Plugin, createSuccessResult } from '../Plugin.js';
14
+ import { ValidationError } from '../../errors/GrafemaError.js';
15
+ import { JS_GLOBAL_FUNCTIONS } from '../../data/builtins/index.js';
14
16
  export class CallResolverValidator extends Plugin {
15
17
  get metadata() {
16
18
  return {
@@ -20,90 +22,113 @@ export class CallResolverValidator extends Plugin {
20
22
  creates: {
21
23
  nodes: [],
22
24
  edges: []
23
- }
25
+ },
26
+ dependencies: ['FunctionCallResolver', 'ExternalCallResolver']
24
27
  };
25
28
  }
26
29
  async execute(context) {
27
30
  const { graph } = context;
28
31
  const logger = this.log(context);
29
- logger.info('Starting call resolution validation using Datalog');
30
- // Check if graph supports checkGuarantee
31
- if (!graph.checkGuarantee) {
32
- logger.debug('Graph does not support checkGuarantee, skipping validation');
33
- return createSuccessResult({ nodes: 0, edges: 0 }, { skipped: true });
34
- }
35
- // Datalog гарантия:
36
- // CALL без "object" (т.е. CALL_SITE) должен иметь CALLS ребро
37
- const violations = await graph.checkGuarantee(`
38
- violation(X) :- node(X, "CALL"), \\+ attr(X, "object", _), \\+ edge(X, _, "CALLS").
39
- `);
40
- const issues = [];
41
- if (violations.length > 0) {
42
- logger.debug('Unresolved function calls found', { count: violations.length });
43
- for (const v of violations) {
44
- const nodeId = v.bindings.find(b => b.name === 'X')?.value;
45
- if (nodeId) {
46
- const node = await graph.getNode(nodeId);
47
- if (node) {
48
- issues.push({
49
- type: 'UNRESOLVED_FUNCTION_CALL',
50
- severity: 'WARNING',
51
- message: `Call to "${node.name}" at ${node.file}:${node.line || '?'} does not resolve to a function definition`,
52
- callName: node.name,
53
- nodeId: nodeId,
54
- file: node.file,
55
- line: node.line
56
- });
57
- }
58
- }
59
- }
60
- }
61
- // Также проверим METHOD_CALL на известные внешние методы
62
- // (это информационно, не ошибка)
63
- const methodCallStats = await this.countMethodCalls(graph);
32
+ logger.info('Starting call resolution validation');
33
+ const warnings = [];
64
34
  const summary = {
65
- totalCalls: methodCallStats.total,
66
- resolvedInternalCalls: methodCallStats.resolved,
67
- unresolvedInternalCalls: issues.length,
68
- externalMethodCalls: methodCallStats.external,
69
- issues: issues.length
35
+ totalCalls: 0,
36
+ resolvedInternal: 0,
37
+ resolvedExternal: 0,
38
+ resolvedBuiltin: 0,
39
+ methodCalls: 0,
40
+ unresolvedCalls: 0,
41
+ warnings: 0
70
42
  };
43
+ // Process all CALL nodes
44
+ for await (const node of graph.queryNodes({ nodeType: 'CALL' })) {
45
+ summary.totalCalls++;
46
+ const callNode = node;
47
+ const resolutionType = await this.determineResolutionType(graph, callNode);
48
+ switch (resolutionType) {
49
+ case 'internal':
50
+ summary.resolvedInternal++;
51
+ break;
52
+ case 'external':
53
+ summary.resolvedExternal++;
54
+ break;
55
+ case 'builtin':
56
+ summary.resolvedBuiltin++;
57
+ break;
58
+ case 'method':
59
+ summary.methodCalls++;
60
+ break;
61
+ case 'unresolved':
62
+ summary.unresolvedCalls++;
63
+ summary.warnings++;
64
+ warnings.push(this.createWarning(callNode));
65
+ break;
66
+ }
67
+ }
71
68
  logger.info('Validation complete', { ...summary });
72
- if (issues.length > 0) {
73
- logger.warn('Unresolved calls detected', { count: issues.length });
74
- for (const issue of issues.slice(0, 10)) { // Show first 10
75
- logger.warn(issue.message);
69
+ if (warnings.length > 0) {
70
+ logger.warn('Unresolved calls detected', { count: warnings.length });
71
+ for (const warning of warnings.slice(0, 10)) {
72
+ logger.warn(warning.message);
76
73
  }
77
- if (issues.length > 10) {
78
- logger.debug(`... and ${issues.length - 10} more`);
74
+ if (warnings.length > 10) {
75
+ logger.debug(`... and ${warnings.length - 10} more`);
79
76
  }
80
77
  }
81
- return createSuccessResult({ nodes: 0, edges: 0 }, { summary, issues });
78
+ return createSuccessResult({ nodes: 0, edges: 0 }, { summary }, warnings);
82
79
  }
83
80
  /**
84
- * Подсчитывает статистику по вызовам
81
+ * Determine the resolution type for a CALL node.
82
+ *
83
+ * Resolution priority:
84
+ * 1. Method call (has 'object' attribute) -> 'method'
85
+ * 2. Has CALLS edge to FUNCTION -> 'internal'
86
+ * 3. Has CALLS edge to EXTERNAL_MODULE -> 'external'
87
+ * 4. Name in JS_GLOBAL_FUNCTIONS -> 'builtin'
88
+ * 5. Otherwise -> 'unresolved'
85
89
  */
86
- async countMethodCalls(graph) {
87
- const stats = {
88
- total: 0,
89
- resolved: 0,
90
- external: 0
91
- };
92
- // Подсчитываем все CALL узлы
93
- for await (const node of graph.queryNodes({ nodeType: 'CALL' })) {
94
- stats.total++;
95
- // Проверяем наличие "object" в метаданных (METHOD_CALL)
96
- if (node.object) {
97
- stats.external++;
98
- }
99
- else {
100
- // CALL_SITE - проверяем есть ли CALLS ребро
101
- const edges = await graph.getOutgoingEdges(node.id, ['CALLS']);
102
- if (edges.length > 0) {
103
- stats.resolved++;
90
+ async determineResolutionType(graph, callNode) {
91
+ // 1. Check if method call (has object attribute)
92
+ if (callNode.object) {
93
+ return 'method';
94
+ }
95
+ // 2. Check for CALLS edges
96
+ const edges = await graph.getOutgoingEdges(callNode.id, ['CALLS']);
97
+ if (edges.length > 0) {
98
+ // Determine destination type
99
+ const edge = edges[0];
100
+ const dstNode = await graph.getNode(edge.dst);
101
+ if (dstNode) {
102
+ if (dstNode.type === 'FUNCTION') {
103
+ return 'internal';
104
+ }
105
+ if (dstNode.type === 'EXTERNAL_MODULE') {
106
+ return 'external';
104
107
  }
105
108
  }
109
+ // Has edge but unknown destination type - treat as resolved
110
+ return 'internal';
111
+ }
112
+ // 3. Check if builtin
113
+ const calledName = callNode.name;
114
+ if (calledName && JS_GLOBAL_FUNCTIONS.has(calledName)) {
115
+ return 'builtin';
106
116
  }
107
- return stats;
117
+ // 4. Unresolved
118
+ return 'unresolved';
119
+ }
120
+ /**
121
+ * Create a warning for an unresolved call.
122
+ */
123
+ createWarning(callNode) {
124
+ return new ValidationError(`Unresolved call to "${callNode.name}" at ${callNode.file}:${callNode.line || '?'}`, 'WARN_UNRESOLVED_CALL', {
125
+ filePath: callNode.file,
126
+ lineNumber: callNode.line,
127
+ phase: 'VALIDATION',
128
+ plugin: 'CallResolverValidator',
129
+ nodeId: callNode.id,
130
+ callName: callNode.name,
131
+ }, 'Ensure the function is defined, imported, or is a known global', 'warning' // Severity: warning (not error)
132
+ );
108
133
  }
109
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataFlowValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/DataFlowValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA4ChF,qBAAa,iBAAkB,SAAQ,MAAM;IAC3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAsH5D;;OAEG;IACH,OAAO,CAAC,cAAc;CA2CvB"}
1
+ {"version":3,"file":"DataFlowValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/DataFlowValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAgChF,qBAAa,iBAAkB,SAAQ,MAAM;IAC3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAwI5D;;OAEG;IACH,OAAO,CAAC,cAAc;CAsDvB"}
@@ -12,6 +12,7 @@
12
12
  * - EVENT_LISTENER: события
13
13
  */
14
14
  import { Plugin, createSuccessResult } from '../Plugin.js';
15
+ import { ValidationError } from '../../errors/GrafemaError.js';
15
16
  export class DataFlowValidator extends Plugin {
16
17
  get metadata() {
17
18
  return {
@@ -38,7 +39,7 @@ export class DataFlowValidator extends Plugin {
38
39
  const allEdges = await graph.getAllEdges();
39
40
  const variables = allNodes.filter(n => n.type === 'VARIABLE_DECLARATION' || n.type === 'CONSTANT');
40
41
  logger.debug('Variables collected', { count: variables.length });
41
- const issues = [];
42
+ const errors = [];
42
43
  const leafTypes = new Set([
43
44
  'LITERAL',
44
45
  'net:stdio',
@@ -55,70 +56,69 @@ export class DataFlowValidator extends Plugin {
55
56
  // Проверяем наличие ASSIGNED_FROM ребра
56
57
  const assignment = allEdges.find(e => e.type === 'ASSIGNED_FROM' && e.src === variable.id);
57
58
  if (!assignment) {
58
- issues.push({
59
- type: 'MISSING_ASSIGNMENT',
60
- severity: 'WARNING',
61
- message: `Variable "${variable.name}" (${variable.file}:${variable.line}) has no ASSIGNED_FROM edge`,
59
+ errors.push(new ValidationError(`Variable "${variable.name}" (${variable.file}:${variable.line}) has no ASSIGNED_FROM edge`, 'ERR_MISSING_ASSIGNMENT', {
60
+ filePath: variable.file,
61
+ lineNumber: variable.line,
62
+ phase: 'VALIDATION',
63
+ plugin: 'DataFlowValidator',
62
64
  variable: variable.name,
63
- file: variable.file,
64
- line: variable.line
65
- });
65
+ }, undefined, 'warning'));
66
66
  continue;
67
67
  }
68
68
  // Проверяем что источник существует
69
69
  const source = allNodes.find(n => n.id === assignment.dst);
70
70
  if (!source) {
71
- issues.push({
72
- type: 'BROKEN_REFERENCE',
73
- severity: 'ERROR',
74
- message: `Variable "${variable.name}" references non-existent node ${assignment.dst}`,
71
+ errors.push(new ValidationError(`Variable "${variable.name}" references non-existent node ${assignment.dst}`, 'ERR_BROKEN_REFERENCE', {
72
+ filePath: variable.file,
73
+ lineNumber: variable.line,
74
+ phase: 'VALIDATION',
75
+ plugin: 'DataFlowValidator',
75
76
  variable: variable.name,
76
- file: variable.file,
77
- line: variable.line
78
- });
77
+ targetNodeId: assignment.dst,
78
+ }, undefined, 'error'));
79
79
  continue;
80
80
  }
81
81
  // Проверяем путь до листового узла
82
82
  const path = this.findPathToLeaf(variable, allNodes, allEdges, leafTypes);
83
83
  if (!path.found) {
84
- issues.push({
85
- type: 'NO_LEAF_NODE',
86
- severity: 'WARNING',
87
- message: `Variable "${variable.name}" (${variable.file}:${variable.line}) does not trace to a leaf node. Chain: ${path.chain.join(' -> ')}`,
84
+ errors.push(new ValidationError(`Variable "${variable.name}" (${variable.file}:${variable.line}) does not trace to a leaf node. Chain: ${path.chain.join(' -> ')}`, 'ERR_NO_LEAF_NODE', {
85
+ filePath: variable.file,
86
+ lineNumber: variable.line,
87
+ phase: 'VALIDATION',
88
+ plugin: 'DataFlowValidator',
88
89
  variable: variable.name,
89
- file: variable.file,
90
- line: variable.line,
91
- chain: path.chain
92
- });
90
+ chain: path.chain,
91
+ }, undefined, 'warning'));
93
92
  }
94
93
  }
95
- // Группируем issues по типу
94
+ // Группируем errors по коду
95
+ const byCode = {};
96
+ for (const error of errors) {
97
+ if (!byCode[error.code]) {
98
+ byCode[error.code] = 0;
99
+ }
100
+ byCode[error.code]++;
101
+ }
96
102
  const summary = {
97
103
  total: variables.length,
98
- validated: variables.length - issues.length,
99
- issues: issues.length,
100
- byType: {}
104
+ validated: variables.length - errors.length,
105
+ issues: errors.length,
106
+ byType: byCode
101
107
  };
102
- for (const issue of issues) {
103
- if (!summary.byType[issue.type]) {
104
- summary.byType[issue.type] = 0;
105
- }
106
- summary.byType[issue.type]++;
107
- }
108
108
  logger.info('Validation complete', { ...summary });
109
- // Выводим issues
110
- if (issues.length > 0) {
111
- logger.warn('Data flow issues found', { count: issues.length });
112
- for (const issue of issues) {
113
- if (issue.severity === 'ERROR') {
114
- logger.error(`[${issue.type}] ${issue.message}`);
109
+ // Выводим errors
110
+ if (errors.length > 0) {
111
+ logger.warn('Data flow issues found', { count: errors.length });
112
+ for (const error of errors) {
113
+ if (error.severity === 'error') {
114
+ logger.error(`[${error.code}] ${error.message}`);
115
115
  }
116
116
  else {
117
- logger.warn(`[${issue.type}] ${issue.message}`);
117
+ logger.warn(`[${error.code}] ${error.message}`);
118
118
  }
119
119
  }
120
120
  }
121
- return createSuccessResult({ nodes: 0, edges: 0 }, { summary, issues });
121
+ return createSuccessResult({ nodes: 0, edges: 0 }, { summary }, errors);
122
122
  }
123
123
  /**
124
124
  * Находит путь от переменной до листового узла
@@ -134,6 +134,14 @@ export class DataFlowValidator extends Plugin {
134
134
  if (leafTypes.has(startNode.type)) {
135
135
  return { found: true, chain };
136
136
  }
137
+ // REG-262: Check if variable is used by a method call (incoming USES edge)
138
+ // If something USES this variable, the variable is not dead
139
+ const usedByCall = allEdges.find(e => e.type === 'USES' && e.dst === startNode.id);
140
+ if (usedByCall) {
141
+ const callNode = allNodes.find(n => n.id === usedByCall.src);
142
+ const callName = callNode?.name ?? usedByCall.src;
143
+ return { found: true, chain: [...chain, `(used by ${callName})`] };
144
+ }
137
145
  // Ищем ASSIGNED_FROM ребро
138
146
  const assignment = allEdges.find(e => e.type === 'ASSIGNED_FROM' && e.src === startNode.id);
139
147
  if (!assignment) {
@@ -1 +1 @@
1
- {"version":3,"file":"GraphConnectivityValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/GraphConnectivityValidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAyChF,qBAAa,0BAA2B,SAAQ,MAAM;IACpD,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAwI7D"}
1
+ {"version":3,"file":"GraphConnectivityValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/GraphConnectivityValidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA0ChF,qBAAa,0BAA2B,SAAQ,MAAM;IACpD,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CA6K7D"}
@@ -3,6 +3,7 @@
3
3
  * Находит "островки" - узлы которые не имеют путей до SERVICE/MODULE
4
4
  */
5
5
  import { Plugin, createSuccessResult } from '../Plugin.js';
6
+ import { ValidationError } from '../../errors/GrafemaError.js';
6
7
  export class GraphConnectivityValidator extends Plugin {
7
8
  get metadata() {
8
9
  return {
@@ -73,6 +74,7 @@ export class GraphConnectivityValidator extends Plugin {
73
74
  }
74
75
  // Находим недостижимые узлы
75
76
  const unreachable = allNodes.filter(n => !reachable.has(n.id));
77
+ const errors = [];
76
78
  if (unreachable.length > 0) {
77
79
  const percentage = ((unreachable.length / allNodes.length) * 100).toFixed(1);
78
80
  logger.error('GRAPH VALIDATION ERROR: DISCONNECTED NODES FOUND');
@@ -116,6 +118,28 @@ export class GraphConnectivityValidator extends Plugin {
116
118
  manifestWithValidation.validation.reachableNodes = reachable.size;
117
119
  manifestWithValidation.validation.unreachableCount = unreachable.length;
118
120
  manifestWithValidation.validation.unreachableByType = Object.fromEntries(Object.entries(byType).map(([type, nodes]) => [type, nodes.length]));
121
+ // Create summary error for disconnected nodes
122
+ errors.push(new ValidationError(`Found ${unreachable.length} unreachable nodes (${percentage}% of total)`, 'ERR_DISCONNECTED_NODES', {
123
+ phase: 'VALIDATION',
124
+ plugin: 'GraphConnectivityValidator',
125
+ totalNodes: allNodes.length,
126
+ reachableNodes: reachable.size,
127
+ unreachableCount: unreachable.length,
128
+ unreachableByType: Object.fromEntries(Object.entries(byType).map(([type, nodes]) => [type, nodes.length])),
129
+ }, 'Fix analysis plugins to ensure all nodes are connected'));
130
+ // Create individual errors for each disconnected node (limit to 50)
131
+ const maxIndividualErrors = 50;
132
+ for (const node of unreachable.slice(0, maxIndividualErrors)) {
133
+ errors.push(new ValidationError(`Node "${node.name || node.id}" (type: ${node.type}) is not connected to the main graph`, 'ERR_DISCONNECTED_NODE', {
134
+ filePath: node.file,
135
+ lineNumber: node.line,
136
+ phase: 'VALIDATION',
137
+ plugin: 'GraphConnectivityValidator',
138
+ nodeId: node.id,
139
+ nodeType: node.type,
140
+ nodeName: node.name,
141
+ }));
142
+ }
119
143
  }
120
144
  else {
121
145
  logger.info('All nodes are reachable from root nodes');
@@ -126,6 +150,6 @@ export class GraphConnectivityValidator extends Plugin {
126
150
  manifestWithValidation.validation.reachableNodes = reachable.size;
127
151
  }
128
152
  logger.info('Validation complete', { reachable: reachable.size, total: allNodes.length });
129
- return createSuccessResult({ nodes: 0, edges: 0 }, { totalNodes: allNodes.length, reachableNodes: reachable.size });
153
+ return createSuccessResult({ nodes: 0, edges: 0 }, { totalNodes: allNodes.length, reachableNodes: reachable.size }, errors);
130
154
  }
131
155
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SQLInjectionValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/SQLInjectionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsEhF,qBAAa,qBAAsB,SAAQ,MAAM;IAC/C,OAAO,CAAC,aAAa,CAAsB;;IAO3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAgH5D;;OAEG;YACW,gBAAgB;IAgF9B;;OAEG;YACW,gCAAgC;IAsC9C;;;OAGG;YACW,oBAAoB;CAsDnC;AAED,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"SQLInjectionValidator.d.ts","sourceRoot":"","sources":["../../../src/plugins/validation/SQLInjectionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAuB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAsEhF,qBAAa,qBAAsB,SAAQ,MAAM;IAC/C,OAAO,CAAC,aAAa,CAAsB;;IAO3C,IAAI,QAAQ,IAAI,cAAc,CAU7B;IAEK,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAgH5D;;OAEG;YACW,gBAAgB;IA8E9B;;OAEG;YACW,gCAAgC;IAqC9C;;;OAGG;YACW,oBAAoB;CAsDnC;AAED,eAAe,qBAAqB,CAAC"}
@@ -149,7 +149,7 @@ export class SQLInjectionValidator extends Plugin {
149
149
  // We need to check if it has nondeterministic content
150
150
  // Check if this call has PASSES_ARGUMENT edges
151
151
  const outgoing = await graph.getOutgoingEdges(call.id);
152
- const argEdges = outgoing.filter(e => (e.edgeType || e.edge_type) === 'PASSES_ARGUMENT');
152
+ const argEdges = outgoing.filter(e => e.type === 'PASSES_ARGUMENT');
153
153
  if (argEdges.length === 0) {
154
154
  // No tracked arguments - check via queryArgName attribute if available
155
155
  if (call.queryArgName) {
@@ -214,8 +214,7 @@ export class SQLInjectionValidator extends Plugin {
214
214
  const result = { hasUnknown: false, sources: [] };
215
215
  // Check DERIVES_FROM edges
216
216
  const outgoing = await graph.getOutgoingEdges(exprNode.id);
217
- const derivesFromEdges = outgoing.filter(e => (e.edgeType || e.edge_type) === 'DERIVES_FROM' ||
218
- (e.edgeType || e.edge_type) === 'ASSIGNED_FROM');
217
+ const derivesFromEdges = outgoing.filter(e => e.type === 'DERIVES_FROM' || e.type === 'ASSIGNED_FROM');
219
218
  for (const edge of derivesFromEdges) {
220
219
  const sourceId = edge.dst || edge.target_id;
221
220
  const sourceNode = await graph.getNode(sourceId);
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Find all CALL and METHOD_CALL nodes inside a function.
3
+ *
4
+ * Graph structure:
5
+ * ```
6
+ * FUNCTION -[HAS_SCOPE]-> SCOPE -[CONTAINS]-> CALL
7
+ * SCOPE -[CONTAINS]-> METHOD_CALL
8
+ * SCOPE -[CONTAINS]-> SCOPE (nested blocks)
9
+ * ```
10
+ *
11
+ * Algorithm:
12
+ * 1. Get function's scope via HAS_SCOPE edge
13
+ * 2. BFS through CONTAINS edges, collecting CALL and METHOD_CALL nodes
14
+ * 3. Stop at nested FUNCTION/CLASS boundaries (don't enter inner functions)
15
+ * 4. For each call, check CALLS edge to determine if resolved
16
+ * 5. If transitive=true, recursively follow resolved CALLS edges
17
+ *
18
+ * Performance: O(S + C) where S = scopes, C = calls
19
+ * For functions with 100 calls, expect ~200 DB operations.
20
+ *
21
+ * @module queries/findCallsInFunction
22
+ */
23
+ import type { CallInfo, FindCallsOptions } from './types.js';
24
+ /**
25
+ * Graph backend interface (minimal surface)
26
+ */
27
+ interface GraphBackend {
28
+ getNode(id: string): Promise<{
29
+ id: string;
30
+ type: string;
31
+ name: string;
32
+ file?: string;
33
+ line?: number;
34
+ object?: string;
35
+ } | null>;
36
+ getOutgoingEdges(nodeId: string, edgeTypes: string[] | null): Promise<Array<{
37
+ src: string;
38
+ dst: string;
39
+ type: string;
40
+ }>>;
41
+ }
42
+ /**
43
+ * Find all CALL and METHOD_CALL nodes inside a function.
44
+ *
45
+ * @param backend - Graph backend for queries
46
+ * @param functionId - ID of the FUNCTION node
47
+ * @param options - Options for traversal
48
+ * @returns Array of CallInfo objects
49
+ */
50
+ export declare function findCallsInFunction(backend: GraphBackend, functionId: string, options?: FindCallsOptions): Promise<CallInfo[]>;
51
+ export {};
52
+ //# sourceMappingURL=findCallsInFunction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findCallsInFunction.d.ts","sourceRoot":"","sources":["../../src/queries/findCallsInFunction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE7D;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAC3B,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC,CAAC;IACV,gBAAgB,CACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,GACzB,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAkErB"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Find all CALL and METHOD_CALL nodes inside a function.
3
+ *
4
+ * Graph structure:
5
+ * ```
6
+ * FUNCTION -[HAS_SCOPE]-> SCOPE -[CONTAINS]-> CALL
7
+ * SCOPE -[CONTAINS]-> METHOD_CALL
8
+ * SCOPE -[CONTAINS]-> SCOPE (nested blocks)
9
+ * ```
10
+ *
11
+ * Algorithm:
12
+ * 1. Get function's scope via HAS_SCOPE edge
13
+ * 2. BFS through CONTAINS edges, collecting CALL and METHOD_CALL nodes
14
+ * 3. Stop at nested FUNCTION/CLASS boundaries (don't enter inner functions)
15
+ * 4. For each call, check CALLS edge to determine if resolved
16
+ * 5. If transitive=true, recursively follow resolved CALLS edges
17
+ *
18
+ * Performance: O(S + C) where S = scopes, C = calls
19
+ * For functions with 100 calls, expect ~200 DB operations.
20
+ *
21
+ * @module queries/findCallsInFunction
22
+ */
23
+ /**
24
+ * Find all CALL and METHOD_CALL nodes inside a function.
25
+ *
26
+ * @param backend - Graph backend for queries
27
+ * @param functionId - ID of the FUNCTION node
28
+ * @param options - Options for traversal
29
+ * @returns Array of CallInfo objects
30
+ */
31
+ export async function findCallsInFunction(backend, functionId, options = {}) {
32
+ const { maxDepth = 10, transitive = false, transitiveDepth = 5, } = options;
33
+ const calls = [];
34
+ const visited = new Set();
35
+ const seenTargets = new Set(); // For deduplication in transitive mode
36
+ // Add the starting function to seenTargets to prevent cycles back to it
37
+ if (transitive) {
38
+ seenTargets.add(functionId);
39
+ }
40
+ // Step 1: Get function's scope via HAS_SCOPE
41
+ const hasScopeEdges = await backend.getOutgoingEdges(functionId, ['HAS_SCOPE']);
42
+ // BFS queue: { nodeId, currentDepth }
43
+ const queue = [];
44
+ for (const edge of hasScopeEdges) {
45
+ queue.push({ id: edge.dst, depth: 0 });
46
+ }
47
+ // Step 2: BFS through scopes
48
+ while (queue.length > 0) {
49
+ const { id, depth } = queue.shift();
50
+ if (visited.has(id) || depth > maxDepth)
51
+ continue;
52
+ visited.add(id);
53
+ const containsEdges = await backend.getOutgoingEdges(id, ['CONTAINS']);
54
+ for (const edge of containsEdges) {
55
+ const child = await backend.getNode(edge.dst);
56
+ if (!child)
57
+ continue;
58
+ // Collect CALL and METHOD_CALL nodes
59
+ if (child.type === 'CALL' || child.type === 'METHOD_CALL') {
60
+ const callInfo = await buildCallInfo(backend, child, 0);
61
+ calls.push(callInfo);
62
+ // Transitive: follow resolved calls
63
+ if (transitive && callInfo.resolved && callInfo.target) {
64
+ await collectTransitiveCalls(backend, callInfo.target.id, 1, // Starting at depth 1
65
+ transitiveDepth, calls, seenTargets);
66
+ }
67
+ }
68
+ // Continue into nested scopes, but NOT into nested functions/classes
69
+ if (child.type === 'SCOPE') {
70
+ queue.push({ id: child.id, depth: depth + 1 });
71
+ }
72
+ // Skip FUNCTION, CLASS - they have their own scope hierarchy
73
+ }
74
+ }
75
+ return calls;
76
+ }
77
+ /**
78
+ * Build CallInfo from a call node
79
+ */
80
+ async function buildCallInfo(backend, callNode, depth) {
81
+ // Check for CALLS edge (resolved target)
82
+ const callsEdges = await backend.getOutgoingEdges(callNode.id, ['CALLS']);
83
+ const isResolved = callsEdges.length > 0;
84
+ let target = undefined;
85
+ if (isResolved) {
86
+ const targetNode = await backend.getNode(callsEdges[0].dst);
87
+ if (targetNode) {
88
+ target = {
89
+ id: targetNode.id,
90
+ name: targetNode.name,
91
+ file: targetNode.file,
92
+ line: targetNode.line,
93
+ };
94
+ }
95
+ }
96
+ return {
97
+ id: callNode.id,
98
+ name: callNode.name,
99
+ type: callNode.type,
100
+ object: callNode.object,
101
+ resolved: isResolved,
102
+ target,
103
+ file: callNode.file,
104
+ line: callNode.line,
105
+ depth,
106
+ };
107
+ }
108
+ /**
109
+ * Recursively collect transitive calls
110
+ *
111
+ * Infinite loop prevention:
112
+ * - Track seen function IDs in seenTargets
113
+ * - Stop when we've seen a function before (handles recursion)
114
+ * - Stop at transitiveDepth limit
115
+ */
116
+ async function collectTransitiveCalls(backend, functionId, currentDepth, maxTransitiveDepth, calls, seenTargets) {
117
+ // Prevent infinite loops and limit depth
118
+ if (seenTargets.has(functionId) || currentDepth > maxTransitiveDepth) {
119
+ return;
120
+ }
121
+ seenTargets.add(functionId);
122
+ // Find calls in this function (non-transitive to avoid recursion)
123
+ const innerCalls = await findCallsInFunction(backend, functionId, {
124
+ maxDepth: 10,
125
+ transitive: false,
126
+ });
127
+ for (const call of innerCalls) {
128
+ // Add with updated depth
129
+ calls.push({ ...call, depth: currentDepth });
130
+ // Continue transitively if resolved
131
+ if (call.resolved && call.target) {
132
+ await collectTransitiveCalls(backend, call.target.id, currentDepth + 1, maxTransitiveDepth, calls, seenTargets);
133
+ }
134
+ }
135
+ }