cgraphx 2.0.1 → 2.0.3
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/dist/.claude-template/FLOW-MAP.md +7 -5
- package/dist/.claude-template/commands/end.md +1 -1
- package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +2 -1
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +4 -2
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.md +5 -2
- package/dist/.claude-template/skills/iboc-check/SKILL.md +116 -0
- package/dist/.claude-template/skills/iboc-check/filler-prompt.md +75 -0
- package/dist/.claude-template/skills/implementation/SKILL.md +7 -0
- package/dist/.claude-template/skills/init-project-guides/SKILL.md +1 -1
- package/dist/.claude-template/skills/run-api-test/references/db-verification.md +2 -2
- package/dist/.claude-template/skills/subagent-implement/SKILL.md +3 -2
- package/dist/.claude-template/skills/write-api/assets/template-request.bru +3 -3
- package/dist/.claude-template/skills/write-api/references/bru-format.md +6 -6
- package/dist/.claude-template/skills/write-delivery-guide/SKILL.md +97 -0
- package/dist/.claude-template/skills/write-delivery-guide/template-change-type.md +120 -0
- package/dist/.claude-template/skills/write-delivery-guide/template-multi-role-flow.md +148 -0
- package/dist/.claude-template/skills/write-unit-test-code/SKILL.md +23 -6
- package/dist/core/code/engine/cli/analyze-config.js +320 -0
- package/dist/core/code/engine/cli/analyze.js +1086 -0
- package/dist/core/code/engine/cli/cli-message.js +83 -0
- package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
- package/dist/core/code/engine/cli/embedding-dims.js +43 -0
- package/dist/core/code/engine/cli/format-elapsed.js +12 -0
- package/dist/core/code/engine/cli/help-i18n.js +144 -0
- package/dist/core/code/engine/cli/i18n/en.js +110 -0
- package/dist/core/code/engine/cli/i18n/index.js +47 -0
- package/dist/core/code/engine/cli/i18n/resources.js +9 -0
- package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
- package/dist/core/code/engine/cli/lazy-action.js +67 -0
- package/dist/core/code/engine/cli/optional-grammars.js +136 -0
- package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
- package/dist/core/code/engine/cli/status.js +156 -0
- package/dist/core/code/engine/cli/tool.js +384 -0
- package/dist/core/code/engine/config/ignore-service.js +511 -0
- package/dist/core/code/engine/config/supported-languages.js +17 -0
- package/dist/core/code/engine/core/analysis-features.js +64 -0
- package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
- package/dist/core/code/engine/core/git-staleness.js +180 -0
- package/dist/core/code/engine/core/graph/graph.js +180 -0
- package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
- package/dist/core/code/engine/core/graph/types.js +2 -0
- package/dist/core/code/engine/core/index-freshness.js +12 -0
- package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
- package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
- package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
- package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
- package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
- package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
- package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
- package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
- package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
- package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
- package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
- package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
- package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
- package/dist/core/code/engine/core/ingestion/constants.js +26 -0
- package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
- package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
- package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
- package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
- package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
- package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
- package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
- package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
- package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
- package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
- package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
- package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
- package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
- package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
- package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
- package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
- package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
- package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
- package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
- package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
- package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
- package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
- package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
- package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
- package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
- package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
- package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
- package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
- package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
- package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
- package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
- package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
- package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
- package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
- package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
- package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
- package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
- package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
- package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
- package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
- package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
- package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
- package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
- package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
- package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
- package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
- package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
- package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
- package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
- package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
- package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
- package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
- package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
- package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
- package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
- package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
- package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
- package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
- package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
- package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
- package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
- package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
- package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
- package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
- package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
- package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
- package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
- package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
- package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
- package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
- package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
- package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
- package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
- package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
- package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
- package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
- package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
- package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
- package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
- package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
- package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
- package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
- package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
- package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
- package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
- package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
- package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
- package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
- package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
- package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
- package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
- package/dist/core/code/engine/core/lbug/native-check.js +435 -0
- package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
- package/dist/core/code/engine/core/lbug/query-params.js +25 -0
- package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
- package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
- package/dist/core/code/engine/core/lbug/schema.js +771 -0
- package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
- package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
- package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
- package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
- package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
- package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
- package/dist/core/code/engine/core/logger.js +339 -0
- package/dist/core/code/engine/core/platform/capabilities.js +91 -0
- package/dist/core/code/engine/core/run-analyze.js +1098 -0
- package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
- package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
- package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
- package/dist/core/code/engine/lib/utils.js +121 -0
- package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
- package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
- package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
- package/dist/core/code/engine/mcp/local/limits.js +15 -0
- package/dist/core/code/engine/mcp/local/line-display.js +6 -0
- package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
- package/dist/core/code/engine/storage/branch-index.js +72 -0
- package/dist/core/code/engine/storage/file-hash.js +95 -0
- package/dist/core/code/engine/storage/fs-atomic.js +34 -0
- package/dist/core/code/engine/storage/git.js +555 -0
- package/dist/core/code/engine/storage/index-lock.js +664 -0
- package/dist/core/code/engine/storage/parse-cache.js +650 -0
- package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
- package/dist/core/code/engine/storage/repo-manager.js +1061 -0
- package/dist/core/code/engine/storage/scope-index-store.js +247 -0
- package/dist/core/code/engine/types/pipeline.js +2 -0
- package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
- package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
- package/dist/core/code/shared/graph/types.js +8 -0
- package/dist/core/code/shared/index.js +105 -0
- package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
- package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
- package/dist/core/code/shared/integrations/retry.js +70 -0
- package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
- package/dist/core/code/shared/language-detection.js +162 -0
- package/dist/core/code/shared/languages.js +27 -0
- package/dist/core/code/shared/lbug/schema-constants.js +98 -0
- package/dist/core/code/shared/mro-strategy.js +2 -0
- package/dist/core/code/shared/pipeline.js +5 -0
- package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
- package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
- package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
- package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
- package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
- package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
- package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
- package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
- package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
- package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
- package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
- package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
- package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
- package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
- package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
- package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
- package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
- package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
- package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
- package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
- package/dist/core/code/shared/scope-resolution/types.js +25 -0
- package/dist/core/code/shared/test-helpers.js +17 -0
- package/dist/core/code/vendor/leiden/index.cjs +355 -0
- package/dist/core/code/vendor/leiden/utils.cjs +419 -0
- package/dist/core/features/scanner.d.ts +2 -0
- package/dist/core/features/scanner.d.ts.map +1 -1
- package/dist/core/features/scanner.js +27 -6
- package/dist/core/features/scanner.js.map +1 -1
- package/dist/core/timeline/cli.d.ts.map +1 -1
- package/dist/core/timeline/cli.js +13 -6
- package/dist/core/timeline/cli.js.map +1 -1
- package/dist/core/timeline/debris.d.ts +20 -0
- package/dist/core/timeline/debris.d.ts.map +1 -0
- package/dist/core/timeline/debris.js +124 -0
- package/dist/core/timeline/debris.js.map +1 -0
- package/dist/core/timeline/hook-runner.d.ts.map +1 -1
- package/dist/core/timeline/hook-runner.js +3 -1
- package/dist/core/timeline/hook-runner.js.map +1 -1
- package/dist/core/timeline/hooks.d.ts.map +1 -1
- package/dist/core/timeline/hooks.js +13 -5
- package/dist/core/timeline/hooks.js.map +1 -1
- package/dist/core/timeline/installer.d.ts +2 -0
- package/dist/core/timeline/installer.d.ts.map +1 -1
- package/dist/core/timeline/installer.js +12 -0
- package/dist/core/timeline/installer.js.map +1 -1
- package/dist/core/timeline/project-root.d.ts +21 -0
- package/dist/core/timeline/project-root.d.ts.map +1 -0
- package/dist/core/timeline/project-root.js +83 -0
- package/dist/core/timeline/project-root.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1975 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emitCppScopeCaptures = emitCppScopeCaptures;
|
|
4
|
+
const ast_helpers_js_1 = require("../../utils/ast-helpers.js");
|
|
5
|
+
const query_js_1 = require("./query.js");
|
|
6
|
+
const constants_js_1 = require("../../constants.js");
|
|
7
|
+
const safe_parse_js_1 = require("../../../tree-sitter/safe-parse.js");
|
|
8
|
+
const cpp_ue_preprocessor_js_1 = require("../../cpp-ue-preprocessor.js");
|
|
9
|
+
const qualified_name_js_1 = require("../../utils/qualified-name.js");
|
|
10
|
+
const import_decomposer_js_1 = require("./import-decomposer.js");
|
|
11
|
+
const arity_metadata_js_1 = require("./arity-metadata.js");
|
|
12
|
+
const file_local_linkage_js_1 = require("./file-local-linkage.js");
|
|
13
|
+
const two_phase_lookup_js_1 = require("./two-phase-lookup.js");
|
|
14
|
+
const adl_js_1 = require("./adl.js");
|
|
15
|
+
const inline_namespaces_js_1 = require("./inline-namespaces.js");
|
|
16
|
+
const constraint_extractor_js_1 = require("./constraint-extractor.js");
|
|
17
|
+
const member_lookup_js_1 = require("./member-lookup.js");
|
|
18
|
+
const conversion_rank_js_1 = require("./conversion-rank.js");
|
|
19
|
+
const logger_js_1 = require("../../../logger.js");
|
|
20
|
+
const receiver_chain_captures_js_1 = require("../../utils/receiver-chain-captures.js");
|
|
21
|
+
const callable_flow_captures_js_1 = require("../../utils/callable-flow-captures.js");
|
|
22
|
+
const CPP_CALLABLE_CAPTURE_OPTIONS = {
|
|
23
|
+
functionNodeTypes: new Set(['function_definition', 'lambda_expression']),
|
|
24
|
+
callNodeTypes: new Set(['call_expression']),
|
|
25
|
+
parameterListNodeTypes: new Set(['parameter_list', 'argument_list']),
|
|
26
|
+
parameterNodeTypes: new Set(['parameter_declaration', 'optional_parameter_declaration']),
|
|
27
|
+
bindingNodeTypes: new Set(['init_declarator']),
|
|
28
|
+
assignmentNodeTypes: new Set(['assignment_expression']),
|
|
29
|
+
identifierNodeTypes: new Set([
|
|
30
|
+
'identifier',
|
|
31
|
+
'field_identifier',
|
|
32
|
+
'type_identifier',
|
|
33
|
+
'namespace_identifier',
|
|
34
|
+
]),
|
|
35
|
+
callableSignatureDeclarationNodeTypes: new Set([
|
|
36
|
+
'declaration',
|
|
37
|
+
'field_declaration',
|
|
38
|
+
'parameter_declaration',
|
|
39
|
+
'optional_parameter_declaration',
|
|
40
|
+
]),
|
|
41
|
+
callableReferenceNodeTypes: new Set(['qualified_identifier']),
|
|
42
|
+
emitCanonicalInvokeReference: true,
|
|
43
|
+
memberPointerOperators: new Set(['.*', '->*']),
|
|
44
|
+
memberPointerParts: (node) => cppRecoveredMemberPointerParts(node),
|
|
45
|
+
parameterPassingMode: (parameter) => cppOutermostPassingMode(parameter),
|
|
46
|
+
isTrueReferenceBinding: (_container, destination) => cppContainsNodeType(destination, 'reference_declarator'),
|
|
47
|
+
expectedSignature: (container, destination) => cppFunctionDeclaratorSignature(destination) ?? cppFunctionDeclaratorSignature(container),
|
|
48
|
+
normalizeQualifiedName: (raw) => raw.replaceAll('::', '.'),
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Passing mode from the parameter's OUTERMOST declarator chain only. A deep
|
|
52
|
+
* subtree scan inverted copy vs alias: `void reg(void (*cb)(int& out))` has a
|
|
53
|
+
* `reference_declarator` inside the nested parameter list, but `cb` itself is
|
|
54
|
+
* a by-value pointer copy — classifying it 'reference' made the solver
|
|
55
|
+
* back-propagate formal targets into every caller's argument cell (#2522
|
|
56
|
+
* review, M5). The chain walk never descends into nested parameter lists.
|
|
57
|
+
*/
|
|
58
|
+
function cppOutermostPassingMode(parameter) {
|
|
59
|
+
let sawReference = false;
|
|
60
|
+
let sawPointer = false;
|
|
61
|
+
let node = parameter.childForFieldName('declarator') ?? null;
|
|
62
|
+
const visited = new Set();
|
|
63
|
+
while (node !== null && !visited.has(node.id)) {
|
|
64
|
+
visited.add(node.id);
|
|
65
|
+
if (node.type === 'reference_declarator' || node.type === 'abstract_reference_declarator') {
|
|
66
|
+
// A reference ANYWHERE on the chain aliases the caller's storage —
|
|
67
|
+
// `void (*&cb)(int)` is a reference to pointer, i.e. an alias.
|
|
68
|
+
sawReference = true;
|
|
69
|
+
}
|
|
70
|
+
else if (node.type === 'pointer_declarator' || node.type === 'abstract_pointer_declarator') {
|
|
71
|
+
sawPointer = true;
|
|
72
|
+
}
|
|
73
|
+
const next = node.childForFieldName('declarator');
|
|
74
|
+
if (next !== null) {
|
|
75
|
+
node = next;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (node.type === 'parenthesized_declarator') {
|
|
79
|
+
node =
|
|
80
|
+
node.namedChildren.find((child) => child !== null && child.type.includes('declarator')) ?? null;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return sawReference ? 'reference' : sawPointer ? 'pointer' : 'value';
|
|
86
|
+
}
|
|
87
|
+
function cppRecoveredMemberPointerParts(node) {
|
|
88
|
+
if (!node.type.includes('parenthesized'))
|
|
89
|
+
return undefined;
|
|
90
|
+
const recovered = node.namedChildren.find((child) => child !== null && child.type === 'ERROR');
|
|
91
|
+
if (recovered === undefined)
|
|
92
|
+
return undefined;
|
|
93
|
+
const operator = recovered.children.find((child) => child !== null && child.text === '->*');
|
|
94
|
+
const sibling = node.namedChildren.find((child) => child !== null && child.id !== recovered.id);
|
|
95
|
+
const errIdentifier = recovered.namedChildren.find((child) => child !== null);
|
|
96
|
+
if (operator === undefined || sibling === undefined || errIdentifier === undefined) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
// tree-sitter's error recovery groups `(obj->*ptr)` two ways depending on
|
|
100
|
+
// recovery cost (identifier lengths!): either `[identifier, ERROR "->*m"]`
|
|
101
|
+
// or `[ERROR "obj->*", identifier]`. Disambiguate by token order INSIDE the
|
|
102
|
+
// ERROR: an identifier BEFORE `->*` is the receiver (the sibling is the
|
|
103
|
+
// pointer/member); an identifier AFTER `->*` is the member (the sibling is
|
|
104
|
+
// the receiver). Assuming one fixed grouping swapped the roles and silently
|
|
105
|
+
// dropped the call site (#2522 review, H2).
|
|
106
|
+
if (errIdentifier.startIndex < operator.startIndex) {
|
|
107
|
+
return { receiver: errIdentifier, member: sibling, operator: operator.text };
|
|
108
|
+
}
|
|
109
|
+
return { receiver: sibling, member: errIdentifier, operator: operator.text };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Per-file wall-clock budget for the capture-emit loop (#2432). A worker
|
|
113
|
+
* thread stuck in this loop cannot be terminated safely (terminating a
|
|
114
|
+
* thread mid-N-API call aborts the whole process with Napi::Error), so the
|
|
115
|
+
* loop must bound itself: on breach we return the captures accumulated so
|
|
116
|
+
* far with a warning — degraded coverage for one file, never a crash or a
|
|
117
|
+
* thrown error (a throw here would make the language-group catch drop every
|
|
118
|
+
* remaining file in the batch).
|
|
119
|
+
*
|
|
120
|
+
* `CGRAPH_CPP_CAPTURE_BUDGET_MS`: unset/invalid/negative → 20000; explicit
|
|
121
|
+
* 0 → expires immediately (deterministic test hook).
|
|
122
|
+
*/
|
|
123
|
+
const CPP_CAPTURE_BUDGET_DEFAULT_MS = 20_000;
|
|
124
|
+
function cppCaptureBudgetMs() {
|
|
125
|
+
const raw = process.env.CGRAPH_CPP_CAPTURE_BUDGET_MS;
|
|
126
|
+
if (raw === undefined || raw === '')
|
|
127
|
+
return CPP_CAPTURE_BUDGET_DEFAULT_MS;
|
|
128
|
+
const parsed = Number(raw);
|
|
129
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : CPP_CAPTURE_BUDGET_DEFAULT_MS;
|
|
130
|
+
}
|
|
131
|
+
function emitCppScopeCaptures(sourceText, filePath, cachedTree) {
|
|
132
|
+
let tree = cachedTree;
|
|
133
|
+
if (tree === undefined) {
|
|
134
|
+
// Idempotent re-application: `extractParsedFile` already preprocesses, but
|
|
135
|
+
// direct emitter callers (benchmarks, capture goldens) must see the same
|
|
136
|
+
// program the pipeline does.
|
|
137
|
+
const parseText = (0, cpp_ue_preprocessor_js_1.stripUeMacros)(sourceText);
|
|
138
|
+
tree = (0, safe_parse_js_1.parseSourceSafe)((0, query_js_1.getCppParser)(), parseText, undefined, {
|
|
139
|
+
bufferSize: (0, constants_js_1.getTreeSitterBufferSize)(parseText),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const rawMatches = (0, query_js_1.getCppScopeQuery)().matches(tree.rootNode);
|
|
143
|
+
const out = [];
|
|
144
|
+
// #2432: reset the per-file lookup index. The identifier-argument type
|
|
145
|
+
// lookups below used to re-walk the AST per identifier (full-tree DFS in
|
|
146
|
+
// isKnownEnumName, per-scope declaration scans) — O(calls × args × treeSize)
|
|
147
|
+
// per file, 151s on a 194KB file that parses in 46ms. The index makes each
|
|
148
|
+
// lookup O(1) after a single lazily-built pass.
|
|
149
|
+
resetCppFileLookupIndex();
|
|
150
|
+
// Track ranges where typedef-struct/enum was captured as its concrete type
|
|
151
|
+
// so we can suppress the duplicate @declaration.typedef match.
|
|
152
|
+
const concreteTypedefRanges = new Set();
|
|
153
|
+
// #2432: per-file deadline for the loop below (see cppCaptureBudgetMs).
|
|
154
|
+
// Checked every 64 matches — post-index a single iteration is microseconds,
|
|
155
|
+
// so the check granularity costs nothing and bounds the drift past the
|
|
156
|
+
// deadline to well under a second.
|
|
157
|
+
const budgetMs = cppCaptureBudgetMs();
|
|
158
|
+
const deadline = Date.now() + budgetMs;
|
|
159
|
+
let matchIndex = 0;
|
|
160
|
+
for (const m of rawMatches) {
|
|
161
|
+
if ((matchIndex++ & 63) === 0 && Date.now() >= deadline) {
|
|
162
|
+
logger_js_1.logger.warn({ filePath, budgetMs, processedMatches: matchIndex - 1, totalMatches: rawMatches.length }, `C++ capture extraction exceeded its ${budgetMs}ms budget for ${filePath}; returning partial captures for this file (#2432).`);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
const grouped = {};
|
|
166
|
+
// Parallel tag -> captured SyntaxNode map. The tree-sitter query already
|
|
167
|
+
// hands us each matched node as `c.node`, so anchors resolve via a
|
|
168
|
+
// type-guarded lookup (`nodeIfType`) instead of re-deriving them with
|
|
169
|
+
// `findNodeAtRange(tree.rootNode, ...)` per match — the
|
|
170
|
+
// O(matches × rootChildren) root-walk fixed for go #1848 / python #1918 /
|
|
171
|
+
// rust/csharp #1915 / java, mirrored here for C++ (#1951). Each C++
|
|
172
|
+
// scope-query anchor used below captures directly ON the node the old
|
|
173
|
+
// root-walk re-derived (verified against CPP_SCOPE_QUERY in query.ts and a
|
|
174
|
+
// real-parse AST probe), so the type check is exact.
|
|
175
|
+
const nodeMap = {};
|
|
176
|
+
for (const c of m.captures) {
|
|
177
|
+
const tag = '@' + c.name;
|
|
178
|
+
if (tag.startsWith('@_'))
|
|
179
|
+
continue;
|
|
180
|
+
grouped[tag] = (0, ast_helpers_js_1.nodeToCapture)(tag, c.node);
|
|
181
|
+
nodeMap[tag] = c.node;
|
|
182
|
+
}
|
|
183
|
+
if (Object.keys(grouped).length === 0)
|
|
184
|
+
continue;
|
|
185
|
+
// ── Handle #include statements ──────────────────────────────────
|
|
186
|
+
// `@import.statement` is captured directly on the `preproc_include` node.
|
|
187
|
+
if (grouped['@import.statement'] !== undefined) {
|
|
188
|
+
const includeNode = (0, ast_helpers_js_1.nodeIfType)(nodeMap['@import.statement'], 'preproc_include');
|
|
189
|
+
if (includeNode !== null) {
|
|
190
|
+
const split = (0, import_decomposer_js_1.splitCppInclude)(includeNode);
|
|
191
|
+
if (split !== null) {
|
|
192
|
+
out.push(split);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// ── Handle using declarations (using namespace / using name) ────
|
|
198
|
+
// `@import.using-decl` is captured directly on the `using_declaration` node.
|
|
199
|
+
if (grouped['@import.using-decl'] !== undefined) {
|
|
200
|
+
const usingNode = (0, ast_helpers_js_1.nodeIfType)(nodeMap['@import.using-decl'], 'using_declaration');
|
|
201
|
+
if (usingNode !== null) {
|
|
202
|
+
const split = (0, import_decomposer_js_1.splitCppUsingDecl)(usingNode);
|
|
203
|
+
if (split !== null) {
|
|
204
|
+
out.push(split);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// ── Track concrete typedef ranges ───────────────────────────────
|
|
210
|
+
const concreteTypeAnchor = grouped['@declaration.struct'] ??
|
|
211
|
+
grouped['@declaration.class'] ??
|
|
212
|
+
grouped['@declaration.enum'];
|
|
213
|
+
if (concreteTypeAnchor !== undefined) {
|
|
214
|
+
const r = concreteTypeAnchor.range;
|
|
215
|
+
concreteTypedefRanges.add(`${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`);
|
|
216
|
+
}
|
|
217
|
+
// Suppress @declaration.typedef if the same range was already captured
|
|
218
|
+
const typedefAnchor = grouped['@declaration.typedef'];
|
|
219
|
+
if (typedefAnchor !== undefined) {
|
|
220
|
+
const r = typedefAnchor.range;
|
|
221
|
+
const key = `${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`;
|
|
222
|
+
if (concreteTypedefRanges.has(key))
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// ── Enrich function/method declarations with arity metadata ─────
|
|
226
|
+
// `@declaration.function` / `@declaration.method` capture directly on the
|
|
227
|
+
// `function_definition` (definitions/templates), `declaration` (free/
|
|
228
|
+
// constructor prototypes), or `field_declaration` (class-body method
|
|
229
|
+
// prototypes) node — the node the old findNodeAtRange re-derived.
|
|
230
|
+
const declAnchorNode = nodeMap['@declaration.function'] ?? nodeMap['@declaration.method'];
|
|
231
|
+
if (declAnchorNode !== undefined) {
|
|
232
|
+
const fnNode = (0, ast_helpers_js_1.nodeIfType)(declAnchorNode, 'function_definition', 'declaration', 'field_declaration');
|
|
233
|
+
if (fnNode !== null) {
|
|
234
|
+
const arity = (0, arity_metadata_js_1.computeCppDeclarationArity)(fnNode);
|
|
235
|
+
if (arity.parameterCount !== undefined) {
|
|
236
|
+
grouped['@declaration.parameter-count'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.parameter-count', fnNode, String(arity.parameterCount));
|
|
237
|
+
}
|
|
238
|
+
if (arity.requiredParameterCount !== undefined) {
|
|
239
|
+
grouped['@declaration.required-parameter-count'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.required-parameter-count', fnNode, String(arity.requiredParameterCount));
|
|
240
|
+
}
|
|
241
|
+
if (arity.parameterTypes !== undefined) {
|
|
242
|
+
grouped['@declaration.parameter-types'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.parameter-types', fnNode, JSON.stringify(arity.parameterTypes));
|
|
243
|
+
}
|
|
244
|
+
if (arity.parameterTypeClasses !== undefined) {
|
|
245
|
+
grouped['@declaration.parameter-type-classes'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.parameter-type-classes', fnNode, JSON.stringify(arity.parameterTypeClasses));
|
|
246
|
+
}
|
|
247
|
+
const returnType = extractCppDeclarationReturnType(fnNode);
|
|
248
|
+
if (returnType !== undefined) {
|
|
249
|
+
grouped['@declaration.return-type'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.return-type', fnNode, returnType);
|
|
250
|
+
}
|
|
251
|
+
if (hasExplicitSpecifier(fnNode)) {
|
|
252
|
+
grouped['@declaration.is-explicit'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.is-explicit', fnNode, 'true');
|
|
253
|
+
}
|
|
254
|
+
if (hasDeletedMethodClause(fnNode, grouped['@declaration.name']?.text)) {
|
|
255
|
+
grouped['@declaration.is-deleted'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.is-deleted', fnNode, 'true');
|
|
256
|
+
}
|
|
257
|
+
// Detect static storage class (file-local linkage)
|
|
258
|
+
if (hasStaticStorageClass(fnNode)) {
|
|
259
|
+
const nameText = grouped['@declaration.name']?.text;
|
|
260
|
+
if (nameText !== undefined) {
|
|
261
|
+
(0, file_local_linkage_js_1.markFileLocal)(filePath, nameText);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Detect anonymous namespace (file-local linkage)
|
|
265
|
+
if (isInsideAnonymousNamespace(fnNode)) {
|
|
266
|
+
const nameText = grouped['@declaration.name']?.text;
|
|
267
|
+
if (nameText !== undefined) {
|
|
268
|
+
(0, file_local_linkage_js_1.markFileLocal)(filePath, nameText);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// SFINAE / `requires`-clause aware constraints for overload
|
|
272
|
+
// narrowing (issue #1579). Walk from the enclosing
|
|
273
|
+
// `template_declaration` — not the inner `function_definition` —
|
|
274
|
+
// so inline method templates (`template<...> class C { template<...> void f(); }`)
|
|
275
|
+
// pick up the correct outer constraint scope.
|
|
276
|
+
const templateDecl = findEnclosingTemplateDeclaration(fnNode);
|
|
277
|
+
if (templateDecl !== null) {
|
|
278
|
+
const funcDeclarator = findFunctionDeclarator(fnNode);
|
|
279
|
+
const constraints = (0, constraint_extractor_js_1.extractCppTemplateConstraints)(templateDecl, funcDeclarator);
|
|
280
|
+
if (constraints !== undefined) {
|
|
281
|
+
grouped['@declaration.template-constraints'] = (0, ast_helpers_js_1.syntheticCapture)('@declaration.template-constraints', fnNode, JSON.stringify(constraints));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// ── Detect static variables (file-local linkage) ────────────────
|
|
287
|
+
// `@declaration.variable` is captured directly on the `declaration` node.
|
|
288
|
+
if (grouped['@declaration.variable'] !== undefined) {
|
|
289
|
+
const varNode = (0, ast_helpers_js_1.nodeIfType)(nodeMap['@declaration.variable'], 'declaration');
|
|
290
|
+
if (varNode !== null) {
|
|
291
|
+
if (hasStaticStorageClass(varNode) || isInsideAnonymousNamespace(varNode)) {
|
|
292
|
+
const nameText = grouped['@declaration.name']?.text;
|
|
293
|
+
if (nameText !== undefined) {
|
|
294
|
+
(0, file_local_linkage_js_1.markFileLocal)(filePath, nameText);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// ── Enrich call references with arity ───────────────────────────
|
|
300
|
+
// `@reference.call.free` / `.member` capture on the `call_expression` (plain
|
|
301
|
+
// / member / template calls) or on the `binary_expression` (the operator-call
|
|
302
|
+
// patterns: `a + b`, `lhs << rhs`); `@reference.call.qualified` always on the
|
|
303
|
+
// `call_expression`. The captured node IS the node the old findNodeAtRange
|
|
304
|
+
// re-derived (verified against CPP_SCOPE_QUERY + a real-parse probe).
|
|
305
|
+
const callAnchor = grouped['@reference.call.free'] ??
|
|
306
|
+
grouped['@reference.call.member'] ??
|
|
307
|
+
grouped['@reference.call.qualified'];
|
|
308
|
+
const callAnchorNode = nodeMap['@reference.call.free'] ??
|
|
309
|
+
nodeMap['@reference.call.member'] ??
|
|
310
|
+
nodeMap['@reference.call.qualified'];
|
|
311
|
+
const operatorAnchor = grouped['@reference.operator'];
|
|
312
|
+
if (operatorAnchor !== undefined) {
|
|
313
|
+
// When `@reference.operator` fires, the co-captured call anchor is the
|
|
314
|
+
// enclosing `binary_expression` itself, so a type guard reproduces the
|
|
315
|
+
// old findNodeAtRange(callAnchor.range, 'binary_expression').
|
|
316
|
+
const operatorNode = callAnchorNode !== undefined ? (0, ast_helpers_js_1.nodeIfType)(callAnchorNode, 'binary_expression') : null;
|
|
317
|
+
if (operatorNode !== null && isPrimitiveOnlyBinaryOperator(operatorNode))
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (callAnchorNode !== undefined && grouped['@reference.arity'] === undefined) {
|
|
321
|
+
const callNode = (0, ast_helpers_js_1.nodeIfType)(callAnchorNode, 'call_expression', 'binary_expression');
|
|
322
|
+
if (callNode?.type === 'call_expression') {
|
|
323
|
+
grouped['@reference.arity'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.arity', callNode, String((0, arity_metadata_js_1.computeCppCallArity)(callNode)));
|
|
324
|
+
}
|
|
325
|
+
else if (callNode?.type === 'binary_expression') {
|
|
326
|
+
grouped['@reference.arity'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.arity', callNode, grouped['@reference.call.member'] !== undefined ? '1' : '2');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (operatorAnchor !== undefined && grouped['@reference.name'] === undefined) {
|
|
330
|
+
// The old code did `findNodeAtRange(tree.rootNode, operatorAnchor.range,
|
|
331
|
+
// operatorAnchor.text)`, searching for a node of type `+` / `<<` at the
|
|
332
|
+
// operator-token range. That token is an UNNAMED grammar node, and
|
|
333
|
+
// findNodeAtRange only descends `namedChild`ren, so the search NEVER hit
|
|
334
|
+
// and ALWAYS fell back to `tree.rootNode`. Use `tree.rootNode` directly to
|
|
335
|
+
// preserve the exact synthetic-capture range while dropping the root-walk.
|
|
336
|
+
grouped['@reference.name'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.name', tree.rootNode, `operator${operatorAnchor.text}`);
|
|
337
|
+
}
|
|
338
|
+
// ── Enrich constructor calls (new Foo()) with arity ─────────────
|
|
339
|
+
// `@reference.call.constructor` is captured directly on the `new_expression`.
|
|
340
|
+
const ctorCallAnchor = grouped['@reference.call.constructor'];
|
|
341
|
+
const ctorCallAnchorNode = nodeMap['@reference.call.constructor'];
|
|
342
|
+
if (ctorCallAnchor !== undefined && grouped['@reference.arity'] === undefined) {
|
|
343
|
+
const newNode = (0, ast_helpers_js_1.nodeIfType)(ctorCallAnchorNode, 'new_expression');
|
|
344
|
+
if (newNode !== null) {
|
|
345
|
+
grouped['@reference.arity'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.arity', newNode, String((0, arity_metadata_js_1.computeCppCallArity)(newNode)));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// ── Synthesize argument types for overload narrowing ────────────
|
|
349
|
+
// The any-call anchor is either the call/operator anchor (`call_expression`
|
|
350
|
+
// / `binary_expression`) or the constructor anchor (`new_expression`); the
|
|
351
|
+
// captured node IS what the old findNodeAtRange re-derived.
|
|
352
|
+
const anyCallAnchor = callAnchor ?? ctorCallAnchor;
|
|
353
|
+
const anyCallAnchorNode = callAnchorNode ?? ctorCallAnchorNode;
|
|
354
|
+
if (anyCallAnchor !== undefined && grouped['@reference.parameter-types'] === undefined) {
|
|
355
|
+
const cNode = (0, ast_helpers_js_1.nodeIfType)(anyCallAnchorNode, 'call_expression', 'new_expression', 'binary_expression');
|
|
356
|
+
if (cNode !== null) {
|
|
357
|
+
const argTypes = cNode.type === 'binary_expression'
|
|
358
|
+
? inferCppBinaryOperatorArgTypes(cNode, grouped['@reference.call.free'] !== undefined)
|
|
359
|
+
: inferCppCallArgTypes(cNode);
|
|
360
|
+
if (argTypes !== undefined && argTypes.length > 0) {
|
|
361
|
+
grouped['@reference.parameter-types'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.parameter-types', cNode, JSON.stringify(argTypes));
|
|
362
|
+
}
|
|
363
|
+
const argTypeClasses = cNode.type === 'binary_expression'
|
|
364
|
+
? inferCppBinaryOperatorArgTypeClasses(cNode, grouped['@reference.call.free'] !== undefined)
|
|
365
|
+
: inferCppCallArgTypeClasses(cNode);
|
|
366
|
+
if (argTypeClasses !== undefined && argTypeClasses.length > 0) {
|
|
367
|
+
grouped['@reference.parameter-type-classes'] = (0, ast_helpers_js_1.syntheticCapture)('@reference.parameter-type-classes', cNode, JSON.stringify(argTypeClasses));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// ── Inline namespace detection ──────────────────────────────────
|
|
372
|
+
// `inline namespace v1 { ... }` — tree-sitter-cpp exposes the
|
|
373
|
+
// `inline` keyword as a child of `namespace_definition`. Record the
|
|
374
|
+
// namespace's source range so `populateCppInlineNamespaceScopes`
|
|
375
|
+
// (during populateOwners) can match it back to the corresponding
|
|
376
|
+
// Namespace scope.
|
|
377
|
+
// `@declaration.namespace` fires only for NAMED namespaces (the query
|
|
378
|
+
// requires a `name: (namespace_identifier)` child). Use the unconditional
|
|
379
|
+
// `@scope.namespace` capture so the anonymous-namespace branch also runs.
|
|
380
|
+
// `@declaration.namespace` and `@scope.namespace` both capture directly on
|
|
381
|
+
// the `namespace_definition` node.
|
|
382
|
+
const namespaceScopeAnchorNode = nodeMap['@declaration.namespace'] ?? nodeMap['@scope.namespace'];
|
|
383
|
+
if (namespaceScopeAnchorNode !== undefined) {
|
|
384
|
+
const nsNode = (0, ast_helpers_js_1.nodeIfType)(namespaceScopeAnchorNode, 'namespace_definition');
|
|
385
|
+
if (nsNode !== null) {
|
|
386
|
+
// Range coords stored in the shared Range shape use 1-based
|
|
387
|
+
// line numbers (see `ast-helpers.ts` rangeForNode where
|
|
388
|
+
// `startPosition.row + 1` is applied). Match that convention so
|
|
389
|
+
// the populators can join against `Scope.range`.
|
|
390
|
+
const nsRange = {
|
|
391
|
+
startLine: nsNode.startPosition.row + 1,
|
|
392
|
+
startCol: nsNode.startPosition.column,
|
|
393
|
+
endLine: nsNode.endPosition.row + 1,
|
|
394
|
+
endCol: nsNode.endPosition.column,
|
|
395
|
+
};
|
|
396
|
+
if (isInlineNamespace(nsNode)) {
|
|
397
|
+
(0, inline_namespaces_js_1.markCppInlineNamespaceRange)(filePath, nsRange);
|
|
398
|
+
}
|
|
399
|
+
// Anonymous namespace: `namespace_definition` with no `name` field.
|
|
400
|
+
// Recorded so `expandCppWildcardNames` can propagate its members
|
|
401
|
+
// to including TUs even though their names are also `markFileLocal`'d
|
|
402
|
+
// (which blocks the global free-call fallback's cross-file path).
|
|
403
|
+
if ((nsNode.childForFieldName?.('name') ?? null) === null) {
|
|
404
|
+
(0, file_local_linkage_js_1.markCppAnonymousNamespaceRange)(filePath, nsRange);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// ── ADL (Koenig lookup) per-site recording ──────────────────────
|
|
409
|
+
// Only free-call sites (no explicit receiver) participate in ADL —
|
|
410
|
+
// qualified `Ns::f(s)` and member `obj.f(s)` calls bypass the
|
|
411
|
+
// free-call fallback entirely (handled by receiver-bound-calls).
|
|
412
|
+
if (grouped['@reference.call.free'] !== undefined) {
|
|
413
|
+
// `@reference.call.free` captures on a `call_expression` (plain/template
|
|
414
|
+
// free call) or a `binary_expression` (the `lhs << rhs` operator-call
|
|
415
|
+
// pattern). The old findNodeAtRange filtered to `call_expression`, so the
|
|
416
|
+
// `binary_expression` case yields null here — `nodeIfType` matches exactly.
|
|
417
|
+
const freeCallNode = (0, ast_helpers_js_1.nodeIfType)(nodeMap['@reference.call.free'], 'call_expression');
|
|
418
|
+
if (freeCallNode !== null) {
|
|
419
|
+
const adlAnchorRange = grouped['@reference.call.free'].range;
|
|
420
|
+
if (isParenthesizedFunctionCall(freeCallNode)) {
|
|
421
|
+
(0, adl_js_1.markCppAdlSiteNoAdl)(filePath, adlAnchorRange.startLine, adlAnchorRange.startCol);
|
|
422
|
+
}
|
|
423
|
+
const adlArgs = inferCppCallAdlArgs(freeCallNode);
|
|
424
|
+
if (adlArgs.length > 0) {
|
|
425
|
+
(0, adl_js_1.markCppAdlSiteArgs)(filePath, adlAnchorRange.startLine, adlAnchorRange.startCol, adlArgs);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// ── Post-process @type-binding.assignment for auto declarations ──
|
|
430
|
+
// The wildcard `type: (_)` in the @type-binding.assignment query
|
|
431
|
+
// pattern matches before the more specific @type-binding.alias and
|
|
432
|
+
// @type-binding.member-access patterns. When the type is `auto`
|
|
433
|
+
// (placeholder_type_specifier), we re-inspect the AST to synthesize
|
|
434
|
+
// the correct capture tags so interpret.ts can produce the right
|
|
435
|
+
// rawTypeName for compound-receiver chain resolution.
|
|
436
|
+
if (grouped['@type-binding.assignment'] !== undefined &&
|
|
437
|
+
grouped['@type-binding.type']?.text === 'auto') {
|
|
438
|
+
const anchor = grouped['@type-binding.assignment'];
|
|
439
|
+
// `@type-binding.assignment` is captured directly on the `declaration` node.
|
|
440
|
+
const declNode = (0, ast_helpers_js_1.nodeIfType)(nodeMap['@type-binding.assignment'], 'declaration');
|
|
441
|
+
if (declNode !== null) {
|
|
442
|
+
const declarator = declNode.childForFieldName('declarator');
|
|
443
|
+
if (declarator?.type === 'init_declarator') {
|
|
444
|
+
const valueNode = declarator.childForFieldName('value');
|
|
445
|
+
if (valueNode !== null) {
|
|
446
|
+
if (valueNode.type === 'identifier') {
|
|
447
|
+
// auto alias = existingVar → promote to @type-binding.alias
|
|
448
|
+
grouped['@type-binding.alias'] = anchor;
|
|
449
|
+
grouped['@type-binding.type'] = (0, ast_helpers_js_1.nodeToCapture)('@type-binding.type', valueNode);
|
|
450
|
+
delete grouped['@type-binding.assignment'];
|
|
451
|
+
}
|
|
452
|
+
else if (valueNode.type === 'field_expression') {
|
|
453
|
+
// auto addr = user.address → promote to @type-binding.member-access
|
|
454
|
+
const argNode = valueNode.childForFieldName('argument');
|
|
455
|
+
const fieldNode = valueNode.childForFieldName('field');
|
|
456
|
+
if (argNode !== null && fieldNode !== null) {
|
|
457
|
+
grouped['@type-binding.member-access'] = anchor;
|
|
458
|
+
grouped['@type-binding.member-access-receiver'] = (0, ast_helpers_js_1.nodeToCapture)('@type-binding.member-access-receiver', argNode);
|
|
459
|
+
grouped['@type-binding.type'] = (0, ast_helpers_js_1.nodeToCapture)('@type-binding.type', fieldNode);
|
|
460
|
+
delete grouped['@type-binding.assignment'];
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
else if (valueNode.type === 'call_expression') {
|
|
464
|
+
const fnNode = valueNode.childForFieldName('function');
|
|
465
|
+
if (fnNode?.type === 'field_expression') {
|
|
466
|
+
// auto city = addr.getCity() → promote to @type-binding.alias
|
|
467
|
+
// with dotted rawName "addr.getCity" for compound-receiver
|
|
468
|
+
const argNode = fnNode.childForFieldName('argument');
|
|
469
|
+
const fieldNode = fnNode.childForFieldName('field');
|
|
470
|
+
if (argNode !== null && fieldNode !== null) {
|
|
471
|
+
grouped['@type-binding.member-access'] = anchor;
|
|
472
|
+
grouped['@type-binding.member-access-receiver'] = (0, ast_helpers_js_1.nodeToCapture)('@type-binding.member-access-receiver', argNode);
|
|
473
|
+
grouped['@type-binding.type'] = (0, ast_helpers_js_1.nodeToCapture)('@type-binding.type', fieldNode);
|
|
474
|
+
delete grouped['@type-binding.assignment'];
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// Structural receiver chain for a call whose receiver is itself an
|
|
483
|
+
// expression, so resolution can type it by folding over structure
|
|
484
|
+
// instead of re-parsing the receiver's source text. Self-gating: a
|
|
485
|
+
// non-call match, an absent receiver, or a chain with no nameable base
|
|
486
|
+
// all leave `grouped` untouched.
|
|
487
|
+
(0, receiver_chain_captures_js_1.synthesizeReceiverChainCapture)(grouped, nodeMap['@reference.receiver']);
|
|
488
|
+
out.push(grouped);
|
|
489
|
+
}
|
|
490
|
+
// ── Emit inheritance references for scope-resolution MRO / EXTENDS ──
|
|
491
|
+
// Walk every class/struct base list and synthesize `@reference.inherits`
|
|
492
|
+
// captures consumed by the registry-primary graph bridge. The lookup name
|
|
493
|
+
// is normalized to the bare class name so `Base<T>` / `outer::v1::Base<T>`
|
|
494
|
+
// resolve through V1's simple-name `findClassBindingInScope('Base')`.
|
|
495
|
+
emitCppInheritanceCaptures(tree.rootNode, out, filePath);
|
|
496
|
+
// ── Detect dependent-base relationships for two-phase template lookup ──
|
|
497
|
+
// Walk the tree once, finding every `template_declaration` whose
|
|
498
|
+
// child is a class/struct definition with a `base_class_clause` whose
|
|
499
|
+
// base names reference an in-scope template parameter. Record the
|
|
500
|
+
// (className, dependentBaseName) pair so `populateCppDependentBases`
|
|
501
|
+
// (called from the `populateOwners` hook) can resolve names to nodeIds
|
|
502
|
+
// and the resolver can suppress unqualified-call binding to those
|
|
503
|
+
// bases per ISO C++ two-phase lookup.
|
|
504
|
+
detectCppDependentBases(tree.rootNode, filePath);
|
|
505
|
+
(0, member_lookup_js_1.captureCppMemberLookupFacts)(tree.rootNode, filePath);
|
|
506
|
+
out.push(...(0, callable_flow_captures_js_1.synthesizeCallableFlowCaptures)(tree.rootNode, CPP_CALLABLE_CAPTURE_OPTIONS));
|
|
507
|
+
return out;
|
|
508
|
+
}
|
|
509
|
+
function cppFunctionDeclaratorSignature(node) {
|
|
510
|
+
const declarator = cppFindDescendantOfType(node, 'function_declarator');
|
|
511
|
+
const parameters = declarator?.childForFieldName('parameters');
|
|
512
|
+
if (parameters === null || parameters === undefined) {
|
|
513
|
+
return recoverCppMemberPointerSignature(node.text);
|
|
514
|
+
}
|
|
515
|
+
const parameterNodes = parameters.namedChildren.filter((child) => child !== null && child.type.includes('parameter_declaration'));
|
|
516
|
+
const hasEllipsis = parameters.children.some((child) => child.type === '...' || (!child.isNamed && child.text === '...')) || parameterNodes.some((parameter) => parameter.type === 'variadic_parameter_declaration');
|
|
517
|
+
const isVoidOnly = parameterNodes.length === 1 &&
|
|
518
|
+
parameterNodes[0].namedChildCount === 1 &&
|
|
519
|
+
parameterNodes[0].firstNamedChild?.text === 'void';
|
|
520
|
+
if (isVoidOnly) {
|
|
521
|
+
return { parameterCount: 0, parameterTypes: [], parameterTypeClasses: [] };
|
|
522
|
+
}
|
|
523
|
+
const parameterTypes = [];
|
|
524
|
+
const parameterTypeClasses = [];
|
|
525
|
+
for (const parameter of parameterNodes) {
|
|
526
|
+
if (parameter.type === 'variadic_parameter_declaration') {
|
|
527
|
+
parameterTypes.push('...');
|
|
528
|
+
parameterTypeClasses.push({
|
|
529
|
+
base: '...',
|
|
530
|
+
cv: 'unknown',
|
|
531
|
+
indirection: 'unknown',
|
|
532
|
+
pointerDepth: 0,
|
|
533
|
+
});
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const rawType = parameter.childForFieldName('type')?.text ?? 'unknown';
|
|
537
|
+
const declaratorText = parameter.childForFieldName('declarator')?.text;
|
|
538
|
+
parameterTypes.push((0, arity_metadata_js_1.normalizeCppParamType)(rawType));
|
|
539
|
+
parameterTypeClasses.push((0, arity_metadata_js_1.classifyCppParameterType)(rawType, declaratorText, parameter.text));
|
|
540
|
+
}
|
|
541
|
+
if (hasEllipsis && !parameterTypes.includes('...')) {
|
|
542
|
+
parameterTypes.push('...');
|
|
543
|
+
parameterTypeClasses.push({
|
|
544
|
+
base: '...',
|
|
545
|
+
cv: 'unknown',
|
|
546
|
+
indirection: 'unknown',
|
|
547
|
+
pointerDepth: 0,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
return {
|
|
551
|
+
...(hasEllipsis ? {} : { parameterCount: parameterNodes.length }),
|
|
552
|
+
parameterTypes,
|
|
553
|
+
parameterTypeClasses,
|
|
554
|
+
isConst: /\)\s*const(?:\s|$)/.test(declarator.text),
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* tree-sitter-cpp parses a non-const pointer-to-member variable such as
|
|
559
|
+
* `void (Base::*member)()` as nested call expressions (while the cv-qualified
|
|
560
|
+
* twin is a declaration). Recover the callable shape from the declarator text
|
|
561
|
+
* so `const`/non-`const` overload sets remain distinguishable.
|
|
562
|
+
*/
|
|
563
|
+
function recoverCppMemberPointerSignature(text) {
|
|
564
|
+
const match = text.match(/\(\s*[^()]*::\s*\*\s*[A-Za-z_]\w*\s*\)\s*\(([^()]*)\)\s*(const\b)?/);
|
|
565
|
+
if (match === null)
|
|
566
|
+
return undefined;
|
|
567
|
+
const rawParameters = match[1].trim();
|
|
568
|
+
const parameterCount = rawParameters === '' || rawParameters === 'void'
|
|
569
|
+
? 0
|
|
570
|
+
: splitTopLevelCppParameters(rawParameters).length;
|
|
571
|
+
return { parameterCount, isConst: match[2] !== undefined };
|
|
572
|
+
}
|
|
573
|
+
function splitTopLevelCppParameters(text) {
|
|
574
|
+
const out = [];
|
|
575
|
+
let start = 0;
|
|
576
|
+
let angleDepth = 0;
|
|
577
|
+
let parenDepth = 0;
|
|
578
|
+
let bracketDepth = 0;
|
|
579
|
+
for (let index = 0; index < text.length; index++) {
|
|
580
|
+
switch (text[index]) {
|
|
581
|
+
case '<':
|
|
582
|
+
angleDepth++;
|
|
583
|
+
break;
|
|
584
|
+
case '>':
|
|
585
|
+
angleDepth = Math.max(0, angleDepth - 1);
|
|
586
|
+
break;
|
|
587
|
+
case '(':
|
|
588
|
+
parenDepth++;
|
|
589
|
+
break;
|
|
590
|
+
case ')':
|
|
591
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
592
|
+
break;
|
|
593
|
+
case '[':
|
|
594
|
+
bracketDepth++;
|
|
595
|
+
break;
|
|
596
|
+
case ']':
|
|
597
|
+
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
598
|
+
break;
|
|
599
|
+
case ',':
|
|
600
|
+
if (angleDepth === 0 && parenDepth === 0 && bracketDepth === 0) {
|
|
601
|
+
out.push(text.slice(start, index).trim());
|
|
602
|
+
start = index + 1;
|
|
603
|
+
}
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
out.push(text.slice(start).trim());
|
|
608
|
+
return out.filter((parameter) => parameter.length > 0);
|
|
609
|
+
}
|
|
610
|
+
function cppContainsNodeType(root, type) {
|
|
611
|
+
return cppFindDescendantOfType(root, type) !== null;
|
|
612
|
+
}
|
|
613
|
+
function cppFindDescendantOfType(root, type) {
|
|
614
|
+
const stack = [root];
|
|
615
|
+
while (stack.length > 0) {
|
|
616
|
+
const node = stack.pop();
|
|
617
|
+
if (node.type === type)
|
|
618
|
+
return node;
|
|
619
|
+
for (const child of node.namedChildren)
|
|
620
|
+
if (child !== null)
|
|
621
|
+
stack.push(child);
|
|
622
|
+
}
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
function extractCppDeclarationReturnType(fnNode) {
|
|
626
|
+
const typeNode = fnNode.childForFieldName('type');
|
|
627
|
+
if (typeNode === null)
|
|
628
|
+
return undefined;
|
|
629
|
+
const funcDeclarator = findFunctionDeclarator(fnNode);
|
|
630
|
+
if (funcDeclarator !== null && isCppUnsupportedReturnTypeDeclarator(funcDeclarator)) {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
const typeText = typeNode.text.trim();
|
|
634
|
+
if (typeText !== 'auto')
|
|
635
|
+
return typeText.length > 0 ? typeText : undefined;
|
|
636
|
+
if (funcDeclarator === null)
|
|
637
|
+
return typeText;
|
|
638
|
+
for (let i = 0; i < funcDeclarator.namedChildCount; i++) {
|
|
639
|
+
const child = funcDeclarator.namedChild(i);
|
|
640
|
+
if (child?.type !== 'trailing_return_type')
|
|
641
|
+
continue;
|
|
642
|
+
const typeDesc = child.firstNamedChild;
|
|
643
|
+
return typeDesc?.text.trim() || typeText;
|
|
644
|
+
}
|
|
645
|
+
return typeText;
|
|
646
|
+
}
|
|
647
|
+
function isCppUnsupportedReturnTypeDeclarator(funcDeclarator) {
|
|
648
|
+
const text = funcDeclarator.text;
|
|
649
|
+
return /\boperator\b/.test(text) || /(^|[(:\s])~\s*[A-Za-z_]\w*/.test(text);
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Walk every C++ class/struct base clause and emit `@reference.inherits`
|
|
653
|
+
* captures for each base so scope resolution can resolve them into EXTENDS
|
|
654
|
+
* edges. Lookup names are normalized to bare class names (`Base<T>` → `Base`,
|
|
655
|
+
* `outer::v1::Base<T>` → `Base`) to match the V1 simple-name
|
|
656
|
+
* `findClassBindingInScope` contract. This intentionally preserves the
|
|
657
|
+
* existing scope-chain tradeoff: qualified namespace context is discarded
|
|
658
|
+
* here instead of introducing a C++-only name-resolution lane in shared
|
|
659
|
+
* ingestion infrastructure.
|
|
660
|
+
*/
|
|
661
|
+
function emitCppInheritanceCaptures(root, out, filePath) {
|
|
662
|
+
const stack = [root];
|
|
663
|
+
while (stack.length > 0) {
|
|
664
|
+
const node = stack.pop();
|
|
665
|
+
if (node.type === 'class_specifier' || node.type === 'struct_specifier') {
|
|
666
|
+
const baseClause = findChildOfType(node, ['base_class_clause']);
|
|
667
|
+
if (baseClause !== null) {
|
|
668
|
+
for (const base of iterBaseClasses(baseClause)) {
|
|
669
|
+
if (base.isPackExpansion) {
|
|
670
|
+
markClassWithPackExpandedBase(filePath, node);
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
const baseName = extractBaseLookupName(base.node);
|
|
674
|
+
if (baseName.length === 0)
|
|
675
|
+
continue;
|
|
676
|
+
// Preserve the qualified form (`Other::Inner`, template-stripped) when the
|
|
677
|
+
// source wrote one, so a same-tail nested base resolves to the matching
|
|
678
|
+
// qualified node instead of the first-inserted same-tail one (#1982). The
|
|
679
|
+
// bare `@reference.name` stays the V1 simple-name contract; the qualifier
|
|
680
|
+
// is an additive sidecar resolution tries first (see resolveInheritanceBaseInScope).
|
|
681
|
+
const qualifiedBaseName = extractQualifiedBaseName(base.node);
|
|
682
|
+
out.push({
|
|
683
|
+
'@reference.inherits': (0, ast_helpers_js_1.nodeToCapture)('@reference.inherits', base.node),
|
|
684
|
+
'@reference.name': (0, ast_helpers_js_1.syntheticCapture)('@reference.name', base.node, baseName),
|
|
685
|
+
...(qualifiedBaseName.length > 0 && qualifiedBaseName !== baseName
|
|
686
|
+
? {
|
|
687
|
+
'@reference.qualified-name': (0, ast_helpers_js_1.syntheticCapture)('@reference.qualified-name', base.node, qualifiedBaseName),
|
|
688
|
+
}
|
|
689
|
+
: {}),
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
695
|
+
const child = node.child(i);
|
|
696
|
+
if (child !== null)
|
|
697
|
+
stack.push(child);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Walk the AST finding every template_declaration containing a class or
|
|
703
|
+
* struct definition with a dependent base. Records (className, baseName)
|
|
704
|
+
* pairs into the module-level state via `markCppDependentBase`.
|
|
705
|
+
*
|
|
706
|
+
* A base is "dependent" when its name (typically a template_type like
|
|
707
|
+
* `Base<T>`) uses a template parameter of the enclosing template_declaration.
|
|
708
|
+
* Conservative bias: `typename T::U`, `decltype(...)` and template-template
|
|
709
|
+
* parameter shapes are also treated as dependent.
|
|
710
|
+
*/
|
|
711
|
+
function detectCppDependentBases(root, filePath) {
|
|
712
|
+
const stack = [root];
|
|
713
|
+
while (stack.length > 0) {
|
|
714
|
+
const node = stack.pop();
|
|
715
|
+
if (node.type === 'template_declaration') {
|
|
716
|
+
// Collect template-parameter names declared by this declaration.
|
|
717
|
+
// Inner template_declarations shadow outer ones — handled by the
|
|
718
|
+
// recursive descent below (each template_declaration creates its
|
|
719
|
+
// own parameter scope).
|
|
720
|
+
const params = collectTemplateParameterNames(node);
|
|
721
|
+
// Find the class/struct definition inside this template_declaration.
|
|
722
|
+
const classNode = findChildOfType(node, ['class_specifier', 'struct_specifier']);
|
|
723
|
+
if (classNode !== null) {
|
|
724
|
+
const className = getTypeIdentifierName(classNode);
|
|
725
|
+
if (className !== '') {
|
|
726
|
+
const baseClause = findChildOfType(classNode, ['base_class_clause']);
|
|
727
|
+
if (baseClause !== null) {
|
|
728
|
+
for (const base of iterBaseClasses(baseClause)) {
|
|
729
|
+
if (base.isPackExpansion || isBaseDependent(base.node, params)) {
|
|
730
|
+
if (base.isPackExpansion) {
|
|
731
|
+
markClassWithPackExpandedBase(filePath, classNode);
|
|
732
|
+
}
|
|
733
|
+
const baseName = extractBaseLookupName(base.node);
|
|
734
|
+
const baseQualifier = extractBaseLookupQualifier(base.node);
|
|
735
|
+
if (baseName !== '') {
|
|
736
|
+
(0, two_phase_lookup_js_1.markCppDependentBase)(filePath, className, baseName, baseQualifier);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
745
|
+
const child = node.child(i);
|
|
746
|
+
if (child !== null)
|
|
747
|
+
stack.push(child);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
/** Collect simple template parameter names from a template_declaration. */
|
|
752
|
+
function collectTemplateParameterNames(templateDecl) {
|
|
753
|
+
const names = new Set();
|
|
754
|
+
const paramList = findChildOfType(templateDecl, ['template_parameter_list']);
|
|
755
|
+
if (paramList === null)
|
|
756
|
+
return names;
|
|
757
|
+
for (let i = 0; i < paramList.childCount; i++) {
|
|
758
|
+
const param = paramList.child(i);
|
|
759
|
+
if (param === null)
|
|
760
|
+
continue;
|
|
761
|
+
if (param.type === 'type_parameter_declaration' ||
|
|
762
|
+
param.type === 'optional_type_parameter_declaration' ||
|
|
763
|
+
param.type === 'variadic_type_parameter_declaration') {
|
|
764
|
+
const idNode = findFirstDescendantOfType(param, 'type_identifier');
|
|
765
|
+
if (idNode !== null)
|
|
766
|
+
names.add(idNode.text);
|
|
767
|
+
}
|
|
768
|
+
else if (param.type === 'parameter_declaration' ||
|
|
769
|
+
param.type === 'optional_parameter_declaration' ||
|
|
770
|
+
param.type === 'variadic_parameter_declaration') {
|
|
771
|
+
// Non-type template parameter (e.g. `template<int N>`).
|
|
772
|
+
const idNode = findFirstDescendantOfType(param, 'identifier');
|
|
773
|
+
if (idNode !== null)
|
|
774
|
+
names.add(idNode.text);
|
|
775
|
+
}
|
|
776
|
+
else if (param.type === 'template_template_parameter_declaration') {
|
|
777
|
+
// template-template parameter (e.g. `template<template<class> class TT>`)
|
|
778
|
+
const idNode = findFirstDescendantOfType(param, 'type_identifier');
|
|
779
|
+
if (idNode !== null)
|
|
780
|
+
names.add(idNode.text);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return names;
|
|
784
|
+
}
|
|
785
|
+
function markClassWithPackExpandedBase(filePath, classNode) {
|
|
786
|
+
const className = getTypeIdentifierName(classNode);
|
|
787
|
+
if (className !== '')
|
|
788
|
+
(0, two_phase_lookup_js_1.markCppDependentPackBase)(filePath, className);
|
|
789
|
+
}
|
|
790
|
+
/** Yield each base-class entry from a `base_class_clause`. */
|
|
791
|
+
function* iterBaseClasses(baseClause) {
|
|
792
|
+
for (let i = 0; i < baseClause.childCount; i++) {
|
|
793
|
+
const child = baseClause.child(i);
|
|
794
|
+
if (child === null)
|
|
795
|
+
continue;
|
|
796
|
+
// Skip ':', ',', and access_specifier nodes — the base names are
|
|
797
|
+
// type_identifier, template_type, or qualified_identifier.
|
|
798
|
+
if (child.type === 'type_identifier' ||
|
|
799
|
+
child.type === 'template_type' ||
|
|
800
|
+
child.type === 'qualified_identifier') {
|
|
801
|
+
yield { node: child, isPackExpansion: isFollowedByPackExpansion(baseClause, i) };
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
function isFollowedByPackExpansion(baseClause, childIndex) {
|
|
806
|
+
for (let i = childIndex + 1; i < baseClause.childCount; i++) {
|
|
807
|
+
const sibling = baseClause.child(i);
|
|
808
|
+
if (sibling === null)
|
|
809
|
+
continue;
|
|
810
|
+
if (sibling.type === '...' || (!sibling.isNamed && sibling.text === '...'))
|
|
811
|
+
return true;
|
|
812
|
+
if (sibling.type === ',' || sibling.type === 'access_specifier')
|
|
813
|
+
return false;
|
|
814
|
+
if (sibling.type === 'comment')
|
|
815
|
+
continue;
|
|
816
|
+
if (sibling.isNamed)
|
|
817
|
+
return false;
|
|
818
|
+
}
|
|
819
|
+
return false;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* A base is dependent when:
|
|
823
|
+
* - it's a `template_type` and its argument list contains a
|
|
824
|
+
* `type_identifier` matching one of the enclosing template's params
|
|
825
|
+
* (e.g., `Base<T>` where `T` is a template parameter), OR
|
|
826
|
+
* - it contains a `typename`, `decltype`, or `template_template_parameter`
|
|
827
|
+
* shape (conservatively treated as dependent).
|
|
828
|
+
*
|
|
829
|
+
* Non-dependent: `Base<int>`, `ConcreteBase`, `Base<MyConcrete>` where
|
|
830
|
+
* `MyConcrete` is not a template parameter.
|
|
831
|
+
*/
|
|
832
|
+
function isBaseDependent(baseNode, templateParams) {
|
|
833
|
+
if (baseNode.type !== 'template_type') {
|
|
834
|
+
if (baseNode.type === 'qualified_identifier') {
|
|
835
|
+
// Qualified identifier bases (e.g. `detail::Inner<T>`) may contain
|
|
836
|
+
// template_type children — descend into them for template param check.
|
|
837
|
+
// Fall through to the stack walk below.
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
// Bare `type_identifier` bases — not dependent.
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
// Walk all descendants of the template_argument_list looking for any
|
|
845
|
+
// type_identifier matching a template parameter, or any conservative-
|
|
846
|
+
// dependent shape.
|
|
847
|
+
const stack = [baseNode];
|
|
848
|
+
while (stack.length > 0) {
|
|
849
|
+
const node = stack.pop();
|
|
850
|
+
if (node.type === 'type_identifier' && templateParams.has(node.text)) {
|
|
851
|
+
return true;
|
|
852
|
+
}
|
|
853
|
+
if (node.type === 'decltype' ||
|
|
854
|
+
node.type === 'dependent_type' ||
|
|
855
|
+
node.type === 'template_template_parameter_declaration') {
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
if (node.type === 'qualified_identifier') {
|
|
859
|
+
// `typename T::U` or `T::nested` — if any inner identifier matches
|
|
860
|
+
// a template parameter, dependent.
|
|
861
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
862
|
+
const c = node.child(i);
|
|
863
|
+
if (c !== null)
|
|
864
|
+
stack.push(c);
|
|
865
|
+
}
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
869
|
+
const c = node.child(i);
|
|
870
|
+
if (c !== null)
|
|
871
|
+
stack.push(c);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Recursively extract the bare lookup name of a base class node.
|
|
878
|
+
* Examples: `Base` → `Base`, `Base<T>` → `Base`,
|
|
879
|
+
* `outer::v1::Base<T>` → `Base`. Namespace qualifiers are intentionally
|
|
880
|
+
* dropped to align with V1 scope-chain lookup everywhere else in the
|
|
881
|
+
* registry-primary pipeline.
|
|
882
|
+
*/
|
|
883
|
+
function extractBaseLookupName(baseNode) {
|
|
884
|
+
if (baseNode.type === 'type_identifier' || baseNode.type === 'identifier')
|
|
885
|
+
return baseNode.text;
|
|
886
|
+
if (baseNode.type === 'template_type') {
|
|
887
|
+
const nameNode = baseNode.childForFieldName('name');
|
|
888
|
+
if (nameNode !== null)
|
|
889
|
+
return extractBaseLookupName(nameNode);
|
|
890
|
+
const id = findFirstDescendantOfType(baseNode, 'type_identifier') ??
|
|
891
|
+
findFirstDescendantOfType(baseNode, 'identifier');
|
|
892
|
+
if (id !== null)
|
|
893
|
+
return id.text;
|
|
894
|
+
}
|
|
895
|
+
if (baseNode.type === 'qualified_identifier') {
|
|
896
|
+
const nameNode = baseNode.childForFieldName('name');
|
|
897
|
+
if (nameNode !== null) {
|
|
898
|
+
const nested = extractBaseLookupName(nameNode);
|
|
899
|
+
if (nested.length > 0)
|
|
900
|
+
return nested;
|
|
901
|
+
}
|
|
902
|
+
for (let i = baseNode.childCount - 1; i >= 0; i--) {
|
|
903
|
+
const child = baseNode.child(i);
|
|
904
|
+
if (child === null)
|
|
905
|
+
continue;
|
|
906
|
+
const nested = extractBaseLookupName(child);
|
|
907
|
+
if (nested.length > 0)
|
|
908
|
+
return nested;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return '';
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Like `extractBaseLookupName` but PRESERVES the namespace/class qualifier
|
|
915
|
+
* (`Other::Inner`, `ns::v1::Base`) while stripping template arguments
|
|
916
|
+
* (`ns::Base<T>` → `ns::Base`). Returns `''` for shapes it can't qualify, and
|
|
917
|
+
* returns the bare name unchanged for an unqualified base (the emit site then
|
|
918
|
+
* skips the sidecar capture). Powers `@reference.qualified-name` so #1982
|
|
919
|
+
* resolution can pick the matching same-tail nested base via the full-path
|
|
920
|
+
* QualifiedNameIndex instead of the first-inserted same-tail sibling.
|
|
921
|
+
*/
|
|
922
|
+
function extractQualifiedBaseName(baseNode) {
|
|
923
|
+
if (baseNode.type === 'template_type') {
|
|
924
|
+
const nameNode = baseNode.childForFieldName('name');
|
|
925
|
+
return nameNode !== null ? extractQualifiedBaseName(nameNode) : '';
|
|
926
|
+
}
|
|
927
|
+
if (baseNode.type === 'qualified_identifier') {
|
|
928
|
+
// No template args anywhere → the raw text already IS the qualified name.
|
|
929
|
+
if (!baseNode.text.includes('<'))
|
|
930
|
+
return baseNode.text;
|
|
931
|
+
// Template args present: reconstruct scope::name, recursing to strip them.
|
|
932
|
+
const scopeNode = baseNode.childForFieldName('scope');
|
|
933
|
+
const nameNode = baseNode.childForFieldName('name');
|
|
934
|
+
const left = scopeNode !== null ? extractQualifiedBaseName(scopeNode) : '';
|
|
935
|
+
const right = nameNode !== null ? extractQualifiedBaseName(nameNode) : '';
|
|
936
|
+
if (left.length > 0 && right.length > 0)
|
|
937
|
+
return `${left}::${right}`;
|
|
938
|
+
return right.length > 0 ? right : left;
|
|
939
|
+
}
|
|
940
|
+
if (baseNode.type === 'namespace_identifier' ||
|
|
941
|
+
baseNode.type === 'type_identifier' ||
|
|
942
|
+
baseNode.type === 'identifier') {
|
|
943
|
+
return baseNode.text;
|
|
944
|
+
}
|
|
945
|
+
return '';
|
|
946
|
+
}
|
|
947
|
+
/** Extract the syntactic namespace qualifier from a base class node.
|
|
948
|
+
* For `detail::Inner<T>`, returns `'detail'`.
|
|
949
|
+
* For unqualified bases (`Inner<T>`, `Base<int>`), returns `''`.
|
|
950
|
+
* Nested qualifiers (`a::b::Inner<T>`) return the full scope text.
|
|
951
|
+
*/
|
|
952
|
+
function extractBaseLookupQualifier(baseNode) {
|
|
953
|
+
if (baseNode.type === 'qualified_identifier') {
|
|
954
|
+
const scopeNode = baseNode.childForFieldName('scope');
|
|
955
|
+
if (scopeNode !== null)
|
|
956
|
+
return scopeNode.text;
|
|
957
|
+
}
|
|
958
|
+
// template_type nodes may have a qualified_identifier as their name child
|
|
959
|
+
if (baseNode.type === 'template_type') {
|
|
960
|
+
const nameNode = baseNode.childForFieldName('name');
|
|
961
|
+
if (nameNode !== null && nameNode.type === 'qualified_identifier') {
|
|
962
|
+
const scopeNode = nameNode.childForFieldName('scope');
|
|
963
|
+
if (scopeNode !== null)
|
|
964
|
+
return scopeNode.text;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return '';
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Walk parent chain from a function_definition / declaration / field_declaration
|
|
971
|
+
* to find the enclosing `template_declaration`. Returns null when the function
|
|
972
|
+
* isn't templated. The walk only ascends through wrapper nodes the C++
|
|
973
|
+
* grammar inserts between `template_declaration` and the function — direct
|
|
974
|
+
* parent in the common case, two hops for member templates whose outer
|
|
975
|
+
* class is also templated (we return the INNERMOST template_declaration,
|
|
976
|
+
* which carries this function's own template parameters).
|
|
977
|
+
*/
|
|
978
|
+
function findEnclosingTemplateDeclaration(fnNode) {
|
|
979
|
+
let cur = fnNode.parent;
|
|
980
|
+
// Cap the walk — `template_declaration` is typically the immediate parent
|
|
981
|
+
// or one wrapper away. Anything deeper is an inline-method-in-template
|
|
982
|
+
// shape and we still want the innermost templates_declaration whose body
|
|
983
|
+
// wraps `fnNode`.
|
|
984
|
+
let hops = 8;
|
|
985
|
+
while (cur !== null && hops-- > 0) {
|
|
986
|
+
if (cur.type === 'template_declaration')
|
|
987
|
+
return cur;
|
|
988
|
+
// Don't ascend past structural boundaries that should reset template scope.
|
|
989
|
+
if (cur.type === 'translation_unit')
|
|
990
|
+
return null;
|
|
991
|
+
cur = cur.parent;
|
|
992
|
+
}
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Locate the `function_declarator` AST node within a function definition
|
|
997
|
+
* or declaration. Unwraps pointer/reference declarator wrappers. Returns
|
|
998
|
+
* null when no function_declarator is found (e.g. variable declaration
|
|
999
|
+
* mis-classified upstream).
|
|
1000
|
+
*/
|
|
1001
|
+
function findFunctionDeclarator(fnNode) {
|
|
1002
|
+
const direct = fnNode.childForFieldName('declarator');
|
|
1003
|
+
let cur = direct;
|
|
1004
|
+
let hops = 8;
|
|
1005
|
+
while (cur !== null && hops-- > 0) {
|
|
1006
|
+
if (cur.type === 'function_declarator')
|
|
1007
|
+
return cur;
|
|
1008
|
+
if (cur.type === 'pointer_declarator' || cur.type === 'reference_declarator') {
|
|
1009
|
+
cur = cur.childForFieldName('declarator');
|
|
1010
|
+
continue;
|
|
1011
|
+
}
|
|
1012
|
+
break;
|
|
1013
|
+
}
|
|
1014
|
+
return findFirstDescendantOfType(fnNode, 'function_declarator');
|
|
1015
|
+
}
|
|
1016
|
+
/** Find the first direct child matching one of the given types. */
|
|
1017
|
+
function findChildOfType(node, types) {
|
|
1018
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1019
|
+
const c = node.child(i);
|
|
1020
|
+
if (c !== null && types.includes(c.type))
|
|
1021
|
+
return c;
|
|
1022
|
+
}
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
/** Recursive search for the first descendant of a given type. */
|
|
1026
|
+
function findFirstDescendantOfType(node, type) {
|
|
1027
|
+
if (node.type === type)
|
|
1028
|
+
return node;
|
|
1029
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1030
|
+
const c = node.child(i);
|
|
1031
|
+
if (c === null)
|
|
1032
|
+
continue;
|
|
1033
|
+
const hit = findFirstDescendantOfType(c, type);
|
|
1034
|
+
if (hit !== null)
|
|
1035
|
+
return hit;
|
|
1036
|
+
}
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
/** Get the name of a class/struct/template_type node via its `name` field. */
|
|
1040
|
+
function getTypeIdentifierName(node) {
|
|
1041
|
+
const nameNode = node.childForFieldName('name');
|
|
1042
|
+
if (nameNode !== null)
|
|
1043
|
+
return nameNode.text;
|
|
1044
|
+
const id = findFirstDescendantOfType(node, 'type_identifier');
|
|
1045
|
+
return id !== null ? id.text : '';
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Infer argument types from a call_expression or new_expression node.
|
|
1049
|
+
* Used for overload disambiguation by parameter types.
|
|
1050
|
+
*
|
|
1051
|
+
* Only literal types are inferred — identifiers and complex expressions
|
|
1052
|
+
* return empty string (unknown) so narrowOverloadCandidates treats them
|
|
1053
|
+
* as any-match.
|
|
1054
|
+
*/
|
|
1055
|
+
function inferCppCallArgTypes(node) {
|
|
1056
|
+
const argList = node.childForFieldName('arguments');
|
|
1057
|
+
if (argList === null)
|
|
1058
|
+
return undefined;
|
|
1059
|
+
const types = [];
|
|
1060
|
+
for (let i = 0; i < argList.childCount; i++) {
|
|
1061
|
+
const child = argList.child(i);
|
|
1062
|
+
if (child === null)
|
|
1063
|
+
continue;
|
|
1064
|
+
if (child.type === ',' || child.type === '(' || child.type === ')')
|
|
1065
|
+
continue;
|
|
1066
|
+
const litType = inferCppLiteralType(child);
|
|
1067
|
+
if (litType !== '') {
|
|
1068
|
+
types.push(litType);
|
|
1069
|
+
}
|
|
1070
|
+
else if (child.type === 'identifier') {
|
|
1071
|
+
// Variable reference — look up declared type in enclosing scope
|
|
1072
|
+
types.push(lookupDeclaredTypeForIdentifier(child));
|
|
1073
|
+
}
|
|
1074
|
+
else {
|
|
1075
|
+
types.push('');
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
return types.length > 0 ? types : undefined;
|
|
1079
|
+
}
|
|
1080
|
+
function inferCppCallArgTypeClasses(node) {
|
|
1081
|
+
const argList = node.childForFieldName('arguments');
|
|
1082
|
+
if (argList === null)
|
|
1083
|
+
return undefined;
|
|
1084
|
+
const classes = [];
|
|
1085
|
+
for (let i = 0; i < argList.childCount; i++) {
|
|
1086
|
+
const child = argList.child(i);
|
|
1087
|
+
if (child === null)
|
|
1088
|
+
continue;
|
|
1089
|
+
if (child.type === ',' || child.type === '(' || child.type === ')')
|
|
1090
|
+
continue;
|
|
1091
|
+
const litType = inferCppLiteralType(child);
|
|
1092
|
+
if (litType !== '') {
|
|
1093
|
+
classes.push(valueTypeClass(litType));
|
|
1094
|
+
}
|
|
1095
|
+
else if (child.type === 'identifier') {
|
|
1096
|
+
classes.push(lookupDeclaredTypeClassForIdentifier(child));
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
classes.push(unknownTypeClass('unknown'));
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
return classes.length > 0 ? classes : undefined;
|
|
1103
|
+
}
|
|
1104
|
+
function inferCppBinaryOperatorArgTypes(node, includeLeftOperand) {
|
|
1105
|
+
const operands = binaryOperatorOperands(node, includeLeftOperand);
|
|
1106
|
+
if (operands.length === 0)
|
|
1107
|
+
return undefined;
|
|
1108
|
+
const types = operands.map(inferCppExpressionType);
|
|
1109
|
+
return types.length > 0 ? types : undefined;
|
|
1110
|
+
}
|
|
1111
|
+
function inferCppBinaryOperatorArgTypeClasses(node, includeLeftOperand) {
|
|
1112
|
+
const operands = binaryOperatorOperands(node, includeLeftOperand);
|
|
1113
|
+
if (operands.length === 0)
|
|
1114
|
+
return undefined;
|
|
1115
|
+
const classes = operands.map(inferCppExpressionTypeClass);
|
|
1116
|
+
return classes.length > 0 ? classes : undefined;
|
|
1117
|
+
}
|
|
1118
|
+
function binaryOperatorOperands(node, includeLeftOperand) {
|
|
1119
|
+
const operands = [];
|
|
1120
|
+
const left = node.childForFieldName('left');
|
|
1121
|
+
const right = node.childForFieldName('right');
|
|
1122
|
+
if (includeLeftOperand && left !== null)
|
|
1123
|
+
operands.push(left);
|
|
1124
|
+
if (right !== null)
|
|
1125
|
+
operands.push(right);
|
|
1126
|
+
return operands;
|
|
1127
|
+
}
|
|
1128
|
+
function isPrimitiveOnlyBinaryOperator(node) {
|
|
1129
|
+
const operands = binaryOperatorOperands(node, true);
|
|
1130
|
+
return operands.length > 0 && operands.every((operand) => isBuiltinOperatorType(operand));
|
|
1131
|
+
}
|
|
1132
|
+
function isBuiltinOperatorType(node) {
|
|
1133
|
+
const type = inferCppExpressionType(node);
|
|
1134
|
+
return (type === 'bool' ||
|
|
1135
|
+
type === 'char' ||
|
|
1136
|
+
type === 'double' ||
|
|
1137
|
+
type === 'float' ||
|
|
1138
|
+
type === 'int' ||
|
|
1139
|
+
type === 'long' ||
|
|
1140
|
+
type === 'short' ||
|
|
1141
|
+
type === 'signed' ||
|
|
1142
|
+
type === 'unsigned');
|
|
1143
|
+
}
|
|
1144
|
+
function inferCppExpressionType(node) {
|
|
1145
|
+
const litType = inferCppLiteralType(node);
|
|
1146
|
+
if (litType !== '')
|
|
1147
|
+
return litType;
|
|
1148
|
+
if (node.type === 'identifier')
|
|
1149
|
+
return lookupDeclaredTypeForIdentifier(node);
|
|
1150
|
+
return '';
|
|
1151
|
+
}
|
|
1152
|
+
function inferCppExpressionTypeClass(node) {
|
|
1153
|
+
const litType = inferCppLiteralType(node);
|
|
1154
|
+
if (litType !== '')
|
|
1155
|
+
return valueTypeClass(litType);
|
|
1156
|
+
if (node.type === 'identifier')
|
|
1157
|
+
return lookupDeclaredTypeClassForIdentifier(node);
|
|
1158
|
+
return unknownTypeClass('unknown');
|
|
1159
|
+
}
|
|
1160
|
+
function valueTypeClass(base) {
|
|
1161
|
+
return { base, cv: 'none', indirection: 'value', pointerDepth: 0 };
|
|
1162
|
+
}
|
|
1163
|
+
function unknownTypeClass(base) {
|
|
1164
|
+
return { base, cv: 'unknown', indirection: 'unknown', pointerDepth: 0 };
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Infer the canonical type name of a C++ literal AST node.
|
|
1168
|
+
* Returns empty string for non-literal / unknown nodes.
|
|
1169
|
+
*/
|
|
1170
|
+
function inferCppLiteralType(node) {
|
|
1171
|
+
switch (node.type) {
|
|
1172
|
+
case 'initializer_list':
|
|
1173
|
+
return inferCppBracedInitType(node);
|
|
1174
|
+
case 'number_literal': {
|
|
1175
|
+
const text = node.text;
|
|
1176
|
+
// Floating-point literals contain '.', 'e', 'E', or end with 'f'/'F'
|
|
1177
|
+
if (text.includes('.') ||
|
|
1178
|
+
text.includes('e') ||
|
|
1179
|
+
text.includes('E') ||
|
|
1180
|
+
text.endsWith('f') ||
|
|
1181
|
+
text.endsWith('F')) {
|
|
1182
|
+
return 'double';
|
|
1183
|
+
}
|
|
1184
|
+
return 'int';
|
|
1185
|
+
}
|
|
1186
|
+
case 'string_literal':
|
|
1187
|
+
case 'raw_string_literal':
|
|
1188
|
+
case 'concatenated_string':
|
|
1189
|
+
return 'string';
|
|
1190
|
+
case 'char_literal':
|
|
1191
|
+
return 'char';
|
|
1192
|
+
case 'true':
|
|
1193
|
+
case 'false':
|
|
1194
|
+
return 'bool';
|
|
1195
|
+
case 'null':
|
|
1196
|
+
case 'nullptr':
|
|
1197
|
+
return 'null';
|
|
1198
|
+
default:
|
|
1199
|
+
return '';
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
function inferCppBracedInitType(node) {
|
|
1203
|
+
const elementTypes = [];
|
|
1204
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1205
|
+
const child = node.child(i);
|
|
1206
|
+
if (child === null)
|
|
1207
|
+
continue;
|
|
1208
|
+
if (child.type === ',' || child.type === '{' || child.type === '}')
|
|
1209
|
+
continue;
|
|
1210
|
+
const elementType = inferCppLiteralType(child);
|
|
1211
|
+
if (elementType === '' || elementType.startsWith(conversion_rank_js_1.CPP_BRACED_INIT_TYPE_PREFIX)) {
|
|
1212
|
+
return `${conversion_rank_js_1.CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length + 1}`;
|
|
1213
|
+
}
|
|
1214
|
+
elementTypes.push(elementType);
|
|
1215
|
+
}
|
|
1216
|
+
if (elementTypes.length === 0)
|
|
1217
|
+
return `${conversion_rank_js_1.CPP_BRACED_INIT_TYPE_PREFIX}unknown:0`;
|
|
1218
|
+
const first = elementTypes[0];
|
|
1219
|
+
return elementTypes.every((type) => type === first)
|
|
1220
|
+
? `${conversion_rank_js_1.CPP_BRACED_INIT_TYPE_PREFIX}${first}:${elementTypes.length}`
|
|
1221
|
+
: `${conversion_rank_js_1.CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length}`;
|
|
1222
|
+
}
|
|
1223
|
+
let fileLookupIndex = {
|
|
1224
|
+
enumNames: null,
|
|
1225
|
+
scopeDecls: new Map(),
|
|
1226
|
+
fnParams: new Map(),
|
|
1227
|
+
};
|
|
1228
|
+
function resetCppFileLookupIndex() {
|
|
1229
|
+
fileLookupIndex = { enumNames: null, scopeDecls: new Map(), fnParams: new Map() };
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* First-declaration-wins map of the scope's `declaration` children that
|
|
1233
|
+
* carry a concrete (non-placeholder) type and a nameable declarator —
|
|
1234
|
+
* exactly the entries the replaced per-identifier scans could match.
|
|
1235
|
+
*/
|
|
1236
|
+
function scopeDeclarationsFor(scope) {
|
|
1237
|
+
const cached = fileLookupIndex.scopeDecls.get(scope.id);
|
|
1238
|
+
if (cached !== undefined)
|
|
1239
|
+
return cached;
|
|
1240
|
+
const decls = new Map();
|
|
1241
|
+
for (let i = 0; i < scope.childCount; i++) {
|
|
1242
|
+
const stmt = scope.child(i);
|
|
1243
|
+
if (stmt === null || stmt.type !== 'declaration')
|
|
1244
|
+
continue;
|
|
1245
|
+
const typeNode = stmt.childForFieldName('type');
|
|
1246
|
+
if (typeNode === null)
|
|
1247
|
+
continue;
|
|
1248
|
+
if (typeNode.type === 'placeholder_type_specifier')
|
|
1249
|
+
continue;
|
|
1250
|
+
const declarator = stmt.childForFieldName('declarator');
|
|
1251
|
+
if (declarator === null)
|
|
1252
|
+
continue;
|
|
1253
|
+
const nameChild = declaredNameNode(declarator);
|
|
1254
|
+
if (nameChild === null)
|
|
1255
|
+
continue;
|
|
1256
|
+
const name = extractDeclaratorLeafName(nameChild);
|
|
1257
|
+
if (name === '' || decls.has(name))
|
|
1258
|
+
continue;
|
|
1259
|
+
decls.set(name, stmt);
|
|
1260
|
+
}
|
|
1261
|
+
fileLookupIndex.scopeDecls.set(scope.id, decls);
|
|
1262
|
+
return decls;
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Look up the declared type of a variable by scanning sibling declarations
|
|
1266
|
+
* in the enclosing compound_statement (function body). Handles:
|
|
1267
|
+
* - `std::string result = ...` → 'string'
|
|
1268
|
+
* - `int n = ...` → 'int'
|
|
1269
|
+
* - `const int n = ...` → 'int'
|
|
1270
|
+
* Returns empty string if no declaration found or type is auto/placeholder.
|
|
1271
|
+
*
|
|
1272
|
+
* Limitation: only `declaration` siblings inside the enclosing
|
|
1273
|
+
* `compound_statement` are inspected. Function parameters live in the
|
|
1274
|
+
* `function_declarator`'s `parameter_list` and are NOT resolved here, so
|
|
1275
|
+
* `void run(int n) { process(n); }`
|
|
1276
|
+
* infers `''` for `n` and the constraint filter falls through to
|
|
1277
|
+
* `'unknown'` → ambiguity suppression → 0 CALLS edges. This is a
|
|
1278
|
+
* "degrade not lie" gap (no wrong edges, just missing ones); extending
|
|
1279
|
+
* the scan to `parameter_list` is tracked under #1579 as a follow-up.
|
|
1280
|
+
*/
|
|
1281
|
+
function lookupDeclaredTypeForIdentifier(identNode) {
|
|
1282
|
+
const varName = identNode.text;
|
|
1283
|
+
// Walk up to the enclosing compound_statement (function body)
|
|
1284
|
+
let scope = identNode.parent;
|
|
1285
|
+
while (scope !== null &&
|
|
1286
|
+
scope.type !== 'compound_statement' &&
|
|
1287
|
+
scope.type !== 'translation_unit') {
|
|
1288
|
+
scope = scope.parent;
|
|
1289
|
+
}
|
|
1290
|
+
if (scope === null)
|
|
1291
|
+
return '';
|
|
1292
|
+
const paramType = lookupFunctionParameterType(scope, varName);
|
|
1293
|
+
if (paramType !== '')
|
|
1294
|
+
return paramType;
|
|
1295
|
+
// Indexed scope-declaration lookup (#2432; was a per-identifier scan).
|
|
1296
|
+
const stmt = scopeDeclarationsFor(scope).get(varName);
|
|
1297
|
+
if (stmt === undefined)
|
|
1298
|
+
return '';
|
|
1299
|
+
const typeNode = stmt.childForFieldName('type');
|
|
1300
|
+
if (typeNode === null)
|
|
1301
|
+
return '';
|
|
1302
|
+
return normalizeCppTypeText(typeNode.text);
|
|
1303
|
+
}
|
|
1304
|
+
function lookupDeclaredTypeClassForIdentifier(identNode) {
|
|
1305
|
+
const varName = identNode.text;
|
|
1306
|
+
let scope = identNode.parent;
|
|
1307
|
+
while (scope !== null &&
|
|
1308
|
+
scope.type !== 'compound_statement' &&
|
|
1309
|
+
scope.type !== 'translation_unit') {
|
|
1310
|
+
scope = scope.parent;
|
|
1311
|
+
}
|
|
1312
|
+
if (scope === null)
|
|
1313
|
+
return unknownTypeClass('unknown');
|
|
1314
|
+
const paramTypeClass = lookupFunctionParameterTypeClass(scope, varName, identNode);
|
|
1315
|
+
if (paramTypeClass !== undefined)
|
|
1316
|
+
return paramTypeClass;
|
|
1317
|
+
// Indexed scope-declaration lookup (#2432; was a per-identifier scan).
|
|
1318
|
+
const stmt = scopeDeclarationsFor(scope).get(varName);
|
|
1319
|
+
if (stmt === undefined)
|
|
1320
|
+
return unknownTypeClass('unknown');
|
|
1321
|
+
const typeNode = stmt.childForFieldName('type');
|
|
1322
|
+
const declarator = stmt.childForFieldName('declarator');
|
|
1323
|
+
const nameChild = declarator !== null ? declaredNameNode(declarator) : null;
|
|
1324
|
+
if (typeNode === null || nameChild === null)
|
|
1325
|
+
return unknownTypeClass('unknown');
|
|
1326
|
+
const typeClass = (0, arity_metadata_js_1.classifyCppParameterType)(typeNode.text, nameChild.text, stmt.text.replace(/;\s*$/, ''));
|
|
1327
|
+
if (isKnownEnumName(identNode, typeClass.base)) {
|
|
1328
|
+
return { ...typeClass, base: `enum:${typeClass.base}` };
|
|
1329
|
+
}
|
|
1330
|
+
return typeClass;
|
|
1331
|
+
}
|
|
1332
|
+
function lookupFunctionParameterType(scope, varName) {
|
|
1333
|
+
const param = findEnclosingFunctionParameter(scope, varName);
|
|
1334
|
+
if (param === null)
|
|
1335
|
+
return '';
|
|
1336
|
+
const typeNode = param.childForFieldName('type');
|
|
1337
|
+
if (typeNode === null)
|
|
1338
|
+
return '';
|
|
1339
|
+
return normalizeCppTypeText(typeNode.text);
|
|
1340
|
+
}
|
|
1341
|
+
function lookupFunctionParameterTypeClass(scope, varName, identNode) {
|
|
1342
|
+
const param = findEnclosingFunctionParameter(scope, varName);
|
|
1343
|
+
if (param === null)
|
|
1344
|
+
return undefined;
|
|
1345
|
+
const typeNode = param.childForFieldName('type');
|
|
1346
|
+
if (typeNode === null)
|
|
1347
|
+
return undefined;
|
|
1348
|
+
const declarator = param.childForFieldName('declarator');
|
|
1349
|
+
if (declarator === null)
|
|
1350
|
+
return undefined;
|
|
1351
|
+
const typeClass = (0, arity_metadata_js_1.classifyCppParameterType)(typeNode.text, declarator.text, param.text);
|
|
1352
|
+
if (isKnownEnumName(identNode, typeClass.base)) {
|
|
1353
|
+
return { ...typeClass, base: `enum:${typeClass.base}` };
|
|
1354
|
+
}
|
|
1355
|
+
return typeClass;
|
|
1356
|
+
}
|
|
1357
|
+
function findEnclosingFunctionParameter(scope, varName) {
|
|
1358
|
+
let node = scope.parent;
|
|
1359
|
+
while (node !== null) {
|
|
1360
|
+
if (node.type === 'function_definition' || node.type === 'function_declarator') {
|
|
1361
|
+
return enclosingFunctionParametersFor(node)?.get(varName) ?? null;
|
|
1362
|
+
}
|
|
1363
|
+
node = node.parent;
|
|
1364
|
+
}
|
|
1365
|
+
return null;
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* First-wins map of a function's `parameter_declaration`s by declarator
|
|
1369
|
+
* leaf name (#2432; was a per-identifier scan). `null` when the function
|
|
1370
|
+
* has no parameter list — the caller returns null without walking further
|
|
1371
|
+
* up, preserving the replaced scan's early-return.
|
|
1372
|
+
*/
|
|
1373
|
+
function enclosingFunctionParametersFor(fnNode) {
|
|
1374
|
+
const cached = fileLookupIndex.fnParams.get(fnNode.id);
|
|
1375
|
+
if (cached !== undefined)
|
|
1376
|
+
return cached;
|
|
1377
|
+
const fnDecl = fnNode.type === 'function_declarator'
|
|
1378
|
+
? fnNode
|
|
1379
|
+
: findFirstDescendantOfType(fnNode, 'function_declarator');
|
|
1380
|
+
const params = fnDecl?.childForFieldName('parameters') ?? null;
|
|
1381
|
+
let index = null;
|
|
1382
|
+
if (params !== null) {
|
|
1383
|
+
index = new Map();
|
|
1384
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
1385
|
+
const param = params.namedChild(i);
|
|
1386
|
+
if (param === null || param.type !== 'parameter_declaration')
|
|
1387
|
+
continue;
|
|
1388
|
+
const declarator = param.childForFieldName('declarator');
|
|
1389
|
+
if (declarator === null)
|
|
1390
|
+
continue;
|
|
1391
|
+
const name = extractDeclaratorLeafName(declarator);
|
|
1392
|
+
if (name === '' || index.has(name))
|
|
1393
|
+
continue;
|
|
1394
|
+
index.set(name, param);
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
fileLookupIndex.fnParams.set(fnNode.id, index);
|
|
1398
|
+
return index;
|
|
1399
|
+
}
|
|
1400
|
+
function declaredNameNode(declarator) {
|
|
1401
|
+
if (declarator.type !== 'init_declarator')
|
|
1402
|
+
return declarator;
|
|
1403
|
+
for (let i = 0; i < declarator.namedChildCount; i++) {
|
|
1404
|
+
const child = declarator.namedChild(i);
|
|
1405
|
+
if (child === null)
|
|
1406
|
+
continue;
|
|
1407
|
+
if (child.type === 'identifier')
|
|
1408
|
+
return child;
|
|
1409
|
+
if (child.type.endsWith('_declarator'))
|
|
1410
|
+
return child;
|
|
1411
|
+
}
|
|
1412
|
+
return declarator.childForFieldName('declarator');
|
|
1413
|
+
}
|
|
1414
|
+
/** Normalize a type-specifier text for argument type matching.
|
|
1415
|
+
* Strips qualifiers (const, volatile), namespace prefixes (std::),
|
|
1416
|
+
* and pointer/reference markers. */
|
|
1417
|
+
function normalizeCppTypeText(text) {
|
|
1418
|
+
let t = text.trim();
|
|
1419
|
+
t = t.replace(/\b(const|volatile|static|extern|mutable)\b/g, '').trim();
|
|
1420
|
+
t = t.replace(/^.*::/, ''); // strip namespace prefix
|
|
1421
|
+
t = t.replace(/[*&]/g, '').trim();
|
|
1422
|
+
return t;
|
|
1423
|
+
}
|
|
1424
|
+
function isKnownEnumName(node, typeName) {
|
|
1425
|
+
if (typeName === '' || typeName === 'unknown')
|
|
1426
|
+
return false;
|
|
1427
|
+
// One full-tree DFS per FILE (lazy), not per identifier argument — the
|
|
1428
|
+
// per-identifier walk here was the dominant cost of #2432 (87s of a 151s
|
|
1429
|
+
// extraction on a file that parses in 46ms).
|
|
1430
|
+
if (fileLookupIndex.enumNames === null) {
|
|
1431
|
+
let root = node;
|
|
1432
|
+
while (root.parent !== null)
|
|
1433
|
+
root = root.parent;
|
|
1434
|
+
const names = new Set();
|
|
1435
|
+
const stack = [root];
|
|
1436
|
+
while (stack.length > 0) {
|
|
1437
|
+
const cur = stack.pop();
|
|
1438
|
+
if (cur.type === 'enum_specifier') {
|
|
1439
|
+
const name = cur.childForFieldName('name');
|
|
1440
|
+
if (name !== null)
|
|
1441
|
+
names.add(name.text);
|
|
1442
|
+
}
|
|
1443
|
+
for (let i = 0; i < cur.childCount; i++) {
|
|
1444
|
+
const child = cur.child(i);
|
|
1445
|
+
if (child !== null)
|
|
1446
|
+
stack.push(child);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
fileLookupIndex.enumNames = names;
|
|
1450
|
+
}
|
|
1451
|
+
return fileLookupIndex.enumNames.has(typeName);
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Detect whether a `namespace_definition` AST node is inline.
|
|
1455
|
+
* Tree-sitter-cpp exposes the `inline` keyword as an anonymous child
|
|
1456
|
+
* node — we scan direct children for that keyword.
|
|
1457
|
+
*/
|
|
1458
|
+
function isInlineNamespace(nsNode) {
|
|
1459
|
+
for (let i = 0; i < nsNode.childCount; i++) {
|
|
1460
|
+
const c = nsNode.child(i);
|
|
1461
|
+
if (c === null)
|
|
1462
|
+
continue;
|
|
1463
|
+
if (c.type === 'inline')
|
|
1464
|
+
return true;
|
|
1465
|
+
// Some grammar variants surface keywords by their text rather than
|
|
1466
|
+
// by a dedicated node type; check both for resilience.
|
|
1467
|
+
if (c.text === 'inline' && (c.type === 'storage_class_specifier' || c.type === 'inline')) {
|
|
1468
|
+
return true;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
/**
|
|
1474
|
+
* Detect `(f)(args)` shape — the call-expression's `function` field is a
|
|
1475
|
+
* `parenthesized_expression`. ISO C++ specifies that this form suppresses
|
|
1476
|
+
* ADL (`[basic.lookup.argdep]/3.1`): the parenthesized name is treated as
|
|
1477
|
+
* an ordinary unqualified-lookup-only callee.
|
|
1478
|
+
*/
|
|
1479
|
+
function isParenthesizedFunctionCall(callNode) {
|
|
1480
|
+
const fn = callNode.childForFieldName('function');
|
|
1481
|
+
return fn !== null && fn.type === 'parenthesized_expression';
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Per-argument ADL classification: walk each argument of a free call and
|
|
1485
|
+
* classify its declared type for associated-namespace lookup.
|
|
1486
|
+
*
|
|
1487
|
+
* Value/pointer/reference class-typed args and template specializations
|
|
1488
|
+
* with explicit type arguments contribute; function pointers, primitives,
|
|
1489
|
+
* literals, and other unsupported shapes produce an empty result.
|
|
1490
|
+
*
|
|
1491
|
+
* Class-typed values/pointers/references (`N::S`, `N::S*`, `N::S&`) all
|
|
1492
|
+
* preserve the class name for associated-namespace lookup.
|
|
1493
|
+
* Function pointers remain excluded even when their return type names a
|
|
1494
|
+
* class, because the associated entity is the pointed-to function type,
|
|
1495
|
+
* not the return type.
|
|
1496
|
+
*/
|
|
1497
|
+
function inferCppCallAdlArgs(callNode) {
|
|
1498
|
+
const argList = callNode.childForFieldName('arguments');
|
|
1499
|
+
if (argList === null)
|
|
1500
|
+
return [];
|
|
1501
|
+
const out = [];
|
|
1502
|
+
for (let i = 0; i < argList.childCount; i++) {
|
|
1503
|
+
const child = argList.child(i);
|
|
1504
|
+
if (child === null)
|
|
1505
|
+
continue;
|
|
1506
|
+
if (child.type === ',' || child.type === '(' || child.type === ')')
|
|
1507
|
+
continue;
|
|
1508
|
+
out.push(classifyAdlArg(child));
|
|
1509
|
+
}
|
|
1510
|
+
return out;
|
|
1511
|
+
}
|
|
1512
|
+
const ADL_TEMPLATE_RECURSION_MAX_DEPTH = 8;
|
|
1513
|
+
const EMPTY_ADL_ARG = {
|
|
1514
|
+
simpleClassName: '',
|
|
1515
|
+
templateSimpleClassName: '',
|
|
1516
|
+
templateNamespace: '',
|
|
1517
|
+
templateArgClassNames: [],
|
|
1518
|
+
templateArgNamespaces: [],
|
|
1519
|
+
};
|
|
1520
|
+
function classifyAdlArg(argNode) {
|
|
1521
|
+
// Literals and primitive-shaped expressions never have associated namespaces.
|
|
1522
|
+
if (argNode.type === 'number_literal' ||
|
|
1523
|
+
argNode.type === 'string_literal' ||
|
|
1524
|
+
argNode.type === 'raw_string_literal' ||
|
|
1525
|
+
argNode.type === 'char_literal' ||
|
|
1526
|
+
argNode.type === 'true' ||
|
|
1527
|
+
argNode.type === 'false' ||
|
|
1528
|
+
argNode.type === 'null' ||
|
|
1529
|
+
argNode.type === 'nullptr') {
|
|
1530
|
+
return EMPTY_ADL_ARG;
|
|
1531
|
+
}
|
|
1532
|
+
// Qualified expression (a::b) — may be a function, variable, enum value,
|
|
1533
|
+
// or static member. Record as a potential function reference; resolution
|
|
1534
|
+
// time verifies via workspace lookup that a Function/Method with this simple
|
|
1535
|
+
// name exists in the extracted namespace before contributing to the set.
|
|
1536
|
+
if (argNode.type === 'qualified_identifier') {
|
|
1537
|
+
return {
|
|
1538
|
+
simpleClassName: '',
|
|
1539
|
+
templateSimpleClassName: '',
|
|
1540
|
+
templateNamespace: '',
|
|
1541
|
+
templateArgClassNames: [],
|
|
1542
|
+
templateArgNamespaces: [],
|
|
1543
|
+
functionRefText: argNode.text,
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
// Variable reference — look up its declared type (preserving pointer /
|
|
1547
|
+
// reference / qualified-name shape; the existing arity-narrowing helper
|
|
1548
|
+
// strips this info).
|
|
1549
|
+
if (argNode.type === 'identifier') {
|
|
1550
|
+
const result = lookupAdlIdentifierType(argNode);
|
|
1551
|
+
if (result === null) {
|
|
1552
|
+
// Not found in the local compound_statement scope — could be a
|
|
1553
|
+
// free-function reference (unqualified name, namespace scope).
|
|
1554
|
+
return {
|
|
1555
|
+
simpleClassName: '',
|
|
1556
|
+
templateSimpleClassName: '',
|
|
1557
|
+
templateNamespace: '',
|
|
1558
|
+
templateArgClassNames: [],
|
|
1559
|
+
templateArgNamespaces: [],
|
|
1560
|
+
functionRefText: argNode.text,
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
return result;
|
|
1564
|
+
}
|
|
1565
|
+
// Other shapes (calls, member access, operators) — V1 unsupported.
|
|
1566
|
+
return EMPTY_ADL_ARG;
|
|
1567
|
+
}
|
|
1568
|
+
/**
|
|
1569
|
+
* Returns `true` when `varName` appears as a parameter name in the nearest
|
|
1570
|
+
* enclosing `function_definition` or `function_declarator` that contains
|
|
1571
|
+
* `identNode`. Parameters live in `parameter_list` (a sibling of the
|
|
1572
|
+
* `compound_statement`), so the `compound_statement`-local declaration scan
|
|
1573
|
+
* in `lookupAdlIdentifierType` would not find them — causing them to be
|
|
1574
|
+
* mistakenly classified as potential free-function references.
|
|
1575
|
+
*
|
|
1576
|
+
* In tree-sitter-cpp a `function_definition` does NOT expose `parameters`
|
|
1577
|
+
* as a direct named field; parameters live inside the nested
|
|
1578
|
+
* `function_declarator`. For `function_declarator` nodes the `parameters`
|
|
1579
|
+
* field IS direct. Both cases are handled below.
|
|
1580
|
+
*/
|
|
1581
|
+
function isIdentifierAFunctionParameter(identNode, varName) {
|
|
1582
|
+
let node = identNode.parent;
|
|
1583
|
+
let safety = 64;
|
|
1584
|
+
while (node !== null && safety-- > 0) {
|
|
1585
|
+
let params = null;
|
|
1586
|
+
if (node.type === 'function_declarator') {
|
|
1587
|
+
// parameters is a direct field on function_declarator.
|
|
1588
|
+
params = node.childForFieldName('parameters');
|
|
1589
|
+
}
|
|
1590
|
+
else if (node.type === 'function_definition') {
|
|
1591
|
+
// function_definition carries parameters inside its `declarator` field
|
|
1592
|
+
// (which is a function_declarator). Walk through it.
|
|
1593
|
+
const decl = node.childForFieldName('declarator');
|
|
1594
|
+
if (decl !== null && decl.type === 'function_declarator') {
|
|
1595
|
+
params = decl.childForFieldName('parameters');
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
if (params !== null) {
|
|
1599
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
1600
|
+
const param = params.namedChild(i);
|
|
1601
|
+
if (param === null)
|
|
1602
|
+
continue;
|
|
1603
|
+
const declNode = param.childForFieldName('declarator');
|
|
1604
|
+
if (declNode === null)
|
|
1605
|
+
continue;
|
|
1606
|
+
const leafName = extractDeclaratorLeafName(declNode);
|
|
1607
|
+
if (leafName === varName)
|
|
1608
|
+
return true;
|
|
1609
|
+
}
|
|
1610
|
+
// Only check the immediately enclosing function — do not climb further.
|
|
1611
|
+
break;
|
|
1612
|
+
}
|
|
1613
|
+
if (node.type === 'translation_unit')
|
|
1614
|
+
break;
|
|
1615
|
+
node = node.parent;
|
|
1616
|
+
}
|
|
1617
|
+
return false;
|
|
1618
|
+
}
|
|
1619
|
+
function lookupAdlIdentifierType(identNode) {
|
|
1620
|
+
const varName = identNode.text;
|
|
1621
|
+
let scope = identNode.parent;
|
|
1622
|
+
while (scope !== null &&
|
|
1623
|
+
scope.type !== 'compound_statement' &&
|
|
1624
|
+
scope.type !== 'translation_unit') {
|
|
1625
|
+
scope = scope.parent;
|
|
1626
|
+
}
|
|
1627
|
+
if (scope === null)
|
|
1628
|
+
return null;
|
|
1629
|
+
// Function parameters live in the enclosing function's `parameter_list`,
|
|
1630
|
+
// NOT inside the `compound_statement`, so the declaration scan below would
|
|
1631
|
+
// never find them and would return `null` — incorrectly triggering the
|
|
1632
|
+
// free-function-reference path. Check the parameter_list first.
|
|
1633
|
+
if (isIdentifierAFunctionParameter(identNode, varName)) {
|
|
1634
|
+
return EMPTY_ADL_ARG;
|
|
1635
|
+
}
|
|
1636
|
+
let foundAsLocalFunctionPointer = false;
|
|
1637
|
+
for (let i = 0; i < scope.childCount; i++) {
|
|
1638
|
+
const stmt = scope.child(i);
|
|
1639
|
+
if (stmt === null || stmt.type !== 'declaration')
|
|
1640
|
+
continue;
|
|
1641
|
+
const typeNode = stmt.childForFieldName('type');
|
|
1642
|
+
if (typeNode === null)
|
|
1643
|
+
continue;
|
|
1644
|
+
if (typeNode.type === 'placeholder_type_specifier')
|
|
1645
|
+
continue;
|
|
1646
|
+
const declarator = stmt.childForFieldName('declarator');
|
|
1647
|
+
if (declarator === null)
|
|
1648
|
+
continue;
|
|
1649
|
+
// Unwrap declarator chain to find pointer/reference markers and the
|
|
1650
|
+
// variable name. `init_declarator > pointer_declarator > identifier`
|
|
1651
|
+
// means pointer-typed; repeated pointer wrappers still count as pointer
|
|
1652
|
+
// typed; `init_declarator > reference_declarator > ...` (or
|
|
1653
|
+
// `rvalue_reference_declarator`) means reference-typed; bare
|
|
1654
|
+
// `init_declarator > identifier` is value.
|
|
1655
|
+
// Function-pointer wrappers (`pointer_declarator > function_declarator`)
|
|
1656
|
+
// must not contribute ADL associated namespaces.
|
|
1657
|
+
let isFunctionPointer = false;
|
|
1658
|
+
let inner = declarator;
|
|
1659
|
+
let nameText = null;
|
|
1660
|
+
let safety = 16; // bound walk depth defensively
|
|
1661
|
+
while (safety-- > 0) {
|
|
1662
|
+
if (inner.type === 'pointer_declarator') {
|
|
1663
|
+
if (findFirstDescendantOfType(inner, 'function_declarator') !== null) {
|
|
1664
|
+
isFunctionPointer = true;
|
|
1665
|
+
// Extract the name from within the function-pointer declarator chain
|
|
1666
|
+
// so `foundAsLocalFunctionPointer` can detect a matching declaration.
|
|
1667
|
+
nameText = extractDeclaratorLeafName(inner);
|
|
1668
|
+
break;
|
|
1669
|
+
}
|
|
1670
|
+
const next = inner.childForFieldName('declarator');
|
|
1671
|
+
if (next === null)
|
|
1672
|
+
break;
|
|
1673
|
+
inner = next;
|
|
1674
|
+
continue;
|
|
1675
|
+
}
|
|
1676
|
+
if (inner.type === 'reference_declarator') {
|
|
1677
|
+
// reference_declarator has a single child (the inner declarator).
|
|
1678
|
+
let next = null;
|
|
1679
|
+
for (let j = 0; j < inner.namedChildCount; j++) {
|
|
1680
|
+
const c = inner.namedChild(j);
|
|
1681
|
+
if (c !== null) {
|
|
1682
|
+
next = c;
|
|
1683
|
+
break;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
if (next === null)
|
|
1687
|
+
break;
|
|
1688
|
+
inner = next;
|
|
1689
|
+
continue;
|
|
1690
|
+
}
|
|
1691
|
+
if (inner.type === 'init_declarator') {
|
|
1692
|
+
const next = inner.childForFieldName('declarator');
|
|
1693
|
+
if (next === null)
|
|
1694
|
+
break;
|
|
1695
|
+
inner = next;
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
if (inner.type === 'function_declarator') {
|
|
1699
|
+
isFunctionPointer = true;
|
|
1700
|
+
// Extract the name from the inner declarator (e.g. `(*g)` in `void (*g)()`).
|
|
1701
|
+
const innerDecl = inner.childForFieldName('declarator');
|
|
1702
|
+
if (innerDecl !== null)
|
|
1703
|
+
nameText = extractDeclaratorLeafName(innerDecl);
|
|
1704
|
+
break;
|
|
1705
|
+
}
|
|
1706
|
+
// Reached the leaf — usually `identifier`. Take its text.
|
|
1707
|
+
nameText = inner.text;
|
|
1708
|
+
break;
|
|
1709
|
+
}
|
|
1710
|
+
if (nameText === varName && isFunctionPointer) {
|
|
1711
|
+
// Explicitly declared as a function-pointer variable — must not be
|
|
1712
|
+
// treated as a free-function reference by the caller.
|
|
1713
|
+
foundAsLocalFunctionPointer = true;
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
if (isFunctionPointer || nameText !== varName)
|
|
1717
|
+
continue;
|
|
1718
|
+
const simpleClassName = extractAdlSimpleTypeName(typeNode);
|
|
1719
|
+
const { templateSimpleClassName, templateNamespace, templateArgClassNames, templateArgNamespaces, } = extractAdlTemplateInfo(typeNode);
|
|
1720
|
+
return {
|
|
1721
|
+
simpleClassName,
|
|
1722
|
+
templateSimpleClassName,
|
|
1723
|
+
templateNamespace,
|
|
1724
|
+
templateArgClassNames,
|
|
1725
|
+
templateArgNamespaces,
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
// If the identifier was found in local scope as a function-pointer variable,
|
|
1729
|
+
// return EMPTY_ADL_ARG so the caller does NOT treat it as a free-function
|
|
1730
|
+
// reference. Otherwise return null to indicate "not in local scope".
|
|
1731
|
+
//
|
|
1732
|
+
// Known limitation (Finding 4): variables whose type is a typedef/using alias
|
|
1733
|
+
// for a function-pointer type are NOT detected here. For example:
|
|
1734
|
+
// using Callback = void (*)();
|
|
1735
|
+
// Callback g;
|
|
1736
|
+
// foo(g); // `g`'s declarator is `identifier` with type `Callback`
|
|
1737
|
+
// The declarator has no `pointer_declarator` wrapper, so `isFunctionPointer`
|
|
1738
|
+
// stays false and `extractAdlSimpleTypeName` returns `"Callback"`. ADL then
|
|
1739
|
+
// looks for a class named `Callback`; if none exists, this degrades to
|
|
1740
|
+
// EMPTY_ADL_ARG (class not found → no namespace contributed). If a class
|
|
1741
|
+
// named `Callback` does exist, a spurious namespace contribution could occur.
|
|
1742
|
+
// Risk is low in practice; a future fix should resolve the typedef/alias chain.
|
|
1743
|
+
return foundAsLocalFunctionPointer ? EMPTY_ADL_ARG : null;
|
|
1744
|
+
}
|
|
1745
|
+
/** Extract the simple class-like type name from a `type:` field node.
|
|
1746
|
+
* Returns '' for primitives and any other
|
|
1747
|
+
* unsupported type-only shape. Function pointers are filtered at the
|
|
1748
|
+
* declarator level in `lookupAdlIdentifierType`. */
|
|
1749
|
+
function extractAdlSimpleTypeName(typeNode) {
|
|
1750
|
+
if (typeNode.type === 'type_descriptor') {
|
|
1751
|
+
const innerType = typeNode.childForFieldName('type');
|
|
1752
|
+
if (innerType !== null)
|
|
1753
|
+
return extractAdlSimpleTypeName(innerType);
|
|
1754
|
+
for (let i = 0; i < typeNode.childCount; i++) {
|
|
1755
|
+
const child = typeNode.child(i);
|
|
1756
|
+
if (child === null)
|
|
1757
|
+
continue;
|
|
1758
|
+
if (child.type === 'type_identifier' ||
|
|
1759
|
+
child.type === 'qualified_identifier' ||
|
|
1760
|
+
child.type === 'template_type') {
|
|
1761
|
+
return extractAdlSimpleTypeName(child);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
return '';
|
|
1765
|
+
}
|
|
1766
|
+
if (typeNode.type === 'primitive_type')
|
|
1767
|
+
return '';
|
|
1768
|
+
if (typeNode.type === 'sized_type_specifier')
|
|
1769
|
+
return '';
|
|
1770
|
+
if (typeNode.type === 'type_identifier')
|
|
1771
|
+
return typeNode.text;
|
|
1772
|
+
if (typeNode.type === 'template_type') {
|
|
1773
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
1774
|
+
if (nameNode !== null)
|
|
1775
|
+
return extractAdlSimpleTypeName(nameNode);
|
|
1776
|
+
const id = findFirstDescendantOfType(typeNode, 'type_identifier');
|
|
1777
|
+
return id !== null ? id.text : '';
|
|
1778
|
+
}
|
|
1779
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
1780
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
1781
|
+
if (nameNode !== null)
|
|
1782
|
+
return extractAdlSimpleTypeName(nameNode);
|
|
1783
|
+
const id = findFirstDescendantOfType(typeNode, 'type_identifier');
|
|
1784
|
+
return id !== null ? id.text : '';
|
|
1785
|
+
}
|
|
1786
|
+
// Function pointers, decltype, etc — unsupported for ADL participation.
|
|
1787
|
+
return '';
|
|
1788
|
+
}
|
|
1789
|
+
function extractAdlTypeNamespace(typeNode) {
|
|
1790
|
+
if (typeNode.type === 'type_descriptor') {
|
|
1791
|
+
const innerType = typeNode.childForFieldName('type');
|
|
1792
|
+
if (innerType !== null)
|
|
1793
|
+
return extractAdlTypeNamespace(innerType);
|
|
1794
|
+
for (let i = 0; i < typeNode.childCount; i++) {
|
|
1795
|
+
const child = typeNode.child(i);
|
|
1796
|
+
if (child === null)
|
|
1797
|
+
continue;
|
|
1798
|
+
if (child.type === 'qualified_identifier' ||
|
|
1799
|
+
child.type === 'template_type' ||
|
|
1800
|
+
child.type === 'type_identifier') {
|
|
1801
|
+
return extractAdlTypeNamespace(child);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
return '';
|
|
1805
|
+
}
|
|
1806
|
+
if (typeNode.type === 'template_type') {
|
|
1807
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
1808
|
+
return nameNode !== null ? extractAdlTypeNamespace(nameNode) : '';
|
|
1809
|
+
}
|
|
1810
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
1811
|
+
const scope = typeNode.childForFieldName('scope');
|
|
1812
|
+
if (scope !== null)
|
|
1813
|
+
return (0, qualified_name_js_1.normalizeQualifiedName)(scope.text);
|
|
1814
|
+
return extractNamespaceFromQualifiedText(typeNode.text);
|
|
1815
|
+
}
|
|
1816
|
+
return '';
|
|
1817
|
+
}
|
|
1818
|
+
function extractAdlTemplateInfo(typeNode) {
|
|
1819
|
+
const templateTypeNode = findTemplateTypeNode(typeNode);
|
|
1820
|
+
if (templateTypeNode === null) {
|
|
1821
|
+
return {
|
|
1822
|
+
templateSimpleClassName: '',
|
|
1823
|
+
templateNamespace: '',
|
|
1824
|
+
templateArgClassNames: [],
|
|
1825
|
+
templateArgNamespaces: [],
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
const templateArgClassNames = [];
|
|
1829
|
+
const templateArgNamespaces = [];
|
|
1830
|
+
collectAdlTemplateArgs(templateTypeNode, 0, templateArgClassNames, templateArgNamespaces);
|
|
1831
|
+
return {
|
|
1832
|
+
templateSimpleClassName: extractAdlSimpleTypeName(templateTypeNode),
|
|
1833
|
+
templateNamespace: extractAdlTypeNamespace(typeNode),
|
|
1834
|
+
templateArgClassNames,
|
|
1835
|
+
templateArgNamespaces,
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
1838
|
+
function collectAdlTemplateArgs(templateTypeNode, depth, outClassNames, outNamespaces) {
|
|
1839
|
+
if (depth >= ADL_TEMPLATE_RECURSION_MAX_DEPTH)
|
|
1840
|
+
return;
|
|
1841
|
+
if (templateTypeNode.type !== 'template_type')
|
|
1842
|
+
return;
|
|
1843
|
+
const argList = templateTypeNode.childForFieldName('arguments') ??
|
|
1844
|
+
findChildOfType(templateTypeNode, ['template_argument_list']);
|
|
1845
|
+
if (argList === null)
|
|
1846
|
+
return;
|
|
1847
|
+
for (let i = 0; i < argList.namedChildCount; i++) {
|
|
1848
|
+
const arg = argList.namedChild(i);
|
|
1849
|
+
if (arg === null || arg.type !== 'type_descriptor')
|
|
1850
|
+
continue;
|
|
1851
|
+
const simpleClassName = extractAdlSimpleTypeName(arg);
|
|
1852
|
+
if (simpleClassName.length > 0)
|
|
1853
|
+
outClassNames.push(simpleClassName);
|
|
1854
|
+
const ns = extractAdlTypeNamespace(arg);
|
|
1855
|
+
if (ns.length > 0)
|
|
1856
|
+
outNamespaces.push(ns);
|
|
1857
|
+
const nestedType = arg.childForFieldName('type');
|
|
1858
|
+
const nestedTemplate = nestedType !== null ? findTemplateTypeNode(nestedType) : null;
|
|
1859
|
+
if (nestedTemplate !== null) {
|
|
1860
|
+
collectAdlTemplateArgs(nestedTemplate, depth + 1, outClassNames, outNamespaces);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
function findTemplateTypeNode(typeNode) {
|
|
1865
|
+
if (typeNode.type === 'template_type')
|
|
1866
|
+
return typeNode;
|
|
1867
|
+
if (typeNode.type === 'type_descriptor') {
|
|
1868
|
+
const innerType = typeNode.childForFieldName('type');
|
|
1869
|
+
if (innerType !== null)
|
|
1870
|
+
return findTemplateTypeNode(innerType);
|
|
1871
|
+
return null;
|
|
1872
|
+
}
|
|
1873
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
1874
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
1875
|
+
if (nameNode !== null)
|
|
1876
|
+
return findTemplateTypeNode(nameNode);
|
|
1877
|
+
return null;
|
|
1878
|
+
}
|
|
1879
|
+
return null;
|
|
1880
|
+
}
|
|
1881
|
+
function extractNamespaceFromQualifiedText(text) {
|
|
1882
|
+
const cleaned = text.replace(/\s+/g, '');
|
|
1883
|
+
const idx = cleaned.lastIndexOf('::');
|
|
1884
|
+
if (idx <= 0)
|
|
1885
|
+
return '';
|
|
1886
|
+
return (0, qualified_name_js_1.normalizeQualifiedName)(cleaned.slice(0, idx));
|
|
1887
|
+
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Walk a declarator node chain, unwrapping pointer/reference/function/
|
|
1890
|
+
* parenthesized wrappers, and return the text of the innermost identifier.
|
|
1891
|
+
* Returns `null` when no identifier is found within `safety` steps.
|
|
1892
|
+
* Used by `lookupAdlIdentifierType` to extract the variable name from
|
|
1893
|
+
* function-pointer declarator trees such as `(*g)()` in `void (*g)()`.
|
|
1894
|
+
*/
|
|
1895
|
+
function extractDeclaratorLeafName(node) {
|
|
1896
|
+
let cur = node;
|
|
1897
|
+
let safety = 16;
|
|
1898
|
+
while (safety-- > 0) {
|
|
1899
|
+
if (cur.type === 'identifier' ||
|
|
1900
|
+
cur.type === 'type_identifier' ||
|
|
1901
|
+
cur.type === 'operator_name') {
|
|
1902
|
+
return cur.text;
|
|
1903
|
+
}
|
|
1904
|
+
// Common wrapper nodes — follow the 'declarator' field when present.
|
|
1905
|
+
const next = cur.childForFieldName('declarator') ??
|
|
1906
|
+
// parenthesized_declarator: single named child
|
|
1907
|
+
(cur.type === 'parenthesized_declarator' || cur.type.endsWith('_declarator')
|
|
1908
|
+
? cur.namedChild(0)
|
|
1909
|
+
: null);
|
|
1910
|
+
if (next === null)
|
|
1911
|
+
return null;
|
|
1912
|
+
cur = next;
|
|
1913
|
+
}
|
|
1914
|
+
return null;
|
|
1915
|
+
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Check if a C++ declaration has an `explicit` specifier. Tree-sitter-cpp
|
|
1918
|
+
* exposes `explicit` as a direct keyword child on constructor declarations in
|
|
1919
|
+
* current grammar builds; the bounded text prefix keeps this resilient across
|
|
1920
|
+
* small grammar shape differences without scanning whole function bodies.
|
|
1921
|
+
*/
|
|
1922
|
+
function hasExplicitSpecifier(node) {
|
|
1923
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1924
|
+
const child = node.child(i);
|
|
1925
|
+
if (child !== null && child.text === 'explicit')
|
|
1926
|
+
return true;
|
|
1927
|
+
}
|
|
1928
|
+
return /\bexplicit\b/.test(node.text.slice(0, 128));
|
|
1929
|
+
}
|
|
1930
|
+
function hasDeletedMethodClause(node, callableName) {
|
|
1931
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
1932
|
+
const child = node.namedChild(i);
|
|
1933
|
+
if (child?.type === 'delete_method_clause')
|
|
1934
|
+
return true;
|
|
1935
|
+
// tree-sitter-cpp 0.23 parses a deleted free-function declaration as
|
|
1936
|
+
// `declaration > init_declarator > delete_expression`, while class
|
|
1937
|
+
// members use the dedicated `delete_method_clause`.
|
|
1938
|
+
if (child?.type === 'init_declarator' &&
|
|
1939
|
+
child.childForFieldName('value')?.type === 'delete_expression' &&
|
|
1940
|
+
callableName !== undefined &&
|
|
1941
|
+
extractDeclaratorLeafName(child.childForFieldName('declarator') ?? child) === callableName) {
|
|
1942
|
+
return true;
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return false;
|
|
1946
|
+
}
|
|
1947
|
+
/**
|
|
1948
|
+
* Check if a C++ function_definition or declaration has `static` storage class.
|
|
1949
|
+
*/
|
|
1950
|
+
function hasStaticStorageClass(node) {
|
|
1951
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1952
|
+
const child = node.child(i);
|
|
1953
|
+
if (child !== null && child.type === 'storage_class_specifier' && child.text === 'static') {
|
|
1954
|
+
return true;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
return false;
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* Check if a node is inside an anonymous namespace (file-local linkage in C++).
|
|
1961
|
+
* Anonymous namespaces have no `name` field in tree-sitter-cpp.
|
|
1962
|
+
*/
|
|
1963
|
+
function isInsideAnonymousNamespace(node) {
|
|
1964
|
+
let ancestor = node.parent ?? null;
|
|
1965
|
+
while (ancestor !== null) {
|
|
1966
|
+
if (ancestor.type === 'namespace_definition') {
|
|
1967
|
+
// Anonymous namespace: has declaration_list but no name child
|
|
1968
|
+
const nameChild = ancestor.childForFieldName?.('name') ?? null;
|
|
1969
|
+
if (nameChild === null)
|
|
1970
|
+
return true;
|
|
1971
|
+
}
|
|
1972
|
+
ancestor = ancestor.parent;
|
|
1973
|
+
}
|
|
1974
|
+
return false;
|
|
1975
|
+
}
|