cgraphx 2.0.2 → 2.0.6
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 +13 -3
- package/dist/.claude-template/agents/task-history.md +186 -0
- package/dist/.claude-template/commands/end.md +1 -0
- package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +5 -3
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +8 -8
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.md +8 -8
- package/dist/.claude-template/skills/clarify-requirements/SKILL.md +13 -9
- package/dist/.claude-template/skills/db-query/SKILL.md +19 -2
- package/dist/.claude-template/skills/iboc-check/SKILL.md +51 -23
- package/dist/.claude-template/skills/iboc-check/filler-prompt.md +3 -4
- package/dist/.claude-template/skills/run-api-test/SKILL.md +15 -15
- package/dist/.claude-template/skills/run-api-test/assets/{template-test-report.md → template-/346/216/245/345/217/243/346/265/213/350/257/225/346/212/245/345/221/212.md} +4 -4
- package/dist/.claude-template/skills/run-api-test/references/bru-run.md +1 -1
- package/dist/.claude-template/skills/run-api-test/references/db-verification.md +2 -2
- package/dist/.claude-template/skills/run-api-test/references/report-format.md +6 -6
- package/dist/.claude-template/skills/run-api-test/references/service-readiness.md +1 -1
- package/dist/.claude-template/skills/run-api-test/references/test-scope.md +6 -6
- package/dist/.claude-template/skills/run-ui-test/SKILL.md +186 -0
- package/dist/.claude-template/skills/run-ui-test/references/report-format.md +77 -0
- package/dist/.claude-template/skills/subagent-implement/SKILL.md +3 -2
- package/dist/.claude-template/skills/write-api/SKILL.md +18 -18
- package/dist/.claude-template/skills/write-api/assets/{template-api-spec.md → template-/346/216/245/345/217/243/346/265/213/350/257/225-spec.md} +1 -1
- package/dist/.claude-template/skills/write-api/references/{api-spec-format.md → /346/216/245/345/217/243/346/265/213/350/257/225-spec-format.md} +3 -3
- package/dist/.claude-template/skills/write-plan/SKILL.md +4 -2
- package/dist/.claude-template/skills/write-ui-test/SKILL.md +125 -0
- package/dist/.claude-template/skills/write-ui-test/references//347/224/250/344/276/213/350/247/204/346/240/274-format.md +94 -0
- 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/dbquery/cli.d.ts.map +1 -1
- package/dist/core/dbquery/cli.js +5 -4
- package/dist/core/dbquery/cli.js.map +1 -1
- package/dist/core/dbquery/config.d.ts.map +1 -1
- package/dist/core/dbquery/config.js +39 -3
- package/dist/core/dbquery/config.js.map +1 -1
- package/dist/core/dbquery/drivers/http.d.ts +23 -0
- package/dist/core/dbquery/drivers/http.d.ts.map +1 -0
- package/dist/core/dbquery/drivers/http.js +125 -0
- package/dist/core/dbquery/drivers/http.js.map +1 -0
- package/dist/core/dbquery/drivers/mysql.js +1 -1
- package/dist/core/dbquery/drivers/mysql.js.map +1 -1
- package/dist/core/dbquery/drivers/postgres.js +1 -1
- package/dist/core/dbquery/drivers/postgres.js.map +1 -1
- package/dist/core/dbquery/executor.d.ts.map +1 -1
- package/dist/core/dbquery/executor.js +46 -12
- package/dist/core/dbquery/executor.js.map +1 -1
- package/dist/core/dbquery/format.d.ts.map +1 -1
- package/dist/core/dbquery/format.js +2 -1
- package/dist/core/dbquery/format.js.map +1 -1
- package/dist/core/dbquery/init.d.ts.map +1 -1
- package/dist/core/dbquery/init.js +7 -0
- package/dist/core/dbquery/init.js.map +1 -1
- package/dist/core/dbquery/types.d.ts +55 -7
- package/dist/core/dbquery/types.d.ts.map +1 -1
- package/dist/core/directory.d.ts +17 -0
- package/dist/core/directory.d.ts.map +1 -1
- package/dist/core/directory.js +37 -0
- package/dist/core/directory.js.map +1 -1
- package/dist/core/features/cli.d.ts.map +1 -1
- package/dist/core/features/cli.js +3 -2
- package/dist/core/features/cli.js.map +1 -1
- package/dist/core/features/scanner.d.ts +1 -1
- package/dist/core/features/scanner.d.ts.map +1 -1
- package/dist/core/features/scanner.js +20 -4
- package/dist/core/features/scanner.js.map +1 -1
- package/dist/core/markdown/cli.d.ts.map +1 -1
- package/dist/core/markdown/cli.js +9 -8
- package/dist/core/markdown/cli.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/dist/web/register.d.ts.map +1 -1
- package/dist/web/register.js +2 -1
- package/dist/web/register.js.map +1 -1
- package/package.json +1 -1
- package/dist/.claude-template/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-deck/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-deck/references/.cgraphx/timeline-current-turn.json +0 -1
- package/dist/.claude-template/skills/handdrawn-sketch-engine/.cgraphx/timeline-current-turn.json +0 -1
- /package/dist/.claude-template/skills/run-api-test/assets/{template-test-verify.jsonl → template-/346/216/245/345/217/243/346/265/213/350/257/225/351/252/214/350/257/201.jsonl"} +0 -0
|
@@ -0,0 +1,1693 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLeadingDocDescriptionExtractor = exports.DOC_BEARING_LABELS = exports.stripBidiAndZeroWidth = exports.SPLIT_SIGNATURE_NODE_TYPES = exports.LOCAL_SCOPE_BODY_NODE_TYPES = exports.PARAMETER_LIST_NODE_TYPES = exports.CALL_ARGUMENT_LIST_TYPES = exports.inferFunctionLabel = exports.CONSTRUCTOR_LABEL_NODE_TYPES = exports.METHOD_LABEL_NODE_TYPES = exports.genericFuncName = exports.findSiblingChild = exports.findEnclosingClassId = exports.isThisMemberAssignmentNode = exports.isCjsDefaultExportAssignment = exports.isPrototypeMemberAssignmentNode = exports.thisAssignmentOwnerName = exports.prototypeAssignmentOwnerName = exports.findMemberAssignmentOwnerInfo = exports.findObjectLiteralBindingInfo = exports.findEnclosingClassInfo = exports.synthesizeJavaTypeIdentity = exports.javaLocalTypeDeclarationContainer = exports.CONTAINER_TYPE_TO_LABEL = exports.MEMBER_OWNER_NODE_TYPES = exports.CLASS_CONTAINER_TYPES = exports.FUNCTION_NODE_TYPES = exports.buildDefinitionPreScan = exports.isValueDefinitionLabel = exports.isSuppressedConcreteTypedefDuplicate = exports.getDefinitionNodeFromCaptures = exports.DEFINITION_CAPTURE_KEYS = exports.isQualifiableScopeLabel = exports.qualifyRustImplTargetByModScope = exports.qualifyByEnclosingModScope = void 0;
|
|
4
|
+
exports.walkNamedTree = walkNamedTree;
|
|
5
|
+
exports.findAncestorBeforeBoundary = findAncestorBeforeBoundary;
|
|
6
|
+
exports.findSplitBodyCallableAncestor = findSplitBodyCallableAncestor;
|
|
7
|
+
exports.getLabelFromCaptures = getLabelFromCaptures;
|
|
8
|
+
exports.findDescendant = findDescendant;
|
|
9
|
+
exports.extractStringContent = extractStringContent;
|
|
10
|
+
exports.findChild = findChild;
|
|
11
|
+
exports.extractLeadingDocComment = extractLeadingDocComment;
|
|
12
|
+
exports.nodeToCapture = nodeToCapture;
|
|
13
|
+
exports.syntheticCapture = syntheticCapture;
|
|
14
|
+
exports.findNodeAtRange = findNodeAtRange;
|
|
15
|
+
exports.nodeIfType = nodeIfType;
|
|
16
|
+
const utils_js_1 = require("../../../lib/utils.js");
|
|
17
|
+
const template_arguments_js_1 = require("./template-arguments.js");
|
|
18
|
+
const qualified_name_js_1 = require("./qualified-name.js");
|
|
19
|
+
const callable_labels_js_1 = require("./callable-labels.js");
|
|
20
|
+
/**
|
|
21
|
+
* Qualify a name by its enclosing `mod_item` scope, so two same-tail items nested
|
|
22
|
+
* under different modules get DISTINCT paths (`outer.Inner` vs `other.Inner`).
|
|
23
|
+
* Walks `mod_item` ancestors (outermost → innermost) and joins them with the
|
|
24
|
+
* normalized raw text via the shared `splitQualifiedName`. Keyed purely on
|
|
25
|
+
* tree-sitter node types (no language name), so it is a no-op for every grammar
|
|
26
|
+
* without such a node.
|
|
27
|
+
*
|
|
28
|
+
* TWO callers, with different contracts — read both before widening either:
|
|
29
|
+
*
|
|
30
|
+
* 1. The inherent-impl target (`impl Inner { … }`) — the #1982 follow-up to
|
|
31
|
+
* #1975, reachable through the {@link qualifyRustImplTargetByModScope} alias
|
|
32
|
+
* and mirrored by the inherent-impl branch in `findEnclosingClassInfo` so the
|
|
33
|
+
* owner edge and the node id agree byte-for-byte. That caller gates on an
|
|
34
|
+
* UNSCOPED `type_identifier`, which is what keeps a SCOPED `impl a::Inner` on
|
|
35
|
+
* its full raw text.
|
|
36
|
+
*
|
|
37
|
+
* 2. Free items, for module node identity (#2742). That caller gates on the node
|
|
38
|
+
* being on neither side of an owner edge (`MEMBER_OWNER_NODE_TYPES`,
|
|
39
|
+
* `enclosingClassInfo`) and not inside a callable, because only the id moves
|
|
40
|
+
* here — every owner-edge anchor is minted separately and does not follow.
|
|
41
|
+
*
|
|
42
|
+
* A name with NO enclosing `mod` is returned verbatim, never normalized: rewriting
|
|
43
|
+
* a scoped target's separator (`a::Inner` → `a.Inner`) would move its node id away
|
|
44
|
+
* from the id its owner edge emits, which is how caller 2 first broke caller 1's
|
|
45
|
+
* #1975 contract. Splitting an unscoped name has always been the identity, so
|
|
46
|
+
* caller 1 is unaffected either way.
|
|
47
|
+
*/
|
|
48
|
+
const qualifyByEnclosingModScope = (node, rawText) => {
|
|
49
|
+
const modSegments = [];
|
|
50
|
+
let current = node.parent;
|
|
51
|
+
while (current) {
|
|
52
|
+
if (current.type === 'mod_item') {
|
|
53
|
+
const nameNode = current.childForFieldName?.('name') ??
|
|
54
|
+
current.children?.find((c) => c.type === 'identifier');
|
|
55
|
+
if (nameNode)
|
|
56
|
+
modSegments.unshift(nameNode.text);
|
|
57
|
+
}
|
|
58
|
+
current = current.parent;
|
|
59
|
+
}
|
|
60
|
+
// No enclosing `mod`: return the raw text UNTOUCHED. Normalizing here would
|
|
61
|
+
// rewrite a scoped target's separator (`a::Inner` -> `a.Inner`) and silently
|
|
62
|
+
// move its node id away from the one the owner edge emits, which is how this
|
|
63
|
+
// helper first broke the #1975 scoped-impl ownership when it was generalized
|
|
64
|
+
// beyond unscoped targets. Callers that pass an unscoped name are unaffected,
|
|
65
|
+
// since splitting one has always been the identity.
|
|
66
|
+
if (modSegments.length === 0)
|
|
67
|
+
return rawText;
|
|
68
|
+
return [...modSegments, ...(0, qualified_name_js_1.splitQualifiedName)(rawText)].filter(Boolean).join('.');
|
|
69
|
+
};
|
|
70
|
+
exports.qualifyByEnclosingModScope = qualifyByEnclosingModScope;
|
|
71
|
+
/**
|
|
72
|
+
* Impl-target alias of {@link qualifyByEnclosingModScope}, kept as its own name
|
|
73
|
+
* because the caller gates it on UNSCOPED targets (see the contract above).
|
|
74
|
+
*/
|
|
75
|
+
exports.qualifyRustImplTargetByModScope = exports.qualifyByEnclosingModScope;
|
|
76
|
+
/**
|
|
77
|
+
* #1991: scope-label predicate that single-sources the `nodeLabel === 'Trait'`
|
|
78
|
+
* checks in parsing-processor.ts / parse-worker.ts. A Ruby `module` maps to the
|
|
79
|
+
* `Trait` registry label but is NOT a typeDeclaration, so `extractQualifiedName`
|
|
80
|
+
* bails on it; these node labels are instead qualified via the scope walk
|
|
81
|
+
* (`qualifyScopeName`) so same-tail nested modules get distinct ids. Keeping the
|
|
82
|
+
* literal in one place stops the four hand-maintained copies (two each in the
|
|
83
|
+
* sequential and worker definition paths) from drifting apart. Pure predicate —
|
|
84
|
+
* value-identical to the inlined `nodeLabel === 'Trait'`.
|
|
85
|
+
*/
|
|
86
|
+
const isQualifiableScopeLabel = (nodeLabel) => nodeLabel === 'Trait';
|
|
87
|
+
exports.isQualifiableScopeLabel = isQualifiableScopeLabel;
|
|
88
|
+
/**
|
|
89
|
+
* Ordered list of definition capture keys for tree-sitter query matches.
|
|
90
|
+
* Used to extract the definition node from a capture map.
|
|
91
|
+
*/
|
|
92
|
+
exports.DEFINITION_CAPTURE_KEYS = [
|
|
93
|
+
'definition.function',
|
|
94
|
+
'definition.class',
|
|
95
|
+
'definition.interface',
|
|
96
|
+
'definition.method',
|
|
97
|
+
'definition.struct',
|
|
98
|
+
'definition.enum',
|
|
99
|
+
'definition.namespace',
|
|
100
|
+
'definition.module',
|
|
101
|
+
'definition.trait',
|
|
102
|
+
'definition.impl',
|
|
103
|
+
'definition.type',
|
|
104
|
+
'definition.const',
|
|
105
|
+
'definition.static',
|
|
106
|
+
'definition.variable',
|
|
107
|
+
'definition.typedef',
|
|
108
|
+
'definition.macro',
|
|
109
|
+
'definition.union',
|
|
110
|
+
'definition.property',
|
|
111
|
+
'definition.record',
|
|
112
|
+
'definition.delegate',
|
|
113
|
+
'definition.annotation',
|
|
114
|
+
'definition.constructor',
|
|
115
|
+
'definition.template',
|
|
116
|
+
];
|
|
117
|
+
/** Extract the definition node from a tree-sitter query capture map. */
|
|
118
|
+
const getDefinitionNodeFromCaptures = (captureMap) => {
|
|
119
|
+
for (const key of exports.DEFINITION_CAPTURE_KEYS) {
|
|
120
|
+
if (captureMap[key])
|
|
121
|
+
return captureMap[key];
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
exports.getDefinitionNodeFromCaptures = getDefinitionNodeFromCaptures;
|
|
126
|
+
const nodeRangeKey = (node) => `${node.startPosition.row}:${node.startPosition.column}:${node.endPosition.row}:${node.endPosition.column}`;
|
|
127
|
+
const isConcreteTypedefCapture = (captureMap) => {
|
|
128
|
+
const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
|
|
129
|
+
return (definitionNode?.type === 'type_definition' &&
|
|
130
|
+
(captureMap['definition.struct'] !== undefined || captureMap['definition.enum'] !== undefined));
|
|
131
|
+
};
|
|
132
|
+
const isSuppressedConcreteTypedefDuplicate = (captureMap, concreteTypedefRanges) => {
|
|
133
|
+
const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
|
|
134
|
+
return (definitionNode?.type === 'type_definition' &&
|
|
135
|
+
captureMap['definition.typedef'] !== undefined &&
|
|
136
|
+
concreteTypedefRanges.has(nodeRangeKey(definitionNode)));
|
|
137
|
+
};
|
|
138
|
+
exports.isSuppressedConcreteTypedefDuplicate = isSuppressedConcreteTypedefDuplicate;
|
|
139
|
+
/**
|
|
140
|
+
* Graph labels produced by a value capture (`@definition.const` /
|
|
141
|
+
* `@definition.static` / `@definition.variable`) — a binding that holds a value.
|
|
142
|
+
*
|
|
143
|
+
* `Property` is deliberately NOT here. It outranks these: Python matches both
|
|
144
|
+
* `@definition.property` (annotated) and `@definition.variable` (bare) on one
|
|
145
|
+
* assignment, and the property must win so a typed class attribute keeps its
|
|
146
|
+
* `Property` node and its owning `HAS_PROPERTY` edge. `Property` is instead
|
|
147
|
+
* suppressed only by a *callable* claim — see {@link buildDefinitionNameClaims}.
|
|
148
|
+
*/
|
|
149
|
+
const VALUE_DEFINITION_LABELS = new Set([
|
|
150
|
+
'Const',
|
|
151
|
+
'Static',
|
|
152
|
+
'Variable',
|
|
153
|
+
]);
|
|
154
|
+
/** True when `label` is the kind of node a value capture emits. */
|
|
155
|
+
const isValueDefinitionLabel = (label) => VALUE_DEFINITION_LABELS.has(label);
|
|
156
|
+
exports.isValueDefinitionLabel = isValueDefinitionLabel;
|
|
157
|
+
/**
|
|
158
|
+
* Pre-scan `matches` for the `${definitionNode.startIndex}:${name}` keys already
|
|
159
|
+
* claimed by a higher-ranked definition capture, so the parse-worker's duplicate
|
|
160
|
+
* suppression is order-independent.
|
|
161
|
+
*
|
|
162
|
+
* Rank, highest first: callable (`Function`/`Method`/`Constructor`) → `Property`
|
|
163
|
+
* → value (`Const`/`Static`/`Variable`). A capture is dropped only when a
|
|
164
|
+
* STRICTLY higher rank claimed the same declaration node and name, so no capture
|
|
165
|
+
* can suppress itself and no rank can suppress a peer.
|
|
166
|
+
*
|
|
167
|
+
* ## Why this exists (#2687)
|
|
168
|
+
*
|
|
169
|
+
* `const X = () => {}` matches BOTH `@definition.function` and
|
|
170
|
+
* `@definition.const` on the same `lexical_declaration`. Only one graph node
|
|
171
|
+
* should survive — the `Function`, because that is what `CALLS` edges target.
|
|
172
|
+
* The parse-worker's in-loop dedup intends exactly that, but only the value
|
|
173
|
+
* branch consults its `processedDefinitionNodes` set, so suppression worked only
|
|
174
|
+
* if the function match happened to be processed first. It is not: tree-sitter
|
|
175
|
+
* completes the const pattern at `@name`, while the function pattern must also
|
|
176
|
+
* match the trailing `(arrow_function)` / `(function_expression)` value, so the
|
|
177
|
+
* const match is yielded FIRST and the edgeless `Const:` twin escaped.
|
|
178
|
+
*
|
|
179
|
+
* Consulting this set makes the outcome independent of match order.
|
|
180
|
+
*
|
|
181
|
+
* ## Keying
|
|
182
|
+
*
|
|
183
|
+
* Keys are `startIndex:name`, never `startIndex` alone — a multi-name
|
|
184
|
+
* declaration (`const a = 1, b = () => {}`) shares ONE definition node, and a
|
|
185
|
+
* bare-index key would wrongly suppress `a`'s legitimate `Const` node.
|
|
186
|
+
*
|
|
187
|
+
* Labels come from {@link getLabelFromCaptures}, the same function the main loop
|
|
188
|
+
* uses, so the pre-scan and the loop can never disagree about what counts as a
|
|
189
|
+
* value capture — including when a provider's `labelOverride` reclassifies one.
|
|
190
|
+
* A match that resolves to a value label registers nothing, so a match can never
|
|
191
|
+
* suppress itself.
|
|
192
|
+
*
|
|
193
|
+
* Language-agnostic: keyed off capture names and labels only.
|
|
194
|
+
*
|
|
195
|
+
* Also collects the concrete-typedef ranges that suppress the analogous
|
|
196
|
+
* typedef/struct duplicate, so both suppression sets come from one traversal.
|
|
197
|
+
*/
|
|
198
|
+
const buildDefinitionPreScan = (matches, provider) => {
|
|
199
|
+
const nonValue = new Set();
|
|
200
|
+
const callable = new Set();
|
|
201
|
+
const concreteTypedefRanges = new Set();
|
|
202
|
+
for (const match of matches) {
|
|
203
|
+
// ONE capture-map build per match feeds both suppression sets. These used
|
|
204
|
+
// to be two independent passes over `matches` (each rebuilding this object)
|
|
205
|
+
// on the hot per-file parse path.
|
|
206
|
+
const captureMap = {};
|
|
207
|
+
for (const capture of match.captures) {
|
|
208
|
+
captureMap[capture.name] = capture.node;
|
|
209
|
+
}
|
|
210
|
+
const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
|
|
211
|
+
if (definitionNode === null)
|
|
212
|
+
continue;
|
|
213
|
+
if (isConcreteTypedefCapture(captureMap)) {
|
|
214
|
+
concreteTypedefRanges.add(nodeRangeKey(definitionNode));
|
|
215
|
+
}
|
|
216
|
+
// No `@name` capture means nothing a lower-ranked capture could collide
|
|
217
|
+
// with — a value or property pattern always binds a name. Checked before
|
|
218
|
+
// `getLabelFromCaptures` so a nameless match never pays for label
|
|
219
|
+
// resolution (which can reach a provider's `labelOverride`).
|
|
220
|
+
const nameNode = captureMap['name'];
|
|
221
|
+
if (nameNode === undefined)
|
|
222
|
+
continue;
|
|
223
|
+
const label = getLabelFromCaptures(captureMap, provider);
|
|
224
|
+
if (label === null || (0, exports.isValueDefinitionLabel)(label))
|
|
225
|
+
continue;
|
|
226
|
+
const key = `${definitionNode.startIndex}:${nameNode.text}`;
|
|
227
|
+
nonValue.add(key);
|
|
228
|
+
if ((0, callable_labels_js_1.isOverloadableCallable)(label))
|
|
229
|
+
callable.add(key);
|
|
230
|
+
}
|
|
231
|
+
return { nonValue, callable, concreteTypedefRanges };
|
|
232
|
+
};
|
|
233
|
+
exports.buildDefinitionPreScan = buildDefinitionPreScan;
|
|
234
|
+
/**
|
|
235
|
+
* Node types that represent function/method definitions across languages.
|
|
236
|
+
* Used by parent-walk in call-processor, parse-worker, and type-env to detect
|
|
237
|
+
* enclosing function scope boundaries.
|
|
238
|
+
*
|
|
239
|
+
* INVARIANT: This set MUST be a superset of every language's
|
|
240
|
+
* MethodExtractionConfig.methodNodeTypes. When adding a new node type to a
|
|
241
|
+
* MethodExtractor config, add it here too — otherwise enclosing-function
|
|
242
|
+
* resolution will silently miss that node type during parent-walks.
|
|
243
|
+
*/
|
|
244
|
+
exports.FUNCTION_NODE_TYPES = new Set([
|
|
245
|
+
// TypeScript/JavaScript
|
|
246
|
+
'function_declaration',
|
|
247
|
+
'arrow_function',
|
|
248
|
+
'function_expression',
|
|
249
|
+
'method_definition',
|
|
250
|
+
'generator_function_declaration',
|
|
251
|
+
// Python
|
|
252
|
+
'function_definition',
|
|
253
|
+
// Common async variants
|
|
254
|
+
'async_function_declaration',
|
|
255
|
+
'async_arrow_function',
|
|
256
|
+
// Java
|
|
257
|
+
'method_declaration',
|
|
258
|
+
'constructor_declaration',
|
|
259
|
+
'compact_constructor_declaration',
|
|
260
|
+
'annotation_type_element_declaration',
|
|
261
|
+
// C/C++
|
|
262
|
+
// 'function_definition' already included above
|
|
263
|
+
// Go
|
|
264
|
+
// 'method_declaration' already included from Java
|
|
265
|
+
// C#
|
|
266
|
+
'local_function_statement',
|
|
267
|
+
// Rust
|
|
268
|
+
'function_item',
|
|
269
|
+
'impl_item', // Methods inside impl blocks
|
|
270
|
+
// PHP
|
|
271
|
+
'anonymous_function',
|
|
272
|
+
// Kotlin
|
|
273
|
+
'lambda_literal',
|
|
274
|
+
'secondary_constructor', // F48: methodNodeTypes superset invariant
|
|
275
|
+
// Swift
|
|
276
|
+
'init_declaration',
|
|
277
|
+
'deinit_declaration',
|
|
278
|
+
// Ruby
|
|
279
|
+
'method', // def foo
|
|
280
|
+
'singleton_method', // def self.foo
|
|
281
|
+
// Dart
|
|
282
|
+
'function_signature',
|
|
283
|
+
'method_signature',
|
|
284
|
+
]);
|
|
285
|
+
/**
|
|
286
|
+
* AST node types that represent a class-like container (for HAS_METHOD edge extraction).
|
|
287
|
+
*
|
|
288
|
+
* INVARIANT: When a language config adds a new node type to `typeDeclarationNodes`,
|
|
289
|
+
* that type must also be added here AND to `CONTAINER_TYPE_TO_LABEL` below,
|
|
290
|
+
* otherwise `findEnclosingClassNode` won't recognize it and methods may get
|
|
291
|
+
* orphaned HAS_METHOD edges or incorrect labels.
|
|
292
|
+
*/
|
|
293
|
+
exports.CLASS_CONTAINER_TYPES = new Set([
|
|
294
|
+
'class_declaration',
|
|
295
|
+
'abstract_class_declaration',
|
|
296
|
+
'interface_declaration',
|
|
297
|
+
'struct_declaration',
|
|
298
|
+
'record_declaration',
|
|
299
|
+
'class_specifier',
|
|
300
|
+
'struct_specifier',
|
|
301
|
+
'impl_item',
|
|
302
|
+
'trait_item',
|
|
303
|
+
'struct_item',
|
|
304
|
+
'enum_item',
|
|
305
|
+
'class_definition',
|
|
306
|
+
'trait_declaration',
|
|
307
|
+
// PHP
|
|
308
|
+
'enum_declaration',
|
|
309
|
+
'protocol_declaration',
|
|
310
|
+
// Dart
|
|
311
|
+
'mixin_declaration',
|
|
312
|
+
'extension_declaration',
|
|
313
|
+
// Ruby
|
|
314
|
+
'class',
|
|
315
|
+
'module',
|
|
316
|
+
'singleton_class', // Ruby: class << self
|
|
317
|
+
// Kotlin
|
|
318
|
+
'object_declaration',
|
|
319
|
+
'companion_object',
|
|
320
|
+
// Go
|
|
321
|
+
'struct_type',
|
|
322
|
+
'interface_type',
|
|
323
|
+
]);
|
|
324
|
+
/**
|
|
325
|
+
* Node types whose OWN node id must not be re-keyed by an enclosing-scope
|
|
326
|
+
* qualifier (see {@link qualifyByEnclosingModScope}) unless the owner-edge
|
|
327
|
+
* anchor moves in the same change.
|
|
328
|
+
*
|
|
329
|
+
* These are the containers a member can be declared inside. Their members'
|
|
330
|
+
* `HAS_METHOD` / `HAS_PROPERTY` edges anchor on `findEnclosingClassInfo().classId`,
|
|
331
|
+
* which is minted from the container's bare `nameNode.text` further down this
|
|
332
|
+
* file and only follows a qualified shape when the provider opts in via
|
|
333
|
+
* `classExtractor.qualifiedNodeId`. So qualifying a container's id alone points
|
|
334
|
+
* every one of its member edges at a node that does not exist — the edges are
|
|
335
|
+
* dropped at COPY time and the container silently loses all its members.
|
|
336
|
+
*
|
|
337
|
+
* Derived from `CLASS_CONTAINER_TYPES` on purpose: that set is already the
|
|
338
|
+
* single source of "this node type owns member edges", carries the INVARIANT
|
|
339
|
+
* note above binding it to `CONTAINER_TYPE_TO_LABEL`, and so a language adding
|
|
340
|
+
* a container cannot gain a mismatched id shape here without also failing that
|
|
341
|
+
* invariant. Keyed purely on tree-sitter node types — no language names.
|
|
342
|
+
*/
|
|
343
|
+
exports.MEMBER_OWNER_NODE_TYPES = new Set([
|
|
344
|
+
...exports.CLASS_CONTAINER_TYPES,
|
|
345
|
+
// Rust `union_item` owns a `field_declaration_list` exactly as `struct_item`
|
|
346
|
+
// does, and its fields ARE captured as `Property`, but it is absent from
|
|
347
|
+
// `CLASS_CONTAINER_TYPES`, so `findEnclosingClassInfo` does not recognize it as
|
|
348
|
+
// an owner: union fields carry no `HAS_PROPERTY` edge at all and therefore
|
|
349
|
+
// cannot dangle. Listed here so the union's own id keeps the same shape as the
|
|
350
|
+
// struct beside it, and so making it a real owner later starts from a
|
|
351
|
+
// consistent id rather than having to move one.
|
|
352
|
+
'union_item',
|
|
353
|
+
]);
|
|
354
|
+
exports.CONTAINER_TYPE_TO_LABEL = {
|
|
355
|
+
class_declaration: 'Class',
|
|
356
|
+
abstract_class_declaration: 'Class',
|
|
357
|
+
interface_declaration: 'Interface',
|
|
358
|
+
struct_declaration: 'Struct',
|
|
359
|
+
struct_specifier: 'Struct',
|
|
360
|
+
class_specifier: 'Class',
|
|
361
|
+
class_definition: 'Class',
|
|
362
|
+
impl_item: 'Impl',
|
|
363
|
+
trait_item: 'Trait',
|
|
364
|
+
struct_item: 'Struct',
|
|
365
|
+
enum_item: 'Enum',
|
|
366
|
+
trait_declaration: 'Trait',
|
|
367
|
+
enum_declaration: 'Enum',
|
|
368
|
+
record_declaration: 'Record',
|
|
369
|
+
protocol_declaration: 'Interface',
|
|
370
|
+
mixin_declaration: 'Mixin',
|
|
371
|
+
extension_declaration: 'Class',
|
|
372
|
+
class: 'Class',
|
|
373
|
+
// Ruby `module` declarations map to `Trait` so they participate in the
|
|
374
|
+
// class-like type registry used by `lookupClassByName` / inheritance
|
|
375
|
+
// resolution. This lets `include` / `extend` / `prepend` mixin heritage
|
|
376
|
+
// resolve to the providing module. Safe for non-Ruby languages: the only supported
|
|
377
|
+
// grammar that uses the bare `module` AST node type as a container is
|
|
378
|
+
// Ruby (Rust uses `mod_item`). Any new language adding a `module` node
|
|
379
|
+
// type must explicitly reclassify here.
|
|
380
|
+
module: 'Trait',
|
|
381
|
+
singleton_class: 'Class', // Ruby: class << self inherits enclosing class name
|
|
382
|
+
object_declaration: 'Class',
|
|
383
|
+
companion_object: 'Class',
|
|
384
|
+
struct_type: 'Struct',
|
|
385
|
+
interface_type: 'Interface',
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Pre-order walk over a node and all its named descendants, invoking `cb` on
|
|
389
|
+
* each. Replaces the per-language `visit`/`visitGo`/`visitRust`/`visitSwift`
|
|
390
|
+
* clones that every language's capture-synthesis walker re-implemented (#1956
|
|
391
|
+
* tri-review U6).
|
|
392
|
+
*
|
|
393
|
+
* Iterates by index with a null guard: `node.namedChild(i)` is typed
|
|
394
|
+
* `SyntaxNode | null`, and most callers already guarded it. The Go and C#
|
|
395
|
+
* callers previously iterated `node.namedChildren`; the Go one had no null
|
|
396
|
+
* guard, so this standardizes them onto the guarded indexed form — a deliberate,
|
|
397
|
+
* strictly-safer behavior addition (the traversal *sequence* is identical, so
|
|
398
|
+
* capture output stays byte-identical on well-formed trees; the guard only
|
|
399
|
+
* matters for a null named child, which the fixture corpus never produces).
|
|
400
|
+
*/
|
|
401
|
+
function walkNamedTree(node, cb) {
|
|
402
|
+
cb(node);
|
|
403
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
404
|
+
const child = node.namedChild(i);
|
|
405
|
+
if (child !== null)
|
|
406
|
+
walkNamedTree(child, cb);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/** Return the first matching ancestor unless a boundary ancestor is reached first. */
|
|
410
|
+
function findAncestorBeforeBoundary(node, targetTypes, boundaryTypes) {
|
|
411
|
+
let current = node.parent;
|
|
412
|
+
while (current !== null) {
|
|
413
|
+
if (boundaryTypes.has(current.type))
|
|
414
|
+
return null;
|
|
415
|
+
if (targetTypes.has(current.type))
|
|
416
|
+
return current;
|
|
417
|
+
current = current.parent;
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Enclosing callable for grammars that split a callable into a SIGNATURE node
|
|
423
|
+
* and a SIBLING body, where the callable is therefore never an ancestor of the
|
|
424
|
+
* code inside it.
|
|
425
|
+
*
|
|
426
|
+
* Dart is the case that forced this: `int outer() { … }` parses as
|
|
427
|
+
* `function_signature` followed by `function_body` as SIBLINGS, so an ancestor
|
|
428
|
+
* walk from a closure inside the body can never reach `outer`. No membership
|
|
429
|
+
* set fixes that — the walk is looking in the wrong direction (#2699).
|
|
430
|
+
*
|
|
431
|
+
* Deliberately a FALLBACK, used only when the ancestor walk found nothing.
|
|
432
|
+
*
|
|
433
|
+
* The sibling must be a BARE SIGNATURE, and that restriction is load-bearing —
|
|
434
|
+
* "any preceding callable sibling" is WRONG and was caught regressing PHP. In
|
|
435
|
+
* `<?php function target($x) {…} $handler = function ($x) {…};` the closure is
|
|
436
|
+
* at FILE level, so the primary ancestor walk correctly finds nothing and this
|
|
437
|
+
* fallback runs; an unrestricted version then grabs the preceding
|
|
438
|
+
* `function_definition` and mis-qualifies the file-level `$handler` as
|
|
439
|
+
* `target.$handler`. A preceding sibling is only an ENCLOSING callable when it
|
|
440
|
+
* cannot hold its own body — i.e. when the grammar split the body off.
|
|
441
|
+
*
|
|
442
|
+
* `SPLIT_SIGNATURE_NODE_TYPES` is exactly that set, and it is derived rather
|
|
443
|
+
* than listed: `LOCAL_SCOPE_BODY_NODE_TYPES` already filters the bare-signature
|
|
444
|
+
* types out of `FUNCTION_NODE_TYPES`, so the difference between them IS the
|
|
445
|
+
* split-signature set. PHP's `function_definition` carries a body and is in
|
|
446
|
+
* both, so it is excluded; Dart's `function_signature` is in only the former,
|
|
447
|
+
* so it qualifies.
|
|
448
|
+
*
|
|
449
|
+
* Language-neutral by construction — it names no grammar, and any future
|
|
450
|
+
* signature/body-split language is covered for free.
|
|
451
|
+
*/
|
|
452
|
+
function findSplitBodyCallableAncestor(node, signatureOnlyTypes, boundaryTypes) {
|
|
453
|
+
let current = node.parent;
|
|
454
|
+
while (current !== null) {
|
|
455
|
+
if (boundaryTypes.has(current.type))
|
|
456
|
+
return null;
|
|
457
|
+
const prev = current.previousNamedSibling;
|
|
458
|
+
if (prev !== null &&
|
|
459
|
+
signatureOnlyTypes.has(prev.type) &&
|
|
460
|
+
// `current` must be the signature's BODY, not merely the next thing after
|
|
461
|
+
// it. Without this, valid TypeScript trips the fallback: in
|
|
462
|
+
// declare namespace Api {
|
|
463
|
+
// function internalHelper(x): number;
|
|
464
|
+
// export function send(x): number;
|
|
465
|
+
// }
|
|
466
|
+
// `send`'s `export_statement` is the next sibling of `internalHelper`'s
|
|
467
|
+
// `function_signature`, so `send` was mis-qualified as
|
|
468
|
+
// `internalHelper.send@r:c`. TypeScript emits bodyless
|
|
469
|
+
// function_signature/method_signature for overloads and ambient
|
|
470
|
+
// declarations, so the split-signature set is NOT Dart-only.
|
|
471
|
+
//
|
|
472
|
+
// A body contains statements; a declaration wrapper contains another
|
|
473
|
+
// signature. Rejecting any `current` that directly holds a signature of
|
|
474
|
+
// its own separates the two without naming a grammar.
|
|
475
|
+
!current.namedChildren.some((child) => signatureOnlyTypes.has(child.type))) {
|
|
476
|
+
return prev;
|
|
477
|
+
}
|
|
478
|
+
current = current.parent;
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
// SPLIT_SIGNATURE_NODE_TYPES is defined next to LOCAL_SCOPE_BODY_NODE_TYPES,
|
|
483
|
+
// which it derives from — declaring it here would read it in its temporal dead
|
|
484
|
+
// zone and throw at module load (tsc does NOT catch that; only running does).
|
|
485
|
+
/**
|
|
486
|
+
* Determine the graph node label from a tree-sitter capture map.
|
|
487
|
+
* Handles language-specific reclassification via the provider's labelOverride hook
|
|
488
|
+
* (e.g. C/C++ duplicate skipping, Kotlin Method promotion).
|
|
489
|
+
* Returns null if the capture should be skipped (import, call, C/C++ duplicate, missing name).
|
|
490
|
+
*/
|
|
491
|
+
function getLabelFromCaptures(captureMap, provider) {
|
|
492
|
+
if (captureMap['import'] || captureMap['call'])
|
|
493
|
+
return null;
|
|
494
|
+
const hasDefaultExportHocNameSeed = captureMap['definition.function'] !== undefined &&
|
|
495
|
+
(captureMap['hoc'] !== undefined || captureMap['callee'] !== undefined);
|
|
496
|
+
// Nameless `definition.class` passes through: a class extractor may
|
|
497
|
+
// synthesize the name (Java anonymous class bodies → `Worker$N`, #2550).
|
|
498
|
+
// Downstream stays safe — parse-worker skips any nameless definition the
|
|
499
|
+
// extractor could not name (its `!nameNode && !extractedClassSymbol` gate).
|
|
500
|
+
if (!captureMap['name'] &&
|
|
501
|
+
!captureMap['definition.constructor'] &&
|
|
502
|
+
!captureMap['definition.class'] &&
|
|
503
|
+
!hasDefaultExportHocNameSeed)
|
|
504
|
+
return null;
|
|
505
|
+
if (captureMap['definition.function']) {
|
|
506
|
+
if (provider.labelOverride) {
|
|
507
|
+
const override = provider.labelOverride(captureMap['definition.function'], 'Function');
|
|
508
|
+
if (override !== 'Function')
|
|
509
|
+
return override;
|
|
510
|
+
}
|
|
511
|
+
return 'Function';
|
|
512
|
+
}
|
|
513
|
+
if (captureMap['definition.class'])
|
|
514
|
+
return 'Class';
|
|
515
|
+
if (captureMap['definition.interface'])
|
|
516
|
+
return 'Interface';
|
|
517
|
+
if (captureMap['definition.method'])
|
|
518
|
+
return 'Method';
|
|
519
|
+
if (captureMap['definition.struct'])
|
|
520
|
+
return 'Struct';
|
|
521
|
+
if (captureMap['definition.enum'])
|
|
522
|
+
return 'Enum';
|
|
523
|
+
if (captureMap['definition.namespace'])
|
|
524
|
+
return 'Namespace';
|
|
525
|
+
if (captureMap['definition.module']) {
|
|
526
|
+
// Let providers reclassify module captures (e.g. Ruby remaps `Module`→`Trait`
|
|
527
|
+
// so mixin heritage resolves through `lookupClassByName`). Returning null
|
|
528
|
+
// from labelOverride means "skip this symbol"; treat it as a no-op here so
|
|
529
|
+
// we keep the default label rather than dropping a real definition.
|
|
530
|
+
if (provider.labelOverride) {
|
|
531
|
+
const override = provider.labelOverride(captureMap['definition.module'], 'Module');
|
|
532
|
+
if (override && override !== 'Module')
|
|
533
|
+
return override;
|
|
534
|
+
}
|
|
535
|
+
return 'Module';
|
|
536
|
+
}
|
|
537
|
+
if (captureMap['definition.trait'])
|
|
538
|
+
return 'Trait';
|
|
539
|
+
if (captureMap['definition.impl'])
|
|
540
|
+
return 'Impl';
|
|
541
|
+
if (captureMap['definition.type'])
|
|
542
|
+
return 'TypeAlias';
|
|
543
|
+
if (captureMap['definition.const'])
|
|
544
|
+
return 'Const';
|
|
545
|
+
if (captureMap['definition.static'])
|
|
546
|
+
return 'Static';
|
|
547
|
+
if (captureMap['definition.variable'])
|
|
548
|
+
return 'Variable';
|
|
549
|
+
if (captureMap['definition.typedef'])
|
|
550
|
+
return 'Typedef';
|
|
551
|
+
if (captureMap['definition.macro'])
|
|
552
|
+
return 'Macro';
|
|
553
|
+
if (captureMap['definition.union'])
|
|
554
|
+
return 'Union';
|
|
555
|
+
if (captureMap['definition.property'])
|
|
556
|
+
return 'Property';
|
|
557
|
+
if (captureMap['definition.record'])
|
|
558
|
+
return 'Record';
|
|
559
|
+
if (captureMap['definition.delegate'])
|
|
560
|
+
return 'Delegate';
|
|
561
|
+
if (captureMap['definition.annotation'])
|
|
562
|
+
return 'Annotation';
|
|
563
|
+
if (captureMap['definition.constructor'])
|
|
564
|
+
return 'Constructor';
|
|
565
|
+
if (captureMap['definition.template'])
|
|
566
|
+
return 'Template';
|
|
567
|
+
return 'CodeElement';
|
|
568
|
+
}
|
|
569
|
+
/** Walk up AST to find enclosing class/struct/interface/impl, return its ID and name.
|
|
570
|
+
* For Go method_declaration nodes, extracts receiver type (e.g. `func (u *User) Save()` → User struct).
|
|
571
|
+
*
|
|
572
|
+
* @param resolveEnclosingOwner Optional language-specific hook for container remapping.
|
|
573
|
+
* When provided and a CLASS_CONTAINER_TYPES node is found, this hook is called:
|
|
574
|
+
* - Return a different SyntaxNode to remap the container (e.g., Ruby singleton_class → class).
|
|
575
|
+
* - Return `null` to skip this container and keep walking up.
|
|
576
|
+
* - Return the input node (identity) to use the container as-is.
|
|
577
|
+
* When omitted, the container node is used as-is.
|
|
578
|
+
*
|
|
579
|
+
* INVARIANT: Implementers SHOULD return either `null`, the input node, or
|
|
580
|
+
* another CLASS_CONTAINER_TYPES node. Returning a non-container node is
|
|
581
|
+
* permitted but discouraged — it will cause the walk to skip the current
|
|
582
|
+
* container and continue from the redirected node's parent. The
|
|
583
|
+
* `MAX_ENCLOSING_WALK_ITERATIONS` defense-in-depth guard below prevents
|
|
584
|
+
* pathological hooks from creating an infinite loop. */
|
|
585
|
+
const MAX_ENCLOSING_WALK_ITERATIONS = 4096;
|
|
586
|
+
/** Named Java declarations that can host, or themselves be, local types. */
|
|
587
|
+
const JAVA_NAMED_TYPE_NODE_LABELS = new Map([
|
|
588
|
+
['class_declaration', 'Class'],
|
|
589
|
+
['enum_declaration', 'Enum'],
|
|
590
|
+
['interface_declaration', 'Interface'],
|
|
591
|
+
['record_declaration', 'Record'],
|
|
592
|
+
]);
|
|
593
|
+
const JAVA_ANON_HOST_TYPES = new Set(JAVA_NAMED_TYPE_NODE_LABELS.keys());
|
|
594
|
+
const JAVA_LOCAL_TYPE_CONTAINERS = new Set([
|
|
595
|
+
'block',
|
|
596
|
+
'constructor_body',
|
|
597
|
+
'switch_block_statement_group',
|
|
598
|
+
]);
|
|
599
|
+
/** A legal local type declaration is a class, enum, record, or interface
|
|
600
|
+
* directly occupying a block-statement position. Annotation interfaces are
|
|
601
|
+
* deliberately excluded: javac rejects local annotation declarations. */
|
|
602
|
+
const javaLocalTypeDeclarationContainer = (node) => {
|
|
603
|
+
if (!JAVA_NAMED_TYPE_NODE_LABELS.has(node.type))
|
|
604
|
+
return null;
|
|
605
|
+
const parent = node.parent;
|
|
606
|
+
return parent !== null && JAVA_LOCAL_TYPE_CONTAINERS.has(parent.type) ? parent : null;
|
|
607
|
+
};
|
|
608
|
+
exports.javaLocalTypeDeclarationContainer = javaLocalTypeDeclarationContainer;
|
|
609
|
+
const isJavaLocalTypeNode = (node) => (0, exports.javaLocalTypeDeclarationContainer)(node) !== null;
|
|
610
|
+
/** The two Java anonymous-class-body shapes (#2550/#2555): an
|
|
611
|
+
* `object_creation_expression` with a `class_body` child
|
|
612
|
+
* (`new Runnable() { ... }`), and an `enum_constant` with a `body:`
|
|
613
|
+
* field (`enum E { A { ... } }` — javac's other `E$N` shape). */
|
|
614
|
+
const isJavaAnonymousBodyNode = (node) => (node.type === 'object_creation_expression' &&
|
|
615
|
+
node.namedChildren?.some((c) => c.type === 'class_body') === true) ||
|
|
616
|
+
(node.type === 'enum_constant' && node.childForFieldName?.('body')?.type === 'class_body');
|
|
617
|
+
/** Nearest ancestor of `node` that is an enclosing type per JLS 13.1. */
|
|
618
|
+
const nearestJavaEnclosingType = (node) => {
|
|
619
|
+
let cursor = node.parent;
|
|
620
|
+
let iterations = 0;
|
|
621
|
+
while (cursor) {
|
|
622
|
+
if (++iterations > MAX_ENCLOSING_WALK_ITERATIONS)
|
|
623
|
+
return null;
|
|
624
|
+
if (JAVA_ANON_HOST_TYPES.has(cursor.type) || isJavaAnonymousBodyNode(cursor))
|
|
625
|
+
return cursor;
|
|
626
|
+
cursor = cursor.parent;
|
|
627
|
+
}
|
|
628
|
+
return null;
|
|
629
|
+
};
|
|
630
|
+
/** Parse-tree-bounded memo. Sequence ordinals are built once per tree, avoiding
|
|
631
|
+
* a host-candidate scan for every extraction/ownership consumer. */
|
|
632
|
+
const javaTypeIdentityMemo = new WeakMap();
|
|
633
|
+
const javaHostKey = (node) => `${node.type}:${node.startIndex}`;
|
|
634
|
+
const javaIdentityCandidatesBelow = (root) => {
|
|
635
|
+
const seen = new Set();
|
|
636
|
+
const candidates = [];
|
|
637
|
+
for (const type of [
|
|
638
|
+
'object_creation_expression',
|
|
639
|
+
'enum_constant',
|
|
640
|
+
...JAVA_NAMED_TYPE_NODE_LABELS.keys(),
|
|
641
|
+
]) {
|
|
642
|
+
for (const candidate of root.descendantsOfType?.(type) ?? []) {
|
|
643
|
+
if (!isJavaAnonymousBodyNode(candidate) && !isJavaLocalTypeNode(candidate))
|
|
644
|
+
continue;
|
|
645
|
+
const key = javaHostKey(candidate);
|
|
646
|
+
if (seen.has(key))
|
|
647
|
+
continue;
|
|
648
|
+
seen.add(key);
|
|
649
|
+
candidates.push(candidate);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return candidates.sort((left, right) => left.startIndex - right.startIndex);
|
|
653
|
+
};
|
|
654
|
+
const buildJavaTypeIdentityState = (root) => {
|
|
655
|
+
const ordinalByStart = new Map();
|
|
656
|
+
const sequenceCounts = new Map();
|
|
657
|
+
for (const candidate of javaIdentityCandidatesBelow(root)) {
|
|
658
|
+
const host = nearestJavaEnclosingType(candidate);
|
|
659
|
+
if (host === null)
|
|
660
|
+
continue;
|
|
661
|
+
const isAnonymous = isJavaAnonymousBodyNode(candidate);
|
|
662
|
+
const bindingName = isAnonymous ? '' : candidate.childForFieldName?.('name')?.text;
|
|
663
|
+
// Anonymous types deliberately use the empty sequence key; malformed named
|
|
664
|
+
// declarations must not enter that sequence.
|
|
665
|
+
if (!isAnonymous && !bindingName)
|
|
666
|
+
continue;
|
|
667
|
+
const sequenceKey = `${javaHostKey(host)}:${bindingName}`;
|
|
668
|
+
const ordinal = (sequenceCounts.get(sequenceKey) ?? 0) + 1;
|
|
669
|
+
sequenceCounts.set(sequenceKey, ordinal);
|
|
670
|
+
ordinalByStart.set(candidate.startIndex, ordinal);
|
|
671
|
+
}
|
|
672
|
+
return { byStart: new Map(), ordinalByStart };
|
|
673
|
+
};
|
|
674
|
+
const javaTypeIdentityStateFor = (node) => {
|
|
675
|
+
const tree = node.tree;
|
|
676
|
+
if (tree === undefined) {
|
|
677
|
+
const host = nearestJavaEnclosingType(node);
|
|
678
|
+
return buildJavaTypeIdentityState(host ?? node);
|
|
679
|
+
}
|
|
680
|
+
let state = javaTypeIdentityMemo.get(tree);
|
|
681
|
+
if (state === undefined) {
|
|
682
|
+
state = buildJavaTypeIdentityState(tree.rootNode ?? node);
|
|
683
|
+
javaTypeIdentityMemo.set(tree, state);
|
|
684
|
+
}
|
|
685
|
+
return state;
|
|
686
|
+
};
|
|
687
|
+
/** Source-type-relative binary name of a Java enclosing type, including
|
|
688
|
+
* synthesized local/anonymous hosts and named member-type chains. */
|
|
689
|
+
const javaBinaryNameOfType = (node) => {
|
|
690
|
+
if (isJavaAnonymousBodyNode(node) || isJavaLocalTypeNode(node)) {
|
|
691
|
+
return (0, exports.synthesizeJavaTypeIdentity)(node)?.name;
|
|
692
|
+
}
|
|
693
|
+
if (!JAVA_ANON_HOST_TYPES.has(node.type))
|
|
694
|
+
return undefined;
|
|
695
|
+
const simpleName = node.childForFieldName?.('name')?.text;
|
|
696
|
+
if (simpleName === undefined || simpleName.length === 0)
|
|
697
|
+
return undefined;
|
|
698
|
+
const enclosing = nearestJavaEnclosingType(node);
|
|
699
|
+
if (enclosing === null)
|
|
700
|
+
return simpleName;
|
|
701
|
+
const enclosingName = javaBinaryNameOfType(enclosing);
|
|
702
|
+
return enclosingName === undefined ? undefined : `${enclosingName}$${simpleName}`;
|
|
703
|
+
};
|
|
704
|
+
/**
|
|
705
|
+
* Authoritative Java local/anonymous type identity.
|
|
706
|
+
*
|
|
707
|
+
* JLS 13.1 defines the shape and immediate-host prefix. OpenJDK javac's
|
|
708
|
+
* Check.localClassName allocates N independently for each
|
|
709
|
+
* (enclosing binary name, local simple name) pair; anonymous types use the
|
|
710
|
+
* empty simple name and therefore have their own sequence. Package names are
|
|
711
|
+
* omitted from this project identity because graph ids already include the
|
|
712
|
+
* file path.
|
|
713
|
+
*/
|
|
714
|
+
const synthesizeJavaTypeIdentity = (node) => {
|
|
715
|
+
const localLabel = JAVA_NAMED_TYPE_NODE_LABELS.get(node.type);
|
|
716
|
+
const isLocal = localLabel !== undefined && isJavaLocalTypeNode(node);
|
|
717
|
+
const isAnonymous = isJavaAnonymousBodyNode(node);
|
|
718
|
+
const enclosing = nearestJavaEnclosingType(node);
|
|
719
|
+
const memberSimpleName = !isLocal && !isAnonymous && localLabel !== undefined
|
|
720
|
+
? node.childForFieldName?.('name')?.text
|
|
721
|
+
: undefined;
|
|
722
|
+
const synthesizedHostIdentity = memberSimpleName !== undefined && enclosing !== null
|
|
723
|
+
? (0, exports.synthesizeJavaTypeIdentity)(enclosing)
|
|
724
|
+
: undefined;
|
|
725
|
+
if (!isLocal && !isAnonymous && synthesizedHostIdentity === undefined)
|
|
726
|
+
return undefined;
|
|
727
|
+
if (enclosing === null)
|
|
728
|
+
return undefined;
|
|
729
|
+
const state = javaTypeIdentityStateFor(node);
|
|
730
|
+
const cached = state.byStart.get(node.startIndex);
|
|
731
|
+
if (cached !== undefined)
|
|
732
|
+
return cached;
|
|
733
|
+
const prefix = javaBinaryNameOfType(enclosing);
|
|
734
|
+
if (prefix === undefined)
|
|
735
|
+
return undefined;
|
|
736
|
+
if (memberSimpleName !== undefined) {
|
|
737
|
+
const identity = {
|
|
738
|
+
name: `${prefix}$${memberSimpleName}`,
|
|
739
|
+
label: localLabel,
|
|
740
|
+
bindingName: memberSimpleName,
|
|
741
|
+
};
|
|
742
|
+
state.byStart.set(node.startIndex, identity);
|
|
743
|
+
return identity;
|
|
744
|
+
}
|
|
745
|
+
const bindingName = isLocal ? node.childForFieldName?.('name')?.text : undefined;
|
|
746
|
+
if (isLocal && !bindingName)
|
|
747
|
+
return undefined;
|
|
748
|
+
const ordinal = state.ordinalByStart.get(node.startIndex);
|
|
749
|
+
if (ordinal === undefined)
|
|
750
|
+
return undefined;
|
|
751
|
+
const identity = {
|
|
752
|
+
name: `${prefix}$${ordinal}${bindingName ?? ''}`,
|
|
753
|
+
label: isAnonymous ? 'Class' : localLabel,
|
|
754
|
+
...(bindingName === undefined ? {} : { bindingName }),
|
|
755
|
+
};
|
|
756
|
+
state.byStart.set(node.startIndex, identity);
|
|
757
|
+
return identity;
|
|
758
|
+
};
|
|
759
|
+
exports.synthesizeJavaTypeIdentity = synthesizeJavaTypeIdentity;
|
|
760
|
+
const findEnclosingClassInfo = (node, filePath, resolveEnclosingOwner,
|
|
761
|
+
/**
|
|
762
|
+
* Optional (#1978): returns the enclosing type's fully-qualified name
|
|
763
|
+
* (e.g. "Outer.Inner") for a type-declaration container, or null. Callers
|
|
764
|
+
* pass `classExtractor.extractQualifiedName` ONLY when the language's
|
|
765
|
+
* `qualifiedNodeId` flag is on — so when omitted, behavior is byte-identical
|
|
766
|
+
* to before (qualifiedClassId stays undefined). Used by the standard
|
|
767
|
+
* class-container branch to compute `qualifiedClassId` from the SAME function
|
|
768
|
+
* the node-id is built from, guaranteeing owner-id == node-id by construction.
|
|
769
|
+
*/
|
|
770
|
+
getQualifiedOwnerName) => {
|
|
771
|
+
let current = node.parent;
|
|
772
|
+
let iterations = 0;
|
|
773
|
+
// Tracks container nodes already visited via the hook so a misbehaving hook
|
|
774
|
+
// that keeps redirecting back to the same container cannot loop forever.
|
|
775
|
+
const visitedContainers = new Set();
|
|
776
|
+
while (current) {
|
|
777
|
+
if (++iterations > MAX_ENCLOSING_WALK_ITERATIONS) {
|
|
778
|
+
// Defense-in-depth: a real source tree has nowhere near this many ancestors.
|
|
779
|
+
// Bail out rather than hang ingestion.
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
// Go: method_declaration has a receiver parameter with the struct type
|
|
783
|
+
if (current.type === 'method_declaration') {
|
|
784
|
+
const receiver = current.childForFieldName?.('receiver');
|
|
785
|
+
if (receiver) {
|
|
786
|
+
const paramDecl = receiver.namedChildren?.find?.((c) => c.type === 'parameter_declaration');
|
|
787
|
+
if (paramDecl) {
|
|
788
|
+
const typeNode = paramDecl.childForFieldName?.('type');
|
|
789
|
+
if (typeNode) {
|
|
790
|
+
const inner = typeNode.type === 'pointer_type' ? typeNode.firstNamedChild : typeNode;
|
|
791
|
+
if (inner && (inner.type === 'type_identifier' || inner.type === 'identifier')) {
|
|
792
|
+
return {
|
|
793
|
+
classId: (0, utils_js_1.generateId)('Struct', `${filePath}:${inner.text}`),
|
|
794
|
+
className: inner.text,
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
// Go: the `type_spec` IS the declared type (`type User struct { ... }`, and
|
|
802
|
+
// one per member of a grouped `type ( A struct{…}; B struct{…} )` block).
|
|
803
|
+
//
|
|
804
|
+
// Matched here rather than on the enclosing `type_declaration` (#2837): this
|
|
805
|
+
// walk climbs `node.parent`, so it passes THROUGH the containing spec on its
|
|
806
|
+
// way up from any member, and the structure it already has is the answer.
|
|
807
|
+
// Keying on the wrapper instead meant picking one spec out of several with
|
|
808
|
+
// no reference point — which filed every member of a grouped block under its
|
|
809
|
+
// FIRST struct, so two same-named fields minted one id and first-write-wins
|
|
810
|
+
// dropped the second.
|
|
811
|
+
if (current.type === 'type_spec') {
|
|
812
|
+
const typeBody = current.childForFieldName?.('type');
|
|
813
|
+
if (typeBody?.type === 'struct_type' || typeBody?.type === 'interface_type') {
|
|
814
|
+
const nameNode = current.childForFieldName?.('name');
|
|
815
|
+
if (nameNode) {
|
|
816
|
+
const label = typeBody.type === 'struct_type' ? 'Struct' : 'Interface';
|
|
817
|
+
return {
|
|
818
|
+
classId: (0, utils_js_1.generateId)(label, `${filePath}:${nameNode.text}`),
|
|
819
|
+
className: nameNode.text,
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
// Java: an anonymous class body owns its members — attribute to the
|
|
825
|
+
// synthesized `Worker$N`/`E$N` class, not the lexically enclosing
|
|
826
|
+
// named type (#2550/#2555). Covers both shapes: `new Runnable() { ... }`
|
|
827
|
+
// and enum constant bodies (`enum E { A { ... } }`). The synthesis
|
|
828
|
+
// returns undefined for shape-less nodes (plain `new Foo()`, a body-less
|
|
829
|
+
// enum constant, and every C# `object_creation_expression`), so the
|
|
830
|
+
// walk continues unchanged for those — including on to
|
|
831
|
+
// `enum_declaration`, which sits in CLASS_CONTAINER_TYPES below.
|
|
832
|
+
if (isJavaAnonymousBodyNode(current) || JAVA_ANON_HOST_TYPES.has(current.type)) {
|
|
833
|
+
const identity = (0, exports.synthesizeJavaTypeIdentity)(current);
|
|
834
|
+
if (identity !== undefined) {
|
|
835
|
+
return {
|
|
836
|
+
classId: (0, utils_js_1.generateId)(identity.label, `${filePath}:${identity.name}`),
|
|
837
|
+
className: identity.name,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (exports.CLASS_CONTAINER_TYPES.has(current.type)) {
|
|
842
|
+
// Delegate language-specific container remapping to the provider hook.
|
|
843
|
+
if (resolveEnclosingOwner) {
|
|
844
|
+
if (visitedContainers.has(current)) {
|
|
845
|
+
// We've already asked the hook about this container once — a loop
|
|
846
|
+
// would form (e.g., hook redirects to a child node whose parent is
|
|
847
|
+
// this same container). Skip and walk up.
|
|
848
|
+
current = current.parent;
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
visitedContainers.add(current);
|
|
852
|
+
const resolved = resolveEnclosingOwner(current);
|
|
853
|
+
if (resolved === null) {
|
|
854
|
+
// Provider says skip this container — keep walking up.
|
|
855
|
+
current = current.parent;
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
if (resolved !== current) {
|
|
859
|
+
// Provider remapped to a different node — re-evaluate from there.
|
|
860
|
+
current = resolved;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
// Rust impl_item: for `impl Trait for Struct {}`, pick the type after `for`
|
|
865
|
+
// NOTE: This impl_item ownership logic is mirrored in
|
|
866
|
+
// method-extractors/configs/rust.ts (extractOwnerName, metadata only).
|
|
867
|
+
if (current.type === 'impl_item') {
|
|
868
|
+
const children = current.children ?? [];
|
|
869
|
+
const forIdx = children.findIndex((c) => c.text === 'for');
|
|
870
|
+
if (forIdx !== -1) {
|
|
871
|
+
const nameNode = children
|
|
872
|
+
.slice(forIdx + 1)
|
|
873
|
+
.find((c) => c.type === 'type_identifier' ||
|
|
874
|
+
c.type === 'scoped_type_identifier' ||
|
|
875
|
+
c.type === 'identifier');
|
|
876
|
+
if (nameNode) {
|
|
877
|
+
// `for` target keeps its raw text. A scoped path (impl T for a::Inner)
|
|
878
|
+
// therefore owns through `a::Inner`, which only resolves once the
|
|
879
|
+
// referenced struct is keyed by its qualified path — deferred to #1978.
|
|
880
|
+
return {
|
|
881
|
+
classId: (0, utils_js_1.generateId)('Struct', `${filePath}:${nameNode.text}`),
|
|
882
|
+
className: nameNode.text,
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
// Inherent impl target.
|
|
887
|
+
// - SCOPED (`impl a::Inner`, scoped_type_identifier): key by FULL text,
|
|
888
|
+
// matching the @definition.impl scoped arm (#1975). UNCHANGED.
|
|
889
|
+
// - UNSCOPED (`impl Inner`, type_identifier): qualify by the enclosing
|
|
890
|
+
// `mod_item` scope (`outer.Inner`) so two same-tail bare impls under
|
|
891
|
+
// different mods own through DISTINCT nodes. The Impl-node
|
|
892
|
+
// materialization (parsing-processor / parse-worker) mirrors this, so
|
|
893
|
+
// the owner id == the Impl node id byte-for-byte (#1982).
|
|
894
|
+
// - GENERIC (`impl<T> Inner<T>`, generic_type): the @definition.impl
|
|
895
|
+
// node is materialized only when the generic base is a bare
|
|
896
|
+
// `type_identifier` (tree-sitter-queries.ts), qualified the same way —
|
|
897
|
+
// so drill into the base and mirror that gate, keeping the owner id ==
|
|
898
|
+
// the node id byte-for-byte (#1992). A generic over a SCOPED base
|
|
899
|
+
// (`impl<T> a::Inner<T>`) materializes NO node, so it must produce NO
|
|
900
|
+
// owner (the method orphans — scoped-generic deferred, #1992).
|
|
901
|
+
const implTarget = children.find((c) => c.type === 'type_identifier' ||
|
|
902
|
+
c.type === 'scoped_type_identifier' ||
|
|
903
|
+
c.type === 'generic_type');
|
|
904
|
+
if (implTarget) {
|
|
905
|
+
const baseType = implTarget.type === 'generic_type'
|
|
906
|
+
? (implTarget.childForFieldName?.('type') ?? null)
|
|
907
|
+
: implTarget;
|
|
908
|
+
if (baseType?.type === 'type_identifier') {
|
|
909
|
+
// Bare target (`impl Inner` or `impl<T> Inner<T>`): qualify by mod scope.
|
|
910
|
+
// #1992 follow-up: qualify `className` too (not just `classId`). The
|
|
911
|
+
// method node id is keyed `${className}.${name}`, so a bare tail collapses
|
|
912
|
+
// two same-tail bare impls that ALSO share a method name (`a::Inner::m` +
|
|
913
|
+
// `b::Inner::m` both → `Inner.m`) onto one Method node (graph addNode is
|
|
914
|
+
// first-write-wins). Qualifying className → `a.Inner.m` / `b.Inner.m` keeps
|
|
915
|
+
// them distinct. Symmetric: the call-resolution fallback rebuilds the same
|
|
916
|
+
// `${className}.${name}` from the same enclosing-impl walk, so def and call
|
|
917
|
+
// ids still agree. Owner edge anchors on `classId` (already qualified).
|
|
918
|
+
const qualified = (0, exports.qualifyRustImplTargetByModScope)(current, baseType.text);
|
|
919
|
+
return {
|
|
920
|
+
classId: (0, utils_js_1.generateId)('Impl', `${filePath}:${qualified}`),
|
|
921
|
+
className: qualified,
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
if (baseType?.type === 'scoped_type_identifier' && implTarget.type !== 'generic_type') {
|
|
925
|
+
// Top-level scoped `impl a::Inner`: key by full raw text (#1975).
|
|
926
|
+
return {
|
|
927
|
+
classId: (0, utils_js_1.generateId)('Impl', `${filePath}:${baseType.text}`),
|
|
928
|
+
className: baseType.text,
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
// generic-over-scoped (`impl<T> a::Inner<T>`) and any other base: fall
|
|
932
|
+
// through with no owner — no @definition.impl node exists, so attributing
|
|
933
|
+
// a method to a synthesized id would orphan it against a phantom owner.
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
const nameNode = current.childForFieldName?.('name') ??
|
|
937
|
+
current.children?.find((c) => c.type === 'type_identifier' ||
|
|
938
|
+
c.type === 'identifier' ||
|
|
939
|
+
c.type === 'name' ||
|
|
940
|
+
c.type === 'constant');
|
|
941
|
+
if (nameNode) {
|
|
942
|
+
let label = exports.CONTAINER_TYPE_TO_LABEL[current.type] || 'Class';
|
|
943
|
+
// Kotlin: class_declaration with an anonymous "interface" keyword child
|
|
944
|
+
// is actually an interface, not a class. Refine the label to match the
|
|
945
|
+
// node ID generated from the tree-sitter query capture (@definition.interface).
|
|
946
|
+
if (current.type === 'class_declaration' &&
|
|
947
|
+
label === 'Class' &&
|
|
948
|
+
current.children?.some((c) => c.type === 'interface')) {
|
|
949
|
+
label = 'Interface';
|
|
950
|
+
}
|
|
951
|
+
// class_declaration with a `declaration_kind` field collapses several
|
|
952
|
+
// type kinds onto one node (tree-sitter-swift: class / struct / enum /
|
|
953
|
+
// extension / actor). The structure query labels struct → Struct and
|
|
954
|
+
// enum → Enum; refine the owner label to match so a member edge
|
|
955
|
+
// (HAS_METHOD / HAS_PROPERTY) anchors on the real Enum/Struct node id
|
|
956
|
+
// rather than a non-existent `Class:` id (F79). Gated on the field
|
|
957
|
+
// being present, so it is a no-op for grammars whose class_declaration
|
|
958
|
+
// has no `declaration_kind` field (e.g. Kotlin).
|
|
959
|
+
if (current.type === 'class_declaration' && label === 'Class') {
|
|
960
|
+
const declKind = current.childForFieldName?.('declaration_kind')?.text;
|
|
961
|
+
if (declKind === 'struct')
|
|
962
|
+
label = 'Struct';
|
|
963
|
+
else if (declKind === 'enum')
|
|
964
|
+
label = 'Enum';
|
|
965
|
+
}
|
|
966
|
+
const templateArguments = (0, template_arguments_js_1.extractTemplateArguments)(nameNode.text);
|
|
967
|
+
const classIdName = templateArguments !== undefined
|
|
968
|
+
? `${(0, template_arguments_js_1.stripTemplateArguments)(nameNode.text)}${(0, template_arguments_js_1.templateArgumentsIdTag)(templateArguments)}`
|
|
969
|
+
: nameNode.text;
|
|
970
|
+
// #1978: when the language opts into qualified node ids, key the owner
|
|
971
|
+
// edge by the enclosing type's qualified path (e.g. "Outer.Inner") so it
|
|
972
|
+
// matches the qualified class node id. Derived from the SAME
|
|
973
|
+
// extractQualifiedName the node-id uses → agree by construction. Only set
|
|
974
|
+
// when actually nested (qualified !== simple); top-level types are
|
|
975
|
+
// unchanged. (Go receiver / Rust impl branches return earlier and are
|
|
976
|
+
// intentionally untouched here.)
|
|
977
|
+
const qualifiedOwnerName = getQualifiedOwnerName?.(current, nameNode.text);
|
|
978
|
+
const qualifiedClassId = qualifiedOwnerName != null && qualifiedOwnerName !== nameNode.text
|
|
979
|
+
? (0, utils_js_1.generateId)(label, `${filePath}:${templateArguments !== undefined
|
|
980
|
+
? `${(0, template_arguments_js_1.stripTemplateArguments)(qualifiedOwnerName)}${(0, template_arguments_js_1.templateArgumentsIdTag)(templateArguments)}`
|
|
981
|
+
: qualifiedOwnerName}`)
|
|
982
|
+
: undefined;
|
|
983
|
+
return {
|
|
984
|
+
classId: (0, utils_js_1.generateId)(label, `${filePath}:${classIdName}`),
|
|
985
|
+
className: nameNode.text,
|
|
986
|
+
...(qualifiedClassId !== undefined ? { qualifiedClassId } : {}),
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
current = current.parent;
|
|
991
|
+
}
|
|
992
|
+
return null;
|
|
993
|
+
};
|
|
994
|
+
exports.findEnclosingClassInfo = findEnclosingClassInfo;
|
|
995
|
+
/**
|
|
996
|
+
* Block-statement AST types that disqualify an object-literal binding from
|
|
997
|
+
* carrying a HAS_METHOD edge. A `const` declared inside one of these is block-
|
|
998
|
+
* scoped and cannot be imported, so attributing methods to it would create
|
|
999
|
+
* false-positive cross-file edges.
|
|
1000
|
+
*/
|
|
1001
|
+
const BLOCK_SCOPE_BOUNDARY_TYPES = new Set([
|
|
1002
|
+
'statement_block',
|
|
1003
|
+
'if_statement',
|
|
1004
|
+
'else_clause',
|
|
1005
|
+
'for_statement',
|
|
1006
|
+
'for_in_statement',
|
|
1007
|
+
'for_of_statement',
|
|
1008
|
+
'while_statement',
|
|
1009
|
+
'do_statement',
|
|
1010
|
+
'try_statement',
|
|
1011
|
+
'catch_clause',
|
|
1012
|
+
'finally_clause',
|
|
1013
|
+
'switch_statement',
|
|
1014
|
+
'switch_case',
|
|
1015
|
+
'switch_default',
|
|
1016
|
+
'with_statement',
|
|
1017
|
+
]);
|
|
1018
|
+
/**
|
|
1019
|
+
* Find the file-scope variable that owns an object literal method definition.
|
|
1020
|
+
*
|
|
1021
|
+
* Covers TypeScript/JavaScript shorthand object methods such as:
|
|
1022
|
+
*
|
|
1023
|
+
* export const service = { async load() {} };
|
|
1024
|
+
*
|
|
1025
|
+
* tree-sitter represents `load` as a `method_definition` inside an `object`,
|
|
1026
|
+
* not inside a class container. Without this fallback, ingestion emits a
|
|
1027
|
+
* top-level `Method` node but no edge from the exported `service` value to
|
|
1028
|
+
* that method, so impact queries cannot discover `service.load`.
|
|
1029
|
+
*
|
|
1030
|
+
* Two-phase walk:
|
|
1031
|
+
* Phase A walks up from `node` tracking how many `object` ancestors we
|
|
1032
|
+
* cross. The first `variable_declarator` reached with `objectDepth >= 1`
|
|
1033
|
+
* is the candidate owner — unless `objectDepth > 1` (the method belongs
|
|
1034
|
+
* to a nested object literal; we return null rather than misattribute
|
|
1035
|
+
* to the outer binding). Hitting a function/class container before the
|
|
1036
|
+
* declarator returns null (catches IIFE-wrapped literals).
|
|
1037
|
+
* Phase B walks the declarator's own ancestors. Any function or class
|
|
1038
|
+
* ancestor before reaching `program`/`export_statement` returns null
|
|
1039
|
+
* (catches `const` declared inside a function body). Any block-statement
|
|
1040
|
+
* ancestor also returns null (catches block-scoped declarations inside
|
|
1041
|
+
* top-level `if`/`for`/`try`/etc., which cannot be imported).
|
|
1042
|
+
*/
|
|
1043
|
+
const findObjectLiteralBindingInfo = (node, filePath) => {
|
|
1044
|
+
// ── Phase A: walk up from node, count `object` ancestors, find declarator
|
|
1045
|
+
let current = node;
|
|
1046
|
+
let objectDepth = 0;
|
|
1047
|
+
let declarator = null;
|
|
1048
|
+
while (current) {
|
|
1049
|
+
if (current.type === 'object') {
|
|
1050
|
+
objectDepth += 1;
|
|
1051
|
+
}
|
|
1052
|
+
if (current.type === 'variable_declarator' && objectDepth >= 1) {
|
|
1053
|
+
if (objectDepth > 1) {
|
|
1054
|
+
// Method belongs to a nested object literal; safe under-approximation.
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
declarator = current;
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
if (current !== node &&
|
|
1061
|
+
(exports.FUNCTION_NODE_TYPES.has(current.type) || exports.CLASS_CONTAINER_TYPES.has(current.type))) {
|
|
1062
|
+
// Function/class container encountered before owning declarator
|
|
1063
|
+
// (e.g. IIFE-wrapped object literal). Bail out.
|
|
1064
|
+
return null;
|
|
1065
|
+
}
|
|
1066
|
+
current = current.parent;
|
|
1067
|
+
}
|
|
1068
|
+
if (!declarator)
|
|
1069
|
+
return null;
|
|
1070
|
+
// ── Phase B: declarator must live at file scope (program / export_statement)
|
|
1071
|
+
// with no function, class, or block-statement ancestor in between.
|
|
1072
|
+
let anc = declarator.parent;
|
|
1073
|
+
while (anc) {
|
|
1074
|
+
if (anc.type === 'program' || anc.type === 'export_statement') {
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
if (exports.FUNCTION_NODE_TYPES.has(anc.type) || exports.CLASS_CONTAINER_TYPES.has(anc.type)) {
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
if (BLOCK_SCOPE_BOUNDARY_TYPES.has(anc.type)) {
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
anc = anc.parent;
|
|
1084
|
+
}
|
|
1085
|
+
const nameNode = declarator.childForFieldName?.('name');
|
|
1086
|
+
if (!nameNode || nameNode.type !== 'identifier')
|
|
1087
|
+
return null;
|
|
1088
|
+
const declaration = declarator.parent;
|
|
1089
|
+
const ownerLabel = declaration?.type === 'variable_declaration' ? 'Variable' : 'Const';
|
|
1090
|
+
return {
|
|
1091
|
+
ownerId: (0, utils_js_1.generateId)(ownerLabel, `${filePath}:${nameNode.text}`),
|
|
1092
|
+
};
|
|
1093
|
+
};
|
|
1094
|
+
exports.findObjectLiteralBindingInfo = findObjectLiteralBindingInfo;
|
|
1095
|
+
/**
|
|
1096
|
+
* Find the owner of a member assigned by `<Owner>.prototype.<member> = fn`
|
|
1097
|
+
* (#2723 follow-up).
|
|
1098
|
+
*
|
|
1099
|
+
* Sibling of {@link findObjectLiteralBindingInfo}: same seam, same return
|
|
1100
|
+
* shape, different syntax. There the owner is the variable the literal is
|
|
1101
|
+
* bound to; here it is the identifier to the left of `.prototype`.
|
|
1102
|
+
*
|
|
1103
|
+
* The owner label is read from the file's own module-scope declaration, so the
|
|
1104
|
+
* edge points at the node that actually exists — `function Foo() {}` is a
|
|
1105
|
+
* `Function` node, `class Foo {}` is a `Class` node. When the file declares no
|
|
1106
|
+
* such name (the constructor lives in another module) no owner is claimed:
|
|
1107
|
+
* a HAS_METHOD edge to a fabricated node is worse than a top-level Method.
|
|
1108
|
+
*/
|
|
1109
|
+
const findMemberAssignmentOwnerInfo = (node, filePath) => {
|
|
1110
|
+
const ownerName = (0, exports.prototypeAssignmentOwnerName)(node) ?? (0, exports.thisAssignmentOwnerName)(node);
|
|
1111
|
+
if (ownerName === null)
|
|
1112
|
+
return null;
|
|
1113
|
+
const root = node.tree?.rootNode;
|
|
1114
|
+
if (!root)
|
|
1115
|
+
return null;
|
|
1116
|
+
const ownerLabel = prototypeOwnerLabel(root, ownerName);
|
|
1117
|
+
if (ownerLabel === null)
|
|
1118
|
+
return null;
|
|
1119
|
+
return { ownerId: (0, utils_js_1.generateId)(ownerLabel, `${filePath}:${ownerName}`), ownerName };
|
|
1120
|
+
};
|
|
1121
|
+
exports.findMemberAssignmentOwnerInfo = findMemberAssignmentOwnerInfo;
|
|
1122
|
+
/** Right-hand-side node types that make an assignment a callable binding. */
|
|
1123
|
+
const CALLABLE_ASSIGNMENT_VALUE_TYPES = new Set([
|
|
1124
|
+
'arrow_function',
|
|
1125
|
+
'function_expression',
|
|
1126
|
+
'generator_function',
|
|
1127
|
+
]);
|
|
1128
|
+
/**
|
|
1129
|
+
* The receiver name of a `<Owner>.prototype.<member> = <function>` assignment,
|
|
1130
|
+
* or null when `assignment` is not that shape.
|
|
1131
|
+
*
|
|
1132
|
+
* Only a bare identifier owner is accepted. `a.b.prototype.c = …` and
|
|
1133
|
+
* `getClass().prototype.c = …` name an owner this layer cannot resolve to a
|
|
1134
|
+
* definition, so they are left alone rather than attributed to a guess.
|
|
1135
|
+
*/
|
|
1136
|
+
const prototypeAssignmentOwnerName = (assignment) => {
|
|
1137
|
+
const left = callableAssignmentTarget(assignment);
|
|
1138
|
+
if (left === null)
|
|
1139
|
+
return null;
|
|
1140
|
+
const protoRef = left.childForFieldName('object');
|
|
1141
|
+
if (protoRef === null || protoRef.type !== 'member_expression')
|
|
1142
|
+
return null;
|
|
1143
|
+
if (protoRef.childForFieldName('property')?.text !== 'prototype')
|
|
1144
|
+
return null;
|
|
1145
|
+
const owner = protoRef.childForFieldName('object');
|
|
1146
|
+
if (owner === null || owner.type !== 'identifier')
|
|
1147
|
+
return null;
|
|
1148
|
+
return owner.text;
|
|
1149
|
+
};
|
|
1150
|
+
exports.prototypeAssignmentOwnerName = prototypeAssignmentOwnerName;
|
|
1151
|
+
/** The `member_expression` being assigned a function value, or null. */
|
|
1152
|
+
const callableAssignmentTarget = (assignment) => {
|
|
1153
|
+
if (assignment.type !== 'assignment_expression')
|
|
1154
|
+
return null;
|
|
1155
|
+
const right = assignment.childForFieldName('right');
|
|
1156
|
+
if (right === null || !CALLABLE_ASSIGNMENT_VALUE_TYPES.has(right.type))
|
|
1157
|
+
return null;
|
|
1158
|
+
const left = assignment.childForFieldName('left');
|
|
1159
|
+
return left !== null && left.type === 'member_expression' ? left : null;
|
|
1160
|
+
};
|
|
1161
|
+
/**
|
|
1162
|
+
* The constructor function that owns a `this.member = <function>` assignment,
|
|
1163
|
+
* or null when there is none (module top level, or an owner this layer cannot
|
|
1164
|
+
* name).
|
|
1165
|
+
*
|
|
1166
|
+
* Only a `function_declaration` counts. An `arrow_function` does NOT bind its
|
|
1167
|
+
* own `this` (ECMA-262 gives it `[[ThisMode]] = lexical`), so the walk passes
|
|
1168
|
+
* through arrows to the function that actually binds the receiver — the same
|
|
1169
|
+
* rule `@receiver-owner.this` encodes in the scope queries (#2701). A class
|
|
1170
|
+
* method never reaches here: parse-worker resolves its owner from the
|
|
1171
|
+
* enclosing class container first.
|
|
1172
|
+
*/
|
|
1173
|
+
const thisAssignmentOwnerName = (assignment) => {
|
|
1174
|
+
const left = callableAssignmentTarget(assignment);
|
|
1175
|
+
if (left === null)
|
|
1176
|
+
return null;
|
|
1177
|
+
if (left.childForFieldName('object')?.type !== 'this')
|
|
1178
|
+
return null;
|
|
1179
|
+
for (let anc = assignment.parent; anc !== null; anc = anc.parent) {
|
|
1180
|
+
if (anc.type === 'arrow_function')
|
|
1181
|
+
continue;
|
|
1182
|
+
if (anc.type === 'function_declaration') {
|
|
1183
|
+
const name = anc.childForFieldName('name');
|
|
1184
|
+
return name !== null && name.type === 'identifier' ? name.text : null;
|
|
1185
|
+
}
|
|
1186
|
+
// Any other receiver-binding form (function_expression, method_definition,
|
|
1187
|
+
// generator) owns the `this` but gives this layer no module-scope name to
|
|
1188
|
+
// point an owner edge at.
|
|
1189
|
+
if (exports.FUNCTION_NODE_TYPES.has(anc.type) || exports.CLASS_CONTAINER_TYPES.has(anc.type))
|
|
1190
|
+
return null;
|
|
1191
|
+
}
|
|
1192
|
+
return null;
|
|
1193
|
+
};
|
|
1194
|
+
exports.thisAssignmentOwnerName = thisAssignmentOwnerName;
|
|
1195
|
+
/**
|
|
1196
|
+
* True when `node` is a `X.prototype.Y = <function>` or `this.Y = <function>`
|
|
1197
|
+
* assignment — i.e. a callable MEMBER rather than a free function.
|
|
1198
|
+
*
|
|
1199
|
+
* Takes the ASSIGNMENT node, because that is what the `@definition.function`
|
|
1200
|
+
* capture is anchored on and therefore what `provider.labelOverride` receives.
|
|
1201
|
+
*/
|
|
1202
|
+
const isPrototypeMemberAssignmentNode = (node) => (0, exports.prototypeAssignmentOwnerName)(node) !== null || (0, exports.isThisMemberAssignmentNode)(node);
|
|
1203
|
+
exports.isPrototypeMemberAssignmentNode = isPrototypeMemberAssignmentNode;
|
|
1204
|
+
/**
|
|
1205
|
+
* True when `node` is `module.exports = <anonymous function>` (#2723).
|
|
1206
|
+
*
|
|
1207
|
+
* The whole module IS the callable, so there is no property to take a name
|
|
1208
|
+
* from and the caller supplies a file-derived one. A NAMED function expression
|
|
1209
|
+
* is excluded — its own name is captured directly and is more informative.
|
|
1210
|
+
*/
|
|
1211
|
+
/**
|
|
1212
|
+
* True when `node` is `module.exports = <function>`, named or anonymous — the
|
|
1213
|
+
* CommonJS default export, where the whole module IS the callable.
|
|
1214
|
+
*
|
|
1215
|
+
* `exports = fn` is deliberately NOT this shape: reassigning the `exports`
|
|
1216
|
+
* binding does not export anything in CommonJS, it only breaks the alias to
|
|
1217
|
+
* `module.exports`.
|
|
1218
|
+
*/
|
|
1219
|
+
const isCjsDefaultExportAssignment = (node) => {
|
|
1220
|
+
if (node.type !== 'assignment_expression')
|
|
1221
|
+
return false;
|
|
1222
|
+
const right = node.childForFieldName('right');
|
|
1223
|
+
if (right === null || !CALLABLE_ASSIGNMENT_VALUE_TYPES.has(right.type))
|
|
1224
|
+
return false;
|
|
1225
|
+
const left = node.childForFieldName('left');
|
|
1226
|
+
if (left === null || left.type !== 'member_expression')
|
|
1227
|
+
return false;
|
|
1228
|
+
return (left.childForFieldName('object')?.text === 'module' &&
|
|
1229
|
+
left.childForFieldName('property')?.text === 'exports');
|
|
1230
|
+
};
|
|
1231
|
+
exports.isCjsDefaultExportAssignment = isCjsDefaultExportAssignment;
|
|
1232
|
+
/** True when `node` is a `this.Y = <function>` assignment, at any nesting. */
|
|
1233
|
+
const isThisMemberAssignmentNode = (node) => {
|
|
1234
|
+
const left = callableAssignmentTarget(node);
|
|
1235
|
+
return left !== null && left.childForFieldName('object')?.type === 'this';
|
|
1236
|
+
};
|
|
1237
|
+
exports.isThisMemberAssignmentNode = isThisMemberAssignmentNode;
|
|
1238
|
+
/**
|
|
1239
|
+
* The label the owner named by {@link prototypeAssignmentOwnerName} carries in
|
|
1240
|
+
* the graph, so the owner edge points at the node that actually exists.
|
|
1241
|
+
* Returns null when the file declares no such module-scope name.
|
|
1242
|
+
*/
|
|
1243
|
+
const prototypeOwnerLabel = (root, ownerName) => {
|
|
1244
|
+
for (const child of root.namedChildren) {
|
|
1245
|
+
const decl = child.type === 'export_statement' ? child.childForFieldName('declaration') : child;
|
|
1246
|
+
if (decl === null)
|
|
1247
|
+
continue;
|
|
1248
|
+
if (decl.childForFieldName('name')?.text === ownerName) {
|
|
1249
|
+
if (decl.type === 'class_declaration')
|
|
1250
|
+
return 'Class';
|
|
1251
|
+
if (decl.type === 'function_declaration' || decl.type === 'generator_function_declaration')
|
|
1252
|
+
return 'Function';
|
|
1253
|
+
}
|
|
1254
|
+
// `var Foo = function () {}` / `const Foo = () => {}` / `const Foo = class {}`.
|
|
1255
|
+
// The dominant pre-ES6 constructor form, and the population this whole
|
|
1256
|
+
// change targets. Without it `prototypeOwnerLabel` returned null, the
|
|
1257
|
+
// member fell back to an UNQUALIFIED `Method:<file>:<member>` id, and two
|
|
1258
|
+
// constructors defining the same member name in one file collapsed onto a
|
|
1259
|
+
// single node with no owner edges at all (#2729 review F6).
|
|
1260
|
+
if (!VARIABLE_DECLARATION_NODE_TYPES.has(decl.type))
|
|
1261
|
+
continue;
|
|
1262
|
+
for (const declarator of decl.namedChildren) {
|
|
1263
|
+
if (declarator.type !== 'variable_declarator')
|
|
1264
|
+
continue;
|
|
1265
|
+
if (declarator.childForFieldName('name')?.text !== ownerName)
|
|
1266
|
+
continue;
|
|
1267
|
+
const value = declarator.childForFieldName('value');
|
|
1268
|
+
if (value === null)
|
|
1269
|
+
continue;
|
|
1270
|
+
// Only a callable value is claimed. A closure binding reliably emits
|
|
1271
|
+
// `Function:<file>:<name>` (the #2687/#2693 convention), so the owner id
|
|
1272
|
+
// resolves to a node that exists. A class EXPRESSION or a require()-bound
|
|
1273
|
+
// value names an owner whose node label this layer cannot predict —
|
|
1274
|
+
// claim none rather than point an edge at a node that may not exist,
|
|
1275
|
+
// which is the same defect class this fix exists to remove.
|
|
1276
|
+
if (CALLABLE_ASSIGNMENT_VALUE_TYPES.has(value.type))
|
|
1277
|
+
return 'Function';
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
return null;
|
|
1281
|
+
};
|
|
1282
|
+
/** Declaration nodes carrying `variable_declarator` children (JS/TS). */
|
|
1283
|
+
const VARIABLE_DECLARATION_NODE_TYPES = new Set([
|
|
1284
|
+
'lexical_declaration',
|
|
1285
|
+
'variable_declaration',
|
|
1286
|
+
]);
|
|
1287
|
+
/** Convenience wrapper: returns just the class ID string (backward compat). */
|
|
1288
|
+
const findEnclosingClassId = (node, filePath) => {
|
|
1289
|
+
return (0, exports.findEnclosingClassInfo)(node, filePath)?.classId ?? null;
|
|
1290
|
+
};
|
|
1291
|
+
exports.findEnclosingClassId = findEnclosingClassId;
|
|
1292
|
+
/**
|
|
1293
|
+
* Find a child of `childType` within a sibling node of `siblingType`.
|
|
1294
|
+
* Used for Kotlin AST traversal where visibility_modifier lives inside a modifiers sibling.
|
|
1295
|
+
*/
|
|
1296
|
+
const findSiblingChild = (parent, siblingType, childType) => {
|
|
1297
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
1298
|
+
const sibling = parent.child(i);
|
|
1299
|
+
if (sibling?.type === siblingType) {
|
|
1300
|
+
for (let j = 0; j < sibling.childCount; j++) {
|
|
1301
|
+
const child = sibling.child(j);
|
|
1302
|
+
if (child?.type === childType)
|
|
1303
|
+
return child;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return null;
|
|
1308
|
+
};
|
|
1309
|
+
exports.findSiblingChild = findSiblingChild;
|
|
1310
|
+
/** Generic name extraction from a function-like AST node.
|
|
1311
|
+
* Tries `node.childForFieldName('name')?.text`, then scans children for
|
|
1312
|
+
* `identifier` / `property_identifier` / `simple_identifier`.
|
|
1313
|
+
*
|
|
1314
|
+
* `arrow_function` and `function_expression` (TS/JS) are inherently
|
|
1315
|
+
* anonymous — they have no `name` field, and their first identifier
|
|
1316
|
+
* child is a *parameter*, not a function name. Returning a parameter
|
|
1317
|
+
* identifier here would synthesize phantom Function IDs (e.g. callers
|
|
1318
|
+
* walking up from a call inside `arr.map(x => fn(x))` would get
|
|
1319
|
+
* attributed to a non-existent "Function x"). The language's
|
|
1320
|
+
* `methodExtractor.extractFunctionName` hook is responsible for naming
|
|
1321
|
+
* these via parent context (variable_declarator, pair, etc.); when it
|
|
1322
|
+
* declines, the parent walk should continue rather than fall through
|
|
1323
|
+
* here. See issue #1166. */
|
|
1324
|
+
const genericFuncName = (node) => {
|
|
1325
|
+
const nameField = node.childForFieldName?.('name');
|
|
1326
|
+
if (nameField)
|
|
1327
|
+
return nameField.text;
|
|
1328
|
+
if (node.type === 'arrow_function' || node.type === 'function_expression') {
|
|
1329
|
+
return null;
|
|
1330
|
+
}
|
|
1331
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
1332
|
+
const c = node.child(i);
|
|
1333
|
+
if (c?.type === 'identifier' ||
|
|
1334
|
+
c?.type === 'property_identifier' ||
|
|
1335
|
+
c?.type === 'simple_identifier')
|
|
1336
|
+
return c.text;
|
|
1337
|
+
}
|
|
1338
|
+
return null;
|
|
1339
|
+
};
|
|
1340
|
+
exports.genericFuncName = genericFuncName;
|
|
1341
|
+
/** AST node types that represent a method definition (for `inferFunctionLabel`). */
|
|
1342
|
+
exports.METHOD_LABEL_NODE_TYPES = new Set([
|
|
1343
|
+
'method_definition',
|
|
1344
|
+
'method_declaration',
|
|
1345
|
+
'method',
|
|
1346
|
+
'singleton_method',
|
|
1347
|
+
]);
|
|
1348
|
+
/** AST node types that represent a constructor definition (for `inferFunctionLabel`). */
|
|
1349
|
+
exports.CONSTRUCTOR_LABEL_NODE_TYPES = new Set([
|
|
1350
|
+
'constructor_declaration',
|
|
1351
|
+
'compact_constructor_declaration',
|
|
1352
|
+
]);
|
|
1353
|
+
/** Infer node label from AST node type for function-like nodes without a provider hook. */
|
|
1354
|
+
const inferFunctionLabel = (nodeType) => exports.METHOD_LABEL_NODE_TYPES.has(nodeType)
|
|
1355
|
+
? 'Method'
|
|
1356
|
+
: exports.CONSTRUCTOR_LABEL_NODE_TYPES.has(nodeType)
|
|
1357
|
+
? 'Constructor'
|
|
1358
|
+
: 'Function';
|
|
1359
|
+
exports.inferFunctionLabel = inferFunctionLabel;
|
|
1360
|
+
/** Argument list node types shared between countCallArguments and call-resolution helpers. */
|
|
1361
|
+
exports.CALL_ARGUMENT_LIST_TYPES = new Set(['arguments', 'argument_list', 'value_arguments']);
|
|
1362
|
+
/**
|
|
1363
|
+
* Function/method parameter-list node types across grammars. Used to tell a
|
|
1364
|
+
* PARAMETER-property (a constructor parameter that is also a class field, e.g.
|
|
1365
|
+
* TypeScript `constructor(public name: string)`) apart from a function-BODY
|
|
1366
|
+
* local: a property reached through one of these — rather than through the
|
|
1367
|
+
* function's executable body — is a genuine class member, so the
|
|
1368
|
+
* function-local-property guard must NOT strip its owner edge.
|
|
1369
|
+
*/
|
|
1370
|
+
exports.PARAMETER_LIST_NODE_TYPES = new Set([
|
|
1371
|
+
'formal_parameters', // TypeScript / JavaScript
|
|
1372
|
+
'parameters', // Python / C#
|
|
1373
|
+
'parameter_list', // Java / Go / C / Swift
|
|
1374
|
+
'function_value_parameters', // Kotlin
|
|
1375
|
+
'class_parameters', // Scala-like / future grammars
|
|
1376
|
+
]);
|
|
1377
|
+
/**
|
|
1378
|
+
* Executable local-scope boundaries for the property-ownership guard
|
|
1379
|
+
* (`isFunctionLocalProperty` in parse-worker.ts). A `Property` capture whose
|
|
1380
|
+
* nearest enclosing scope — walking up before any class container — is one of
|
|
1381
|
+
* these executable bodies is a function-local binding, NOT a class member, so it
|
|
1382
|
+
* must not receive a class `HAS_PROPERTY` owner edge.
|
|
1383
|
+
*
|
|
1384
|
+
* Derived from FUNCTION_NODE_TYPES, with two deliberate adjustments found by the
|
|
1385
|
+
* #1919 review of the original guard:
|
|
1386
|
+
* - EXCLUDES Dart's bare signature wrappers (`function_signature` /
|
|
1387
|
+
* `method_signature`). A Dart getter/setter NAME lives under `method_signature`,
|
|
1388
|
+
* yet it is a class-member declaration, not a local inside an executable body;
|
|
1389
|
+
* treating the signature as a scope boundary OVER-stripped every Dart class
|
|
1390
|
+
* accessor's owner edge. (Signatures are Dart-only; no language emits a
|
|
1391
|
+
* legitimately-function-local Property under one.)
|
|
1392
|
+
* - INCLUDES accessor + initializer bodies (Kotlin `anonymous_initializer` /
|
|
1393
|
+
* `getter` / `setter`, Swift `computed_property` / `computed_getter` /
|
|
1394
|
+
* `computed_setter` / `computed_modify`). Destructuring/locals inside these ARE
|
|
1395
|
+
* function-local, yet they are absent from FUNCTION_NODE_TYPES; omitting them
|
|
1396
|
+
* UNDER-stripped and emitted spurious class `HAS_PROPERTY` edges for
|
|
1397
|
+
* `init {}` / accessor-body destructuring bindings.
|
|
1398
|
+
*
|
|
1399
|
+
* Kept separate from FUNCTION_NODE_TYPES because that set has many other consumers
|
|
1400
|
+
* (e.g. enclosing-callable resolution) where signatures must remain function nodes
|
|
1401
|
+
* and accessor bodies must not.
|
|
1402
|
+
*/
|
|
1403
|
+
exports.LOCAL_SCOPE_BODY_NODE_TYPES = new Set([...exports.FUNCTION_NODE_TYPES]
|
|
1404
|
+
.filter((t) => t !== 'function_signature' && t !== 'method_signature')
|
|
1405
|
+
.concat([
|
|
1406
|
+
'anonymous_initializer', // Kotlin: init { }
|
|
1407
|
+
'getter', // Kotlin: val x get() { }
|
|
1408
|
+
'setter', // Kotlin: var x set(v) { }
|
|
1409
|
+
'computed_property', // Swift: var x: T { get set }
|
|
1410
|
+
'computed_getter', // Swift: get { }
|
|
1411
|
+
'computed_setter', // Swift: set { }
|
|
1412
|
+
'computed_modify', // Swift: _modify { }
|
|
1413
|
+
]));
|
|
1414
|
+
/**
|
|
1415
|
+
* Callable node types whose grammar splits the body off into a SIBLING node, so
|
|
1416
|
+
* the callable is never an ancestor of the code inside it (Dart
|
|
1417
|
+
* `function_signature` / `method_signature`).
|
|
1418
|
+
*
|
|
1419
|
+
* Derived, not listed, so it cannot drift from the two sets that define it:
|
|
1420
|
+
* `LOCAL_SCOPE_BODY_NODE_TYPES` is `FUNCTION_NODE_TYPES` minus exactly the bare
|
|
1421
|
+
* signature types, so the difference IS the split-signature set.
|
|
1422
|
+
*
|
|
1423
|
+
* Must stay BELOW `LOCAL_SCOPE_BODY_NODE_TYPES` — reading it earlier hits the
|
|
1424
|
+
* temporal dead zone and throws at module load.
|
|
1425
|
+
*/
|
|
1426
|
+
exports.SPLIT_SIGNATURE_NODE_TYPES = new Set([...exports.FUNCTION_NODE_TYPES].filter((t) => !exports.LOCAL_SCOPE_BODY_NODE_TYPES.has(t)));
|
|
1427
|
+
// ============================================================================
|
|
1428
|
+
// Generic AST traversal helpers (shared by parse-worker + php-helpers)
|
|
1429
|
+
// ============================================================================
|
|
1430
|
+
/** Walk an AST node depth-first, returning the first descendant with the given type. */
|
|
1431
|
+
function findDescendant(root, type) {
|
|
1432
|
+
const stack = [root];
|
|
1433
|
+
while (stack.length > 0) {
|
|
1434
|
+
const node = stack.pop();
|
|
1435
|
+
if (node.type === type)
|
|
1436
|
+
return node;
|
|
1437
|
+
// Push in reverse order so left children are visited first (depth-first)
|
|
1438
|
+
const children = node.children ?? [];
|
|
1439
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
1440
|
+
stack.push(children[i]);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return null;
|
|
1444
|
+
}
|
|
1445
|
+
/** Extract the text content from a string or encapsed_string AST node. */
|
|
1446
|
+
function extractStringContent(node) {
|
|
1447
|
+
if (!node)
|
|
1448
|
+
return null;
|
|
1449
|
+
const content = node.children?.find((c) => c.type === 'string_content');
|
|
1450
|
+
if (content)
|
|
1451
|
+
return content.text;
|
|
1452
|
+
if (node.type === 'string_content')
|
|
1453
|
+
return node.text;
|
|
1454
|
+
return null;
|
|
1455
|
+
}
|
|
1456
|
+
/** Find the first direct named child of a tree-sitter node matching the given type. */
|
|
1457
|
+
function findChild(node, type) {
|
|
1458
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
1459
|
+
const child = node.namedChild(i);
|
|
1460
|
+
if (child?.type === type)
|
|
1461
|
+
return child;
|
|
1462
|
+
}
|
|
1463
|
+
return null;
|
|
1464
|
+
}
|
|
1465
|
+
/** Remove bidi-override and zero-width control characters from attacker-
|
|
1466
|
+
* influenced repository text before it is exposed through graph descriptions
|
|
1467
|
+
* or MCP output (#2286). Global `sanitizeUTF8` intentionally remains focused
|
|
1468
|
+
* on encoding/control-character validity. */
|
|
1469
|
+
const stripBidiAndZeroWidth = (text) => Array.from(text)
|
|
1470
|
+
.filter((ch) => {
|
|
1471
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
1472
|
+
// Bidi overrides/isolates (U+202A–202E, U+2066–2069), zero-width
|
|
1473
|
+
// space/joiners (U+200B–200D), and BOM/zero-width-no-break (U+FEFF).
|
|
1474
|
+
return !((c >= 0x202a && c <= 0x202e) ||
|
|
1475
|
+
(c >= 0x2066 && c <= 0x2069) ||
|
|
1476
|
+
(c >= 0x200b && c <= 0x200d) ||
|
|
1477
|
+
c === 0xfeff);
|
|
1478
|
+
})
|
|
1479
|
+
.join('');
|
|
1480
|
+
exports.stripBidiAndZeroWidth = stripBidiAndZeroWidth;
|
|
1481
|
+
/** Normalize a block doc comment body: strip the opening (double-star or
|
|
1482
|
+
* bang) delimiter, the closing delimiter, and per-line gutter stars, then
|
|
1483
|
+
* collapse whitespace so tag content stays as searchable words. */
|
|
1484
|
+
const normalizeBlockDocComment = (text) => {
|
|
1485
|
+
const inner = (0, exports.stripBidiAndZeroWidth)(text
|
|
1486
|
+
.replace(/^\/\*[*!]/, '')
|
|
1487
|
+
// Close delimiter: tolerate the degenerate empty comment `/**/`, where the
|
|
1488
|
+
// opening strip already consumed the shared `*`, leaving a lone `/`.
|
|
1489
|
+
.replace(/\*?\/\s*$/, '')
|
|
1490
|
+
.replace(/^[ \t]*\*[ \t]?/gm, ' ')
|
|
1491
|
+
.replace(/\s+/g, ' ')
|
|
1492
|
+
.trim());
|
|
1493
|
+
return inner.length > 0 ? inner : undefined;
|
|
1494
|
+
};
|
|
1495
|
+
/** Default line-comment prefixes treated as documentation: the universal
|
|
1496
|
+
* triple-slash / bang-slash doc markers (Rust, C#, Dart, Swift, Doxygen).
|
|
1497
|
+
* Go (`//`) and Ruby (`#`) opt into their conventional markers explicitly. */
|
|
1498
|
+
const DEFAULT_LINE_DOC_PREFIXES = ['///', '//!'];
|
|
1499
|
+
/** Default block-comment doc openers: Javadoc/JSDoc-style `/**` and Doxygen
|
|
1500
|
+
* `/*!`. Rust opts out of `/*!` (and `//!`) because those are *inner* docs that
|
|
1501
|
+
* document the enclosing item, not the following one. */
|
|
1502
|
+
const DEFAULT_BLOCK_DOC_PREFIXES = ['/**', '/*!'];
|
|
1503
|
+
/** A file-top `/** … *\/` license/copyright/file-overview block has no
|
|
1504
|
+
* package/import sibling to shield it, so it would otherwise be absorbed as the
|
|
1505
|
+
* first declaration's description (PR #2286 review). These markers identify such
|
|
1506
|
+
* headers; they are specific enough not to fire on an ordinary symbol doc that
|
|
1507
|
+
* merely mentions the word "copyright". `@file`/`@fileoverview` are explicitly
|
|
1508
|
+
* file-level JSDoc tags, so a block carrying them is not a symbol doc. */
|
|
1509
|
+
const FILE_HEADER_MARKER = /SPDX-License-Identifier|@licen[sc]e\b|@fileoverview\b|@file\b|Licen[sc]ed under|copyright\s*(\(c\)|©|\d{4})/i;
|
|
1510
|
+
function extractLeadingDocComment(node, opts = {}) {
|
|
1511
|
+
const lineCommentPrefixes = opts.lineCommentPrefixes ?? DEFAULT_LINE_DOC_PREFIXES;
|
|
1512
|
+
const wrapperNodeTypes = opts.wrapperNodeTypes ?? [];
|
|
1513
|
+
const lineDirectivePrefixes = opts.lineDirectivePrefixes ?? [];
|
|
1514
|
+
const blockDocPrefixes = opts.blockDocPrefixes ?? DEFAULT_BLOCK_DOC_PREFIXES;
|
|
1515
|
+
const fromNode = (anchor) => {
|
|
1516
|
+
const prev = anchor.previousNamedSibling;
|
|
1517
|
+
if (!prev)
|
|
1518
|
+
return undefined;
|
|
1519
|
+
// Block doc comment: /** ... */ or /*! ... */
|
|
1520
|
+
if (blockDocPrefixes.some((p) => prev.text.startsWith(p))) {
|
|
1521
|
+
// Skip a file-top license/copyright/overview header (no package/import
|
|
1522
|
+
// sibling shields it from the first declaration). A strict row-adjacency
|
|
1523
|
+
// check is unreliable here — some grammars fold the trailing newline into
|
|
1524
|
+
// the comment node — so match header markers instead.
|
|
1525
|
+
if (FILE_HEADER_MARKER.test(prev.text))
|
|
1526
|
+
return undefined;
|
|
1527
|
+
return normalizeBlockDocComment(prev.text);
|
|
1528
|
+
}
|
|
1529
|
+
// Run of row-adjacent preceding line doc comments (e.g. `///` or `//`).
|
|
1530
|
+
const matchedPrefix = (text) => lineCommentPrefixes.find((prefix) => text.trimStart().startsWith(prefix));
|
|
1531
|
+
const isDirective = (text) => lineDirectivePrefixes.some((prefix) => text.trimStart().startsWith(prefix));
|
|
1532
|
+
const lines = [];
|
|
1533
|
+
let current = prev;
|
|
1534
|
+
let expectedRow = anchor.startPosition.row - 1;
|
|
1535
|
+
while (current) {
|
|
1536
|
+
const text = current.text;
|
|
1537
|
+
const prefix = matchedPrefix(text);
|
|
1538
|
+
if (prefix === undefined || current.startPosition.row !== expectedRow)
|
|
1539
|
+
break;
|
|
1540
|
+
// A build/tool directive or magic comment (e.g. `//go:build`,
|
|
1541
|
+
// `# frozen_string_literal:`) is not documentation: skip it but keep
|
|
1542
|
+
// walking the adjacent run, so a real doc above it is still collected.
|
|
1543
|
+
if (!isDirective(text))
|
|
1544
|
+
lines.unshift(text.trimStart().slice(prefix.length));
|
|
1545
|
+
expectedRow = current.startPosition.row - 1;
|
|
1546
|
+
current = current.previousNamedSibling;
|
|
1547
|
+
}
|
|
1548
|
+
const joined = (0, exports.stripBidiAndZeroWidth)(lines.join(' ').replace(/\s+/g, ' ').trim());
|
|
1549
|
+
return joined.length > 0 ? joined : undefined;
|
|
1550
|
+
};
|
|
1551
|
+
const direct = fromNode(node);
|
|
1552
|
+
if (direct !== undefined)
|
|
1553
|
+
return direct;
|
|
1554
|
+
const parent = node.parent;
|
|
1555
|
+
if (parent && wrapperNodeTypes.includes(parent.type)) {
|
|
1556
|
+
return fromNode(parent);
|
|
1557
|
+
}
|
|
1558
|
+
return undefined;
|
|
1559
|
+
}
|
|
1560
|
+
/** Node labels that can carry a leading doc comment — callables and type-like
|
|
1561
|
+
* declarations. Field/property/variable/const doc is intentionally excluded
|
|
1562
|
+
* (issue #2270 scopes this to method/type documentation). Language-neutral:
|
|
1563
|
+
* a label a given grammar never emits simply never matches.
|
|
1564
|
+
*
|
|
1565
|
+
* Bounded to labels that are also in `embeddings/types.ts` `EMBEDDABLE_LABELS`:
|
|
1566
|
+
* the description is only useful once it reaches the embedding metadata header,
|
|
1567
|
+
* and the embedding pipeline only queries embeddable labels. Extracting docs
|
|
1568
|
+
* for a non-embeddable label is a wasted write that never becomes searchable.
|
|
1569
|
+
* A subset invariant in the unit tests guards against drift. Making currently-
|
|
1570
|
+
* non-embeddable doc-bearing labels (Module, Delegate, Annotation, and C++
|
|
1571
|
+
* `Template`) searchable is tracked as a follow-up — it needs an embedding-
|
|
1572
|
+
* pipeline/schema change beyond this fix. */
|
|
1573
|
+
exports.DOC_BEARING_LABELS = new Set([
|
|
1574
|
+
'Function',
|
|
1575
|
+
'Method',
|
|
1576
|
+
'Constructor',
|
|
1577
|
+
'Class',
|
|
1578
|
+
'Interface',
|
|
1579
|
+
'Enum',
|
|
1580
|
+
'Struct',
|
|
1581
|
+
'Trait',
|
|
1582
|
+
'Record',
|
|
1583
|
+
'Union',
|
|
1584
|
+
'Namespace',
|
|
1585
|
+
'TypeAlias',
|
|
1586
|
+
'Macro',
|
|
1587
|
+
]);
|
|
1588
|
+
/**
|
|
1589
|
+
* Build a `LanguageProvider.descriptionExtractor` that surfaces a definition's
|
|
1590
|
+
* leading doc comment as its `description` (issue #2270). For labels in
|
|
1591
|
+
* {@link DOC_BEARING_LABELS} (which is bounded to embeddable labels) the text
|
|
1592
|
+
* then reaches the embedding metadata header and becomes semantically searchable.
|
|
1593
|
+
*
|
|
1594
|
+
* Language-neutral factory (names no language): guards on
|
|
1595
|
+
* {@link DOC_BEARING_LABELS}; callers pass per-language doc-comment behavior via
|
|
1596
|
+
* {@link LeadingDocCommentOptions} (line prefixes, export-style wrappers, …)
|
|
1597
|
+
* which is threaded straight through to {@link extractLeadingDocComment}.
|
|
1598
|
+
*/
|
|
1599
|
+
const createLeadingDocDescriptionExtractor = (opts = {}) => {
|
|
1600
|
+
return (nodeLabel, _nodeName, captureMap) => {
|
|
1601
|
+
if (!exports.DOC_BEARING_LABELS.has(nodeLabel))
|
|
1602
|
+
return undefined;
|
|
1603
|
+
const definitionNode = (0, exports.getDefinitionNodeFromCaptures)(captureMap);
|
|
1604
|
+
return definitionNode ? extractLeadingDocComment(definitionNode, opts) : undefined;
|
|
1605
|
+
};
|
|
1606
|
+
};
|
|
1607
|
+
exports.createLeadingDocDescriptionExtractor = createLeadingDocDescriptionExtractor;
|
|
1608
|
+
// ============================================================================
|
|
1609
|
+
// Capture + range helpers (formerly python/ast-utils.ts — language-agnostic)
|
|
1610
|
+
// ============================================================================
|
|
1611
|
+
/** Convert a tree-sitter node to a `Capture` with 1-based line numbers
|
|
1612
|
+
* (matching RFC §2.1). The tag includes the leading `@`. */
|
|
1613
|
+
function nodeToCapture(name, node) {
|
|
1614
|
+
return {
|
|
1615
|
+
name,
|
|
1616
|
+
range: {
|
|
1617
|
+
startLine: node.startPosition.row + 1,
|
|
1618
|
+
startCol: node.startPosition.column,
|
|
1619
|
+
endLine: node.endPosition.row + 1,
|
|
1620
|
+
endCol: node.endPosition.column,
|
|
1621
|
+
},
|
|
1622
|
+
text: node.text,
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
/** Build a `Capture` whose range mirrors `atNode` but whose `text` is
|
|
1626
|
+
* caller-supplied. Used to synthesize markers that don't have a
|
|
1627
|
+
* corresponding source token. */
|
|
1628
|
+
function syntheticCapture(name, atNode, text) {
|
|
1629
|
+
return {
|
|
1630
|
+
name,
|
|
1631
|
+
range: {
|
|
1632
|
+
startLine: atNode.startPosition.row + 1,
|
|
1633
|
+
startCol: atNode.startPosition.column,
|
|
1634
|
+
endLine: atNode.endPosition.row + 1,
|
|
1635
|
+
endCol: atNode.endPosition.column,
|
|
1636
|
+
},
|
|
1637
|
+
text,
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
function rangeMatches(node, range) {
|
|
1641
|
+
return (node.startPosition.row + 1 === range.startLine &&
|
|
1642
|
+
node.startPosition.column === range.startCol &&
|
|
1643
|
+
node.endPosition.row + 1 === range.endLine &&
|
|
1644
|
+
node.endPosition.column === range.endCol);
|
|
1645
|
+
}
|
|
1646
|
+
/** Walk a subtree to find a node whose range exactly matches AND whose
|
|
1647
|
+
* type matches `expectedType` (when given). When multiple nodes share
|
|
1648
|
+
* the range — e.g., `function_definition` and its inner `block` body
|
|
1649
|
+
* for a one-liner — the type filter disambiguates.
|
|
1650
|
+
*
|
|
1651
|
+
* Iterative depth-first-left-to-right via an explicit stack. Children
|
|
1652
|
+
* are pushed in reverse index order so LIFO pop visits them in source
|
|
1653
|
+
* order. Prunes branches that can't contain the target range by
|
|
1654
|
+
* row bounds — same optimization the prior recursive form used, minus
|
|
1655
|
+
* the early-break since stack-push is cheap. */
|
|
1656
|
+
function findNodeAtRange(root, range, expectedType) {
|
|
1657
|
+
const startRow = range.startLine - 1;
|
|
1658
|
+
const endRow = range.endLine - 1;
|
|
1659
|
+
const stack = [root];
|
|
1660
|
+
while (stack.length > 0) {
|
|
1661
|
+
const node = stack.pop();
|
|
1662
|
+
if (rangeMatches(node, range) && (expectedType === undefined || node.type === expectedType)) {
|
|
1663
|
+
return node;
|
|
1664
|
+
}
|
|
1665
|
+
for (let i = node.namedChildCount - 1; i >= 0; i--) {
|
|
1666
|
+
const child = node.namedChild(i);
|
|
1667
|
+
if (child === null)
|
|
1668
|
+
continue;
|
|
1669
|
+
if (child.endPosition.row < startRow)
|
|
1670
|
+
continue;
|
|
1671
|
+
if (child.startPosition.row > endRow)
|
|
1672
|
+
continue;
|
|
1673
|
+
stack.push(child);
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
return null;
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Return the captured node if its type is one of `types`, else null.
|
|
1680
|
+
*
|
|
1681
|
+
* The threaded-node equivalent of `findNodeAtRange(root, capture.range, type)`
|
|
1682
|
+
* for the common case where a tree-sitter query already hands you the matched
|
|
1683
|
+
* node (`c.node`): the captured node IS the node at that range, so a type check
|
|
1684
|
+
* is exact and there is no need to re-walk from the tree root (the
|
|
1685
|
+
* O(matches × rootChildren) hot path #1848 hit). Unlike `findNodeAtRange`, this
|
|
1686
|
+
* does NOT traverse — the caller must already hold the node; for a multi-type
|
|
1687
|
+
* call the node must literally be one of `types` (no fallback search).
|
|
1688
|
+
*
|
|
1689
|
+
* Used by every language's scope-capture path (go/python/ruby/php/rust/csharp).
|
|
1690
|
+
*/
|
|
1691
|
+
function nodeIfType(node, ...types) {
|
|
1692
|
+
return node !== undefined && types.includes(node.type) ? node : null;
|
|
1693
|
+
}
|