@optave/codegraph 3.12.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -46
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +38 -40
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/b2.d.ts +7 -0
- package/dist/ast-analysis/rules/b2.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b2.js +240 -0
- package/dist/ast-analysis/rules/b2.js.map +1 -0
- package/dist/ast-analysis/rules/b3.d.ts +6 -0
- package/dist/ast-analysis/rules/b3.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b3.js +105 -0
- package/dist/ast-analysis/rules/b3.js.map +1 -0
- package/dist/ast-analysis/rules/b4.d.ts +9 -0
- package/dist/ast-analysis/rules/b4.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b4.js +361 -0
- package/dist/ast-analysis/rules/b4.js.map +1 -0
- package/dist/ast-analysis/rules/b5.d.ts +4 -0
- package/dist/ast-analysis/rules/b5.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b5.js +52 -0
- package/dist/ast-analysis/rules/b5.js.map +1 -0
- package/dist/ast-analysis/rules/c.d.ts +4 -0
- package/dist/ast-analysis/rules/c.d.ts.map +1 -0
- package/dist/ast-analysis/rules/c.js +143 -0
- package/dist/ast-analysis/rules/c.js.map +1 -0
- package/dist/ast-analysis/rules/index.d.ts.map +1 -1
- package/dist/ast-analysis/rules/index.js +34 -0
- package/dist/ast-analysis/rules/index.js.map +1 -1
- package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
- package/dist/ast-analysis/rules/javascript.js +3 -0
- package/dist/ast-analysis/rules/javascript.js.map +1 -1
- package/dist/ast-analysis/shared.d.ts.map +1 -1
- package/dist/ast-analysis/shared.js +2 -0
- package/dist/ast-analysis/shared.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts +1 -0
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +5 -0
- package/dist/ast-analysis/visitor-utils.js.map +1 -1
- package/dist/ast-analysis/visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitor.js +60 -47
- package/dist/ast-analysis/visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/cfg-visitor.js +126 -76
- package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js +27 -15
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js +54 -21
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +2 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +1 -0
- package/dist/cli/commands/batch.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +6 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +275 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/roles.d.ts.map +1 -1
- package/dist/cli/commands/roles.js +6 -1
- package/dist/cli/commands/roles.js.map +1 -1
- package/dist/cli/commands/triage.js +1 -1
- package/dist/cli/commands/triage.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/shared/options.d.ts +2 -1
- package/dist/cli/shared/options.d.ts.map +1 -1
- package/dist/cli/shared/options.js +11 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/db/better-sqlite3.d.ts +2 -1
- package/dist/db/better-sqlite3.d.ts.map +1 -1
- package/dist/db/better-sqlite3.js.map +1 -1
- package/dist/db/connection.d.ts +7 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +20 -5
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +69 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/repository/build-stmts.d.ts.map +1 -1
- package/dist/db/repository/build-stmts.js +18 -0
- package/dist/db/repository/build-stmts.js.map +1 -1
- package/dist/db/repository/dataflow.d.ts +5 -0
- package/dist/db/repository/dataflow.d.ts.map +1 -1
- package/dist/db/repository/dataflow.js +14 -0
- package/dist/db/repository/dataflow.js.map +1 -1
- package/dist/db/repository/index.d.ts +1 -1
- package/dist/db/repository/index.d.ts.map +1 -1
- package/dist/db/repository/index.js +1 -1
- package/dist/db/repository/index.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts.map +1 -1
- package/dist/db/repository/native-repository.js +47 -34
- package/dist/db/repository/native-repository.js.map +1 -1
- package/dist/domain/analysis/context.d.ts +2 -2
- package/dist/domain/analysis/dependencies.d.ts +2 -2
- package/dist/domain/analysis/diff-impact.d.ts +2 -2
- package/dist/domain/analysis/fn-impact.d.ts +3 -1
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +4 -0
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/implementations.d.ts +2 -2
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +32 -5
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/roles.d.ts +7 -1
- package/dist/domain/analysis/roles.d.ts.map +1 -1
- package/dist/domain/analysis/roles.js +16 -0
- package/dist/domain/analysis/roles.js.map +1 -1
- package/dist/domain/analysis/symbol-lookup.d.ts +4 -4
- package/dist/domain/graph/builder/call-resolver.d.ts +29 -13
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +125 -205
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/cha.d.ts +9 -1
- package/dist/domain/graph/builder/cha.d.ts.map +1 -1
- package/dist/domain/graph/builder/cha.js +17 -2
- package/dist/domain/graph/builder/cha.js.map +1 -1
- package/dist/domain/graph/builder/context.d.ts +1 -0
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +24 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +174 -65
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +166 -97
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +46 -5
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts +0 -2
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +554 -538
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +10 -7
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +3 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +4 -0
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.js +952 -343
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/resolver/points-to.d.ts.map +1 -1
- package/dist/domain/graph/resolver/points-to.js +105 -57
- package/dist/domain/graph/resolver/points-to.js.map +1 -1
- package/dist/domain/graph/resolver/strategy.d.ts +61 -0
- package/dist/domain/graph/resolver/strategy.d.ts.map +1 -0
- package/dist/domain/graph/resolver/strategy.js +222 -0
- package/dist/domain/graph/resolver/strategy.js.map +1 -0
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +16 -9
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +16 -5
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +58 -17
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/queries.d.ts +1 -1
- package/dist/domain/queries.d.ts.map +1 -1
- package/dist/domain/queries.js +1 -1
- package/dist/domain/queries.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +13 -2
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
- package/dist/domain/wasm-worker-pool.js +26 -5
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +8 -0
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/cpp.d.ts.map +1 -1
- package/dist/extractors/cpp.js +42 -1
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/cuda.d.ts.map +1 -1
- package/dist/extractors/cuda.js +42 -1
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/dart.js +48 -3
- package/dist/extractors/dart.js.map +1 -1
- package/dist/extractors/groovy.js +62 -3
- package/dist/extractors/groovy.js.map +1 -1
- package/dist/extractors/helpers.d.ts +15 -2
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +45 -1
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +85 -8
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +686 -169
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +58 -3
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/objc.js +25 -2
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/scala.js +62 -2
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/swift.js +52 -3
- package/dist/extractors/swift.js.map +1 -1
- package/dist/features/audit.js +26 -23
- package/dist/features/audit.js.map +1 -1
- package/dist/features/boundaries.d.ts.map +1 -1
- package/dist/features/boundaries.js +12 -9
- package/dist/features/boundaries.js.map +1 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +25 -18
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +18 -5
- package/dist/features/check.js.map +1 -1
- package/dist/features/communities.d.ts +4 -2
- package/dist/features/communities.d.ts.map +1 -1
- package/dist/features/communities.js +6 -4
- package/dist/features/communities.js.map +1 -1
- package/dist/features/dataflow.d.ts +60 -0
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +530 -6
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/manifesto.d.ts.map +1 -1
- package/dist/features/manifesto.js +59 -72
- package/dist/features/manifesto.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +27 -22
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/snapshot.d.ts.map +1 -1
- package/dist/features/snapshot.js +36 -28
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure-query.d.ts +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +6 -6
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +150 -62
- package/dist/features/structure.js.map +1 -1
- package/dist/features/triage.d.ts.map +1 -1
- package/dist/features/triage.js +18 -11
- package/dist/features/triage.js.map +1 -1
- package/dist/graph/algorithms/bfs.d.ts +1 -1
- package/dist/graph/algorithms/bfs.d.ts.map +1 -1
- package/dist/graph/algorithms/bfs.js +14 -13
- package/dist/graph/algorithms/bfs.js.map +1 -1
- package/dist/graph/algorithms/tarjan.d.ts.map +1 -1
- package/dist/graph/algorithms/tarjan.js +5 -0
- package/dist/graph/algorithms/tarjan.js.map +1 -1
- package/dist/graph/builders/dependency.js +28 -22
- package/dist/graph/builders/dependency.js.map +1 -1
- package/dist/graph/classifiers/roles.d.ts +10 -1
- package/dist/graph/classifiers/roles.d.ts.map +1 -1
- package/dist/graph/classifiers/roles.js +60 -6
- package/dist/graph/classifiers/roles.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config.d.ts +87 -4
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +424 -22
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +27 -7
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +79 -5
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/infrastructure/update-check.d.ts.map +1 -1
- package/dist/infrastructure/update-check.js +49 -31
- package/dist/infrastructure/update-check.js.map +1 -1
- package/dist/mcp/server.d.ts +2 -10
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/ast-query.d.ts +1 -1
- package/dist/mcp/tools/ast-query.d.ts.map +1 -1
- package/dist/mcp/tools/audit.d.ts +1 -1
- package/dist/mcp/tools/audit.d.ts.map +1 -1
- package/dist/mcp/tools/batch-query.d.ts +1 -1
- package/dist/mcp/tools/batch-query.d.ts.map +1 -1
- package/dist/mcp/tools/branch-compare.d.ts +1 -1
- package/dist/mcp/tools/branch-compare.d.ts.map +1 -1
- package/dist/mcp/tools/brief.d.ts +1 -1
- package/dist/mcp/tools/brief.d.ts.map +1 -1
- package/dist/mcp/tools/cfg.d.ts +1 -1
- package/dist/mcp/tools/cfg.d.ts.map +1 -1
- package/dist/mcp/tools/check.d.ts +1 -1
- package/dist/mcp/tools/check.d.ts.map +1 -1
- package/dist/mcp/tools/co-changes.d.ts +1 -1
- package/dist/mcp/tools/co-changes.d.ts.map +1 -1
- package/dist/mcp/tools/code-owners.d.ts +1 -1
- package/dist/mcp/tools/code-owners.d.ts.map +1 -1
- package/dist/mcp/tools/communities.d.ts +1 -1
- package/dist/mcp/tools/communities.d.ts.map +1 -1
- package/dist/mcp/tools/complexity.d.ts +1 -1
- package/dist/mcp/tools/complexity.d.ts.map +1 -1
- package/dist/mcp/tools/context.d.ts +1 -1
- package/dist/mcp/tools/context.d.ts.map +1 -1
- package/dist/mcp/tools/dataflow.d.ts +1 -1
- package/dist/mcp/tools/dataflow.d.ts.map +1 -1
- package/dist/mcp/tools/diff-impact.d.ts +1 -1
- package/dist/mcp/tools/diff-impact.d.ts.map +1 -1
- package/dist/mcp/tools/execution-flow.d.ts +1 -1
- package/dist/mcp/tools/execution-flow.d.ts.map +1 -1
- package/dist/mcp/tools/export-graph.d.ts +1 -1
- package/dist/mcp/tools/export-graph.d.ts.map +1 -1
- package/dist/mcp/tools/file-deps.d.ts +1 -1
- package/dist/mcp/tools/file-deps.d.ts.map +1 -1
- package/dist/mcp/tools/file-exports.d.ts +1 -1
- package/dist/mcp/tools/file-exports.d.ts.map +1 -1
- package/dist/mcp/tools/find-cycles.d.ts +1 -1
- package/dist/mcp/tools/find-cycles.d.ts.map +1 -1
- package/dist/mcp/tools/fn-impact.d.ts +1 -1
- package/dist/mcp/tools/fn-impact.d.ts.map +1 -1
- package/dist/mcp/tools/impact-analysis.d.ts +1 -1
- package/dist/mcp/tools/impact-analysis.d.ts.map +1 -1
- package/dist/mcp/tools/implementations.d.ts +1 -1
- package/dist/mcp/tools/implementations.d.ts.map +1 -1
- package/dist/mcp/tools/index.d.ts +2 -5
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/interfaces.d.ts +1 -1
- package/dist/mcp/tools/interfaces.d.ts.map +1 -1
- package/dist/mcp/tools/list-functions.d.ts +1 -1
- package/dist/mcp/tools/list-functions.d.ts.map +1 -1
- package/dist/mcp/tools/list-repos.d.ts +1 -1
- package/dist/mcp/tools/list-repos.d.ts.map +1 -1
- package/dist/mcp/tools/module-map.d.ts +1 -1
- package/dist/mcp/tools/module-map.d.ts.map +1 -1
- package/dist/mcp/tools/node-roles.d.ts +1 -1
- package/dist/mcp/tools/node-roles.d.ts.map +1 -1
- package/dist/mcp/tools/path.d.ts +1 -1
- package/dist/mcp/tools/path.d.ts.map +1 -1
- package/dist/mcp/tools/query.d.ts +1 -1
- package/dist/mcp/tools/query.d.ts.map +1 -1
- package/dist/mcp/tools/semantic-search.d.ts +1 -1
- package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
- package/dist/mcp/tools/sequence.d.ts +1 -1
- package/dist/mcp/tools/sequence.d.ts.map +1 -1
- package/dist/mcp/tools/structure.d.ts +1 -1
- package/dist/mcp/tools/structure.d.ts.map +1 -1
- package/dist/mcp/tools/symbol-children.d.ts +1 -1
- package/dist/mcp/tools/symbol-children.d.ts.map +1 -1
- package/dist/mcp/tools/triage.d.ts +1 -1
- package/dist/mcp/tools/triage.d.ts.map +1 -1
- package/dist/mcp/tools/where.d.ts +1 -1
- package/dist/mcp/tools/where.d.ts.map +1 -1
- package/dist/mcp/types.d.ts +19 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +6 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/presentation/queries-cli/index.d.ts +1 -1
- package/dist/presentation/queries-cli/index.d.ts.map +1 -1
- package/dist/presentation/queries-cli/index.js +1 -1
- package/dist/presentation/queries-cli/index.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts +1 -0
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +20 -1
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/presentation/queries-cli.d.ts +1 -1
- package/dist/presentation/queries-cli.d.ts.map +1 -1
- package/dist/presentation/queries-cli.js +1 -1
- package/dist/presentation/queries-cli.js.map +1 -1
- package/dist/presentation/structure.d.ts +1 -1
- package/dist/presentation/structure.d.ts.map +1 -1
- package/dist/presentation/structure.js +2 -2
- package/dist/presentation/structure.js.map +1 -1
- package/dist/presentation/viewer.d.ts.map +1 -1
- package/dist/presentation/viewer.js +45 -32
- package/dist/presentation/viewer.js.map +1 -1
- package/dist/shared/constants.d.ts +21 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +25 -0
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/normalize.d.ts.map +1 -1
- package/dist/shared/normalize.js +12 -22
- package/dist/shared/normalize.js.map +1 -1
- package/dist/shared/paginate.d.ts +4 -17
- package/dist/shared/paginate.d.ts.map +1 -1
- package/dist/shared/paginate.js.map +1 -1
- package/dist/types.d.ts +113 -1
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +7 -8
- package/src/ast-analysis/engine.ts +43 -63
- package/src/ast-analysis/rules/b2.ts +263 -0
- package/src/ast-analysis/rules/b3.ts +127 -0
- package/src/ast-analysis/rules/b4.ts +378 -0
- package/src/ast-analysis/rules/b5.ts +65 -0
- package/src/ast-analysis/rules/c.ts +157 -0
- package/src/ast-analysis/rules/index.ts +34 -0
- package/src/ast-analysis/rules/javascript.ts +3 -0
- package/src/ast-analysis/shared.ts +2 -0
- package/src/ast-analysis/visitor-utils.ts +5 -0
- package/src/ast-analysis/visitor.ts +82 -52
- package/src/ast-analysis/visitors/cfg-visitor.ts +198 -84
- package/src/ast-analysis/visitors/complexity-visitor.ts +44 -16
- package/src/ast-analysis/visitors/dataflow-visitor.ts +68 -29
- package/src/cli/commands/audit.ts +2 -1
- package/src/cli/commands/batch.ts +1 -0
- package/src/cli/commands/build.ts +6 -1
- package/src/cli/commands/config.ts +353 -0
- package/src/cli/commands/roles.ts +6 -1
- package/src/cli/commands/triage.ts +1 -1
- package/src/cli/index.ts +10 -0
- package/src/cli/shared/options.ts +11 -1
- package/src/cli/types.ts +2 -0
- package/src/db/better-sqlite3.ts +5 -4
- package/src/db/connection.ts +23 -5
- package/src/db/index.ts +1 -0
- package/src/db/migrations.ts +69 -1
- package/src/db/repository/build-stmts.ts +30 -0
- package/src/db/repository/dataflow.ts +16 -0
- package/src/db/repository/index.ts +1 -1
- package/src/db/repository/native-repository.ts +56 -40
- package/src/domain/analysis/fn-impact.ts +4 -0
- package/src/domain/analysis/module-map.ts +38 -6
- package/src/domain/analysis/roles.ts +23 -0
- package/src/domain/graph/builder/call-resolver.ts +156 -218
- package/src/domain/graph/builder/cha.ts +18 -1
- package/src/domain/graph/builder/context.ts +1 -0
- package/src/domain/graph/builder/helpers.ts +205 -67
- package/src/domain/graph/builder/incremental.ts +249 -119
- package/src/domain/graph/builder/pipeline.ts +59 -6
- package/src/domain/graph/builder/stages/build-edges.ts +783 -652
- package/src/domain/graph/builder/stages/collect-files.ts +12 -6
- package/src/domain/graph/builder/stages/detect-changes.ts +4 -2
- package/src/domain/graph/builder/stages/finalize.ts +4 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +1214 -398
- package/src/domain/graph/builder/stages/resolve-imports.ts +1 -1
- package/src/domain/graph/resolver/points-to.ts +182 -59
- package/src/domain/graph/resolver/strategy.ts +265 -0
- package/src/domain/graph/watcher.ts +19 -9
- package/src/domain/parser.ts +57 -16
- package/src/domain/queries.ts +1 -1
- package/src/domain/wasm-worker-entry.ts +13 -2
- package/src/domain/wasm-worker-pool.ts +29 -4
- package/src/domain/wasm-worker-protocol.ts +5 -0
- package/src/extractors/cpp.ts +44 -1
- package/src/extractors/cuda.ts +44 -1
- package/src/extractors/dart.ts +48 -3
- package/src/extractors/groovy.ts +62 -2
- package/src/extractors/helpers.ts +48 -2
- package/src/extractors/java.ts +88 -8
- package/src/extractors/javascript.ts +693 -167
- package/src/extractors/kotlin.ts +57 -3
- package/src/extractors/objc.ts +25 -1
- package/src/extractors/scala.ts +63 -1
- package/src/extractors/swift.ts +46 -3
- package/src/features/audit.ts +43 -34
- package/src/features/boundaries.ts +17 -9
- package/src/features/cfg.ts +31 -22
- package/src/features/check.ts +21 -5
- package/src/features/communities.ts +28 -19
- package/src/features/dataflow.ts +755 -6
- package/src/features/manifesto.ts +76 -75
- package/src/features/sequence.ts +29 -23
- package/src/features/snapshot.ts +36 -25
- package/src/features/structure-query.ts +7 -7
- package/src/features/structure.ts +185 -55
- package/src/features/triage.ts +28 -15
- package/src/graph/algorithms/bfs.ts +13 -12
- package/src/graph/algorithms/tarjan.ts +5 -0
- package/src/graph/builders/dependency.ts +35 -23
- package/src/graph/classifiers/roles.ts +74 -7
- package/src/index.ts +5 -1
- package/src/infrastructure/config.ts +511 -23
- package/src/infrastructure/registry.ts +117 -12
- package/src/infrastructure/update-check.ts +55 -33
- package/src/mcp/server.ts +2 -8
- package/src/mcp/tools/ast-query.ts +1 -1
- package/src/mcp/tools/audit.ts +1 -1
- package/src/mcp/tools/batch-query.ts +1 -1
- package/src/mcp/tools/branch-compare.ts +1 -1
- package/src/mcp/tools/brief.ts +1 -1
- package/src/mcp/tools/cfg.ts +1 -1
- package/src/mcp/tools/check.ts +1 -1
- package/src/mcp/tools/co-changes.ts +1 -1
- package/src/mcp/tools/code-owners.ts +1 -1
- package/src/mcp/tools/communities.ts +1 -1
- package/src/mcp/tools/complexity.ts +1 -1
- package/src/mcp/tools/context.ts +1 -1
- package/src/mcp/tools/dataflow.ts +1 -1
- package/src/mcp/tools/diff-impact.ts +1 -1
- package/src/mcp/tools/execution-flow.ts +1 -1
- package/src/mcp/tools/export-graph.ts +1 -1
- package/src/mcp/tools/file-deps.ts +1 -1
- package/src/mcp/tools/file-exports.ts +1 -1
- package/src/mcp/tools/find-cycles.ts +1 -1
- package/src/mcp/tools/fn-impact.ts +1 -1
- package/src/mcp/tools/impact-analysis.ts +1 -1
- package/src/mcp/tools/implementations.ts +1 -1
- package/src/mcp/tools/index.ts +2 -5
- package/src/mcp/tools/interfaces.ts +1 -1
- package/src/mcp/tools/list-functions.ts +1 -1
- package/src/mcp/tools/list-repos.ts +1 -1
- package/src/mcp/tools/module-map.ts +1 -1
- package/src/mcp/tools/node-roles.ts +1 -1
- package/src/mcp/tools/path.ts +1 -1
- package/src/mcp/tools/query.ts +1 -1
- package/src/mcp/tools/semantic-search.ts +1 -1
- package/src/mcp/tools/sequence.ts +1 -1
- package/src/mcp/tools/structure.ts +1 -1
- package/src/mcp/tools/symbol-children.ts +1 -1
- package/src/mcp/tools/triage.ts +1 -1
- package/src/mcp/tools/where.ts +1 -1
- package/src/mcp/types.ts +21 -0
- package/src/presentation/queries-cli/index.ts +1 -1
- package/src/presentation/queries-cli/overview.ts +35 -1
- package/src/presentation/queries-cli.ts +1 -0
- package/src/presentation/structure.ts +3 -3
- package/src/presentation/viewer.ts +98 -87
- package/src/shared/constants.ts +26 -0
- package/src/shared/normalize.ts +13 -22
- package/src/shared/paginate.ts +4 -18
- package/src/types.ts +127 -1
package/src/domain/parser.ts
CHANGED
|
@@ -158,6 +158,7 @@ const COMMON_QUERY_PATTERNS: string[] = [
|
|
|
158
158
|
'(variable_declarator name: (identifier) @varfn_name value: (generator_function) @varfn_value)',
|
|
159
159
|
'(method_definition name: (property_identifier) @meth_name) @meth_node',
|
|
160
160
|
'(method_definition name: (private_property_identifier) @meth_name) @meth_node',
|
|
161
|
+
'(method_definition name: (computed_property_name) @meth_name) @meth_node',
|
|
161
162
|
'(import_statement source: (string) @imp_source) @imp_node',
|
|
162
163
|
'(export_statement) @exp_node',
|
|
163
164
|
'(call_expression function: (identifier) @callfn_name) @callfn_node',
|
|
@@ -221,7 +222,9 @@ async function doLoadLanguage(entry: LanguageRegistryEntry): Promise<void> {
|
|
|
221
222
|
file: entry.grammarFile,
|
|
222
223
|
cause: e as Error,
|
|
223
224
|
});
|
|
224
|
-
|
|
225
|
+
const isEnoent = (e as NodeJS.ErrnoException).code === 'ENOENT';
|
|
226
|
+
const log = isEnoent ? debug : warn;
|
|
227
|
+
log(
|
|
225
228
|
`${entry.id} parser failed to initialize: ${(e as Error).message}. ${entry.id} files will be skipped.`,
|
|
226
229
|
);
|
|
227
230
|
_cachedParsers!.set(entry.id, null);
|
|
@@ -465,7 +468,7 @@ export function getInstalledWasmExtensions(): Set<string> {
|
|
|
465
468
|
* Lowercase file extensions covered by the native Rust addon.
|
|
466
469
|
*
|
|
467
470
|
* Mirrors `LanguageKind::from_extension` in
|
|
468
|
-
* `crates/codegraph-core/src/
|
|
471
|
+
* `crates/codegraph-core/src/domain/parser.rs`. Used to classify why the
|
|
469
472
|
* native orchestrator dropped a file: extensions outside this set are a
|
|
470
473
|
* legitimate parser limit (no Rust extractor exists), while extensions inside
|
|
471
474
|
* it indicate a real native bug (parse/read/extract failure).
|
|
@@ -713,7 +716,17 @@ function patchReturnTypeMap(r: any): void {
|
|
|
713
716
|
}
|
|
714
717
|
|
|
715
718
|
/** Wrap bindingType into binding object for dataflow argFlows and mutations. */
|
|
716
|
-
|
|
719
|
+
/**
|
|
720
|
+
* Normalise a DataflowResult from the native Rust extractor to the VisitorArgFlow
|
|
721
|
+
* shape expected by the TypeScript dataflow analysis layer.
|
|
722
|
+
*
|
|
723
|
+
* The Rust `DataflowArgFlow` emits `bindingType: string | null` as a flat field.
|
|
724
|
+
* The TS analysis layer (`buildDataflowVerticesAndEdges`, `collectCallerStitchCandidates`)
|
|
725
|
+
* expects `binding: { type: string; index?: number }` on each argFlow/mutation entry.
|
|
726
|
+
* This normalisation must be applied whenever `extractDataflowAnalysis` is called
|
|
727
|
+
* outside the standard `patchNativeResult` pipeline.
|
|
728
|
+
*/
|
|
729
|
+
export function patchDataflowResult(dataflow: any): void {
|
|
717
730
|
if (dataflow.argFlows) {
|
|
718
731
|
for (const f of dataflow.argFlows) {
|
|
719
732
|
f.binding = f.bindingType ? { type: f.bindingType } : null;
|
|
@@ -735,7 +748,7 @@ function patchNativeResult(r: any): ExtractorOutput {
|
|
|
735
748
|
if (r.imports) patchImports(r.imports);
|
|
736
749
|
patchTypeMap(r);
|
|
737
750
|
patchReturnTypeMap(r);
|
|
738
|
-
if (r.dataflow)
|
|
751
|
+
if (r.dataflow) patchDataflowResult(r.dataflow);
|
|
739
752
|
|
|
740
753
|
return r;
|
|
741
754
|
}
|
|
@@ -1181,12 +1194,25 @@ async function parseFilesWasm(
|
|
|
1181
1194
|
/**
|
|
1182
1195
|
* Files at or below this count use the inline parse path (no worker spawn).
|
|
1183
1196
|
*
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1197
|
+
* The worker pool exists for crash safety (#965): exotic (non-required) WASM
|
|
1198
|
+
* grammars can trigger uncatchable V8 fatal errors that would kill the main
|
|
1199
|
+
* process. Running them in a worker means only the worker dies; the pool
|
|
1200
|
+
* detects the exit, skips the file, respawns, and continues.
|
|
1201
|
+
*
|
|
1202
|
+
* JS/TS/TSX are required-tier grammars — they have never triggered the V8
|
|
1203
|
+
* fatal crash class and are safe to run inline. The primary hot caller
|
|
1204
|
+
* (this/super dispatch post-pass) exclusively handles JS/TS/TSX files and
|
|
1205
|
+
* measured ~55–64ms/file through the pool vs ~8–10ms/file inline (#1435);
|
|
1206
|
+
* IPC overhead scales linearly with file count, not amortised.
|
|
1207
|
+
*
|
|
1208
|
+
* The threshold is set high enough to keep typical this-dispatch batches
|
|
1209
|
+
* (≤ 18 files on the codegraph corpus) on the inline path, while still
|
|
1210
|
+
* routing truly large exotic-language drops (rare; typical HCL case is 4
|
|
1211
|
+
* files) through the pool for crash isolation. Exotic-language drops are
|
|
1212
|
+
* almost always well under this limit anyway, so they benefit from the
|
|
1213
|
+
* inline fast path too without meaningful crash risk increase.
|
|
1188
1214
|
*/
|
|
1189
|
-
const INLINE_BACKFILL_THRESHOLD =
|
|
1215
|
+
const INLINE_BACKFILL_THRESHOLD = 32;
|
|
1190
1216
|
|
|
1191
1217
|
/**
|
|
1192
1218
|
* Inline WASM parse (no worker) for small file batches.
|
|
@@ -1198,11 +1224,16 @@ const INLINE_BACKFILL_THRESHOLD = 16;
|
|
|
1198
1224
|
*
|
|
1199
1225
|
* Returns symbols with `_tree` set so `runAnalyses` can run AST/CFG/dataflow
|
|
1200
1226
|
* visitors via the unified walker (mirrors how WASM-engine results behaved
|
|
1201
|
-
* before the worker pool was introduced)
|
|
1227
|
+
* before the worker pool was introduced), unless `symbolsOnly` is true — in
|
|
1228
|
+
* that case `_tree` is not set, skipping all analysis visitor walks. Use
|
|
1229
|
+
* `symbolsOnly` when only definitions/calls/typeMap are needed (e.g. the
|
|
1230
|
+
* this/super dispatch post-pass) to avoid the analysis overhead on the inline
|
|
1231
|
+
* path, matching the optimization already applied to the worker-pool path.
|
|
1202
1232
|
*/
|
|
1203
1233
|
async function parseFilesWasmInline(
|
|
1204
1234
|
filePaths: string[],
|
|
1205
1235
|
rootDir: string,
|
|
1236
|
+
symbolsOnly = false,
|
|
1206
1237
|
): Promise<Map<string, ExtractorOutput>> {
|
|
1207
1238
|
const result = new Map<string, ExtractorOutput>();
|
|
1208
1239
|
if (filePaths.length === 0) return result;
|
|
@@ -1220,7 +1251,18 @@ async function parseFilesWasmInline(
|
|
|
1220
1251
|
if (!extracted) continue;
|
|
1221
1252
|
const relPath = path.relative(rootDir, filePath).split(path.sep).join('/');
|
|
1222
1253
|
const symbols = extracted.symbols as ExtractorOutput & { _tree?: unknown; _langId?: string };
|
|
1223
|
-
|
|
1254
|
+
// When symbolsOnly=true, skip setting _tree so runAnalyses does not run
|
|
1255
|
+
// AST/complexity/CFG/dataflow visitor walks — only definitions/calls/typeMap
|
|
1256
|
+
// are needed by callers like the this/super dispatch post-pass.
|
|
1257
|
+
if (!symbolsOnly) {
|
|
1258
|
+
symbols._tree = extracted.tree;
|
|
1259
|
+
} else if (typeof (extracted.tree as any)?.delete === 'function') {
|
|
1260
|
+
// Free the WASM-backed tree immediately — web-tree-sitter trees are backed
|
|
1261
|
+
// by WASM linear memory and require explicit disposal. When symbolsOnly is
|
|
1262
|
+
// true the tree is never stored anywhere, so we must delete it here to
|
|
1263
|
+
// avoid leaking WASM heap on every incremental rebuild.
|
|
1264
|
+
(extracted.tree as any).delete();
|
|
1265
|
+
}
|
|
1224
1266
|
symbols._langId = extracted.langId;
|
|
1225
1267
|
result.set(relPath, symbols);
|
|
1226
1268
|
}
|
|
@@ -1230,14 +1272,13 @@ async function parseFilesWasmInline(
|
|
|
1230
1272
|
/**
|
|
1231
1273
|
* Backfill helper: small batches use the inline (main-thread) path; larger
|
|
1232
1274
|
* batches keep the worker-pool isolation against tree-sitter WASM crashes
|
|
1233
|
-
* (#965).
|
|
1234
|
-
* files in one or two languages).
|
|
1275
|
+
* (#965). See INLINE_BACKFILL_THRESHOLD for threshold rationale.
|
|
1235
1276
|
*
|
|
1236
1277
|
* `opts.symbolsOnly` skips the AST/complexity/CFG/dataflow visitors in the
|
|
1237
1278
|
* worker (and their result serialization across the thread boundary) for
|
|
1238
1279
|
* callers that only consume definitions/calls/typeMap — the native
|
|
1239
|
-
* orchestrator's
|
|
1240
|
-
*
|
|
1280
|
+
* orchestrator's this-dispatch post-pass. Callers that ingest the files into
|
|
1281
|
+
* the DB (dropped-language backfill) must keep
|
|
1241
1282
|
* the default full analysis.
|
|
1242
1283
|
*/
|
|
1243
1284
|
export async function parseFilesWasmForBackfill(
|
|
@@ -1246,7 +1287,7 @@ export async function parseFilesWasmForBackfill(
|
|
|
1246
1287
|
opts: { symbolsOnly?: boolean } = {},
|
|
1247
1288
|
): Promise<Map<string, ExtractorOutput>> {
|
|
1248
1289
|
if (filePaths.length <= INLINE_BACKFILL_THRESHOLD) {
|
|
1249
|
-
return parseFilesWasmInline(filePaths, rootDir);
|
|
1290
|
+
return parseFilesWasmInline(filePaths, rootDir, opts.symbolsOnly);
|
|
1250
1291
|
}
|
|
1251
1292
|
return parseFilesWasm(filePaths, rootDir, opts.symbolsOnly ? EXTRACT_ONLY : FULL_ANALYSIS);
|
|
1252
1293
|
}
|
package/src/domain/queries.ts
CHANGED
|
@@ -39,7 +39,7 @@ export {
|
|
|
39
39
|
moduleMapData,
|
|
40
40
|
statsData,
|
|
41
41
|
} from './analysis/module-map.js';
|
|
42
|
-
export { rolesData } from './analysis/roles.js';
|
|
42
|
+
export { dynamicCallsData, rolesData } from './analysis/roles.js';
|
|
43
43
|
// ── Analysis modules ─────────────────────────────────────────────────────
|
|
44
44
|
export {
|
|
45
45
|
childrenData,
|
|
@@ -115,6 +115,7 @@ const COMMON_QUERY_PATTERNS: string[] = [
|
|
|
115
115
|
'(variable_declarator name: (identifier) @varfn_name value: (generator_function) @varfn_value)',
|
|
116
116
|
'(method_definition name: (property_identifier) @meth_name) @meth_node',
|
|
117
117
|
'(method_definition name: (private_property_identifier) @meth_name) @meth_node',
|
|
118
|
+
'(method_definition name: (computed_property_name) @meth_name) @meth_node',
|
|
118
119
|
'(import_statement source: (string) @imp_source) @imp_node',
|
|
119
120
|
'(export_statement) @exp_node',
|
|
120
121
|
'(call_expression function: (identifier) @callfn_name) @callfn_node',
|
|
@@ -125,11 +126,17 @@ const COMMON_QUERY_PATTERNS: string[] = [
|
|
|
125
126
|
'(expression_statement (assignment_expression left: (member_expression) @assign_left right: (_) @assign_right)) @assign_node',
|
|
126
127
|
];
|
|
127
128
|
|
|
128
|
-
const
|
|
129
|
+
const JS_CLASS_PATTERNS: string[] = [
|
|
130
|
+
'(class_declaration name: (identifier) @cls_name) @cls_node',
|
|
131
|
+
// class expressions: `return class Foo extends Bar { ... }` or `const X = class Foo { ... }`
|
|
132
|
+
'(class name: (identifier) @cls_name) @cls_node',
|
|
133
|
+
];
|
|
129
134
|
|
|
130
135
|
const TS_EXTRA_PATTERNS: string[] = [
|
|
131
136
|
'(class_declaration name: (type_identifier) @cls_name) @cls_node',
|
|
132
137
|
'(abstract_class_declaration name: (type_identifier) @cls_name) @cls_node',
|
|
138
|
+
// class expressions: `return class Foo extends Bar { ... }`
|
|
139
|
+
'(class name: (type_identifier) @cls_name) @cls_node',
|
|
133
140
|
'(interface_declaration name: (type_identifier) @iface_name) @iface_node',
|
|
134
141
|
'(type_alias_declaration name: (type_identifier) @type_name) @type_node',
|
|
135
142
|
];
|
|
@@ -433,7 +440,7 @@ async function loadLanguageLazy(entry: LanguageRegistryEntry): Promise<Parser |
|
|
|
433
440
|
const isTS = entry.id === 'typescript' || entry.id === 'tsx';
|
|
434
441
|
const patterns = isTS
|
|
435
442
|
? [...COMMON_QUERY_PATTERNS, ...TS_EXTRA_PATTERNS]
|
|
436
|
-
: [...COMMON_QUERY_PATTERNS,
|
|
443
|
+
: [...COMMON_QUERY_PATTERNS, ...JS_CLASS_PATTERNS];
|
|
437
444
|
_queries.set(entry.id, new Query(lang, patterns.join('\n')));
|
|
438
445
|
}
|
|
439
446
|
return parser;
|
|
@@ -818,6 +825,7 @@ function serializeExtractorOutput(
|
|
|
818
825
|
...(symbols.objectPropBindings?.length
|
|
819
826
|
? { objectPropBindings: symbols.objectPropBindings }
|
|
820
827
|
: {}),
|
|
828
|
+
...(symbols.thisCallBindings?.length ? { thisCallBindings: symbols.thisCallBindings } : {}),
|
|
821
829
|
...(symbols.newExpressions?.length ? { newExpressions: symbols.newExpressions } : {}),
|
|
822
830
|
...(symbols.definePropertyReceivers?.size
|
|
823
831
|
? { definePropertyReceivers: Array.from(symbols.definePropertyReceivers.entries()) }
|
|
@@ -826,6 +834,9 @@ function serializeExtractorOutput(
|
|
|
826
834
|
? { returnTypeMap: Array.from(symbols.returnTypeMap.entries()) }
|
|
827
835
|
: {}),
|
|
828
836
|
...(symbols.callAssignments?.length ? { callAssignments: symbols.callAssignments } : {}),
|
|
837
|
+
...(symbols.cjsRequireBindings?.length
|
|
838
|
+
? { cjsRequireBindings: symbols.cjsRequireBindings }
|
|
839
|
+
: {}),
|
|
829
840
|
};
|
|
830
841
|
}
|
|
831
842
|
|
|
@@ -86,11 +86,14 @@ interface PendingJob {
|
|
|
86
86
|
*/
|
|
87
87
|
const WORKER_PARSE_TIMEOUT_MS = 60_000;
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
/** Deserialize the core fields and metadata scalars from a serialized result. */
|
|
90
|
+
function deserializeCoreFields(
|
|
91
|
+
ser: SerializedExtractorOutput,
|
|
92
|
+
): Pick<ExtractorOutput, 'definitions' | 'calls' | 'imports' | 'classes' | 'exports' | 'typeMap'> &
|
|
93
|
+
Partial<Pick<ExtractorOutput, '_langId' | '_lineCount' | 'dataflow' | 'astNodes'>> {
|
|
91
94
|
const typeMap = new Map<string, TypeMapEntry>();
|
|
92
95
|
for (const [k, v] of ser.typeMap) typeMap.set(k, v);
|
|
93
|
-
const out:
|
|
96
|
+
const out: ReturnType<typeof deserializeCoreFields> = {
|
|
94
97
|
definitions: ser.definitions,
|
|
95
98
|
calls: ser.calls,
|
|
96
99
|
imports: ser.imports,
|
|
@@ -106,6 +109,11 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
|
|
|
106
109
|
// {line, kind, name, text?, receiver?} shape — see engine.ts:822 where the
|
|
107
110
|
// visitor output is cast the same way.
|
|
108
111
|
if (ser.astNodes !== undefined) out.astNodes = ser.astNodes as unknown as ASTNodeRow[];
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Deserialize the simple array binding fields (present when non-empty). */
|
|
116
|
+
function deserializeBindingFields(ser: SerializedExtractorOutput, out: ExtractorOutput): void {
|
|
109
117
|
if (ser.fnRefBindings?.length) out.fnRefBindings = ser.fnRefBindings;
|
|
110
118
|
if (ser.paramBindings?.length) out.paramBindings = ser.paramBindings;
|
|
111
119
|
if (ser.arrayElemBindings?.length) out.arrayElemBindings = ser.arrayElemBindings;
|
|
@@ -115,7 +123,14 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
|
|
|
115
123
|
if (ser.objectRestParamBindings?.length)
|
|
116
124
|
out.objectRestParamBindings = ser.objectRestParamBindings;
|
|
117
125
|
if (ser.objectPropBindings?.length) out.objectPropBindings = ser.objectPropBindings;
|
|
126
|
+
if (ser.thisCallBindings?.length) out.thisCallBindings = ser.thisCallBindings;
|
|
118
127
|
if (ser.newExpressions?.length) out.newExpressions = ser.newExpressions;
|
|
128
|
+
if (ser.callAssignments?.length) out.callAssignments = ser.callAssignments;
|
|
129
|
+
if (ser.cjsRequireBindings?.length) out.cjsRequireBindings = ser.cjsRequireBindings;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Deserialize the Map-typed fields that require entry-by-entry reconstruction. */
|
|
133
|
+
function deserializeMapFields(ser: SerializedExtractorOutput, out: ExtractorOutput): void {
|
|
119
134
|
if (ser.definePropertyReceivers?.length) {
|
|
120
135
|
const m = new Map<string, string>();
|
|
121
136
|
for (const [k, v] of ser.definePropertyReceivers) m.set(k, v);
|
|
@@ -126,7 +141,17 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
|
|
|
126
141
|
for (const [k, v] of ser.returnTypeMap) returnTypeMap.set(k, v);
|
|
127
142
|
out.returnTypeMap = returnTypeMap;
|
|
128
143
|
}
|
|
129
|
-
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutput | null {
|
|
147
|
+
if (!ser) return null;
|
|
148
|
+
// deserializeCoreFields supplies all required ExtractorOutput fields (definitions,
|
|
149
|
+
// calls, imports, classes, exports, typeMap). The cast is safe: every required field
|
|
150
|
+
// is present in the returned Pick. If a new required field is added to ExtractorOutput,
|
|
151
|
+
// add it to deserializeCoreFields' return Pick and body to keep the cast honest.
|
|
152
|
+
const out = { ...deserializeCoreFields(ser) } as ExtractorOutput;
|
|
153
|
+
deserializeBindingFields(ser, out);
|
|
154
|
+
deserializeMapFields(ser, out);
|
|
130
155
|
return out;
|
|
131
156
|
}
|
|
132
157
|
|
|
@@ -71,11 +71,16 @@ export interface SerializedExtractorOutput {
|
|
|
71
71
|
objectRestParamBindings?: import('../types.js').ObjectRestParamBinding[];
|
|
72
72
|
objectPropBindings?: import('../types.js').ObjectPropBinding[];
|
|
73
73
|
paramBindings?: import('../types.js').ParamBinding[];
|
|
74
|
+
thisCallBindings?: import('../types.js').ThisCallBinding[];
|
|
74
75
|
newExpressions?: readonly string[];
|
|
75
76
|
/** Serialized definePropertyReceivers map (funcName → receiverVarName) as tuple array. */
|
|
76
77
|
definePropertyReceivers?: Array<[string, string]>;
|
|
77
78
|
returnTypeMap?: Array<[string, TypeMapEntry]>;
|
|
78
79
|
callAssignments?: CallAssignment[];
|
|
80
|
+
/** Variable-level dataflow vertices extracted during parsing (P1+). */
|
|
81
|
+
dataflowVertices?: import('../types.js').DataflowVertex[];
|
|
82
|
+
/** CJS require bindings — see ExtractorOutput.cjsRequireBindings (#1661). */
|
|
83
|
+
cjsRequireBindings?: Array<{ names: string[]; source: string }>;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
export interface WorkerParseResponseOk {
|
package/src/extractors/cpp.ts
CHANGED
|
@@ -5,7 +5,13 @@ import type {
|
|
|
5
5
|
TreeSitterNode,
|
|
6
6
|
TreeSitterTree,
|
|
7
7
|
} from '../types.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
extractModifierVisibility,
|
|
10
|
+
findChild,
|
|
11
|
+
isCPrimitiveType,
|
|
12
|
+
nodeEndLine,
|
|
13
|
+
setTypeMapEntry,
|
|
14
|
+
} from './helpers.js';
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Extract symbols from C++ files.
|
|
@@ -50,6 +56,9 @@ function walkCppNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
50
56
|
case 'call_expression':
|
|
51
57
|
handleCppCallExpression(node, ctx);
|
|
52
58
|
break;
|
|
59
|
+
case 'declaration':
|
|
60
|
+
handleCppDeclaration(node, ctx);
|
|
61
|
+
break;
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -204,6 +213,40 @@ function handleCppInclude(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
204
213
|
});
|
|
205
214
|
}
|
|
206
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Seed typeMap for declaration-typed locals: `UserService svc;` and
|
|
218
|
+
* `UserService svc = makeService();` both yield typeMap["svc"] = "UserService"
|
|
219
|
+
* at confidence 0.9. Mirrors `match_c_family_type_map` ("declaration" branch)
|
|
220
|
+
* in the native Rust C++ extractor.
|
|
221
|
+
*/
|
|
222
|
+
function handleCppDeclaration(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
223
|
+
const typeNode = node.childForFieldName('type');
|
|
224
|
+
if (!typeNode) return;
|
|
225
|
+
const typeName = typeNode.text;
|
|
226
|
+
// Skip primitive types — they are never class/struct receivers
|
|
227
|
+
if (isCPrimitiveType(typeName)) return;
|
|
228
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
229
|
+
const child = node.child(i);
|
|
230
|
+
if (!child) continue;
|
|
231
|
+
const kind = child.type;
|
|
232
|
+
let nameNode: TreeSitterNode | null = null;
|
|
233
|
+
if (kind === 'init_declarator') {
|
|
234
|
+
nameNode = child.childForFieldName('declarator') ?? null;
|
|
235
|
+
} else if (kind === 'identifier') {
|
|
236
|
+
nameNode = child;
|
|
237
|
+
}
|
|
238
|
+
// Note: pointer_declarator / reference_declarator children (e.g. `UserService *svc;`)
|
|
239
|
+
// are intentionally skipped here — they are also skipped by the native Rust
|
|
240
|
+
// match_c_family_type_map helper, which only handles 'init_declarator' and
|
|
241
|
+
// 'identifier' children. Both engines have the same scope for this case.
|
|
242
|
+
if (!nameNode) continue;
|
|
243
|
+
const varName = unwrapCppDeclaratorName(nameNode);
|
|
244
|
+
if (varName) {
|
|
245
|
+
setTypeMapEntry(ctx.typeMap, varName, typeName, 0.9);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
207
250
|
function handleCppCallExpression(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
208
251
|
const funcNode = node.childForFieldName('function');
|
|
209
252
|
if (!funcNode) return;
|
package/src/extractors/cuda.ts
CHANGED
|
@@ -5,7 +5,13 @@ import type {
|
|
|
5
5
|
TreeSitterNode,
|
|
6
6
|
TreeSitterTree,
|
|
7
7
|
} from '../types.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
extractModifierVisibility,
|
|
10
|
+
findChild,
|
|
11
|
+
isCPrimitiveType,
|
|
12
|
+
nodeEndLine,
|
|
13
|
+
setTypeMapEntry,
|
|
14
|
+
} from './helpers.js';
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Extract symbols from CUDA files.
|
|
@@ -63,6 +69,9 @@ function walkCudaNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
63
69
|
case 'call_expression':
|
|
64
70
|
handleCudaCallExpression(node, ctx);
|
|
65
71
|
break;
|
|
72
|
+
case 'declaration':
|
|
73
|
+
handleCudaDeclaration(node, ctx);
|
|
74
|
+
break;
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -204,6 +213,40 @@ function handleCudaInclude(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
204
213
|
});
|
|
205
214
|
}
|
|
206
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Seed typeMap for declaration-typed locals: `UserService svc;` and
|
|
218
|
+
* `UserService svc = make();` both yield typeMap["svc"] = "UserService"
|
|
219
|
+
* at confidence 0.9. Mirrors `match_c_family_type_map` ("declaration" branch)
|
|
220
|
+
* in the native Rust CUDA extractor.
|
|
221
|
+
*/
|
|
222
|
+
function handleCudaDeclaration(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
223
|
+
const typeNode = node.childForFieldName('type');
|
|
224
|
+
if (!typeNode) return;
|
|
225
|
+
const typeName = typeNode.text;
|
|
226
|
+
// Skip primitive types — they are never class/struct receivers
|
|
227
|
+
if (isCPrimitiveType(typeName)) return;
|
|
228
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
229
|
+
const child = node.child(i);
|
|
230
|
+
if (!child) continue;
|
|
231
|
+
const kind = child.type;
|
|
232
|
+
let nameNode: TreeSitterNode | null = null;
|
|
233
|
+
if (kind === 'init_declarator') {
|
|
234
|
+
nameNode = child.childForFieldName('declarator') ?? null;
|
|
235
|
+
} else if (kind === 'identifier') {
|
|
236
|
+
nameNode = child;
|
|
237
|
+
}
|
|
238
|
+
// Note: pointer_declarator / reference_declarator children (e.g. `UserService *svc;`)
|
|
239
|
+
// are intentionally skipped here — they are also skipped by the native Rust
|
|
240
|
+
// match_c_family_type_map helper, which only handles 'init_declarator' and
|
|
241
|
+
// 'identifier' children. Both engines have the same scope for this case.
|
|
242
|
+
if (!nameNode) continue;
|
|
243
|
+
const varName = extractCudaFieldName(nameNode);
|
|
244
|
+
if (varName) {
|
|
245
|
+
setTypeMapEntry(ctx.typeMap, varName, typeName, 0.9);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
207
250
|
function handleCudaCallExpression(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
208
251
|
const funcNode = node.childForFieldName('function');
|
|
209
252
|
if (!funcNode) return;
|
package/src/extractors/dart.ts
CHANGED
|
@@ -255,14 +255,59 @@ function handleDartSelector(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
255
255
|
const argPart = findChild(node, 'argument_part');
|
|
256
256
|
if (!argPart) return;
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
const line = node.startPosition.row + 1;
|
|
259
|
+
|
|
260
|
+
// Look for the identifier this selector belongs to.
|
|
261
|
+
// Two layouts are possible depending on grammar version:
|
|
262
|
+
// A) selector has both unconditional_assignable_selector + argument_part (same node)
|
|
263
|
+
// B) one selector node holds unconditional_assignable_selector (.method),
|
|
264
|
+
// the next holds argument_part (the call args) — method name is in the previous sibling
|
|
259
265
|
const unconditional = findChild(node, 'unconditional_assignable_selector');
|
|
266
|
+
let methodName: string | null = null;
|
|
267
|
+
|
|
260
268
|
if (unconditional) {
|
|
261
269
|
const id = findChild(unconditional, 'identifier');
|
|
262
|
-
if (id)
|
|
263
|
-
|
|
270
|
+
if (id) methodName = id.text;
|
|
271
|
+
} else {
|
|
272
|
+
// Layout B: look at the previous sibling selector for the method name
|
|
273
|
+
const parent = node.parent;
|
|
274
|
+
if (parent) {
|
|
275
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
276
|
+
const sibling = parent.child(i);
|
|
277
|
+
if (sibling === node) break;
|
|
278
|
+
if (sibling?.type === 'selector') {
|
|
279
|
+
const unc2 = findChild(sibling, 'unconditional_assignable_selector');
|
|
280
|
+
if (unc2) {
|
|
281
|
+
const id2 = findChild(unc2, 'identifier');
|
|
282
|
+
if (id2) methodName = id2.text;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
264
286
|
}
|
|
265
287
|
}
|
|
288
|
+
|
|
289
|
+
if (!methodName) return;
|
|
290
|
+
|
|
291
|
+
// Function.apply(fn, positionalArgs, namedArgs) — dynamic higher-order dispatch
|
|
292
|
+
if (methodName === 'apply') {
|
|
293
|
+
const parent = node.parent;
|
|
294
|
+
if (parent) {
|
|
295
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
296
|
+
const sibling = parent.child(i);
|
|
297
|
+
if (sibling && sibling !== node && sibling.text === 'Function') {
|
|
298
|
+
ctx.calls.push({
|
|
299
|
+
name: '<dynamic:unresolved>',
|
|
300
|
+
line,
|
|
301
|
+
dynamic: true,
|
|
302
|
+
dynamicKind: 'unresolved-dynamic',
|
|
303
|
+
});
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
ctx.calls.push({ name: methodName, line });
|
|
266
311
|
}
|
|
267
312
|
|
|
268
313
|
function handleDartTypeAlias(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
package/src/extractors/groovy.ts
CHANGED
|
@@ -292,8 +292,26 @@ function handleGroovyImport(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
/** Extract the first string literal argument from a Groovy call node. */
|
|
296
|
+
function getFirstStringArgGroovy(node: TreeSitterNode): string | null {
|
|
297
|
+
const args = node.childForFieldName('arguments') || findChild(node, 'argument_list');
|
|
298
|
+
if (!args) return null;
|
|
299
|
+
for (let i = 0; i < args.childCount; i++) {
|
|
300
|
+
const child = args.child(i);
|
|
301
|
+
if (!child) continue;
|
|
302
|
+
const t = child.type;
|
|
303
|
+
if (t === '(' || t === ')' || t === ',') continue;
|
|
304
|
+
if (t === 'string' || t === 'string_literal' || t === 'string_fragment') {
|
|
305
|
+
return child.text.replace(/^["']|["']$/g, '');
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
|
|
295
312
|
function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
296
313
|
const call: Call = { name: '', line: node.startPosition.row + 1 };
|
|
314
|
+
let fieldNode: TreeSitterNode | null = null;
|
|
297
315
|
|
|
298
316
|
// Try standard call_expression pattern
|
|
299
317
|
const funcNode = node.childForFieldName('function') || node.childForFieldName('method');
|
|
@@ -301,7 +319,10 @@ function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
301
319
|
if (funcNode.type === 'field_expression' || funcNode.type === 'member_access') {
|
|
302
320
|
const field = funcNode.childForFieldName('field') || funcNode.childForFieldName('property');
|
|
303
321
|
const obj = funcNode.childForFieldName('argument') || funcNode.childForFieldName('object');
|
|
304
|
-
if (field)
|
|
322
|
+
if (field) {
|
|
323
|
+
fieldNode = field;
|
|
324
|
+
call.name = field.text;
|
|
325
|
+
}
|
|
305
326
|
if (obj) call.receiver = obj.text;
|
|
306
327
|
} else {
|
|
307
328
|
call.name = funcNode.text;
|
|
@@ -311,12 +332,51 @@ function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void
|
|
|
311
332
|
const nameNode = node.childForFieldName('name');
|
|
312
333
|
const obj = node.childForFieldName('object');
|
|
313
334
|
if (nameNode) {
|
|
335
|
+
fieldNode = nameNode;
|
|
314
336
|
call.name = nameNode.text;
|
|
315
337
|
if (obj) call.receiver = obj.text;
|
|
316
338
|
}
|
|
317
339
|
}
|
|
318
340
|
|
|
319
|
-
if (call.name)
|
|
341
|
+
if (!call.name) return;
|
|
342
|
+
|
|
343
|
+
// obj."$dyn"() or obj."${var}"() — GString method name; cannot resolve statically
|
|
344
|
+
if (fieldNode && (fieldNode.type === 'gstring' || fieldNode.type === 'template_string')) {
|
|
345
|
+
ctx.calls.push({
|
|
346
|
+
name: '<dynamic:unresolved>',
|
|
347
|
+
line: call.line,
|
|
348
|
+
dynamic: true,
|
|
349
|
+
dynamicKind: 'unresolved-dynamic',
|
|
350
|
+
receiver: call.receiver,
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// obj.invokeMethod("name", args) — Groovy's explicit dynamic dispatch
|
|
356
|
+
if (call.name === 'invokeMethod') {
|
|
357
|
+
const literal = getFirstStringArgGroovy(node);
|
|
358
|
+
if (literal) {
|
|
359
|
+
ctx.calls.push({
|
|
360
|
+
name: literal,
|
|
361
|
+
line: call.line,
|
|
362
|
+
dynamic: true,
|
|
363
|
+
dynamicKind: 'reflection',
|
|
364
|
+
keyExpr: literal,
|
|
365
|
+
receiver: call.receiver,
|
|
366
|
+
});
|
|
367
|
+
} else {
|
|
368
|
+
ctx.calls.push({
|
|
369
|
+
name: '<dynamic:computed-key>',
|
|
370
|
+
line: call.line,
|
|
371
|
+
dynamic: true,
|
|
372
|
+
dynamicKind: 'computed-key',
|
|
373
|
+
receiver: call.receiver,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
ctx.calls.push(call);
|
|
320
380
|
}
|
|
321
381
|
|
|
322
382
|
function handleGroovyObjectCreation(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Call,
|
|
3
|
+
DynamicKind,
|
|
3
4
|
ExtractorOutput,
|
|
4
5
|
Import,
|
|
5
6
|
SubDeclaration,
|
|
@@ -270,18 +271,20 @@ export function extractModifierVisibility(
|
|
|
270
271
|
|
|
271
272
|
/**
|
|
272
273
|
* Append a `Call` to the extractor output. `line` defaults to the start line of
|
|
273
|
-
* `node`; pass `extra` for `receiver` / `dynamic`
|
|
274
|
+
* `node`; pass `extra` for `receiver` / `dynamic` / `dynamicKind` / `keyExpr` fields.
|
|
274
275
|
*/
|
|
275
276
|
export function pushCall(
|
|
276
277
|
ctx: ExtractorOutput,
|
|
277
278
|
node: TreeSitterNode,
|
|
278
279
|
name: string,
|
|
279
|
-
extra: { receiver?: string; dynamic?: boolean } = {},
|
|
280
|
+
extra: { receiver?: string; dynamic?: boolean; dynamicKind?: DynamicKind; keyExpr?: string } = {},
|
|
280
281
|
): void {
|
|
281
282
|
if (!name) return;
|
|
282
283
|
const call: Call = { name, line: nodeStartLine(node) };
|
|
283
284
|
if (extra.receiver !== undefined) call.receiver = extra.receiver;
|
|
284
285
|
if (extra.dynamic !== undefined) call.dynamic = extra.dynamic;
|
|
286
|
+
if (extra.dynamicKind !== undefined) call.dynamicKind = extra.dynamicKind;
|
|
287
|
+
if (extra.keyExpr !== undefined) call.keyExpr = extra.keyExpr;
|
|
285
288
|
ctx.calls.push(call);
|
|
286
289
|
}
|
|
287
290
|
|
|
@@ -305,6 +308,49 @@ export function pushImport(
|
|
|
305
308
|
ctx.imports.push(entry);
|
|
306
309
|
}
|
|
307
310
|
|
|
311
|
+
// ── C-family primitive types ───────────────────────────────────────────────
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Primitive C/C++/CUDA types that are never class/struct receivers. Seeding
|
|
315
|
+
* these into typeMap would produce spurious receiver edges (e.g. `int x` → `int`).
|
|
316
|
+
* Shared between the C++ and CUDA extractors to prevent divergence.
|
|
317
|
+
*/
|
|
318
|
+
export const C_PRIMITIVE_TYPES: ReadonlySet<string> = new Set([
|
|
319
|
+
'int',
|
|
320
|
+
'long',
|
|
321
|
+
'short',
|
|
322
|
+
'unsigned',
|
|
323
|
+
'signed',
|
|
324
|
+
'float',
|
|
325
|
+
'double',
|
|
326
|
+
'char',
|
|
327
|
+
'bool',
|
|
328
|
+
'void',
|
|
329
|
+
'wchar_t',
|
|
330
|
+
'auto',
|
|
331
|
+
'size_t',
|
|
332
|
+
'uint8_t',
|
|
333
|
+
'uint16_t',
|
|
334
|
+
'uint32_t',
|
|
335
|
+
'uint64_t',
|
|
336
|
+
'int8_t',
|
|
337
|
+
'int16_t',
|
|
338
|
+
'int32_t',
|
|
339
|
+
'int64_t',
|
|
340
|
+
'ptrdiff_t',
|
|
341
|
+
'intptr_t',
|
|
342
|
+
'uintptr_t',
|
|
343
|
+
]);
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Return true when `typeName` is a primitive C/C++/CUDA type.
|
|
347
|
+
* Strips leading qualifiers (`const int` → `int`) before checking.
|
|
348
|
+
*/
|
|
349
|
+
export function isCPrimitiveType(typeName: string): boolean {
|
|
350
|
+
const base = typeName.split(/\s+/).pop() ?? typeName;
|
|
351
|
+
return C_PRIMITIVE_TYPES.has(base) || C_PRIMITIVE_TYPES.has(typeName);
|
|
352
|
+
}
|
|
353
|
+
|
|
308
354
|
// ── Parameter extraction ───────────────────────────────────────────────────
|
|
309
355
|
|
|
310
356
|
/**
|