gitnexus 1.6.10-rc.99 → 1.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +177 -18
- package/dist/_shared/graph/types.d.ts +21 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +3 -3
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts +16 -0
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js +19 -7
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +3 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +5 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +315 -36
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +115 -0
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/lookup-core.js +58 -2
- package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +47 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +278 -3
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +3 -2
- package/dist/cli/ai-context.js +71 -16
- package/dist/cli/analyze-config.d.ts +1 -1
- package/dist/cli/analyze-options.d.ts +131 -0
- package/dist/cli/analyze-options.js +1 -0
- package/dist/cli/analyze.d.ts +21 -113
- package/dist/cli/analyze.js +172 -29
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/detect-changes-format.js +19 -2
- package/dist/cli/doctor.d.ts +12 -0
- package/dist/cli/doctor.js +32 -5
- package/dist/cli/editor-targets.js +6 -0
- package/dist/cli/eval-server.js +2 -1
- package/dist/cli/format-symbol.d.ts +15 -0
- package/dist/cli/format-symbol.js +17 -0
- package/dist/cli/generated-skill.d.ts +17 -0
- package/dist/cli/generated-skill.js +1 -0
- package/dist/cli/group.js +229 -21
- package/dist/cli/help-i18n.js +1 -2
- package/dist/cli/i18n/en.d.ts +11 -9
- package/dist/cli/i18n/en.js +13 -9
- package/dist/cli/i18n/resources.d.ts +15 -11
- package/dist/cli/i18n/zh-CN.d.ts +4 -2
- package/dist/cli/i18n/zh-CN.js +11 -9
- package/dist/cli/index.js +8 -4
- package/dist/cli/resolve-invocation.d.ts +7 -3
- package/dist/cli/resolve-invocation.js +7 -3
- package/dist/cli/setup.js +4 -3
- package/dist/cli/skill-gen.d.ts +1 -6
- package/dist/cli/tool.d.ts +1 -0
- package/dist/cli/tool.js +74 -17
- package/dist/cli/wiki.js +53 -10
- package/dist/config/ignore-service.d.ts +2 -0
- package/dist/config/ignore-service.js +54 -13
- package/dist/core/analyzer-identity.d.ts +80 -0
- package/dist/core/analyzer-identity.js +364 -26
- package/dist/core/augmentation/engine.js +86 -71
- package/dist/core/embedding-checkpoint.d.ts +143 -0
- package/dist/core/embedding-checkpoint.js +221 -0
- package/dist/core/embedding-count.d.ts +61 -0
- package/dist/core/embedding-count.js +69 -0
- package/dist/core/embeddings/ast-utils.js +9 -1
- package/dist/core/embeddings/embedding-pipeline.d.ts +8 -0
- package/dist/core/embeddings/embedding-pipeline.js +253 -14
- package/dist/core/embeddings/http-client.d.ts +5 -0
- package/dist/core/embeddings/http-client.js +142 -27
- package/dist/core/graph/graph.js +3 -0
- package/dist/core/graph/import-cycles.d.ts +194 -3
- package/dist/core/graph/import-cycles.js +522 -73
- package/dist/core/graph/types.d.ts +18 -0
- package/dist/core/group/bridge-db.d.ts +204 -1
- package/dist/core/group/bridge-db.js +401 -28
- package/dist/core/group/completeness.d.ts +130 -0
- package/dist/core/group/completeness.js +83 -0
- package/dist/core/group/config-parser.js +0 -5
- package/dist/core/group/cross-impact.d.ts +46 -1
- package/dist/core/group/cross-impact.js +220 -19
- package/dist/core/group/cross-trace.d.ts +32 -11
- package/dist/core/group/cross-trace.js +114 -20
- package/dist/core/group/extractors/http-patterns/java.js +278 -22
- package/dist/core/group/extractors/http-patterns/node.js +332 -216
- package/dist/core/group/extractors/http-patterns/types.d.ts +8 -0
- package/dist/core/group/extractors/http-route-extractor.d.ts +1 -0
- package/dist/core/group/extractors/http-route-extractor.js +122 -48
- package/dist/core/group/extractors/include-extractor.js +20 -2
- package/dist/core/group/extractors/manifest-extractor.d.ts +1 -1
- package/dist/core/group/extractors/manifest-extractor.js +7 -7
- package/dist/core/group/extractors/python-workspace-extractor.js +5 -2
- package/dist/core/group/group-lock.d.ts +31 -0
- package/dist/core/group/group-lock.js +166 -0
- package/dist/core/group/service.js +297 -16
- package/dist/core/group/storage.d.ts +3 -0
- package/dist/core/group/storage.js +7 -39
- package/dist/core/group/sync.d.ts +49 -3
- package/dist/core/group/sync.js +0 -0
- package/dist/core/group/types.d.ts +183 -8
- package/dist/core/group/types.js +28 -1
- package/dist/core/incremental/subgraph-extract.d.ts +9 -6
- package/dist/core/incremental/subgraph-extract.js +33 -10
- package/dist/core/index-freshness.d.ts +77 -2
- package/dist/core/index-freshness.js +109 -2
- package/dist/core/ingestion/call-processor.d.ts +13 -1
- package/dist/core/ingestion/call-processor.js +110 -3
- package/dist/core/ingestion/cfg/callee-cell-format.d.ts +42 -0
- package/dist/core/ingestion/cfg/callee-cell-format.js +42 -0
- package/dist/core/ingestion/cfg/emit.d.ts +8 -23
- package/dist/core/ingestion/cfg/emit.js +9 -23
- package/dist/core/ingestion/class-extractors/configs/go.js +10 -5
- package/dist/core/ingestion/cluster-enricher.js +8 -4
- package/dist/core/ingestion/community-processor.d.ts +21 -3
- package/dist/core/ingestion/community-processor.js +81 -82
- package/dist/core/ingestion/di-extractors/index.d.ts +9 -33
- package/dist/core/ingestion/di-extractors/spring.d.ts +1 -1
- package/dist/core/ingestion/di-extractors/spring.js +8 -1
- package/dist/core/ingestion/di-extractors/types.d.ts +60 -0
- package/dist/core/ingestion/di-extractors/types.js +15 -0
- package/dist/core/ingestion/filesystem-walker.js +30 -14
- package/dist/core/ingestion/finalize-orchestrator.js +1 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +6 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +35 -1
- package/dist/core/ingestion/frameworks/spring/annotation-arguments.d.ts +13 -0
- package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +227 -0
- package/dist/core/ingestion/frameworks/spring/aop-candidates.d.ts +15 -0
- package/dist/core/ingestion/frameworks/spring/aop-candidates.js +85 -0
- package/dist/core/ingestion/frameworks/spring/aop.d.ts +118 -0
- package/dist/core/ingestion/frameworks/spring/aop.js +476 -0
- package/dist/core/ingestion/frameworks/spring/auto-configuration.d.ts +8 -0
- package/dist/core/ingestion/frameworks/spring/auto-configuration.js +16 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.js +1 -0
- package/dist/core/ingestion/frameworks/spring/bean-factories.d.ts +33 -0
- package/dist/core/ingestion/frameworks/spring/bean-factories.js +65 -0
- package/dist/core/ingestion/frameworks/spring/conditionals.d.ts +25 -0
- package/dist/core/ingestion/frameworks/spring/conditionals.js +319 -0
- package/dist/core/ingestion/frameworks/spring/di-metadata.d.ts +3 -0
- package/dist/core/ingestion/frameworks/spring/di-metadata.js +162 -13
- package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +28 -0
- package/dist/core/ingestion/frameworks/spring/non-http-handlers.js +152 -0
- package/dist/core/ingestion/frameworks/spring/resource-injection.d.ts +5 -0
- package/dist/core/ingestion/frameworks/spring/resource-injection.js +91 -0
- package/dist/core/ingestion/import-resolvers/configs/csharp.js +5 -1
- package/dist/core/ingestion/import-resolvers/configs/swift.js +13 -0
- package/dist/core/ingestion/import-resolvers/csharp.d.ts +9 -1
- package/dist/core/ingestion/import-resolvers/csharp.js +234 -27
- package/dist/core/ingestion/import-resolvers/go.d.ts +11 -1
- package/dist/core/ingestion/import-resolvers/go.js +44 -17
- package/dist/core/ingestion/import-resolvers/jvm.d.ts +2 -2
- package/dist/core/ingestion/import-resolvers/node-workspace-packages.d.ts +90 -0
- package/dist/core/ingestion/import-resolvers/node-workspace-packages.js +429 -0
- package/dist/core/ingestion/import-resolvers/package-dir-index.d.ts +124 -0
- package/dist/core/ingestion/import-resolvers/package-dir-index.js +223 -0
- package/dist/core/ingestion/import-resolvers/pass-cache.d.ts +50 -0
- package/dist/core/ingestion/import-resolvers/pass-cache.js +60 -0
- package/dist/core/ingestion/import-resolvers/per-file-set.d.ts +71 -0
- package/dist/core/ingestion/import-resolvers/per-file-set.js +11 -0
- package/dist/core/ingestion/import-resolvers/php.d.ts +1 -1
- package/dist/core/ingestion/import-resolvers/php.js +65 -19
- package/dist/core/ingestion/import-resolvers/python-file-index.d.ts +201 -0
- package/dist/core/ingestion/import-resolvers/python-file-index.js +302 -0
- package/dist/core/ingestion/import-resolvers/python.js +25 -6
- package/dist/core/ingestion/import-resolvers/ruby.d.ts +1 -1
- package/dist/core/ingestion/import-resolvers/rust.d.ts +2 -2
- package/dist/core/ingestion/import-resolvers/standard.d.ts +1 -1
- package/dist/core/ingestion/import-resolvers/types.d.ts +1 -12
- package/dist/core/ingestion/import-resolvers/utils.d.ts +65 -6
- package/dist/core/ingestion/import-resolvers/utils.js +215 -36
- package/dist/core/ingestion/import-resolvers/workspace-file-index.d.ts +72 -0
- package/dist/core/ingestion/import-resolvers/workspace-file-index.js +58 -0
- package/dist/core/ingestion/language-config.d.ts +29 -1
- package/dist/core/ingestion/language-config.js +110 -35
- package/dist/core/ingestion/language-provider.d.ts +209 -7
- package/dist/core/ingestion/language-provider.js +37 -0
- package/dist/core/ingestion/languages/c/captures.js +7 -0
- package/dist/core/ingestion/languages/c/import-target.js +12 -16
- package/dist/core/ingestion/languages/c/scope-resolver.js +20 -19
- package/dist/core/ingestion/languages/c/static-linkage.js +12 -16
- package/dist/core/ingestion/languages/c-cpp.js +13 -0
- package/dist/core/ingestion/languages/cobol/scope-resolver.js +27 -20
- package/dist/core/ingestion/languages/cobol.js +13 -0
- package/dist/core/ingestion/languages/cpp/adl.d.ts +2 -2
- package/dist/core/ingestion/languages/cpp/adl.js +67 -44
- package/dist/core/ingestion/languages/cpp/captures.js +14 -2
- package/dist/core/ingestion/languages/cpp/file-local-linkage.js +11 -15
- package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +28 -8
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +242 -68
- package/dist/core/ingestion/languages/cpp/interpret.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/interpret.js +126 -6
- package/dist/core/ingestion/languages/cpp/query.js +106 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +48 -20
- package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +2 -15
- package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +18 -10
- package/dist/core/ingestion/languages/csharp/captures.js +19 -0
- package/dist/core/ingestion/languages/csharp/import-target.js +46 -72
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +5 -1
- package/dist/core/ingestion/languages/csharp/query.js +25 -5
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +75 -2
- package/dist/core/ingestion/languages/dart/captures.d.ts +10 -0
- package/dist/core/ingestion/languages/dart/captures.js +598 -16
- package/dist/core/ingestion/languages/dart/import-target.js +32 -9
- package/dist/core/ingestion/languages/dart/index.d.ts +1 -1
- package/dist/core/ingestion/languages/dart/index.js +1 -1
- package/dist/core/ingestion/languages/dart/query.js +98 -1
- package/dist/core/ingestion/languages/dart/scope-resolver.js +14 -3
- package/dist/core/ingestion/languages/dart/simple-hooks.js +9 -0
- package/dist/core/ingestion/languages/dart.js +6 -1
- package/dist/core/ingestion/languages/go/captures.js +108 -3
- package/dist/core/ingestion/languages/go/generic-type-parameters.d.ts +31 -0
- package/dist/core/ingestion/languages/go/generic-type-parameters.js +140 -0
- package/dist/core/ingestion/languages/go/import-target.d.ts +3 -10
- package/dist/core/ingestion/languages/go/import-target.js +34 -30
- package/dist/core/ingestion/languages/go/index.d.ts +1 -1
- package/dist/core/ingestion/languages/go/interface-impls.d.ts +9 -1
- package/dist/core/ingestion/languages/go/interface-impls.js +693 -87
- package/dist/core/ingestion/languages/go/interpret.d.ts +2 -0
- package/dist/core/ingestion/languages/go/interpret.js +22 -8
- package/dist/core/ingestion/languages/go/method-owners.js +31 -12
- package/dist/core/ingestion/languages/go/package-clause.d.ts +46 -0
- package/dist/core/ingestion/languages/go/package-clause.js +75 -0
- package/dist/core/ingestion/languages/go/package-siblings.js +7 -11
- package/dist/core/ingestion/languages/go/query.js +56 -3
- package/dist/core/ingestion/languages/go/scope-resolver.js +39 -0
- package/dist/core/ingestion/languages/go.js +9 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +4 -0
- package/dist/core/ingestion/languages/java/analysis-features.js +12 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +12 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +48 -0
- package/dist/core/ingestion/languages/java/captures.js +77 -32
- package/dist/core/ingestion/languages/java/import-target.d.ts +49 -9
- package/dist/core/ingestion/languages/java/import-target.js +68 -88
- package/dist/core/ingestion/languages/java/interpret.js +3 -2
- package/dist/core/ingestion/languages/java/module-resolution.d.ts +62 -0
- package/dist/core/ingestion/languages/java/module-resolution.js +142 -0
- package/dist/core/ingestion/languages/java/query.js +15 -3
- package/dist/core/ingestion/languages/java/record-components.d.ts +14 -0
- package/dist/core/ingestion/languages/java/record-components.js +185 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +10 -2
- package/dist/core/ingestion/languages/java/spring-aop.d.ts +12 -0
- package/dist/core/ingestion/languages/java/spring-aop.js +49 -0
- package/dist/core/ingestion/languages/java/spring-conditionals.d.ts +11 -0
- package/dist/core/ingestion/languages/java/spring-conditionals.js +48 -0
- package/dist/core/ingestion/languages/java/spring-di.d.ts +4 -1
- package/dist/core/ingestion/languages/java/spring-di.js +41 -9
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +7 -0
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +32 -0
- package/dist/core/ingestion/languages/java.js +94 -3
- package/dist/core/ingestion/languages/javascript/captures.d.ts +6 -1
- package/dist/core/ingestion/languages/javascript/captures.js +262 -4
- package/dist/core/ingestion/languages/javascript/import-target.d.ts +17 -21
- package/dist/core/ingestion/languages/javascript/import-target.js +24 -41
- package/dist/core/ingestion/languages/javascript/index.d.ts +54 -5
- package/dist/core/ingestion/languages/javascript/index.js +54 -5
- package/dist/core/ingestion/languages/javascript/query.d.ts +1 -0
- package/dist/core/ingestion/languages/javascript/query.js +211 -5
- package/dist/core/ingestion/languages/javascript/scope-resolver.js +12 -0
- package/dist/core/ingestion/languages/javascript/simple-hooks.js +2 -1
- package/dist/core/ingestion/languages/jvm/package-siblings.js +77 -9
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +48 -0
- package/dist/core/ingestion/languages/kotlin/captures.js +43 -1
- package/dist/core/ingestion/languages/kotlin/import-target.d.ts +8 -1
- package/dist/core/ingestion/languages/kotlin/import-target.js +20 -123
- package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
- package/dist/core/ingestion/languages/kotlin/index.js +1 -0
- package/dist/core/ingestion/languages/kotlin/module-resolution.d.ts +22 -0
- package/dist/core/ingestion/languages/kotlin/module-resolution.js +108 -0
- package/dist/core/ingestion/languages/kotlin/query.js +28 -2
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +23 -2
- package/dist/core/ingestion/languages/kotlin/spring-aop.d.ts +12 -0
- package/dist/core/ingestion/languages/kotlin/spring-aop.js +64 -0
- package/dist/core/ingestion/languages/kotlin/spring-conditionals.d.ts +12 -0
- package/dist/core/ingestion/languages/kotlin/spring-conditionals.js +49 -0
- package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +2 -0
- package/dist/core/ingestion/languages/kotlin/spring-di.js +60 -11
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +10 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +41 -0
- package/dist/core/ingestion/languages/php/captures.d.ts +5 -0
- package/dist/core/ingestion/languages/php/captures.js +319 -51
- package/dist/core/ingestion/languages/php/import-target.d.ts +3 -4
- package/dist/core/ingestion/languages/php/import-target.js +192 -62
- package/dist/core/ingestion/languages/php/query.js +31 -0
- package/dist/core/ingestion/languages/python/arity-metadata.d.ts +1 -0
- package/dist/core/ingestion/languages/python/arity-metadata.js +1 -0
- package/dist/core/ingestion/languages/python/captures.js +29 -0
- package/dist/core/ingestion/languages/python/import-decomposer.js +22 -1
- package/dist/core/ingestion/languages/python/import-target.d.ts +42 -1
- package/dist/core/ingestion/languages/python/import-target.js +277 -91
- package/dist/core/ingestion/languages/python/index.d.ts +1 -1
- package/dist/core/ingestion/languages/python/index.js +1 -1
- package/dist/core/ingestion/languages/python/interpret.d.ts +52 -0
- package/dist/core/ingestion/languages/python/interpret.js +249 -7
- package/dist/core/ingestion/languages/python/query.js +9 -0
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +8 -6
- package/dist/core/ingestion/languages/python/receiver-binding.js +108 -12
- package/dist/core/ingestion/languages/python/scope-resolver.js +27 -4
- package/dist/core/ingestion/languages/python/simple-hooks.js +2 -8
- package/dist/core/ingestion/languages/python.js +13 -0
- package/dist/core/ingestion/languages/ruby/captures.js +158 -0
- package/dist/core/ingestion/languages/ruby/import-target.js +7 -5
- package/dist/core/ingestion/languages/ruby/query.js +93 -0
- package/dist/core/ingestion/languages/ruby/scope-resolver.js +2 -0
- package/dist/core/ingestion/languages/ruby/simple-hooks.d.ts +1 -1
- package/dist/core/ingestion/languages/ruby/simple-hooks.js +22 -1
- package/dist/core/ingestion/languages/rust/captures.js +39 -1
- package/dist/core/ingestion/languages/rust/method-owners.js +11 -1
- package/dist/core/ingestion/languages/rust/module-path.d.ts +126 -0
- package/dist/core/ingestion/languages/rust/module-path.js +214 -0
- package/dist/core/ingestion/languages/rust/qualified-call.d.ts +41 -0
- package/dist/core/ingestion/languages/rust/qualified-call.js +481 -0
- package/dist/core/ingestion/languages/rust/query.js +39 -6
- package/dist/core/ingestion/languages/rust/scope-resolver.js +21 -2
- package/dist/core/ingestion/languages/rust.js +17 -0
- package/dist/core/ingestion/languages/swift/captures.js +87 -3
- package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.d.ts +48 -0
- package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.js +253 -0
- package/dist/core/ingestion/languages/swift/import-target.js +4 -9
- package/dist/core/ingestion/languages/swift/query.js +17 -0
- package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +8 -0
- package/dist/core/ingestion/languages/swift/receiver-binding.js +6 -2
- package/dist/core/ingestion/languages/swift.js +2 -0
- package/dist/core/ingestion/languages/typescript/captures.d.ts +90 -1
- package/dist/core/ingestion/languages/typescript/captures.js +267 -5
- package/dist/core/ingestion/languages/typescript/cjs-export-assignment.d.ts +134 -0
- package/dist/core/ingestion/languages/typescript/cjs-export-assignment.js +523 -0
- package/dist/core/ingestion/languages/typescript/cjs-module-exports.d.ts +54 -0
- package/dist/core/ingestion/languages/typescript/cjs-module-exports.js +191 -0
- package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.d.ts +7 -0
- package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.js +92 -0
- package/dist/core/ingestion/languages/typescript/file-candidates.d.ts +29 -0
- package/dist/core/ingestion/languages/typescript/file-candidates.js +70 -0
- package/dist/core/ingestion/languages/typescript/import-decomposer.d.ts +28 -1
- package/dist/core/ingestion/languages/typescript/import-decomposer.js +125 -10
- package/dist/core/ingestion/languages/typescript/import-target.d.ts +25 -37
- package/dist/core/ingestion/languages/typescript/import-target.js +24 -26
- package/dist/core/ingestion/languages/typescript/interpret.d.ts +21 -1
- package/dist/core/ingestion/languages/typescript/interpret.js +45 -5
- package/dist/core/ingestion/languages/typescript/module-resolution.d.ts +48 -0
- package/dist/core/ingestion/languages/typescript/module-resolution.js +171 -0
- package/dist/core/ingestion/languages/typescript/query.d.ts +1 -0
- package/dist/core/ingestion/languages/typescript/query.js +303 -14
- package/dist/core/ingestion/languages/typescript/receiver-binding.d.ts +17 -0
- package/dist/core/ingestion/languages/typescript/receiver-binding.js +27 -0
- package/dist/core/ingestion/languages/typescript/scope-resolver.js +27 -40
- package/dist/core/ingestion/languages/typescript/simple-hooks.d.ts +0 -10
- package/dist/core/ingestion/languages/typescript/simple-hooks.js +22 -22
- package/dist/core/ingestion/languages/typescript/tsconfig.d.ts +59 -0
- package/dist/core/ingestion/languages/typescript/tsconfig.js +292 -0
- package/dist/core/ingestion/languages/typescript.js +93 -2
- package/dist/core/ingestion/languages/vue/import-target.d.ts +6 -22
- package/dist/core/ingestion/languages/vue/import-target.js +11 -47
- package/dist/core/ingestion/languages/vue/scope-resolver.js +4 -2
- package/dist/core/ingestion/local-symbol-pruner.js +11 -11
- package/dist/core/ingestion/method-extractors/configs/csharp.js +1 -0
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/di.d.ts +1 -1
- package/dist/core/ingestion/pipeline-phases/di.js +136 -21
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +15 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +154 -4
- package/dist/core/ingestion/pipeline-phases/parse.js +5 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +3 -2
- package/dist/core/ingestion/pipeline-phases/processes.js +91 -6
- package/dist/core/ingestion/pipeline-phases/routes.js +116 -25
- package/dist/core/ingestion/pipeline-phases/spring-aop.d.ts +34 -0
- package/dist/core/ingestion/pipeline-phases/spring-aop.js +439 -0
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +34 -0
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +255 -0
- package/dist/core/ingestion/pipeline-phases/types.d.ts +7 -0
- package/dist/core/ingestion/pipeline.d.ts +26 -2
- package/dist/core/ingestion/pipeline.js +60 -11
- package/dist/core/ingestion/process-processor.d.ts +109 -2
- package/dist/core/ingestion/process-processor.js +464 -52
- package/dist/core/ingestion/resolve-references.d.ts +6 -1
- package/dist/core/ingestion/resolve-references.js +66 -6
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +8 -2
- package/dist/core/ingestion/route-extractors/constant-resolver.js +11 -7
- package/dist/core/ingestion/route-extractors/data-route-table.d.ts +40 -0
- package/dist/core/ingestion/route-extractors/data-route-table.js +876 -0
- package/dist/core/ingestion/route-extractors/dispatch-guard.d.ts +96 -0
- package/dist/core/ingestion/route-extractors/dispatch-guard.js +1184 -0
- package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +114 -0
- package/dist/core/ingestion/route-extractors/java-const-resolver.js +569 -0
- package/dist/core/ingestion/route-extractors/js-const-resolver.d.ts +192 -0
- package/dist/core/ingestion/route-extractors/js-const-resolver.js +1033 -0
- package/dist/core/ingestion/route-extractors/nest.d.ts +53 -0
- package/dist/core/ingestion/route-extractors/nest.js +523 -0
- package/dist/core/ingestion/route-extractors/spring-shared.d.ts +11 -0
- package/dist/core/ingestion/route-extractors/spring-shared.js +89 -0
- package/dist/core/ingestion/route-extractors/spring.js +214 -29
- package/dist/core/ingestion/scope-extractor-bridge.js +9 -1
- package/dist/core/ingestion/scope-extractor.d.ts +22 -7
- package/dist/core/ingestion/scope-extractor.js +309 -15
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +311 -21
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +16 -5
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +47 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +20 -15
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +280 -42
- package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +123 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +171 -17
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +58 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +137 -34
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +30 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +39 -1
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +18 -1
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +113 -18
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +107 -5
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +590 -33
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +3 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +101 -41
- package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.d.ts +34 -0
- package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.js +62 -0
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +5 -1
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +8 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +105 -5
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +931 -92
- package/dist/core/ingestion/scope-resolution/passes/return-shape-members.d.ts +58 -0
- package/dist/core/ingestion/scope-resolution/passes/return-shape-members.js +458 -0
- package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.d.ts +180 -0
- package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.js +418 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +29 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +57 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +55 -1
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +241 -19
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +112 -2
- package/dist/core/ingestion/scope-resolution/resolution-outcome.js +38 -1
- package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +25 -3
- package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +36 -16
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +210 -9
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +905 -22
- package/dist/core/ingestion/scope-resolution/summary-maps.d.ts +28 -0
- package/dist/core/ingestion/scope-resolution/summary-maps.js +50 -0
- package/dist/core/ingestion/scope-resolution/undecided-satisfaction.d.ts +55 -0
- package/dist/core/ingestion/scope-resolution/undecided-satisfaction.js +37 -0
- package/dist/core/ingestion/scope-resolution/unresolved-receivers.d.ts +109 -0
- package/dist/core/ingestion/scope-resolution/unresolved-receivers.js +204 -0
- package/dist/core/ingestion/scope-resolution/utils/definition-id.d.ts +13 -0
- package/dist/core/ingestion/scope-resolution/utils/definition-id.js +19 -0
- package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.d.ts +171 -0
- package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.js +218 -0
- package/dist/core/ingestion/scope-resolution/workspace-index-types.d.ts +34 -0
- package/dist/core/ingestion/scope-resolution/workspace-index-types.js +15 -0
- package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +7 -20
- package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
- package/dist/core/ingestion/tree-sitter-queries.js +678 -4
- package/dist/core/ingestion/type-env.js +11 -7
- package/dist/core/ingestion/type-extractors/shared.d.ts +17 -0
- package/dist/core/ingestion/type-extractors/shared.js +16 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +12 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +20 -0
- package/dist/core/ingestion/type-extractors/typescript.js +26 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +297 -15
- package/dist/core/ingestion/utils/ast-helpers.js +578 -46
- package/dist/core/ingestion/utils/call-analysis.d.ts +27 -22
- package/dist/core/ingestion/utils/call-analysis.js +202 -7
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +59 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +51 -1
- package/dist/core/ingestion/utils/callable-labels.d.ts +25 -0
- package/dist/core/ingestion/utils/callable-labels.js +31 -0
- package/dist/core/ingestion/utils/effective-ram.d.ts +40 -0
- package/dist/core/ingestion/utils/effective-ram.js +58 -0
- package/dist/core/ingestion/utils/line-base.d.ts +14 -0
- package/dist/core/ingestion/utils/line-base.js +14 -0
- package/dist/core/ingestion/utils/method-props.d.ts +27 -4
- package/dist/core/ingestion/utils/method-props.js +29 -4
- package/dist/core/ingestion/utils/receiver-chain-captures.d.ts +31 -0
- package/dist/core/ingestion/utils/receiver-chain-captures.js +57 -0
- package/dist/core/ingestion/utils/receiver-chain-codec.d.ts +89 -0
- package/dist/core/ingestion/utils/receiver-chain-codec.js +182 -0
- package/dist/core/ingestion/utils/scope-tree-walk.d.ts +22 -0
- package/dist/core/ingestion/utils/scope-tree-walk.js +33 -0
- package/dist/core/ingestion/utils/template-arguments.d.ts +96 -0
- package/dist/core/ingestion/utils/template-arguments.js +196 -0
- package/dist/core/ingestion/utils/type-parameters.d.ts +49 -0
- package/dist/core/ingestion/utils/type-parameters.js +206 -0
- package/dist/core/ingestion/workers/callable-id.d.ts +80 -0
- package/dist/core/ingestion/workers/callable-id.js +125 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +14 -1
- package/dist/core/ingestion/workers/parse-worker.js +493 -54
- package/dist/core/ingestion/workers/worker-pool.d.ts +20 -27
- package/dist/core/ingestion/workers/worker-pool.js +91 -3
- package/dist/core/lbug/csv-generator.d.ts +27 -0
- package/dist/core/lbug/csv-generator.js +72 -17
- package/dist/core/lbug/extension-load-error.js +13 -2
- package/dist/core/lbug/extension-loader.d.ts +29 -0
- package/dist/core/lbug/extension-loader.js +31 -6
- package/dist/core/lbug/graph-emit-sink.d.ts +264 -0
- package/dist/core/lbug/graph-emit-sink.js +581 -0
- package/dist/core/lbug/lbug-adapter.d.ts +290 -11
- package/dist/core/lbug/lbug-adapter.js +652 -69
- package/dist/core/lbug/native-check.d.ts +21 -0
- package/dist/core/lbug/native-check.js +248 -32
- package/dist/core/lbug/pdg-emit-sink.d.ts +13 -4
- package/dist/core/lbug/pdg-emit-sink.js +21 -111
- package/dist/core/lbug/pool-adapter.d.ts +9 -0
- package/dist/core/lbug/pool-adapter.js +164 -14
- package/dist/core/lbug/query-batch.d.ts +75 -0
- package/dist/core/lbug/query-batch.js +102 -0
- package/dist/core/lbug/rel-pair-routing.d.ts +160 -2
- package/dist/core/lbug/rel-pair-routing.js +228 -10
- package/dist/core/lbug/schema.d.ts +163 -4
- package/dist/core/lbug/schema.js +404 -159
- package/dist/core/lbug/sync-csv-writer.d.ts +47 -0
- package/dist/core/lbug/sync-csv-writer.js +108 -0
- package/dist/core/run-analyze.d.ts +147 -0
- package/dist/core/run-analyze.js +1215 -179
- package/dist/core/search/bm25-index.d.ts +11 -0
- package/dist/core/search/bm25-index.js +60 -26
- package/dist/core/search/fts-indexes.d.ts +150 -9
- package/dist/core/search/fts-indexes.js +241 -23
- package/dist/core/wiki/graph-queries.js +145 -112
- package/dist/core/wiki/llm-client.d.ts +29 -3
- package/dist/core/wiki/llm-client.js +47 -12
- package/dist/core/wiki/prompts.d.ts +19 -0
- package/dist/core/wiki/prompts.js +20 -1
- package/dist/lib/utils.d.ts +113 -0
- package/dist/lib/utils.js +185 -0
- package/dist/mcp/local/aop-metadata.d.ts +77 -0
- package/dist/mcp/local/aop-metadata.js +227 -0
- package/dist/mcp/local/bean-metadata.d.ts +2 -1
- package/dist/mcp/local/bean-metadata.js +22 -1
- package/dist/mcp/local/convex-metadata.d.ts +8 -0
- package/dist/mcp/local/convex-metadata.js +45 -0
- package/dist/mcp/local/local-backend.d.ts +174 -11
- package/dist/mcp/local/local-backend.js +1678 -331
- package/dist/mcp/local/path-predicate.d.ts +19 -0
- package/dist/mcp/local/path-predicate.js +21 -0
- package/dist/mcp/local/pdg-impact.d.ts +132 -10
- package/dist/mcp/local/pdg-impact.js +391 -98
- package/dist/mcp/repository-policy.d.ts +1 -0
- package/dist/mcp/repository-policy.js +5 -0
- package/dist/mcp/resources.js +26 -4
- package/dist/mcp/server.js +23 -13
- package/dist/mcp/tools.d.ts +8 -0
- package/dist/mcp/tools.js +76 -23
- package/dist/server/analyze-job.d.ts +37 -2
- package/dist/server/analyze-job.js +13 -2
- package/dist/server/analyze-launch.d.ts +1 -1
- package/dist/server/analyze-launch.js +79 -10
- package/dist/server/analyze-worker-core.d.ts +1 -1
- package/dist/server/analyze-worker-core.js +10 -1
- package/dist/server/analyze-worker-ipc.d.ts +1 -1
- package/dist/server/analyze-worker-ipc.js +4 -0
- package/dist/server/analyze-worker-protocol.d.ts +59 -0
- package/dist/server/analyze-worker-protocol.js +1 -0
- package/dist/server/analyze-worker.d.ts +1 -17
- package/dist/server/api.d.ts +2 -11
- package/dist/server/api.js +164 -163
- package/dist/server/embed-run-outcome.d.ts +89 -0
- package/dist/server/embed-run-outcome.js +88 -0
- package/dist/server/git-clone.js +6 -2
- package/dist/server/middleware.d.ts +116 -9
- package/dist/server/middleware.js +291 -22
- package/dist/server/sse-progress.d.ts +41 -0
- package/dist/server/sse-progress.js +125 -0
- package/dist/storage/branch-index.d.ts +11 -6
- package/dist/storage/branch-index.js +15 -7
- package/dist/storage/file-hash.js +2 -2
- package/dist/storage/fs-atomic.d.ts +25 -0
- package/dist/storage/fs-atomic.js +42 -0
- package/dist/storage/git.d.ts +131 -0
- package/dist/storage/git.js +236 -2
- package/dist/storage/index-lock.d.ts +102 -0
- package/dist/storage/index-lock.js +660 -0
- package/dist/storage/parse-cache.js +588 -6
- package/dist/storage/parsedfile-store.js +76 -6
- package/dist/storage/repo-manager.d.ts +54 -441
- package/dist/storage/repo-manager.js +312 -221
- package/dist/storage/repo-meta.d.ts +530 -0
- package/dist/storage/repo-meta.js +100 -0
- package/dist/types/pipeline.d.ts +37 -0
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +1 -1
- package/hooks/claude/gitnexus-hook.cjs +1 -1
- package/hooks/claude/resolve-analyze-cmd.cjs +80 -13
- package/package.json +11 -2
- package/scripts/cross-platform-shard.ts +153 -0
- package/scripts/cross-platform-tests.ts +122 -0
- package/scripts/run-cross-platform.ts +16 -5
- package/skills/gitnexus-cli.md +3 -3
- package/skills/gitnexus-debugging.md +37 -7
- package/skills/gitnexus-exploring.md +26 -4
- package/skills/gitnexus-impact-analysis.md +71 -10
- package/skills/gitnexus-plan/README.md +11 -6
- package/skills/gitnexus-plan/references/evidence-provenance.md +49 -12
- package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +654 -372
- package/skills/gitnexus-refactoring.md +48 -5
- package/skills/gitnexus-review/SKILL.md +12 -6
- package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +1 -1
- package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +1 -1
- package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +1 -1
- package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +1 -1
- package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +1 -1
- package/skills/gitnexus-review/ci-personas/ci-security-lens.md +1 -1
- package/skills/gitnexus-taint-analysis.md +13 -7
- package/skills/gitnexus-work/SKILL.md +4 -1
- package/skills/gitnexus-work/references/evidence-provenance.md +49 -12
- package/skills/gitnexus-work/scripts/evidence-provenance.mjs +654 -372
- package/vendor/leiden/utils.cjs +28 -1
- package/web/assets/ProcessFlowModal-Badh2Pbg.js +24 -0
- package/web/assets/{__vite-browser-external-bMKyYQkO.js → __vite-browser-external-COxE8F0G.js} +1 -1
- package/web/assets/abnfDiagram-QNN2D4NM-Cq2djWWe.js +1 -0
- package/web/assets/agent-Dr4l5EOp.js +662 -0
- package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +1 -0
- package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-DBefcjof.js → blockDiagram-54WLDVWM-Dg_hrRWE.js} +4 -4
- package/web/assets/{c4Diagram-Y2BXMSZH-EjWnjEJl.js → c4Diagram-X2LASM7V-CnhoT4aV.js} +2 -2
- package/web/assets/chunk-224SPVON-B8gxtXpy.js +1 -0
- package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +127 -0
- package/web/assets/chunk-2SREHG4O-Dip42xOq.js +1 -0
- package/web/assets/chunk-4RFN2BYJ-DHHWuC-n.js +1 -0
- package/web/assets/chunk-66DQ2XMT-CM0xjFAN.js +1 -0
- package/web/assets/chunk-6BELYETK-ChsYtfHW.js +1 -0
- package/web/assets/{chunk-LII3EMHJ-BL6lKJ_P.js → chunk-6L755F7B-CMhLBxi2.js} +1 -1
- package/web/assets/{chunk-QA3QBVWF-DVXPOIxe.js → chunk-7CWYLC5S-DRgGkkpF.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-C3v-4Fsw.js → chunk-A7VWPJGB-B4O3oQdQ.js} +1 -1
- package/web/assets/chunk-BI6VK774-D0oaWk8V.js +1 -0
- package/web/assets/chunk-D6VWDJW2-BxcBdZ9c.js +2 -0
- package/web/assets/chunk-DMV4VAQV-Bn6WXDSX.js +4 -0
- package/web/assets/chunk-E5QJAATJ-dh-5CtIV.js +2 -0
- package/web/assets/chunk-EQFTRU2I-1ix7TzW9.js +2 -0
- package/web/assets/chunk-FWYVLQTC-BgDItRzJ.js +1 -0
- package/web/assets/chunk-HNC4WDU7-DoU3KnA7.js +1 -0
- package/web/assets/chunk-L5GCOVLC-CE2w8Nm_.js +161 -0
- package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +321 -0
- package/web/assets/chunk-LORZLZWG-B57uGw2N.js +88 -0
- package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +62 -0
- package/web/assets/chunk-NV3KIAZN-5yvcpMiu.js +1 -0
- package/web/assets/chunk-OIYT25JQ-CQ6KOZGX.js +1 -0
- package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +10 -0
- package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +156 -0
- package/web/assets/chunk-RRFMTAIC-CMN0wcYA.js +1 -0
- package/web/assets/{chunk-RLI5ZMPA-CkXZ0y0U.js → chunk-SATU7PGQ-B1zhgOvc.js} +1 -1
- package/web/assets/chunk-STOV2HOB-GnExfzIX.js +1 -0
- package/web/assets/{chunk-INKRHTLW-Ckl3_KkO.js → chunk-SZD42YQK-ijyKKVr1.js} +21 -21
- package/web/assets/{chunk-LCXTWHL2-C162wE5z.js → chunk-TFPGFQPA-Dj6a-0pC.js} +3 -3
- package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +2 -0
- package/web/assets/chunk-TZUXEDM2-B7p9AcTw.js +1 -0
- package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +1 -0
- package/web/assets/{chunk-6764PJDD-C7xxk063.js → chunk-VE5CLXGZ-C1vB7wpY.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-ZNgyLFq6.js → chunk-VJFVEZTB-CX66F2ep.js} +3 -3
- package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +1 -0
- package/web/assets/chunk-WJBAP47W-BckNkuEN.js +1 -0
- package/web/assets/chunk-XNMVGMAZ-Cg_LnPtj.js +1 -0
- package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +1 -0
- package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +1 -0
- package/web/assets/{cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js → cose-bilkent-RZA4XIPR-BHpK4Crp.js} +1 -1
- package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +1 -0
- package/web/assets/cynefinDiagram-TR7LZUCG-C3Iar9lZ.js +62 -0
- package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +4 -0
- package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +30 -0
- package/web/assets/diagram-JCD7PQ7C-DC5-9FRr.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-DVRltWbL.js → diagram-KFBZAVDW-Dfmf_4ti.js} +3 -3
- package/web/assets/diagram-L7DVE3PN-GIRyVUtt.js +41 -0
- package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +24 -0
- package/web/assets/ebnfDiagram-DRHRQJWO-D8_CI4ZF.js +1 -0
- package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +85 -0
- package/web/assets/error-D9MtuG9s.js +1 -0
- package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +1 -0
- package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +1 -0
- package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +292 -0
- package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +1 -0
- package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +106 -0
- package/web/assets/{index-D7mTFcvQ.js → index-2zdvEdzg.js} +51 -51
- package/web/assets/index-CJDpyH-n.css +2 -0
- package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +1 -0
- package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js → ishikawaDiagram-4JDSWWDM-DmqWtjkl.js} +2 -2
- package/web/assets/{journeyDiagram-M6C3CM3L-C6wjooas.js → journeyDiagram-QUS3FAKT-XAzVzrQW.js} +3 -3
- package/web/assets/{kanban-definition-75IXJCU3-5_UVY79g.js → kanban-definition-D4L7SQKK-YurRnmYn.js} +6 -6
- package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +257 -0
- package/web/assets/{mindmap-definition-2TDM6QVE-8xDLzk2e.js → mindmap-definition-66QP5TD6-ChrWWnil.js} +5 -5
- package/web/assets/node.browser-U-KyT5AW.js +1 -0
- package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +1 -0
- package/web/assets/pegDiagram-YKIO5C6U-QGeQLEq2.js +1 -0
- package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +1 -0
- package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +39 -0
- package/web/assets/{quadrantDiagram-VICAPDV7-DR54jOeR.js → quadrantDiagram-VO5QLCXA-B7098wSc.js} +3 -3
- package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +1 -0
- package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +1 -0
- package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +1 -0
- package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +1 -0
- package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +1 -0
- package/web/assets/railroadDiagram-M77LTMSB-AXu4vxk_.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-PEkg7sKC.js → requirementDiagram-RASO5HTO-B-l8InpK.js} +4 -4
- package/web/assets/{sankeyDiagram-URQDO5SZ-DDWEtjcs.js → sankeyDiagram-F32LOJ6L-Kd7zjJgX.js} +3 -3
- package/web/assets/{sequenceDiagram-VS2MUI6T-Bv-uwANx.js → sequenceDiagram-URATNSBD-BlcdY9DS.js} +7 -7
- package/web/assets/sizeCapture-5GORAGP4-BEqQzsxs.js +1 -0
- package/web/assets/src-C5sx_gMp.js +1 -0
- package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +1 -0
- package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +1 -0
- package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +2 -0
- package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +8 -0
- package/web/assets/{timeline-definition-O6YCAMPW-Qmsuo7qS.js → timeline-definition-WJXWRH4I-DUfp1R3E.js} +3 -3
- package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +1 -0
- package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +1 -0
- package/web/assets/vennDiagram-K3VCMQLI-Bj-FN-XS.js +34 -0
- package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +1 -0
- package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +78 -0
- package/web/assets/xychartDiagram-5VRUVLCW-CK_rbSWE.js +7 -0
- package/web/index.html +16 -15
- package/dist/core/ingestion/languages/python/index-stats.d.ts +0 -18
- package/dist/core/ingestion/languages/python/index-stats.js +0 -25
- package/web/assets/ProcessFlowModal-CwkpVkv-.js +0 -22
- package/web/assets/agent-Ds-lkZjX.js +0 -626
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +0 -36
- package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +0 -4
- package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +0 -1
- package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +0 -321
- package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +0 -159
- package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +0 -124
- package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +0 -10
- package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +0 -1
- package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +0 -1
- package/web/assets/chunk-J5EP6P6S-L19oz55R.js +0 -1
- package/web/assets/chunk-KGFNY3KK-BZeP-55u.js +0 -62
- package/web/assets/chunk-KGYTTC2M-zm6n242I.js +0 -1
- package/web/assets/chunk-KNLZD3CH-BGlP6X9R.js +0 -1
- package/web/assets/chunk-LRIF4GLE-n59lhprL.js +0 -1
- package/web/assets/chunk-RERM46MO-B5dAdWpP.js +0 -1
- package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +0 -1
- package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +0 -1
- package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +0 -1
- package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +0 -1
- package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +0 -1
- package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +0 -2
- package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +0 -1
- package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +0 -4
- package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +0 -43
- package/web/assets/diagram-GF46GFSD-B2atbzmU.js +0 -24
- package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +0 -10
- package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +0 -85
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +0 -1
- package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +0 -162
- package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +0 -292
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +0 -106
- package/web/assets/index-CX_fADmQ.css +0 -2
- package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +0 -2
- package/web/assets/katex-K3KEBU37-qRQBy-EZ.js +0 -261
- package/web/assets/node-Ct_zna8U.js +0 -8
- package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +0 -1
- package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +0 -30
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +0 -1
- package/web/assets/sdk-CzHHH8tD.js +0 -37
- package/web/assets/src-Cv1eWg0o.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +0 -1
- package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +0 -34
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +0 -1
- package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +0 -78
- package/web/assets/xychartDiagram-N2JHSOCM-CoZ_Tits.js +0 -7
- /package/web/assets/{chunk-7W6UQGC5-pyKGssV3.js → chunk-LIEV3EAG-pyKGssV3.js} +0 -0
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
*
|
|
9
9
|
* 1. **super branch** — `provider.isSuperReceiver(receiverName)` →
|
|
10
10
|
* MRO walk skipping self
|
|
11
|
-
* 2. **Case 0 (compound)** — receiver has `.` or `(` → compound resolver
|
|
11
|
+
* 2. **Case 0 (compound)** — receiver has `.` or `(` → compound resolver.
|
|
12
|
+
* Also emits the interface-dispatch fan-out when the folded receiver type
|
|
13
|
+
* is an Interface (#2829) — see Case 4, which does the same.
|
|
12
14
|
* 3. **Case 0.5 (implicit `this` receiver)** — GATED: fires only when
|
|
13
15
|
* the language sets `resolveThisViaEnclosingClass === true` AND the
|
|
14
16
|
* receiver is literally `this` → enclosing-class + MRO chain walk
|
|
15
17
|
* with C++ member-name-hiding semantics. Languages that leave the
|
|
16
18
|
* toggle unset skip this case entirely; their `this` sites fall
|
|
17
19
|
* through to Case 4 via the synthesized `this` typeBinding (which
|
|
18
|
-
*
|
|
20
|
+
* emits the interface-dispatch fan-out that this case does not —
|
|
21
|
+
* as do Cases 0 since #2829 and 3b since #2832; Case 0.5 remains
|
|
22
|
+
* the only fold-or-walk case without it).
|
|
19
23
|
* 4. **Case 1 (namespace)** — receiver in `namespaceTargets` → exported def
|
|
20
24
|
* 5. **Case 2 (class-name / static receiver)** — receiver resolves to a
|
|
21
25
|
* class-like binding (Class/Interface/Struct/Record/Enum/Trait) → MRO
|
|
@@ -25,7 +29,9 @@
|
|
|
25
29
|
* 6. **Case 3 (dotted typeBinding for namespace prefix)** —
|
|
26
30
|
* `typeRef.rawName` like `models.User`
|
|
27
31
|
* 7. **Case 3b (chain-typebinding)** — `typeRef.rawName` has a dot
|
|
28
|
-
* but not a namespace prefix → compound resolver
|
|
32
|
+
* but not a namespace prefix → compound resolver. Also emits the
|
|
33
|
+
* interface-dispatch fan-out when the folded receiver type is an
|
|
34
|
+
* Interface (#2832) — same call Cases 0 and 4 make.
|
|
29
35
|
* 8. **Case 4 (simple typeBinding)** — `typeRef.rawName` has no dot →
|
|
30
36
|
* MRO walk + `findOwnedMember`
|
|
31
37
|
* 9. **Case 5 (value-receiver bridge)** — receiver is a `Const`/`Variable`
|
|
@@ -33,6 +39,15 @@
|
|
|
33
39
|
* (object-literal services). Last-resort fallback for lowercase
|
|
34
40
|
* receivers with no class-like or type-binding match. Mirrors
|
|
35
41
|
* the legacy DAG bridge in `call-processor.ts`.
|
|
42
|
+
* 10. **Case 6 (class-level member receiver)** — `Holder.repo.save(u)`,
|
|
43
|
+
* where the receiver's head is a CLASS and the one hop past it is a
|
|
44
|
+
* class-level (`isStatic`) field. Types the receiver from that field
|
|
45
|
+
* DEF's declared type rather than from a `typeBindings` entry, which
|
|
46
|
+
* is the thing a per-scope binding map cannot hold for a class that
|
|
47
|
+
* declares both a static and an instance member of one name. Gated on
|
|
48
|
+
* Case 0 having declined the same receiver, so it only ever adds an
|
|
49
|
+
* edge where there was none. Emits the interface-dispatch fan-out
|
|
50
|
+
* alongside Cases 0, 3b and 4.
|
|
36
51
|
*
|
|
37
52
|
* Reordering or merging cases changes resolution semantics.
|
|
38
53
|
*
|
|
@@ -44,55 +59,134 @@
|
|
|
44
59
|
* resolved to a wrong target.
|
|
45
60
|
*/
|
|
46
61
|
import { collectNamespaceTargets } from '../scope/namespace-targets.js';
|
|
47
|
-
import { findClassBindingInScope, findEnclosingClassDef, findExportedDef, findOwnedMember, findReceiverTypeBinding, findValueBindingInScope, isClassLike, } from '../scope/walkers.js';
|
|
62
|
+
import { bindsTypeParameter, findClassBindingInScope, findEnclosingClassDef, isReceiverOwnedButUnbound, findExportedDef, findOwnedMember, findReceiverTypeBinding, findValueBindingInScope, isClassLike, isNamespaceNameShadowed, resolveClassBindingForName, } from '../scope/walkers.js';
|
|
48
63
|
import { tryEmitEdge, tryEmitEdgeWithExplicitTargetId, } from '../graph-bridge/edges.js';
|
|
49
|
-
import { resolveCompoundReceiverClass } from '../passes/compound-receiver.js';
|
|
64
|
+
import { resolveCompoundReceiverClass, resolveCompoundReceiverTyped, } from '../passes/compound-receiver.js';
|
|
65
|
+
import { erasedTypeApplication, typeApplicationArguments } from '../../utils/template-arguments.js';
|
|
66
|
+
import { heritageTypeArgumentsKey, stepHeritageInstantiation, } from '../utils/generic-instantiation.js';
|
|
50
67
|
import { resolveDefGraphId } from '../graph-bridge/ids.js';
|
|
51
68
|
import { narrowOverloadCandidates, isOverloadAmbiguousAfterNormalization, } from './overload-narrowing.js';
|
|
52
|
-
import {
|
|
53
|
-
|
|
54
|
-
|
|
69
|
+
import { classifyReceiverShape } from '../resolution-outcome.js';
|
|
70
|
+
import { decodeReceiverChain } from '../../utils/receiver-chain-codec.js';
|
|
71
|
+
/** A bare, undecorated identifier and nothing else — see {@link isBareTypeName}. */
|
|
72
|
+
const BARE_TYPE_NAME_RE = /^[A-Za-z_$][\w$]*$/;
|
|
73
|
+
/**
|
|
74
|
+
* A type name a built-in test may be asked about: a bare, undecorated
|
|
75
|
+
* identifier and nothing else.
|
|
76
|
+
*
|
|
77
|
+
* `Promise<User>`, `[]Repo` and `Option<Repo>` all name a built-in CONTAINER
|
|
78
|
+
* whose ELEMENT is very often in-program, and an await/index/unwrap step is
|
|
79
|
+
* exactly how a receiver chain reaches that element. Answering "external"
|
|
80
|
+
* because the outer spelling matched a built-in would relabel a real in-program
|
|
81
|
+
* drop, which is the failure this whole function exists to stop. A decorated or
|
|
82
|
+
* dotted spelling is likewise not a built-in name, it merely contains one.
|
|
83
|
+
*/
|
|
84
|
+
function isBareTypeName(rawName) {
|
|
85
|
+
return BARE_TYPE_NAME_RE.test(rawName);
|
|
55
86
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Is this dropped receiver rooted inside the analyzed program?
|
|
89
|
+
*
|
|
90
|
+
* Asks of the receiver's BASE — the leftmost name the chain hangs off — what
|
|
91
|
+
* this index can DEMONSTRATE. Three answers, and the asymmetry between them is
|
|
92
|
+
* the whole point:
|
|
93
|
+
*
|
|
94
|
+
* - `in-program` — the base's declared type resolves here, or the base itself is
|
|
95
|
+
* a class, a qualified name, or a value this program declares. A real edge was
|
|
96
|
+
* lost; the hedge must fire.
|
|
97
|
+
* - `external` — POSITIVE evidence that the target is outside: the language
|
|
98
|
+
* itself names the base (or its bare declared type) a built-in. `console.log`,
|
|
99
|
+
* `fetch(...)`, `JSON.stringify` reach code no index contains, so there is no
|
|
100
|
+
* node an edge could have pointed at and nothing was lost.
|
|
101
|
+
* - `unknown` — everything else. An absence of evidence is NOT evidence of
|
|
102
|
+
* externality: an unannotated parameter (`function f(svc) { svc.a().b(); }`)
|
|
103
|
+
* is recorded nowhere in the scope model at all, and calling that "external"
|
|
104
|
+
* published `epistemic: 'exact'` over a genuinely missing in-program caller —
|
|
105
|
+
* strictly worse than hedging, because it is a confident wrong answer rather
|
|
106
|
+
* than an admitted gap. `unknown` counts WITH `in-program` in
|
|
107
|
+
* `summarizeUnresolvedReceivers`, which is the safe direction.
|
|
108
|
+
*
|
|
109
|
+
* Uses the AST-derived chain base when one was minted, and falls back to the
|
|
110
|
+
* head of the receiver text otherwise — never a regex over the source line.
|
|
111
|
+
*
|
|
112
|
+
* Exported for the unit tests that pin the three-way split; the pass is its only
|
|
113
|
+
* production caller.
|
|
114
|
+
*/
|
|
115
|
+
export function classifyReceiverOrigin(decoded, inScope, receiverName, scopes, options = {}) {
|
|
116
|
+
// The chain's base is authoritative. Without one, take the head of the
|
|
117
|
+
// receiver text up to the first member/call punctuation.
|
|
118
|
+
const base = decoded?.baseReceiverName ?? /^[A-Za-z_$][\w$]*/.exec(receiverName)?.[0];
|
|
119
|
+
if (base === undefined || base.length === 0)
|
|
120
|
+
return 'unknown';
|
|
121
|
+
const strip = options.stripTypePreservingDecoration;
|
|
122
|
+
const isBuiltIn = options.isBuiltInName;
|
|
123
|
+
// The base's declared TYPE, when it has one, is the strongest signal about
|
|
124
|
+
// where the member lives: `inputs.stream()` has an in-program base bound to
|
|
125
|
+
// `List<String>`, whose `stream` is in the JDK.
|
|
126
|
+
const binding = findReceiverTypeBinding(inScope, base, scopes);
|
|
127
|
+
if (binding !== undefined) {
|
|
128
|
+
// `resolveClassBindingForName`, not a bare lookup: it also strips template
|
|
129
|
+
// arguments, so an in-program generic base (`Box<String> b; b.open()`)
|
|
130
|
+
// resolves instead of being mislabelled and dropped from the hedge.
|
|
131
|
+
if (resolveClassBindingForName(binding.declaredAtScope, binding.rawName, scopes, strip) !==
|
|
132
|
+
undefined) {
|
|
133
|
+
return 'in-program';
|
|
73
134
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (defArgs !== undefined &&
|
|
81
|
-
defArgs.length === wantedArgs.length &&
|
|
82
|
-
defArgs.every((value, i) => value === wantedArgs[i])) {
|
|
83
|
-
matches.push(def);
|
|
84
|
-
}
|
|
135
|
+
// The declared type is not one this index contains. That is only proof of
|
|
136
|
+
// externality when the language itself names it — otherwise the type merely
|
|
137
|
+
// failed to resolve (an alias, an inferred callable, a generic parameter),
|
|
138
|
+
// and we fall through to ask what the index knows about the base itself.
|
|
139
|
+
if (isBareTypeName(binding.rawName) && isBuiltIn?.(binding.rawName) === true) {
|
|
140
|
+
return 'external';
|
|
85
141
|
}
|
|
86
|
-
if (matches.length === 1)
|
|
87
|
-
return matches[0];
|
|
88
|
-
// Scope extractor only records class definitions with bodies in C++, so
|
|
89
|
-
// forward declarations are not expected here. Keep fallback behavior for
|
|
90
|
-
// safety in non-ODR or mixed-language edge cases.
|
|
91
142
|
}
|
|
92
|
-
|
|
143
|
+
// Anything else this index knows by that name (namespace, module, free fn).
|
|
144
|
+
// O(1), so it goes ahead of the scope-chain walks below: all three checks are
|
|
145
|
+
// arms of the same `in-program` disjunction and none has a side effect, so
|
|
146
|
+
// answering from the index first is free and changes no verdict.
|
|
147
|
+
if (scopes.qualifiedNames.has(base))
|
|
148
|
+
return 'in-program';
|
|
149
|
+
// A type the program declares, used as a static receiver.
|
|
150
|
+
if (findClassBindingInScope(inScope, base, scopes, strip) !== undefined)
|
|
151
|
+
return 'in-program';
|
|
152
|
+
// A VALUE the program declares — an object-literal service, a local whose
|
|
153
|
+
// initializer we could not type (`const loc = makeIt(); loc.getUser().save()`),
|
|
154
|
+
// a field. The type channel had nothing usable to say about these, but the
|
|
155
|
+
// program demonstrably declares the name, so the lost edge is in-program and
|
|
156
|
+
// failing to type it is a resolver defect. This is the channel Case 5 already
|
|
157
|
+
// dispatches on; consulting it here keeps the diagnostic honest about the
|
|
158
|
+
// same population.
|
|
159
|
+
if (findValueBindingInScope(inScope, base, scopes) !== undefined)
|
|
160
|
+
return 'in-program';
|
|
161
|
+
// Positive external evidence, and the only kind reachable from this pass.
|
|
162
|
+
if (isBuiltIn?.(base) === true)
|
|
163
|
+
return 'external';
|
|
164
|
+
return 'unknown';
|
|
93
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Upper bound on how many implementors ONE interface member may fan out to at a
|
|
168
|
+
* single call site (#2829).
|
|
169
|
+
*
|
|
170
|
+
* Mirrors `MAX_PROPERTY_DISPATCH_FANOUT` in `property-dispatch.ts`, deliberately
|
|
171
|
+
* including its reporting half: a bare cap would silently discard valid dispatch
|
|
172
|
+
* targets, which is the same false-safe silence #2813 was filed about. The
|
|
173
|
+
* default matches that sibling's 32 — the fan-out is a per-call-site product, so
|
|
174
|
+
* an interface with hundreds of implementors (mock proliferation is the usual
|
|
175
|
+
* cause) multiplies the graph without adding information a reader can act on.
|
|
176
|
+
*
|
|
177
|
+
* Override with `GITNEXUS_MAX_INTERFACE_DISPATCH_FANOUT` for a repo with
|
|
178
|
+
* legitimately high implementor counts.
|
|
179
|
+
*/
|
|
180
|
+
export const MAX_INTERFACE_DISPATCH_FANOUT = (() => {
|
|
181
|
+
const env = Number(process.env.GITNEXUS_MAX_INTERFACE_DISPATCH_FANOUT);
|
|
182
|
+
return Number.isInteger(env) && env >= 1 ? env : 32;
|
|
183
|
+
})();
|
|
184
|
+
/** Bound on the sample of over-cap interface members kept for the warning. */
|
|
185
|
+
const MAX_REPORTED_SKIPPED_INTERFACES = 20;
|
|
94
186
|
export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, handledSites, provider, index, model, options = {}) {
|
|
95
187
|
let emitted = 0;
|
|
188
|
+
let dispatchFanoutSkipped = 0;
|
|
189
|
+
const dispatchFanoutSkippedNames = [];
|
|
96
190
|
// Per-pass dedup so the multiple cases don't double-emit if two of
|
|
97
191
|
// them resolve the same site to the same target. NEVER pre-seed
|
|
98
192
|
// from the reference index — see Contract Invariant I5.
|
|
@@ -102,66 +196,394 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
102
196
|
const hoistTypeBindingsToModule = provider.hoistTypeBindingsToModule === true;
|
|
103
197
|
const compoundOpts = {
|
|
104
198
|
fieldFallback,
|
|
105
|
-
|
|
199
|
+
elementTypeOf: provider.elementTypeOf,
|
|
106
200
|
hoistTypeBindingsToModule,
|
|
107
201
|
stripReceiverCastExpressions: provider.stripReceiverCastExpressions === true,
|
|
202
|
+
constructionSyntax: provider.constructionSyntax,
|
|
203
|
+
stripTypePreservingDecoration: provider.stripTypePreservingDecoration,
|
|
204
|
+
resolveThisViaEnclosingClass: provider.resolveThisViaEnclosingClass,
|
|
205
|
+
};
|
|
206
|
+
// Loop-invariant: both hooks come off the pass arguments, so the options bag
|
|
207
|
+
// for `classifyReceiverOrigin` is built once here rather than per dropped site.
|
|
208
|
+
const receiverOriginOpts = {
|
|
209
|
+
stripTypePreservingDecoration: provider.stripTypePreservingDecoration,
|
|
210
|
+
isBuiltInName: options.isBuiltInName,
|
|
108
211
|
};
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
212
|
+
// Maps class-like graph ids back to ALL scope definitions that resolved to
|
|
213
|
+
// them. Same-file partial declarations share one graph id but keep distinct
|
|
214
|
+
// DefIds, and `pickOverload` keys member lookup by those DefIds. Preserving
|
|
215
|
+
// every part makes dispatch independent of declaration order.
|
|
216
|
+
const graphIdToClassDefs = new Map();
|
|
217
|
+
// The same correspondence read the other way, so the dispatch walk can name a
|
|
218
|
+
// heritage EDGE (which is keyed by graph ids) from the two DEFS it holds.
|
|
219
|
+
const classGraphIdByDefId = new Map();
|
|
220
|
+
/**
|
|
221
|
+
* Does THIS language record generic type parameters (#2912)?
|
|
222
|
+
*
|
|
223
|
+
* `SymbolDefinition.typeParameters` is absent both for a non-generic
|
|
224
|
+
* declaration and for every declaration in a language whose captures do not
|
|
225
|
+
* emit `@declaration.type-parameters`, and instantiation filtering needs the
|
|
226
|
+
* two told apart: in the second case a heritage argument `T` is a type
|
|
227
|
+
* VARIABLE that would otherwise read as a concrete type named "T", and
|
|
228
|
+
* `class Box<T> : IValidator<T>` would be pruned out of every instantiation.
|
|
229
|
+
*
|
|
230
|
+
* Evidence rather than a declared capability, because the evidence is exactly
|
|
231
|
+
* as good and costs nothing: one run resolves one language (`phase.ts` loops
|
|
232
|
+
* per language), so a single generic declaration anywhere in it proves the
|
|
233
|
+
* captures record parameters. A run where none exists cannot be harmed by the
|
|
234
|
+
* answer — with no generic declaration there is no type variable to mistake.
|
|
235
|
+
*/
|
|
236
|
+
let languageCapturesTypeParameters = false;
|
|
115
237
|
for (const parsed of parsedFiles) {
|
|
116
238
|
for (const def of parsed.localDefs) {
|
|
117
|
-
if (def.type
|
|
239
|
+
if (!isClassLike(def.type))
|
|
118
240
|
continue;
|
|
119
241
|
const graphId = resolveDefGraphId(parsed.filePath, def, nodeLookup);
|
|
120
|
-
if (graphId
|
|
121
|
-
|
|
242
|
+
if (graphId === undefined)
|
|
243
|
+
continue;
|
|
244
|
+
let defs = graphIdToClassDefs.get(graphId);
|
|
245
|
+
if (defs === undefined) {
|
|
246
|
+
defs = [];
|
|
247
|
+
graphIdToClassDefs.set(graphId, defs);
|
|
248
|
+
}
|
|
249
|
+
defs.push(def);
|
|
250
|
+
classGraphIdByDefId.set(def.nodeId, graphId);
|
|
251
|
+
if (def.typeParameters !== undefined && def.typeParameters.length > 0) {
|
|
252
|
+
languageCapturesTypeParameters = true;
|
|
253
|
+
}
|
|
122
254
|
}
|
|
123
255
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
256
|
+
// Direct subtypes of a type, keyed by the SUPERtype's def id.
|
|
257
|
+
//
|
|
258
|
+
// Built from IMPLEMENTS **and** EXTENDS (#2829). IMPLEMENTS alone is not the
|
|
259
|
+
// set of implementations: `preEmitInheritanceEdges` classifies heritage by the
|
|
260
|
+
// TARGET's kind, so `interface B extends A` is stored as `B IMPLEMENTS A` and
|
|
261
|
+
// an INTERFACE lands in A's list; and a concrete class reaches its interface
|
|
262
|
+
// through `class C extends AbstractBase` (EXTENDS) + `AbstractBase implements
|
|
263
|
+
// I` (IMPLEMENTS), so it is two hops away and invisible to a depth-1 walk.
|
|
264
|
+
// Both shapes previously ended the fan-out on a bodiless declaration while the
|
|
265
|
+
// only executable target got no edge at all.
|
|
266
|
+
const subtypesBySupertypeDefId = new Map();
|
|
267
|
+
const addSubtype = (superId, sub) => {
|
|
268
|
+
let list = subtypesBySupertypeDefId.get(superId);
|
|
131
269
|
if (list === undefined) {
|
|
132
270
|
list = [];
|
|
133
|
-
|
|
271
|
+
subtypesBySupertypeDefId.set(superId, list);
|
|
272
|
+
}
|
|
273
|
+
list.push(sub);
|
|
274
|
+
};
|
|
275
|
+
for (const relType of ['IMPLEMENTS', 'EXTENDS']) {
|
|
276
|
+
for (const rel of graph.iterRelationshipsByType(relType)) {
|
|
277
|
+
const superDefs = graphIdToClassDefs.get(rel.targetId);
|
|
278
|
+
const subDefs = graphIdToClassDefs.get(rel.sourceId);
|
|
279
|
+
if (superDefs === undefined || subDefs === undefined)
|
|
280
|
+
continue;
|
|
281
|
+
for (const superDef of superDefs) {
|
|
282
|
+
for (const subDef of subDefs)
|
|
283
|
+
addSubtype(superDef.nodeId, subDef);
|
|
284
|
+
}
|
|
134
285
|
}
|
|
135
|
-
list.push(implDef);
|
|
136
286
|
}
|
|
137
|
-
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Is this member a bodiless DECLARATION rather than an implementation?
|
|
289
|
+
*
|
|
290
|
+
* An interface method, and an `abstract` method on an abstract base, are
|
|
291
|
+
* both declarations: dispatching to them names something with no body while
|
|
292
|
+
* the executable target sits further down the hierarchy. `isAbstract` lives
|
|
293
|
+
* on the graph NODE (the structure phase sets it), not on `SymbolDefinition`,
|
|
294
|
+
* so this resolves the def to its node. A def that cannot be resolved is
|
|
295
|
+
* treated as NOT abstract — the fail-open direction, matching how the rest of
|
|
296
|
+
* this pass treats an unresolvable lookup.
|
|
297
|
+
*/
|
|
298
|
+
const isDeclarationOnly = (def) => {
|
|
299
|
+
const graphId = resolveDefGraphId(def.filePath, def, nodeLookup);
|
|
300
|
+
if (graphId === undefined)
|
|
301
|
+
return false;
|
|
302
|
+
return graph.getNode(graphId)?.properties.isAbstract === true;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Can an INSTANCE-typed receiver reach this member? A static member cannot be,
|
|
306
|
+
* ever — `class C implements I { static save() {} }` does not satisfy `I`
|
|
307
|
+
* (TypeScript rejects it outright as TS2420, "Property 'save' is missing"), so
|
|
308
|
+
* an edge to it from an `I`-typed receiver names a target no dispatch can
|
|
309
|
+
* produce. Every comparable tool draws the same line: tsserver partitions
|
|
310
|
+
* static from instance results, clangd gates on `isVirtual()` (C++ forbids
|
|
311
|
+
* virtual statics), jdtls filters abstract-or-static, and class-hierarchy
|
|
312
|
+
* analysis expands only VIRTUAL call sites — a static call already has exactly
|
|
313
|
+
* one target and needs no fan-out.
|
|
314
|
+
*
|
|
315
|
+
* Two sources answer this, and the order matters:
|
|
316
|
+
*
|
|
317
|
+
* 1. `provider.isStaticOnly` when the language declares it. It is the
|
|
318
|
+
* precise answer, because a language that needs the distinction defines
|
|
319
|
+
* it exactly — Kotlin marks only COMPANION-promoted defs, so a Kotlin
|
|
320
|
+
* `object Impl : Iface { override fun handle() }` is correctly kept: an
|
|
321
|
+
* `object` is a singleton INSTANCE and its members really are reachable
|
|
322
|
+
* through an `Iface`-typed receiver.
|
|
323
|
+
* 2. Otherwise the graph node's `isStatic`. For every language that does not
|
|
324
|
+
* declare the hook, that flag comes from the member's own modifier (or,
|
|
325
|
+
* for Ruby, from `singleton_class` — `def self.foo`, which is likewise
|
|
326
|
+
* unreachable through an instance), so it means what we need here.
|
|
327
|
+
*
|
|
328
|
+
* Getting that order wrong is a live regression, not a hypothetical: the
|
|
329
|
+
* method extractor derives `isStatic` from the OWNER type as well as the
|
|
330
|
+
* member (`method-extractors/generic.ts`, `staticOwnerTypes`), and the JVM
|
|
331
|
+
* config lists `object_declaration`. Reading the flag first would delete
|
|
332
|
+
* Kotlin object implementations from the fan-out. A language that needs
|
|
333
|
+
* precision declares the hook; that is the upgrade path.
|
|
334
|
+
*
|
|
335
|
+
* Unresolvable defs fail open (treated as reachable), matching
|
|
336
|
+
* `isDeclarationOnly` and the rest of this pass.
|
|
337
|
+
*/
|
|
338
|
+
const isUnreachableByInstanceDispatch = (def) => {
|
|
339
|
+
const staticOnly = provider.isStaticOnly;
|
|
340
|
+
if (staticOnly !== undefined)
|
|
341
|
+
return staticOnly(def) === true;
|
|
342
|
+
const graphId = resolveDefGraphId(def.filePath, def, nodeLookup);
|
|
343
|
+
if (graphId === undefined)
|
|
344
|
+
return false;
|
|
345
|
+
return graph.getNode(graphId)?.properties.isStatic === true;
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* What does this written type argument NAME, as seen from `scopeId` (#2912)?
|
|
349
|
+
*
|
|
350
|
+
* The scope is load-bearing: a heritage argument is resolved from the
|
|
351
|
+
* declaring class's own scope and a receiver argument from the call site's,
|
|
352
|
+
* because a name means what it means where it was WRITTEN. Resolving both
|
|
353
|
+
* makes `Models.User` and an imported `User` one type, which a string
|
|
354
|
+
* comparison could only get wrong.
|
|
355
|
+
*
|
|
356
|
+
* Neither answer is an error: a name that binds nothing and is not built in
|
|
357
|
+
* comes back ungrounded, which the matcher reads as "unknown" and keeps.
|
|
358
|
+
*
|
|
359
|
+
* A TYPE PARAMETER is reported as such rather than left to the ungrounded
|
|
360
|
+
* path, because `resolveClassBindingForName` answers a bounded one with its
|
|
361
|
+
* BOUND's declaration — grounded, and the wrong thing to compare.
|
|
362
|
+
*/
|
|
363
|
+
const groundTypeArgument = (name, scopeId) => {
|
|
364
|
+
const def = scopeId === undefined ? undefined : resolveClassBindingForName(scopeId, name, scopes);
|
|
365
|
+
return {
|
|
366
|
+
...(def !== undefined ? { definitionId: def.nodeId } : {}),
|
|
367
|
+
builtIn: options.isBuiltInName?.(name) === true,
|
|
368
|
+
...(scopeId !== undefined && bindsTypeParameter(scopeId, name, scopes)
|
|
369
|
+
? { typeVariable: true }
|
|
370
|
+
: {}),
|
|
371
|
+
};
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
374
|
+
* Emit secondary CALLS edges with reason='interface-dispatch' when the primary
|
|
375
|
+
* receiver-typed edge targeted an Interface's method.
|
|
376
|
+
*
|
|
377
|
+
* Walks the SUBTYPE CLOSURE of the interface rather than its direct
|
|
378
|
+
* implementors (#2829). Two shapes made the depth-1 walk both wrong and
|
|
379
|
+
* incomplete, each reproduced in plain Java:
|
|
380
|
+
*
|
|
381
|
+
* interface ReadCloser extends Reader { int read(String p); } // re-declares
|
|
382
|
+
* abstract class AbstractHandler implements Handler { public abstract void handle(String s); }
|
|
383
|
+
*
|
|
384
|
+
* In both, the depth-1 list contains a type whose `read`/`handle` is a bodiless
|
|
385
|
+
* declaration, so the fan-out emitted an edge to *that* — while the only class
|
|
386
|
+
* with a body (`FileRC`, `RealHandler`) is one hop further down and received
|
|
387
|
+
* nothing at all. Descending and skipping declarations fixes both directions
|
|
388
|
+
* at once: the wrong edge disappears and the real implementation gains one.
|
|
389
|
+
*
|
|
390
|
+
* Descent continues THROUGH a type that supplied a concrete member, because an
|
|
391
|
+
* override further down is an equally real runtime target — dispatch is an
|
|
392
|
+
* over-approximation by design, and stopping early would silently prefer the
|
|
393
|
+
* base.
|
|
394
|
+
*
|
|
395
|
+
* The closure is walked carrying the receiver's generic INSTANTIATION (#2912).
|
|
396
|
+
* `IValidator<string>` and `IValidator<int>` are one declaration and therefore
|
|
397
|
+
* one subtype list, so without the substitution a `IValidator<string>` call
|
|
398
|
+
* reaches `IntValidator.Check(int)` — a target no dispatch can produce. Each
|
|
399
|
+
* hop unifies the arguments the subtype wrote against the ones the supertype
|
|
400
|
+
* is known to hold; an incompatible hop is skipped BEFORE the visit is
|
|
401
|
+
* recorded, so a type reachable by a second, compatible path still gets its
|
|
402
|
+
* edge, and skipped WITHOUT descending, because its own subtypes inherit the
|
|
403
|
+
* mismatch.
|
|
404
|
+
* Every uncertainty keeps the target — see `generic-instantiation.ts`.
|
|
405
|
+
*/
|
|
406
|
+
const emitInterfaceDispatchFor = (ownerDef, memberName, primaryMemberDef, site, confidence, calleeCapture,
|
|
407
|
+
/** The receiver's declared type AS WRITTEN (`IValidator<string>`), or
|
|
408
|
+
* `undefined` where the case could not recover it — which restores the
|
|
409
|
+
* unfiltered fan-out for that site rather than guessing.
|
|
410
|
+
*
|
|
411
|
+
* The SPELLING rather than the parsed arguments, so the parse happens after
|
|
412
|
+
* the two gates below rather than at every resolved receiver site: all five
|
|
413
|
+
* cases call this unconditionally, and the overwhelming majority of
|
|
414
|
+
* receivers are concrete classes that return at the first line. */
|
|
415
|
+
receiverTypeSpelling) => {
|
|
142
416
|
if (ownerDef.type !== 'Interface')
|
|
143
417
|
return 0;
|
|
144
|
-
|
|
145
|
-
if (impls === undefined)
|
|
418
|
+
if (subtypesBySupertypeDefId.get(ownerDef.nodeId) === undefined)
|
|
146
419
|
return 0;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
420
|
+
const receiverTypeArguments = receiverTypeSpelling === undefined
|
|
421
|
+
? undefined
|
|
422
|
+
: typeApplicationArguments(receiverTypeSpelling);
|
|
423
|
+
// Captures only `site`, so it is built once per SITE rather than once per
|
|
424
|
+
// subtype visited. Its partner below cannot be: it is keyed by the subtype.
|
|
425
|
+
const resolveSupertypeArgument = (name) => groundTypeArgument(name, site.inScope);
|
|
426
|
+
const targetByMemberId = new Map();
|
|
427
|
+
const bestIncomingCount = new Map([[ownerDef.nodeId, 0]]);
|
|
428
|
+
const queue = [
|
|
429
|
+
{
|
|
430
|
+
typeId: ownerDef.nodeId,
|
|
431
|
+
ancestorImplementationCount: 0,
|
|
432
|
+
typeArguments: receiverTypeArguments,
|
|
433
|
+
},
|
|
434
|
+
];
|
|
435
|
+
let head = 0;
|
|
436
|
+
let discoveryOrder = 0;
|
|
437
|
+
while (head < queue.length) {
|
|
438
|
+
const current = queue[head++];
|
|
439
|
+
// The whole instantiation apparatus hangs off ONE question: is the
|
|
440
|
+
// supertype's own instantiation known? It is not for a non-generic
|
|
441
|
+
// receiver, nor for any language that captures no heritage arguments, so
|
|
442
|
+
// those walks skip every lookup below and emit exactly what they did
|
|
443
|
+
// before #2912.
|
|
444
|
+
const superGraphId = current.typeArguments === undefined ? undefined : classGraphIdByDefId.get(current.typeId);
|
|
445
|
+
for (const subDef of subtypesBySupertypeDefId.get(current.typeId) ?? []) {
|
|
446
|
+
const previousIncomingCount = bestIncomingCount.get(subDef.nodeId);
|
|
447
|
+
if (previousIncomingCount !== undefined &&
|
|
448
|
+
previousIncomingCount <= current.ancestorImplementationCount) {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
// What THIS heritage clause instantiated its base with. `superGraphId`
|
|
452
|
+
// already answers "is the supertype's instantiation known?", so it gates
|
|
453
|
+
// the whole lookup once instead of being re-asked at each step below.
|
|
454
|
+
let subtypeArguments;
|
|
455
|
+
if (superGraphId !== undefined) {
|
|
456
|
+
const subGraphId = classGraphIdByDefId.get(subDef.nodeId);
|
|
457
|
+
const heritageArguments = subGraphId === undefined
|
|
458
|
+
? undefined
|
|
459
|
+
: options.heritageTypeArguments?.get(heritageTypeArgumentsKey(subGraphId, superGraphId));
|
|
460
|
+
if (heritageArguments !== undefined) {
|
|
461
|
+
const subtypeScopeId = index.classScopeByDefId.get(subDef.nodeId)?.id;
|
|
462
|
+
const step = stepHeritageInstantiation({
|
|
463
|
+
supertypeArguments: current.typeArguments,
|
|
464
|
+
heritageArguments,
|
|
465
|
+
subtypeParameters: subDef.typeParameters,
|
|
466
|
+
// The "this subtype declares parameters" disjunct an earlier
|
|
467
|
+
// revision carried here could never decide: `subDef` comes out of
|
|
468
|
+
// the same loop that sets this flag, from exactly these defs, so a
|
|
469
|
+
// subtype with parameters has already set it.
|
|
470
|
+
subtypeParametersComplete: languageCapturesTypeParameters,
|
|
471
|
+
resolveSupertypeArgument,
|
|
472
|
+
resolveHeritageArgument: (name) => groundTypeArgument(name, subtypeScopeId),
|
|
473
|
+
normalize: provider.normalizeTypeArgument,
|
|
474
|
+
});
|
|
475
|
+
// Skipped BEFORE the visit is recorded, so a type reachable by a
|
|
476
|
+
// second, compatible path still gets its edge; and without
|
|
477
|
+
// descending, because its own subtypes inherit the mismatch.
|
|
478
|
+
if (!step.compatible)
|
|
479
|
+
continue;
|
|
480
|
+
subtypeArguments = step.subtypeArguments;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
bestIncomingCount.set(subDef.nodeId, current.ancestorImplementationCount);
|
|
484
|
+
const implMember = pickOverload(subDef.nodeId, memberName, site, model, provider);
|
|
485
|
+
let descendantImplementationCount = current.ancestorImplementationCount;
|
|
486
|
+
if (implMember !== undefined &&
|
|
487
|
+
implMember !== OVERLOAD_AMBIGUOUS &&
|
|
488
|
+
implMember.isDeleted !== true &&
|
|
489
|
+
implMember.nodeId !== primaryMemberDef.nodeId &&
|
|
490
|
+
!isDeclarationOnly(implMember) &&
|
|
491
|
+
!isUnreachableByInstanceDispatch(implMember)) {
|
|
492
|
+
const existing = targetByMemberId.get(implMember.nodeId);
|
|
493
|
+
const syntheticOwnerPriority = subDef.isSynthetic === true ? 1 : 0;
|
|
494
|
+
if (existing === undefined ||
|
|
495
|
+
syntheticOwnerPriority < existing.syntheticOwnerPriority ||
|
|
496
|
+
(syntheticOwnerPriority === existing.syntheticOwnerPriority &&
|
|
497
|
+
current.ancestorImplementationCount < existing.ancestorImplementationCount)) {
|
|
498
|
+
targetByMemberId.set(implMember.nodeId, {
|
|
499
|
+
member: implMember,
|
|
500
|
+
syntheticOwnerPriority,
|
|
501
|
+
ancestorImplementationCount: current.ancestorImplementationCount,
|
|
502
|
+
discoveryOrder: existing?.discoveryOrder ?? discoveryOrder++,
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
descendantImplementationCount++;
|
|
506
|
+
}
|
|
507
|
+
queue.push({
|
|
508
|
+
typeId: subDef.nodeId,
|
|
509
|
+
ancestorImplementationCount: descendantImplementationCount,
|
|
510
|
+
typeArguments: subtypeArguments,
|
|
511
|
+
});
|
|
154
512
|
}
|
|
155
|
-
|
|
156
|
-
|
|
513
|
+
}
|
|
514
|
+
const targets = [...targetByMemberId.values()]
|
|
515
|
+
.sort((left, right) => left.syntheticOwnerPriority - right.syntheticOwnerPriority ||
|
|
516
|
+
left.ancestorImplementationCount - right.ancestorImplementationCount ||
|
|
517
|
+
left.discoveryOrder - right.discoveryOrder)
|
|
518
|
+
.map((target) => target.member);
|
|
519
|
+
// Bounded, and NEVER silently (#2829). An interface with a very large
|
|
520
|
+
// implementor set multiplies edges by every call site — Go, TypeScript and
|
|
521
|
+
// Kotlin do not set `collapseMemberCallsByCallerTarget`, so the product is
|
|
522
|
+
// per SITE. Truncating without saying so would recreate the false-safe
|
|
523
|
+
// silence this whole issue is about, which is why the sibling
|
|
524
|
+
// `MAX_PROPERTY_DISPATCH_FANOUT` reports its dropped keys too.
|
|
525
|
+
if (targets.length > MAX_INTERFACE_DISPATCH_FANOUT) {
|
|
526
|
+
dispatchFanoutSkipped += targets.length - MAX_INTERFACE_DISPATCH_FANOUT;
|
|
527
|
+
if (dispatchFanoutSkippedNames.length < MAX_REPORTED_SKIPPED_INTERFACES) {
|
|
528
|
+
const dropped = targets
|
|
529
|
+
.slice(MAX_INTERFACE_DISPATCH_FANOUT, MAX_INTERFACE_DISPATCH_FANOUT + 5)
|
|
530
|
+
.map((target) => target.qualifiedName ?? target.nodeId);
|
|
531
|
+
const omitted = targets.length - MAX_INTERFACE_DISPATCH_FANOUT - dropped.length;
|
|
532
|
+
dispatchFanoutSkippedNames.push(`${ownerDef.qualifiedName ?? ownerDef.nodeId}.${memberName} (${targets.length} targets; ` +
|
|
533
|
+
`dropped: ${dropped.join(', ')}${omitted > 0 ? `, +${omitted} more` : ''})`);
|
|
534
|
+
}
|
|
535
|
+
targets.length = MAX_INTERFACE_DISPATCH_FANOUT;
|
|
536
|
+
}
|
|
537
|
+
let n = 0;
|
|
538
|
+
for (const implMember of targets) {
|
|
157
539
|
const ok = tryEmitEdge(graph, scopes, nodeLookup, site, implMember, 'interface-dispatch', seen, confidence, collapse, calleeCapture);
|
|
158
540
|
if (ok)
|
|
159
541
|
n++;
|
|
160
542
|
}
|
|
161
543
|
return n;
|
|
162
544
|
};
|
|
545
|
+
/**
|
|
546
|
+
* Declared type of the CLASS-LEVEL field named `fieldName` on `ownerId`, or
|
|
547
|
+
* `undefined` when the owner declares no such field, declares only an
|
|
548
|
+
* instance one, or declares one whose type was never captured.
|
|
549
|
+
*
|
|
550
|
+
* Both facts live on the graph NODE rather than on `SymbolDefinition` —
|
|
551
|
+
* `isStatic` is set by the structure phase and `declaredType` by the field
|
|
552
|
+
* extractor — which is the same place {@link isUnreachableByInstanceDispatch}
|
|
553
|
+
* reads `isStatic` from, so this introduces no new dependency.
|
|
554
|
+
*
|
|
555
|
+
* `isStatic === true` is required, not merely preferred. The receiver that
|
|
556
|
+
* asks this question resolved its head to the CLASS, so an instance field of
|
|
557
|
+
* that name is not reachable through it and answering with the instance
|
|
558
|
+
* field's type would type the receiver as something the source cannot
|
|
559
|
+
* denote. A def that resolves to no node, or a node with no captured type,
|
|
560
|
+
* answers `undefined` — the declining direction, matching how the rest of
|
|
561
|
+
* this pass treats an unresolvable lookup.
|
|
562
|
+
*/
|
|
563
|
+
const declaredTypeOfClassLevelField = (ownerId, fieldName) => {
|
|
564
|
+
for (const candidate of model.fields.lookupAllByOwner(ownerId, fieldName)) {
|
|
565
|
+
const graphId = resolveDefGraphId(candidate.filePath, candidate, nodeLookup);
|
|
566
|
+
if (graphId === undefined)
|
|
567
|
+
continue;
|
|
568
|
+
const properties = graph.getNode(graphId)?.properties;
|
|
569
|
+
if (properties?.isStatic !== true)
|
|
570
|
+
continue;
|
|
571
|
+
const declaredType = properties.declaredType;
|
|
572
|
+
if (typeof declaredType !== 'string')
|
|
573
|
+
continue;
|
|
574
|
+
const trimmed = declaredType.trim();
|
|
575
|
+
if (trimmed.length === 0)
|
|
576
|
+
continue;
|
|
577
|
+
return trimmed;
|
|
578
|
+
}
|
|
579
|
+
return undefined;
|
|
580
|
+
};
|
|
163
581
|
for (const parsed of parsedFiles) {
|
|
164
|
-
const namespaceTargets = collectNamespaceTargets(parsed, scopes
|
|
582
|
+
const namespaceTargets = collectNamespaceTargets(parsed, scopes, {
|
|
583
|
+
receiverPaths: provider.namespaceReceiverPaths,
|
|
584
|
+
moduleFileExists: (filePath) => index.moduleScopeByFile.has(filePath),
|
|
585
|
+
});
|
|
586
|
+
const fileCompoundOpts = { ...compoundOpts, namespaceTargets };
|
|
165
587
|
// Per-file resolved-callee-id capture context (#2227 U2). Built once per
|
|
166
588
|
// file; `undefined` when the sink is absent (pdg off) so the `tryEmitEdge`
|
|
167
589
|
// capture is a no-op and emission stays byte-identical (R4).
|
|
@@ -176,6 +598,27 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
176
598
|
const receiverName = site.explicitReceiver.name;
|
|
177
599
|
const memberName = site.name;
|
|
178
600
|
const siteKey = `${parsed.filePath}:${site.atRange.startLine}:${site.atRange.startCol}`;
|
|
601
|
+
// ── owned-but-unbound receiver ───────────────────────────────
|
|
602
|
+
// The language declared this scope REBINDS the receiver and gave
|
|
603
|
+
// it no type — a JS/TS ordinary `function`, whose `this` comes
|
|
604
|
+
// from the call site (#2701). No enclosing type can be its type,
|
|
605
|
+
// so this is a definitive negative, not a miss: suppress the site
|
|
606
|
+
// instead of letting the receiver-blind lexical fallback in
|
|
607
|
+
// `lookupCore` match the enclosing class's member by name.
|
|
608
|
+
// No-op for every language that leaves `Scope.ownsReceivers` unset.
|
|
609
|
+
if (isReceiverOwnedButUnbound(site.inScope, receiverName, scopes)) {
|
|
610
|
+
options.recordResolutionOutcome?.({
|
|
611
|
+
kind: 'suppressed',
|
|
612
|
+
phase: 'receiver-bound-calls',
|
|
613
|
+
filePath: parsed.filePath,
|
|
614
|
+
name: site.name,
|
|
615
|
+
range: site.atRange,
|
|
616
|
+
reason: 'receiver-owned-but-unbound',
|
|
617
|
+
candidateIds: [],
|
|
618
|
+
});
|
|
619
|
+
handledSites.add(siteKey);
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
179
622
|
// ── super branch ─────────────────────────────────────────────
|
|
180
623
|
// Languages with caller-context-dependent super classification
|
|
181
624
|
// (C++) define `isSuperReceiverInContext`; we prefer it. Simple
|
|
@@ -249,9 +692,32 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
249
692
|
}
|
|
250
693
|
}
|
|
251
694
|
// ── Case 0: compound receiver ────────────────────────────────
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
695
|
+
// #2744: remember a compound receiver we could not type. Reported at
|
|
696
|
+
// the end of the site loop, not here — a later case may still resolve
|
|
697
|
+
// the site, and only a site that survives every case is a real drop.
|
|
698
|
+
let compoundReceiverUnresolved = false;
|
|
699
|
+
// The punctuation test is a C-family heuristic and it is the reason
|
|
700
|
+
// `repos[0].save()` is INVISIBLE in all 14 languages: a subscript receiver
|
|
701
|
+
// contains neither `.` nor `(`, so this case never fired, the fold was
|
|
702
|
+
// never consulted, and no drop was recorded either — the call vanished
|
|
703
|
+
// with the instrument blind to it. PHP `->` and `::` receivers are lost
|
|
704
|
+
// the same way.
|
|
705
|
+
//
|
|
706
|
+
// A minted receiver chain is the STRUCTURAL answer to the same question:
|
|
707
|
+
// the capture layer walked the real AST and found the receiver is an
|
|
708
|
+
// expression, whatever punctuation it happens to be spelled with. Trusting
|
|
709
|
+
// that instead of the text is the substitution this whole line of work
|
|
710
|
+
// exists to make.
|
|
711
|
+
if (receiverName.includes('.') ||
|
|
712
|
+
receiverName.includes('(') ||
|
|
713
|
+
site.receiverChain !== undefined) {
|
|
714
|
+
const resolved = resolveCompoundReceiverTyped(receiverName, site.inScope, scopes, index,
|
|
715
|
+
// Group A: the receiver IS this site's expression, so the site's
|
|
716
|
+
// captured chain describes it and the structural fold applies.
|
|
717
|
+
{ ...fileCompoundOpts, receiverChain: site.receiverChain });
|
|
718
|
+
const currentClass = resolved?.def;
|
|
719
|
+
compoundReceiverUnresolved = currentClass === undefined;
|
|
720
|
+
if (resolved !== undefined && currentClass !== undefined) {
|
|
255
721
|
const chain = [currentClass.nodeId, ...scopes.methodDispatch.mroFor(currentClass.nodeId)];
|
|
256
722
|
let memberDef;
|
|
257
723
|
let ambiguousOwnerId;
|
|
@@ -294,6 +760,45 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
294
760
|
const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
|
|
295
761
|
if (ok)
|
|
296
762
|
emitted++;
|
|
763
|
+
// Interface dispatch, exactly as Case 4 does it (#2813). When the
|
|
764
|
+
// folded receiver type is an Interface, the primary edge above
|
|
765
|
+
// lands on the interface's own method DECLARATION; these secondary
|
|
766
|
+
// edges are what reach the implementations.
|
|
767
|
+
//
|
|
768
|
+
// Case 4 had this and Case 0 did not, which made the gap a property
|
|
769
|
+
// of receiver SYNTAX rather than of types: a struct-field receiver
|
|
770
|
+
// (`s.orderRepo`) contains a dot, so it always takes Case 0, while
|
|
771
|
+
// the same interface reached through a local or parameter is a bare
|
|
772
|
+
// name and reaches Case 4. Field-held interfaces — dependency
|
|
773
|
+
// injection, in other words — were the half that silently lost every
|
|
774
|
+
// implementation edge.
|
|
775
|
+
//
|
|
776
|
+
// `currentClass` is the receiver's own folded type, matching what
|
|
777
|
+
// Case 4 passes. `emitInterfaceDispatchFor` self-gates on
|
|
778
|
+
// `ownerDef.type !== 'Interface'`, so this is inert for every
|
|
779
|
+
// concrete receiver and needs no language check of its own — a
|
|
780
|
+
// member whose owner resolved to a Struct emits nothing extra.
|
|
781
|
+
//
|
|
782
|
+
// Confidence mirrors THIS case's own primary emit above — the 0.85
|
|
783
|
+
// literal — so a site's dispatch edges never claim more certainty
|
|
784
|
+
// than the edge they hang off.
|
|
785
|
+
//
|
|
786
|
+
// Case 4 passes a site.kind-dependent value instead (1.0 for
|
|
787
|
+
// read/write, `:1399-1405`) because ITS primary varies the same way.
|
|
788
|
+
// Case 0 does branch on `site.kind` when picking the member
|
|
789
|
+
// (`:713-716`), it simply does not vary reason/confidence with it,
|
|
790
|
+
// so there is no 1.0 arm here to mirror. That leaves a read/write
|
|
791
|
+
// ACCESSES through a compound receiver at 0.85 while the same access
|
|
792
|
+
// through a bare name is 1.0 — a PRE-EXISTING difference between the
|
|
793
|
+
// two cases' primaries, not something this fan-out introduces.
|
|
794
|
+
// Deliberately not "fixed" here: changing Case 0's primary
|
|
795
|
+
// confidence is a separate behavioural change affecting every
|
|
796
|
+
// language, and is out of scope for #2813.
|
|
797
|
+
//
|
|
798
|
+
// The instantiation the FOLD typed this receiver from — the
|
|
799
|
+
// declared spelling of `this.repo` / `svc.get().repo`, which the
|
|
800
|
+
// folded class alone no longer carries (#2912).
|
|
801
|
+
emitted += emitInterfaceDispatchFor(currentClass, memberName, memberDef, site, 0.85, calleeCapture, resolved.declaredSpelling);
|
|
297
802
|
// Always mark handled when the site was resolved, even
|
|
298
803
|
// if the edge was deduplicated (collapse mode), so
|
|
299
804
|
// `emitReferencesViaLookup` doesn't re-emit from the
|
|
@@ -428,7 +933,23 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
428
933
|
}
|
|
429
934
|
}
|
|
430
935
|
// ── Case 1: namespace receiver ───────────────────────────────
|
|
431
|
-
|
|
936
|
+
// `namespaceTargets` is collected per FILE, so a local declaration that
|
|
937
|
+
// shadows the import must suppress it — `def f(pkg): pkg.db.query()`
|
|
938
|
+
// calls a method on the PARAMETER, and resolving it through the import
|
|
939
|
+
// emits a wrong edge, not a missing one. The compound-receiver
|
|
940
|
+
// construction path has applied this guard since #2770; Case 1 never did,
|
|
941
|
+
// for dotted and single-segment receivers alike.
|
|
942
|
+
// Map lookup FIRST: it is an O(1) miss for almost every site, and the
|
|
943
|
+
// guard is a scope-chain walk (a Set allocation plus a linear `ownedDefs`
|
|
944
|
+
// scan per level). Guarding before looking up would charge that walk to
|
|
945
|
+
// every explicit-receiver site in every language, for a candidate set
|
|
946
|
+
// that is usually empty. Mirrors the order the compound-receiver
|
|
947
|
+
// construction path already uses.
|
|
948
|
+
const namespaceCandidates = namespaceTargets.get(receiverName);
|
|
949
|
+
const targetFiles = namespaceCandidates !== undefined &&
|
|
950
|
+
!isNamespaceNameShadowed(receiverName, site.inScope, scopes)
|
|
951
|
+
? namespaceCandidates
|
|
952
|
+
: undefined;
|
|
432
953
|
if (targetFiles !== undefined && provider.resolveQualifiedReceiverMember === undefined) {
|
|
433
954
|
let found = false;
|
|
434
955
|
for (const targetFile of targetFiles) {
|
|
@@ -596,11 +1117,15 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
596
1117
|
// already contain `()` (Ruby member-call-return captures),
|
|
597
1118
|
// pass through directly — the compound resolver handles the
|
|
598
1119
|
// full expression including the call syntax.
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
1120
|
+
// Each attempt carries its OWN spelling: the retry below used to reuse a
|
|
1121
|
+
// recorder reset once, before the first call, so a spelling reported by
|
|
1122
|
+
// the attempt that FAILED could be read as the retry's.
|
|
1123
|
+
let resolved = resolveCompoundReceiverTyped(typeRef.rawName, typeRef.declaredAtScope, scopes, index, fileCompoundOpts);
|
|
1124
|
+
if (resolved === undefined && !typeRef.rawName.includes('(')) {
|
|
1125
|
+
resolved = resolveCompoundReceiverTyped(typeRef.rawName + '()', typeRef.declaredAtScope, scopes, index, fileCompoundOpts);
|
|
602
1126
|
}
|
|
603
|
-
|
|
1127
|
+
const ownerDef = resolved?.def;
|
|
1128
|
+
if (resolved !== undefined && ownerDef !== undefined) {
|
|
604
1129
|
const chain = [ownerDef.nodeId, ...scopes.methodDispatch.mroFor(ownerDef.nodeId)];
|
|
605
1130
|
let memberDef;
|
|
606
1131
|
let ambiguousOwnerId;
|
|
@@ -639,6 +1164,44 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
639
1164
|
const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
|
|
640
1165
|
if (ok)
|
|
641
1166
|
emitted++;
|
|
1167
|
+
// Interface dispatch, exactly as Cases 0 and 4 do it (#2832). Case
|
|
1168
|
+
// 3b folds a chain to a receiver type through the SAME
|
|
1169
|
+
// `resolveCompoundReceiverClass` call and the same MRO walk Case 0
|
|
1170
|
+
// uses, so when that fold lands on an Interface the primary edge
|
|
1171
|
+
// above names the interface's own bodiless DECLARATION and nothing
|
|
1172
|
+
// reaches the implementations.
|
|
1173
|
+
//
|
|
1174
|
+
// Leaving 3b out made the fan-out a property of how the receiver
|
|
1175
|
+
// was SPELLED rather than of what it resolved to: `d.repo.save()`
|
|
1176
|
+
// took Case 0 and fanned out, while binding the identical field to
|
|
1177
|
+
// a local first (`const r = d.repo; r.save()`) took Case 3b and
|
|
1178
|
+
// did not. #2829 closed that gap for Case 0 and left this half of
|
|
1179
|
+
// it open (#2832).
|
|
1180
|
+
//
|
|
1181
|
+
// `ownerDef` is the receiver's own folded type — matching Case 0's
|
|
1182
|
+
// `currentClass` and Case 4's `ownerDef` — NOT the owner of the
|
|
1183
|
+
// member the MRO walk settled on. That distinction matters: a
|
|
1184
|
+
// receiver that folds to a concrete class merely INHERITING an
|
|
1185
|
+
// interface method must not fan out, because its runtime type is
|
|
1186
|
+
// that class. `emitInterfaceDispatchFor` self-gates on
|
|
1187
|
+
// `ownerDef.type !== 'Interface'`, so this is inert for every
|
|
1188
|
+
// concrete receiver and needs no language check of its own.
|
|
1189
|
+
//
|
|
1190
|
+
// That gate is deliberately narrower than "the primary landed on
|
|
1191
|
+
// something bodiless": a chain folding to an ABSTRACT class also
|
|
1192
|
+
// dead-ends on a declaration-only member and does NOT fan out
|
|
1193
|
+
// here. Widening it to `|| isDeclarationOnly(memberDef)` would
|
|
1194
|
+
// cover that, but it changes Cases 0 and 4 identically and for
|
|
1195
|
+
// every language, so it is not #2832's to make.
|
|
1196
|
+
//
|
|
1197
|
+
// Confidence mirrors THIS case's own primary emit above — the 0.85
|
|
1198
|
+
// literal — so a site's dispatch edges never claim more certainty
|
|
1199
|
+
// than the edge they hang off. Case 4 passes a site.kind-dependent
|
|
1200
|
+
// value instead because ITS primary varies that way; Case 3b's
|
|
1201
|
+
// primary, like Case 0's, does not, so there is no 1.0 arm here to
|
|
1202
|
+
// mirror.
|
|
1203
|
+
// Same fold, same recovered spelling as Case 0.
|
|
1204
|
+
emitted += emitInterfaceDispatchFor(ownerDef, memberName, memberDef, site, 0.85, calleeCapture, resolved.declaredSpelling);
|
|
642
1205
|
// Always mark handled when the site was resolved, even
|
|
643
1206
|
// if the edge was deduplicated (collapse mode), so
|
|
644
1207
|
// `emitReferencesViaLookup` doesn't re-emit from the
|
|
@@ -650,13 +1213,27 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
650
1213
|
}
|
|
651
1214
|
// ── Case 4: simple typeBinding (`u: U`) ──────────────────────
|
|
652
1215
|
if (typeRef !== undefined && !typeRef.rawName.includes('.')) {
|
|
653
|
-
|
|
1216
|
+
// A `rawName` the capture layer reduced from a type application is
|
|
1217
|
+
// resolved through the application it was written as, so the erasure
|
|
1218
|
+
// takes the GROUNDED route rather than binding whatever the workspace
|
|
1219
|
+
// declares under that base name — see {@link erasedTypeApplication}.
|
|
1220
|
+
const typeApplication = erasedTypeApplication(typeRef);
|
|
1221
|
+
let ownerDef = resolveClassBindingForName(site.inScope, typeApplication ?? typeRef.rawName, scopes);
|
|
654
1222
|
// `findClassBindingInScope(..., typeRef.rawName)` only works when
|
|
655
1223
|
// rawName is itself a class symbol reachable through scope bindings.
|
|
656
1224
|
// For languages with namespace-style imports (Go), imported types
|
|
657
1225
|
// don't create bindings. Fall back to QualifiedNameIndex — single-
|
|
658
1226
|
// match wins; ambiguous/missing falls through.
|
|
659
|
-
|
|
1227
|
+
//
|
|
1228
|
+
// NOT for an erased base name. This fallback consults no scope, no
|
|
1229
|
+
// import and no module: it binds any name with exactly one workspace
|
|
1230
|
+
// definition. That is a defensible last resort for a name the source
|
|
1231
|
+
// WROTE — the file named it, so the only question is which declaration
|
|
1232
|
+
// it meant — and is not defensible for a name the capture layer
|
|
1233
|
+
// MANUFACTURED by erasing type arguments, where the file may never
|
|
1234
|
+
// have named it at all. The lookup above already answered that case on
|
|
1235
|
+
// grounds; re-asking it here without any would undo them.
|
|
1236
|
+
if (ownerDef === undefined && typeApplication === undefined) {
|
|
660
1237
|
const qnameIds = scopes.qualifiedNames.get(typeRef.rawName);
|
|
661
1238
|
if (qnameIds.length === 1) {
|
|
662
1239
|
const qdef = scopes.defs.get(qnameIds[0]);
|
|
@@ -667,8 +1244,52 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
667
1244
|
// Map for-of tuple bindings (`__MAP_TUPLE_i__:mapId`), callable
|
|
668
1245
|
// aliases (`getUser` → User), and other compound-friendly shapes
|
|
669
1246
|
// need the compound resolver keyed by the receiver identifier.
|
|
670
|
-
|
|
671
|
-
|
|
1247
|
+
//
|
|
1248
|
+
// Not asked for a receiver whose declared type IS an erased type
|
|
1249
|
+
// application the grounded lookup just refused. Those shapes are
|
|
1250
|
+
// alternatives to a declared type, not readings of one: this receiver
|
|
1251
|
+
// HAS a declared type, the question "which class does its base name
|
|
1252
|
+
// denote here" was already put and answered "cannot tell", and the
|
|
1253
|
+
// compound resolver reaches the same base name through its own
|
|
1254
|
+
// scope-free routes (its bare-identifier step re-runs the lookup on
|
|
1255
|
+
// `rawName`; its callable-alias step retries the same name as a
|
|
1256
|
+
// construction). Asking again by a route that cannot see the grounds
|
|
1257
|
+
// would make the refusal decorative.
|
|
1258
|
+
if (ownerDef === undefined && typeApplication === undefined) {
|
|
1259
|
+
ownerDef = resolveCompoundReceiverClass(receiverName, site.inScope, scopes, index,
|
|
1260
|
+
// Group A, same reasoning as Case 0 above.
|
|
1261
|
+
{ ...fileCompoundOpts, receiverChain: site.receiverChain });
|
|
1262
|
+
}
|
|
1263
|
+
// The receiver has a declared type, that type is a type APPLICATION,
|
|
1264
|
+
// and its base name could not be connected to any declaration this
|
|
1265
|
+
// file can see. The site is DROPPED, and dropped deliberately, so it
|
|
1266
|
+
// must be marked handled: `emitReferencesViaLookup` would otherwise
|
|
1267
|
+
// re-emit the very target the grounds refused, because the pre-resolved
|
|
1268
|
+
// reference index answers a name with the single workspace definition
|
|
1269
|
+
// that carries it and knows nothing about erasure. That is exactly why
|
|
1270
|
+
// the static-only filter above marks handled too — a refusal this pass
|
|
1271
|
+
// makes is not a refusal until the fallback emitter is told.
|
|
1272
|
+
//
|
|
1273
|
+
// Recorded as `receiver-unresolved` rather than silently: the receiver's
|
|
1274
|
+
// TYPE could not be established, which is the reason's own definition,
|
|
1275
|
+
// and a consumer counting resolver gaps must see this drop rather than
|
|
1276
|
+
// read the absence as a resolved site. No `receiverOrigin` — the base
|
|
1277
|
+
// name resolving in the index is precisely the evidence just rejected,
|
|
1278
|
+
// so claiming `in-program` from it would relaunder the fabrication as a
|
|
1279
|
+
// diagnostic, and the absent field hedges (the safe direction).
|
|
1280
|
+
if (ownerDef === undefined && typeApplication !== undefined) {
|
|
1281
|
+
options.recordResolutionOutcome?.({
|
|
1282
|
+
kind: 'suppressed',
|
|
1283
|
+
reason: 'receiver-unresolved',
|
|
1284
|
+
candidateIds: [],
|
|
1285
|
+
phase: 'receiver-bound-calls',
|
|
1286
|
+
filePath: parsed.filePath,
|
|
1287
|
+
name: site.name,
|
|
1288
|
+
range: site.atRange,
|
|
1289
|
+
siteKind: site.kind,
|
|
1290
|
+
});
|
|
1291
|
+
handledSites.add(siteKey);
|
|
1292
|
+
continue;
|
|
672
1293
|
}
|
|
673
1294
|
if (ownerDef !== undefined) {
|
|
674
1295
|
const languageResolution = provider.resolveReceiverMember?.(ownerDef, memberName, site, scopes, model);
|
|
@@ -793,7 +1414,13 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
793
1414
|
// Interface dispatch: when the primary owner is an
|
|
794
1415
|
// Interface, emit secondary CALLS edges to every
|
|
795
1416
|
// implementing class's same-named method.
|
|
796
|
-
|
|
1417
|
+
//
|
|
1418
|
+
// This case is the one that KNOWS the instantiation: the receiver
|
|
1419
|
+
// has a declared type, and `typeApplication` is that type restored
|
|
1420
|
+
// to its written `Base<Args>` spelling (`rawName` is the erasure).
|
|
1421
|
+
// A language whose `rawName` was never erased carries the arguments
|
|
1422
|
+
// itself, so both spellings are read (#2912).
|
|
1423
|
+
emitted += emitInterfaceDispatchFor(ownerDef, memberName, memberDef, site, confidence, calleeCapture, typeApplication ?? typeRef.rawName);
|
|
797
1424
|
// Always mark handled when the site was resolved, even
|
|
798
1425
|
// if the edge was deduplicated (collapse mode), so
|
|
799
1426
|
// `emitReferencesViaLookup` doesn't re-emit from the
|
|
@@ -864,10 +1491,222 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
864
1491
|
continue;
|
|
865
1492
|
}
|
|
866
1493
|
}
|
|
1494
|
+
// ── Case 6: class-level (static) member receiver ─────────────
|
|
1495
|
+
// `Holder.repo.save(u)` — the receiver `Holder.repo` reaches a value
|
|
1496
|
+
// through a CLASS-LEVEL member. Both routes that type a compound
|
|
1497
|
+
// receiver (the structural fold and the text cascade) read the same
|
|
1498
|
+
// place for the `repo` hop: the owning class scope's `typeBindings`.
|
|
1499
|
+
// A scope has ONE `typeBindings` map with no static/instance split, so
|
|
1500
|
+
// a language that declares both `p` and `static p` cannot record both
|
|
1501
|
+
// — and at least two resolve that collision by not recording the
|
|
1502
|
+
// static one at all, leaving `Holder.repo` with nothing to type
|
|
1503
|
+
// against. A language that nests its class-level members in a scope of
|
|
1504
|
+
// their own (a companion/singleton body) lands in the same place from
|
|
1505
|
+
// the other direction: the binding exists, but not in the scope keyed
|
|
1506
|
+
// by the class the receiver names. Both were MEASURED as emitting no
|
|
1507
|
+
// edge at all, generic field and non-generic control alike.
|
|
1508
|
+
//
|
|
1509
|
+
// The definition side does not have that ambiguity: a class-level
|
|
1510
|
+
// member and an instance member of one name are two distinct defs, and
|
|
1511
|
+
// the graph node carries both `isStatic` and the member's declared
|
|
1512
|
+
// type. So this case types the receiver off the DEF rather than off a
|
|
1513
|
+
// typeBinding, and needs no scope-tree change to do it.
|
|
1514
|
+
//
|
|
1515
|
+
// ── WHY THIS CANNOT MINT A STATIC-TARGETED EDGE ────────────────────
|
|
1516
|
+
//
|
|
1517
|
+
// `Holder.repo` is a static FIELD whose TYPE is `Repo`; the value it
|
|
1518
|
+
// holds is an INSTANCE. So "reached through a class-level member" says
|
|
1519
|
+
// nothing about the target: `save` is looked up with the ordinary
|
|
1520
|
+
// `pickFirstNonStaticOnly` instance walk that Cases 0/3b/4 use, and a
|
|
1521
|
+
// static-only `save` is skipped exactly as it is there. A genuine
|
|
1522
|
+
// static CALL (`Repo.create()`) never arrives here — its receiver is a
|
|
1523
|
+
// bare class name with no dot, which Case 2 owns and this case's
|
|
1524
|
+
// two-part receiver requirement excludes.
|
|
1525
|
+
//
|
|
1526
|
+
// The `isStatic === true` requirement on the FIELD is the load-bearing
|
|
1527
|
+
// guard in the other direction: the head resolved to the class itself,
|
|
1528
|
+
// so only a class-level member is reachable through it, and an
|
|
1529
|
+
// instance field of the same name must not be substituted. That is a
|
|
1530
|
+
// POSITIVE selection among the defs that exist, never a filter that
|
|
1531
|
+
// deletes otherwise-valid targets — the distinction that matters for a
|
|
1532
|
+
// language whose singleton/companion members all carry `isStatic` from
|
|
1533
|
+
// their OWNER type, where the flag being set is precisely what makes
|
|
1534
|
+
// reaching them through the type name correct.
|
|
1535
|
+
//
|
|
1536
|
+
// Runs LAST, and only for a receiver Case 0 already declined
|
|
1537
|
+
// (`compoundReceiverUnresolved`): a site any earlier case resolved
|
|
1538
|
+
// keeps that answer, so this can only turn a missing edge into an edge
|
|
1539
|
+
// and never retarget an existing one. Contract Invariant I4 holds —
|
|
1540
|
+
// nothing above moved.
|
|
1541
|
+
if (compoundReceiverUnresolved) {
|
|
1542
|
+
const staticMemberReceiver = splitClassLevelMemberReceiver(receiverName, site.receiverChain);
|
|
1543
|
+
const headClass = staticMemberReceiver === undefined
|
|
1544
|
+
? undefined
|
|
1545
|
+
: findClassBindingInScope(site.inScope, staticMemberReceiver.headName, scopes);
|
|
1546
|
+
// The head must be the CLASS ITSELF, not a value that happens to
|
|
1547
|
+
// share its name — the same `currentIsClassConstant` test the text
|
|
1548
|
+
// cascade makes before it treats a head as a class constant. A head
|
|
1549
|
+
// with a type binding is an instance and its members are typed by
|
|
1550
|
+
// the routes above.
|
|
1551
|
+
if (staticMemberReceiver !== undefined &&
|
|
1552
|
+
headClass !== undefined &&
|
|
1553
|
+
findReceiverTypeBinding(site.inScope, staticMemberReceiver.headName, scopes) === undefined) {
|
|
1554
|
+
// MRO walk, so a class-level member declared on an ancestor is
|
|
1555
|
+
// reachable through a subclass name where the language allows it.
|
|
1556
|
+
// First owner that declares one wins, matching every other walk in
|
|
1557
|
+
// this pass.
|
|
1558
|
+
let fieldOwnerId;
|
|
1559
|
+
let fieldDeclaredType;
|
|
1560
|
+
for (const ownerId of [
|
|
1561
|
+
headClass.nodeId,
|
|
1562
|
+
...scopes.methodDispatch.mroFor(headClass.nodeId),
|
|
1563
|
+
]) {
|
|
1564
|
+
const declared = declaredTypeOfClassLevelField(ownerId, staticMemberReceiver.memberName);
|
|
1565
|
+
if (declared === undefined)
|
|
1566
|
+
continue;
|
|
1567
|
+
fieldOwnerId = ownerId;
|
|
1568
|
+
fieldDeclaredType = declared;
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
// Resolve the declared type from where it was WRITTEN — the
|
|
1572
|
+
// declaring class's own scope — not from the call site. A caller
|
|
1573
|
+
// in another file need not have the field's type in scope at all,
|
|
1574
|
+
// and resolving `Repo` against the caller's bindings would either
|
|
1575
|
+
// miss or, worse, find an unrelated same-named class.
|
|
1576
|
+
const declaringScope = fieldOwnerId === undefined ? undefined : index.classScopeByDefId.get(fieldOwnerId)?.id;
|
|
1577
|
+
const receiverClass = declaringScope === undefined || fieldDeclaredType === undefined
|
|
1578
|
+
? undefined
|
|
1579
|
+
: resolveClassBindingForName(declaringScope, fieldDeclaredType, scopes, provider.stripTypePreservingDecoration);
|
|
1580
|
+
if (receiverClass !== undefined) {
|
|
1581
|
+
const chain = [
|
|
1582
|
+
receiverClass.nodeId,
|
|
1583
|
+
...scopes.methodDispatch.mroFor(receiverClass.nodeId),
|
|
1584
|
+
];
|
|
1585
|
+
let memberDef;
|
|
1586
|
+
let ambiguousOwnerId;
|
|
1587
|
+
for (const ownerId of chain) {
|
|
1588
|
+
const picked = pickFirstNonStaticOnly(ownerId, memberName, site, model, provider);
|
|
1589
|
+
if (picked === OVERLOAD_AMBIGUOUS) {
|
|
1590
|
+
ambiguousOwnerId = ownerId;
|
|
1591
|
+
break;
|
|
1592
|
+
}
|
|
1593
|
+
// Same skip-and-walk-on as Case 4: a static-only candidate at
|
|
1594
|
+
// this owner must not block an ancestor's instance member.
|
|
1595
|
+
if (picked === STATIC_ONLY_FILTERED || picked === undefined)
|
|
1596
|
+
continue;
|
|
1597
|
+
memberDef = picked;
|
|
1598
|
+
break;
|
|
1599
|
+
}
|
|
1600
|
+
if (ambiguousOwnerId !== undefined) {
|
|
1601
|
+
recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, ambiguousOwnerId, memberName, model, provider);
|
|
1602
|
+
handledSites.add(siteKey);
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
if (memberDef !== undefined) {
|
|
1606
|
+
if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
|
|
1607
|
+
handledSites.add(siteKey);
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
const reason = site.kind === 'write' || site.kind === 'read'
|
|
1611
|
+
? site.kind
|
|
1612
|
+
: memberDef.filePath !== parsed.filePath
|
|
1613
|
+
? 'import-resolved'
|
|
1614
|
+
: 'global';
|
|
1615
|
+
const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
|
|
1616
|
+
const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
|
|
1617
|
+
if (ok)
|
|
1618
|
+
emitted++;
|
|
1619
|
+
// The receiver's declared type can be an Interface exactly as
|
|
1620
|
+
// in Cases 0/3b/4 — an interface-typed static field is the
|
|
1621
|
+
// canonical service-locator shape — so it fans out the same
|
|
1622
|
+
// way. Omitting it would make the static spelling emit fewer
|
|
1623
|
+
// targets than the identical instance field, which is the very
|
|
1624
|
+
// spelling-dependence #2829/#2842 closed elsewhere.
|
|
1625
|
+
// The field's DECLARED type is the spelling the source wrote, so
|
|
1626
|
+
// its arguments are available here exactly as in Case 4 (#2912).
|
|
1627
|
+
emitted += emitInterfaceDispatchFor(receiverClass, memberName, memberDef, site, confidence, calleeCapture, fieldDeclaredType);
|
|
1628
|
+
handledSites.add(siteKey);
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
// #2744: the site survived every case with a compound receiver we could
|
|
1635
|
+
// not type, so the call is dropped with no candidate. Record it here —
|
|
1636
|
+
// after the cases, so a site a later case resolved is never reported —
|
|
1637
|
+
// keyed by the MEMBER name, which is the only thing still known about a
|
|
1638
|
+
// dropped site (its callee is unknown by definition, so the drop cannot
|
|
1639
|
+
// be attributed to any target symbol).
|
|
1640
|
+
if (compoundReceiverUnresolved && !handledSites.has(siteKey)) {
|
|
1641
|
+
// Decoded once: both the shape census and the origin classifier read the
|
|
1642
|
+
// same chain, and this is inside the drop guard so a resolved site pays
|
|
1643
|
+
// nothing.
|
|
1644
|
+
const decodedChain = decodeReceiverChain(site.receiverChain);
|
|
1645
|
+
options.recordResolutionOutcome?.({
|
|
1646
|
+
kind: 'suppressed',
|
|
1647
|
+
reason: 'receiver-unresolved',
|
|
1648
|
+
candidateIds: [],
|
|
1649
|
+
phase: 'receiver-bound-calls',
|
|
1650
|
+
filePath: parsed.filePath,
|
|
1651
|
+
name: site.name,
|
|
1652
|
+
range: site.atRange,
|
|
1653
|
+
// The gate above tests the receiver's punctuation, not the site's
|
|
1654
|
+
// kind, so property reads and writes with a compound receiver are
|
|
1655
|
+
// recorded here too. Carry the kind so a consumer can separate a
|
|
1656
|
+
// dropped CALL from a dropped property access.
|
|
1657
|
+
siteKind: site.kind,
|
|
1658
|
+
// Structural, from the AST-derived chain the emitter minted — never
|
|
1659
|
+
// re-derived from the source line.
|
|
1660
|
+
// `decodeReceiverChain` opens with a non-string guard, so the
|
|
1661
|
+
// undefined case needs no ternary here.
|
|
1662
|
+
receiverShape: classifyReceiverShape(decodedChain),
|
|
1663
|
+
// Whether anything was actually lost. An external target has no node
|
|
1664
|
+
// to point at, so its absence is completeness, not uncertainty — but
|
|
1665
|
+
// ONLY a positive built-in match may say so. Everything the index
|
|
1666
|
+
// cannot demonstrate stays `unknown` and keeps hedging.
|
|
1667
|
+
receiverOrigin: classifyReceiverOrigin(decodedChain, site.inScope, receiverName, scopes, receiverOriginOpts),
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
867
1670
|
}
|
|
868
1671
|
}
|
|
869
|
-
return emitted;
|
|
1672
|
+
return { emitted, dispatchFanoutSkipped, dispatchFanoutSkippedNames };
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Split a receiver into `Head` + one member hop, or decline.
|
|
1676
|
+
*
|
|
1677
|
+
* The STRUCTURE decides when the capture layer minted a chain: exactly one
|
|
1678
|
+
* step, and that step a FIELD. A `call` step is a different shape entirely
|
|
1679
|
+
* (`Holder.make().save()` — the value comes from a return type, which the
|
|
1680
|
+
* routes above already own), and an `await`/`index` step transforms the value
|
|
1681
|
+
* in a way a field's declared type does not describe.
|
|
1682
|
+
*
|
|
1683
|
+
* Without a chain the receiver TEXT answers, and only in the one spelling that
|
|
1684
|
+
* cannot be read two ways: two bare identifiers around a single dot. Anything
|
|
1685
|
+
* carrying a call, a subscript, a second dot or a decoration declines rather
|
|
1686
|
+
* than being parsed here — re-deriving structure from text is what the chain
|
|
1687
|
+
* exists to replace, and a second, looser text parser beside the cascade's own
|
|
1688
|
+
* would drift from it.
|
|
1689
|
+
*/
|
|
1690
|
+
function splitClassLevelMemberReceiver(receiverText, receiverChain) {
|
|
1691
|
+
const decoded = decodeReceiverChain(receiverChain);
|
|
1692
|
+
if (decoded !== undefined) {
|
|
1693
|
+
if (decoded.truncated || decoded.steps.length !== 1)
|
|
1694
|
+
return undefined;
|
|
1695
|
+
const step = decoded.steps[0];
|
|
1696
|
+
if (step === undefined || step.kind !== 'field')
|
|
1697
|
+
return undefined;
|
|
1698
|
+
return { headName: decoded.baseReceiverName, memberName: step.name };
|
|
1699
|
+
}
|
|
1700
|
+
const match = TWO_PART_RECEIVER_RE.exec(receiverText);
|
|
1701
|
+
if (match === null)
|
|
1702
|
+
return undefined;
|
|
1703
|
+
const [, headName, memberName] = match;
|
|
1704
|
+
if (headName === undefined || memberName === undefined)
|
|
1705
|
+
return undefined;
|
|
1706
|
+
return { headName, memberName };
|
|
870
1707
|
}
|
|
1708
|
+
/** `Holder.repo` and nothing looser — see {@link splitClassLevelMemberReceiver}. */
|
|
1709
|
+
const TWO_PART_RECEIVER_RE = /^([A-Za-z_$][\w$]*)\.([A-Za-z_$][\w$]*)$/;
|
|
871
1710
|
/** Resolve a member by name on a class def, narrowing by argument
|
|
872
1711
|
* types when multiple overloads share the name. Falls back to the
|
|
873
1712
|
* first-seen def (legacy `findOwnedMember` semantics) when there's
|