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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { simpleQualifiedName } from '../../scope-resolution/graph-bridge/ids.js';
|
|
2
2
|
import { resolveInheritanceBaseInScope } from '../../scope-resolution/scope/walkers.js';
|
|
3
|
+
import { goPackageDir } from './package-clause.js';
|
|
4
|
+
import { matchingGoDelimiter, readGoTypeParameters, splitTopLevelGoList, } from './generic-type-parameters.js';
|
|
3
5
|
export function detectGoInterfaceImplementations(parsedFiles, _indexes, _model) {
|
|
4
6
|
return detectGoInterfaceImplementationsFromIndexes(buildDetectionIndexes(parsedFiles, _indexes));
|
|
5
7
|
}
|
|
@@ -12,17 +14,25 @@ function buildDetectionIndexes(parsedFiles, indexes) {
|
|
|
12
14
|
const interfaceOwnMethodsById = new Map();
|
|
13
15
|
const embeddedSitesByInterfaceId = new Map();
|
|
14
16
|
const parentStructIdsByStructId = new Map();
|
|
17
|
+
const valueMethodsByStructId = new Map();
|
|
15
18
|
const structIdsByMethodName = new Map();
|
|
16
19
|
const signatureContextByDefId = new Map();
|
|
17
20
|
const interfaceIdByScopeId = new Map();
|
|
18
21
|
const structIdByScopeId = new Map();
|
|
22
|
+
const typeParametersByInterfaceId = new Map();
|
|
23
|
+
const signatureContextByFilePath = new Map();
|
|
19
24
|
for (const parsed of parsedFiles) {
|
|
20
25
|
const signatureContext = signatureContextForFile(parsed, indexes);
|
|
26
|
+
signatureContextByFilePath.set(parsed.filePath, signatureContext);
|
|
21
27
|
for (const def of parsed.localDefs) {
|
|
22
28
|
signatureContextByDefId.set(def.nodeId, signatureContext);
|
|
23
29
|
if (def.type === 'Interface') {
|
|
24
30
|
interfaces.push(def);
|
|
25
31
|
interfaceById.set(def.nodeId, def);
|
|
32
|
+
const typeParameters = readGoTypeParameters(def);
|
|
33
|
+
if (typeParameters !== undefined) {
|
|
34
|
+
typeParametersByInterfaceId.set(def.nodeId, typeParameters);
|
|
35
|
+
}
|
|
26
36
|
continue;
|
|
27
37
|
}
|
|
28
38
|
if (def.type === 'Struct') {
|
|
@@ -33,14 +43,51 @@ function buildDetectionIndexes(parsedFiles, indexes) {
|
|
|
33
43
|
continue;
|
|
34
44
|
if (def.ownerId === undefined)
|
|
35
45
|
continue;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
// POINTER-receiver methods count toward the method set (#2813).
|
|
47
|
+
//
|
|
48
|
+
// Go's rule is per-type, and there are two types here: the method set of
|
|
49
|
+
// `T` holds only its value-receiver methods, while the method set of `*T`
|
|
50
|
+
// holds BOTH. #1966 kept only the value-receiver half, which makes the
|
|
51
|
+
// `T` answer exactly right — and the `*T` answer permanently empty, so a
|
|
52
|
+
// struct whose methods all read `func (r *T)` satisfied nothing and got
|
|
53
|
+
// no IMPLEMENTS edge at all.
|
|
54
|
+
//
|
|
55
|
+
// That is the shape idiomatic Go actually writes: methods take pointer
|
|
56
|
+
// receivers so they can mutate, and `*T` is what gets stored in an
|
|
57
|
+
// interface-typed field. Excluding it did not make the graph
|
|
58
|
+
// conservative, it made it silent — every call through such a field
|
|
59
|
+
// resolved to the interface DECLARATION and `impact()` on the
|
|
60
|
+
// implementation reported zero callers, indistinguishable from a symbol
|
|
61
|
+
// that genuinely has none.
|
|
62
|
+
//
|
|
63
|
+
// GitNexus models one Struct node per type with no separate `*T` node, so
|
|
64
|
+
// the two method sets cannot both be represented. This picks the `*T`
|
|
65
|
+
// reading: the graph now answers "which types provide this interface's
|
|
66
|
+
// behaviour", and no longer proves `var x I = T{}` invalid. That trade is
|
|
67
|
+
// deliberate — blast radius is what every consumer of IMPLEMENTS asks for
|
|
68
|
+
// (verified: MRO/METHOD_IMPLEMENTS derivation, community clustering, the
|
|
69
|
+
// receiver-dispatch fan-out index, and the epistemic heritage probe; none
|
|
70
|
+
// performs value-assignability checking).
|
|
71
|
+
//
|
|
72
|
+
// `goReceiverKind` is still stamped in method-owners.ts and is the hook a
|
|
73
|
+
// future value/pointer-aware model would read; it is deliberately no
|
|
74
|
+
// longer a filter here.
|
|
75
|
+
const simpleName = simpleQualifiedName(def);
|
|
76
|
+
if (simpleName === undefined || simpleName.length === 0)
|
|
40
77
|
continue;
|
|
41
|
-
addMethod(methodsByOwner, def.ownerId,
|
|
78
|
+
addMethod(methodsByOwner, def.ownerId, methodSetKey(simpleName, def, signatureContextByDefId), def);
|
|
42
79
|
}
|
|
43
80
|
}
|
|
81
|
+
// Built from the nodeId-keyed map, so a def that appears in two ParsedFiles is
|
|
82
|
+
// one interface here just as it is one there — not a name collision with
|
|
83
|
+
// itself.
|
|
84
|
+
const interfacesByQualifiedName = new Map();
|
|
85
|
+
for (const iface of interfaceById.values()) {
|
|
86
|
+
const name = iface.qualifiedName;
|
|
87
|
+
if (name === undefined || name.length === 0)
|
|
88
|
+
continue;
|
|
89
|
+
interfacesByQualifiedName.set(name, interfacesByQualifiedName.has(name) ? null : iface);
|
|
90
|
+
}
|
|
44
91
|
for (const parsed of parsedFiles) {
|
|
45
92
|
for (const scope of parsed.scopes) {
|
|
46
93
|
const iface = scope.ownedDefs.find((def) => def.type === 'Interface');
|
|
@@ -69,10 +116,12 @@ function buildDetectionIndexes(parsedFiles, indexes) {
|
|
|
69
116
|
for (const def of childScope.ownedDefs) {
|
|
70
117
|
if (def.type !== 'Method' && def.type !== 'Function')
|
|
71
118
|
continue;
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
119
|
+
const simpleName = simpleQualifiedName(def);
|
|
120
|
+
if (simpleName === undefined || simpleName.length === 0)
|
|
74
121
|
continue;
|
|
75
|
-
|
|
122
|
+
// Same key function as the struct side — an interface requiring an
|
|
123
|
+
// unexported `seal()` must only be satisfied from its own package.
|
|
124
|
+
addMethodOverload(methods, methodSetKey(simpleName, def, signatureContextByDefId), def);
|
|
76
125
|
}
|
|
77
126
|
}
|
|
78
127
|
interfaceOwnMethodsById.set(ifaceId, methods);
|
|
@@ -93,19 +142,24 @@ function buildDetectionIndexes(parsedFiles, indexes) {
|
|
|
93
142
|
const parent = resolveInheritanceBaseInScope(site.inScope, site.name, indexes);
|
|
94
143
|
if (parent === undefined || parent.type !== 'Struct')
|
|
95
144
|
continue;
|
|
96
|
-
|
|
145
|
+
// `embeddedAsPointer` is the capture-layer record of `*T` vs `T`; the two
|
|
146
|
+
// promote different method sets (go.dev/ref/spec#Struct_types).
|
|
147
|
+
addParentStruct(parentStructIdsByStructId, structId, parent.nodeId, site.embeddedAsPointer === true);
|
|
97
148
|
}
|
|
98
149
|
}
|
|
99
150
|
const structMethodSetCache = new Map();
|
|
100
151
|
for (const structId of structsById.keys()) {
|
|
101
|
-
const
|
|
152
|
+
const dual = collectStructMethodSet(structId, {
|
|
102
153
|
parentStructIdsByStructId,
|
|
103
154
|
methodsByOwner,
|
|
104
155
|
}, new Set(), structMethodSetCache);
|
|
105
|
-
if (
|
|
156
|
+
if (dual === undefined)
|
|
106
157
|
continue;
|
|
107
|
-
|
|
108
|
-
|
|
158
|
+
// `pointer` is MS(*T) and is the superset, so it drives candidate lookup:
|
|
159
|
+
// a type that implements only in pointer form is still an implementor.
|
|
160
|
+
effectiveMethodsByStructId.set(structId, dual.pointer);
|
|
161
|
+
valueMethodsByStructId.set(structId, dual.value);
|
|
162
|
+
for (const methodName of dual.pointer.keys()) {
|
|
109
163
|
addStructMethodCandidate(structIdsByMethodName, methodName, structId);
|
|
110
164
|
}
|
|
111
165
|
}
|
|
@@ -114,17 +168,185 @@ function buildDetectionIndexes(parsedFiles, indexes) {
|
|
|
114
168
|
structsById,
|
|
115
169
|
methodsByOwner,
|
|
116
170
|
effectiveMethodsByStructId,
|
|
117
|
-
|
|
171
|
+
interfacesByQualifiedName,
|
|
118
172
|
interfaceOwnMethodsById,
|
|
119
173
|
embeddedSitesByInterfaceId,
|
|
120
174
|
parentStructIdsByStructId,
|
|
121
175
|
structIdsByMethodName,
|
|
176
|
+
valueMethodsByStructId,
|
|
122
177
|
signatureContextByDefId,
|
|
178
|
+
typeParametersByInterfaceId,
|
|
179
|
+
// Gated on the repo declaring at least one generic interface. A Go codebase
|
|
180
|
+
// with none — the overwhelming majority — never runs the harvest at all,
|
|
181
|
+
// which matters because the spellings it would scan (`[]byte`,
|
|
182
|
+
// `map[string]X`) are among the commonest types in the language.
|
|
183
|
+
instantiationsByInterfaceId: typeParametersByInterfaceId.size === 0
|
|
184
|
+
? new Map()
|
|
185
|
+
: collectGoInstantiations(parsedFiles, signatureContextByFilePath, typeParametersByInterfaceId, interfacesByQualifiedName, indexes),
|
|
123
186
|
scopeIndexes: indexes,
|
|
124
187
|
};
|
|
125
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Every distinct instantiation of a generic interface written anywhere in the
|
|
191
|
+
* program, resolved and deduplicated in one pass.
|
|
192
|
+
*
|
|
193
|
+
* Go records no instantiation anywhere on the DECLARATION — `Repo[User]` exists
|
|
194
|
+
* only where it is written — so the sites are the field/parameter/variable type
|
|
195
|
+
* spellings the capture layer already preserved: `TypeRef.declaredSpelling`
|
|
196
|
+
* (which keeps the arguments `rawName` drops), and the def-side `declaredType` /
|
|
197
|
+
* `parameterTypes` / `returnType`.
|
|
198
|
+
*
|
|
199
|
+
* A spelling is scanned rather than parsed as a whole, so decorated and nested
|
|
200
|
+
* forms yield their inner instantiations too: `[]Repo[User]`, `*Repo[User]` and
|
|
201
|
+
* `map[string]Repo[User]` all yield `Repo[User]`, and `Outer[Repo[User]]` yields
|
|
202
|
+
* both — each of which really is an instantiation present in the program. False
|
|
203
|
+
* bases (`map[` scans as base `map`) resolve to no interface and drop out.
|
|
204
|
+
*/
|
|
205
|
+
function collectGoInstantiations(parsedFiles, signatureContextByFilePath, typeParametersByInterfaceId, interfacesByQualifiedName, indexes) {
|
|
206
|
+
// One map where there were two on the same key: the inner map's KEY is the
|
|
207
|
+
// joined argument list, so holding it is the deduplication.
|
|
208
|
+
const argsByInterfaceId = new Map();
|
|
209
|
+
// A base name resolves once per scope. The bracket gate below cannot filter
|
|
210
|
+
// Go's commonest types — `map[string]string` scans as base `map` — so the
|
|
211
|
+
// FALSE bases dominate this pass, and each one otherwise re-walks the whole
|
|
212
|
+
// scope chain for a name that will never bind.
|
|
213
|
+
const basesInScope = new Map();
|
|
214
|
+
const resolveBase = (baseName, inScope) => {
|
|
215
|
+
// NUL-joined for the same reason `methodSetKey` is: it cannot occur in Go
|
|
216
|
+
// source, so no two (scope, name) pairs can collide on one key.
|
|
217
|
+
const key = `${inScope}\u0000${baseName}`;
|
|
218
|
+
const memo = basesInScope.get(key);
|
|
219
|
+
if (memo !== undefined)
|
|
220
|
+
return memo ?? undefined;
|
|
221
|
+
const iface = resolveGoInstantiationBase(baseName, inScope, interfacesByQualifiedName, indexes);
|
|
222
|
+
basesInScope.set(key, iface ?? null);
|
|
223
|
+
return iface;
|
|
224
|
+
};
|
|
225
|
+
const record = (spelling, inScope, context) => {
|
|
226
|
+
// Cheap gate first: most Go type spellings have no bracket at all, and the
|
|
227
|
+
// scan below is the only per-spelling cost this pass adds.
|
|
228
|
+
if (spelling === undefined || !spelling.includes('['))
|
|
229
|
+
return;
|
|
230
|
+
for (const { baseName, rawArgs } of parseGoInstantiationSpellings(spelling)) {
|
|
231
|
+
const iface = resolveBase(baseName, inScope);
|
|
232
|
+
if (iface === undefined)
|
|
233
|
+
continue;
|
|
234
|
+
const typeParameters = typeParametersByInterfaceId.get(iface.nodeId);
|
|
235
|
+
// A partial or over-long argument list is not a valid instantiation
|
|
236
|
+
// ("For a generic type, all type arguments must always be provided
|
|
237
|
+
// explicitly" — go.dev/ref/spec#Instantiations), so there is nothing to
|
|
238
|
+
// substitute and the site is dropped.
|
|
239
|
+
if (typeParameters === undefined || typeParameters.length !== rawArgs.length)
|
|
240
|
+
continue;
|
|
241
|
+
const normalizedArgs = normalizeGoTypeArguments(rawArgs, context);
|
|
242
|
+
if (normalizedArgs === undefined)
|
|
243
|
+
continue;
|
|
244
|
+
let byArgs = argsByInterfaceId.get(iface.nodeId);
|
|
245
|
+
if (byArgs === undefined) {
|
|
246
|
+
byArgs = new Map();
|
|
247
|
+
argsByInterfaceId.set(iface.nodeId, byArgs);
|
|
248
|
+
}
|
|
249
|
+
const key = normalizedArgs.join(',');
|
|
250
|
+
if (!byArgs.has(key))
|
|
251
|
+
byArgs.set(key, normalizedArgs);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
for (const parsed of parsedFiles) {
|
|
255
|
+
const context = signatureContextByFilePath.get(parsed.filePath);
|
|
256
|
+
if (context === undefined)
|
|
257
|
+
continue;
|
|
258
|
+
for (const scope of parsed.scopes) {
|
|
259
|
+
for (const binding of scope.typeBindings.values()) {
|
|
260
|
+
record(binding.declaredSpelling ?? binding.rawName, scope.id, context);
|
|
261
|
+
}
|
|
262
|
+
for (const def of scope.ownedDefs) {
|
|
263
|
+
record(def.declaredType, scope.id, context);
|
|
264
|
+
record(def.returnType, scope.id, context);
|
|
265
|
+
for (const parameterType of def.parameterTypes ?? []) {
|
|
266
|
+
record(parameterType, scope.id, context);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return argsByInterfaceId;
|
|
272
|
+
}
|
|
273
|
+
/** Every `Ident[…]` / `pkg.Ident[…]` application in a type spelling, with its
|
|
274
|
+
* top-level (comma-separated, delimiter-balanced) arguments. */
|
|
275
|
+
function parseGoInstantiationSpellings(spelling) {
|
|
276
|
+
const out = [];
|
|
277
|
+
const namePattern = /[A-Za-z_][A-Za-z0-9_.]*(?=\[)/g;
|
|
278
|
+
let match;
|
|
279
|
+
while ((match = namePattern.exec(spelling)) !== null) {
|
|
280
|
+
const open = match.index + match[0].length;
|
|
281
|
+
const close = matchingGoDelimiter(spelling, open);
|
|
282
|
+
if (close === -1)
|
|
283
|
+
continue;
|
|
284
|
+
const rawArgs = splitTopLevelGoList(spelling.slice(open + 1, close));
|
|
285
|
+
if (rawArgs.length === 0)
|
|
286
|
+
continue;
|
|
287
|
+
out.push({ baseName: match[0], rawArgs });
|
|
288
|
+
}
|
|
289
|
+
return out;
|
|
290
|
+
}
|
|
291
|
+
/** Normalize each type argument in the context of the file that WROTE it, or
|
|
292
|
+
* `undefined` when any of them carries an unresolvable import qualifier — a
|
|
293
|
+
* half-normalized argument list would compare against nothing meaningful. */
|
|
294
|
+
function normalizeGoTypeArguments(rawArgs, context) {
|
|
295
|
+
const normalizedArgs = [];
|
|
296
|
+
for (const rawArg of rawArgs) {
|
|
297
|
+
const normalized = normalizeSignatureType(rawArg, context);
|
|
298
|
+
if (normalized === undefined)
|
|
299
|
+
return undefined;
|
|
300
|
+
normalizedArgs.push(normalized);
|
|
301
|
+
}
|
|
302
|
+
return normalizedArgs;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Bind an instantiation's base name to the generic interface it names.
|
|
306
|
+
*
|
|
307
|
+
* Goes through `resolveInheritanceBaseInScope` first — the same real scope
|
|
308
|
+
* resolution the embedded-interface path uses — and falls back to a globally
|
|
309
|
+
* UNIQUE name match.
|
|
310
|
+
*/
|
|
311
|
+
function resolveGoInstantiationBase(baseName, inScope, interfacesByQualifiedName, indexes) {
|
|
312
|
+
const bound = resolveInheritanceBaseInScope(inScope, simpleTypeName(baseName), indexes);
|
|
313
|
+
if (bound !== undefined)
|
|
314
|
+
return bound.type === 'Interface' ? bound : undefined;
|
|
315
|
+
return uniqueInterfaceNamed(baseName, interfacesByQualifiedName);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* The one interface a written name denotes by NAME ALONE — the fallback both
|
|
319
|
+
* name-match routes here share, once the real scope resolution above them has
|
|
320
|
+
* declined.
|
|
321
|
+
*
|
|
322
|
+
* Ambiguity drops the site rather than guessing: two same-named interfaces in
|
|
323
|
+
* different packages would otherwise cross-pollinate each other's
|
|
324
|
+
* instantiations, and a dropped site only costs fan-out that does not exist
|
|
325
|
+
* today anyway. A qualified spelling is tried under both its own name and its
|
|
326
|
+
* simple tail, and a hit under EACH is two matches, so it declines as well.
|
|
327
|
+
*
|
|
328
|
+
* One probe rather than a scan of every interface in the program, which is what
|
|
329
|
+
* made this quadratic: the bracket gate in `collectGoInstantiations` cannot
|
|
330
|
+
* filter `map[…]` or `[]T`, so a Go program pays this once per bracketed
|
|
331
|
+
* spelling it writes.
|
|
332
|
+
*/
|
|
333
|
+
function uniqueInterfaceNamed(name, interfacesByQualifiedName) {
|
|
334
|
+
const exact = interfacesByQualifiedName.get(name);
|
|
335
|
+
if (exact === null)
|
|
336
|
+
return undefined;
|
|
337
|
+
const simpleName = simpleTypeName(name);
|
|
338
|
+
if (simpleName === name)
|
|
339
|
+
return exact;
|
|
340
|
+
const simple = interfacesByQualifiedName.get(simpleName);
|
|
341
|
+
if (simple === null)
|
|
342
|
+
return undefined;
|
|
343
|
+
if (exact !== undefined && simple !== undefined)
|
|
344
|
+
return undefined;
|
|
345
|
+
return exact ?? simple;
|
|
346
|
+
}
|
|
126
347
|
function detectGoInterfaceImplementationsFromIndexes(indexes) {
|
|
127
348
|
const implementations = new Map();
|
|
349
|
+
const undecided = [];
|
|
128
350
|
const methodSetCache = new Map();
|
|
129
351
|
for (const iface of indexes.interfaces) {
|
|
130
352
|
const required = collectInterfaceMethodSet(iface, indexes, new Set(), methodSetCache);
|
|
@@ -132,19 +354,244 @@ function detectGoInterfaceImplementationsFromIndexes(indexes) {
|
|
|
132
354
|
continue;
|
|
133
355
|
if (!methodSetHasVerifiableSignatures(required))
|
|
134
356
|
continue;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
357
|
+
// Hoisted, not recomputed per set: `substituteMethodSet` rewrites
|
|
358
|
+
// SIGNATURES and returns the identical key set, and `candidateStructIdsFor`
|
|
359
|
+
// keys off nothing but those method names — so every set below has exactly
|
|
360
|
+
// these candidates. Materialized because it is iterated once per
|
|
361
|
+
// instantiation and one of the branches behind it yields a live iterator.
|
|
362
|
+
const candidateStructIds = [...candidateStructIdsFor(required, indexes)];
|
|
363
|
+
// The declaration's own method set, then one per observed instantiation.
|
|
364
|
+
// The declaration set runs FIRST and unconditionally, so this is strictly
|
|
365
|
+
// additive: every implementor found before #2855 is still found, in the
|
|
366
|
+
// same order, and instantiation only ever appends.
|
|
367
|
+
const formByStructId = new Map();
|
|
368
|
+
const undecidedStructIds = new Set();
|
|
369
|
+
for (const candidateSet of [required, ...instantiatedMethodSetsFor(iface, required, indexes)]) {
|
|
370
|
+
for (const structId of candidateStructIds) {
|
|
371
|
+
if (formByStructId.get(structId) === 'value')
|
|
372
|
+
continue;
|
|
373
|
+
const pointerSet = indexes.effectiveMethodsByStructId.get(structId);
|
|
374
|
+
if (pointerSet === undefined)
|
|
375
|
+
continue;
|
|
376
|
+
// MS(*T) is the superset: if it does not satisfy, neither does MS(T).
|
|
377
|
+
const verdict = methodSetSatisfies(pointerSet, candidateSet, indexes.signatureContextByDefId);
|
|
378
|
+
if (verdict !== 'satisfied') {
|
|
379
|
+
// `undecided` mints no edge — a speculative IMPLEMENTS would fan out
|
|
380
|
+
// into fabricated CALLS through `emitReceiverBoundCalls`. It is
|
|
381
|
+
// recorded instead, so `impact` can report a lower bound rather than
|
|
382
|
+
// a confident zero (#2873). A decided `unsatisfied` records nothing:
|
|
383
|
+
// that answer is trustworthy.
|
|
384
|
+
if (verdict === 'undecided')
|
|
385
|
+
undecidedStructIds.add(structId);
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
// Then ask the narrower question separately — does the VALUE type satisfy?
|
|
389
|
+
// This is the distinction `var x I = T{}` turns on, and it is a fact about
|
|
390
|
+
// the program, not a heuristic.
|
|
391
|
+
const valueSet = indexes.valueMethodsByStructId.get(structId);
|
|
392
|
+
const satisfiesByValue = valueSet !== undefined &&
|
|
393
|
+
methodSetSatisfies(valueSet, candidateSet, indexes.signatureContextByDefId) ===
|
|
394
|
+
'satisfied';
|
|
395
|
+
formByStructId.set(structId, satisfiesByValue ? 'value' : 'pointer');
|
|
396
|
+
undecidedStructIds.delete(structId);
|
|
142
397
|
}
|
|
143
398
|
}
|
|
399
|
+
const implementors = [...formByStructId].map(([structDefId, receiverForm]) => ({ structDefId, receiverForm }));
|
|
144
400
|
if (implementors.length > 0)
|
|
145
401
|
implementations.set(iface.nodeId, implementors);
|
|
402
|
+
if (undecidedStructIds.size > 0) {
|
|
403
|
+
const candidateNames = [];
|
|
404
|
+
for (const structId of undecidedStructIds) {
|
|
405
|
+
const name = indexes.structsById.get(structId)?.qualifiedName;
|
|
406
|
+
if (name !== undefined)
|
|
407
|
+
candidateNames.push(name);
|
|
408
|
+
}
|
|
409
|
+
undecided.push({
|
|
410
|
+
interfaceDefId: iface.nodeId,
|
|
411
|
+
interfaceName: iface.qualifiedName,
|
|
412
|
+
filePath: iface.filePath,
|
|
413
|
+
undecidedCandidates: undecidedStructIds.size,
|
|
414
|
+
candidateNames,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return { implementations, undecided };
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* The method set of each observed INSTANTIATION of a generic interface.
|
|
422
|
+
*
|
|
423
|
+
* Go spec, Instantiations: "A generic function or type is instantiated by
|
|
424
|
+
* substituting type arguments for the type parameters. … Each type argument is
|
|
425
|
+
* substituted for its corresponding type parameter in the generic declaration. …
|
|
426
|
+
* Instantiating a type results in a new non-generic named type." Combined with
|
|
427
|
+
* Type definitions ("Generic types must be instantiated when they are used") the
|
|
428
|
+
* consequence is that `Repo` is not a type at all and `Repo[User]` is — with
|
|
429
|
+
* method set `{ Save(x User) }` after substitution. Implementing an interface
|
|
430
|
+
* then asks whether a type "is an element of the type set of I", and Basic
|
|
431
|
+
* interfaces defines that type set as "the set of types which implement all of
|
|
432
|
+
* those methods". `UserRepo`, whose method set contains `Save(x User)`, is an
|
|
433
|
+
* element of `Repo[User]`'s type set — so it implements `Repo[User]`, and a call
|
|
434
|
+
* through a `Repo[User]`-typed field really can land on `UserRepo.Save`. Before
|
|
435
|
+
* this, it could not: the required parameter type stayed the type PARAMETER `T`,
|
|
436
|
+
* matched no implementor's `User`, and the interface got no IMPLEMENTS edge at
|
|
437
|
+
* all. That is the same false-silence shape as #2813/#2829, one abstraction up.
|
|
438
|
+
*
|
|
439
|
+
* SUBSTITUTION, NOT ERASURE. `Repo[Order]` instantiates to `Save(x Order)` and
|
|
440
|
+
* is NOT satisfied by a `Save(x User)` implementor. Treating `T` as a wildcard
|
|
441
|
+
* would satisfy both and mint an edge Go does not have; the whole point of
|
|
442
|
+
* #2829 was that an exact model beats an approximate one.
|
|
443
|
+
*
|
|
444
|
+
* WHAT THIS DELIBERATELY DOES NOT MODEL. GitNexus holds one node per generic
|
|
445
|
+
* DECLARATION, not one per instantiation, so an interface instantiated at two
|
|
446
|
+
* different arguments in the same program unions their implementors onto the one
|
|
447
|
+
* `Repo` node — `Repo[User]` and `Repo[Order]` in the same repo both fan out to
|
|
448
|
+
* every type satisfying either. That is the same one-node-per-declaration
|
|
449
|
+
* over-approximation every nominal language in the graph already carries (a
|
|
450
|
+
* Kotlin `class UserRepo : Repo<User>` yields `UserRepo IMPLEMENTS Repo`, argument
|
|
451
|
+
* discarded), and it is bounded by the arguments the program actually writes —
|
|
452
|
+
* strictly narrower than erasure, which admits arguments that appear nowhere.
|
|
453
|
+
*
|
|
454
|
+
* Constraints are out of reach by construction and that is correct: a generic
|
|
455
|
+
* interface used as a CONSTRAINT (`func F[T Repo[X]](…)`) is written in a type
|
|
456
|
+
* parameter list, which produces no type binding and no declared type, so no
|
|
457
|
+
* such site is ever harvested. Non-basic interfaces — the union/type-set kind
|
|
458
|
+
* that "may only be used as type constraints" (General interfaces) — declare no
|
|
459
|
+
* methods and are already dropped by the empty-method-set guard above.
|
|
460
|
+
*/
|
|
461
|
+
function instantiatedMethodSetsFor(iface, required, indexes) {
|
|
462
|
+
const typeParameters = indexes.typeParametersByInterfaceId.get(iface.nodeId);
|
|
463
|
+
if (typeParameters === undefined)
|
|
464
|
+
return [];
|
|
465
|
+
const instantiations = indexes.instantiationsByInterfaceId.get(iface.nodeId);
|
|
466
|
+
if (instantiations === undefined || instantiations.size === 0)
|
|
467
|
+
return [];
|
|
468
|
+
const indexByName = new Map(typeParameters.map((name, index) => [name, index]));
|
|
469
|
+
const sets = [];
|
|
470
|
+
for (const normalizedArgs of instantiations.values()) {
|
|
471
|
+
const substituted = substituteMethodSet(required, indexByName, normalizedArgs, indexes.signatureContextByDefId);
|
|
472
|
+
if (substituted !== undefined)
|
|
473
|
+
sets.push(substituted);
|
|
474
|
+
}
|
|
475
|
+
return sets;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Rewrite a required method set under one instantiation, or `undefined` when any
|
|
479
|
+
* signature in it cannot be normalized (an unresolved import qualifier) — a
|
|
480
|
+
* partially substituted set would compare a mix of instantiated and
|
|
481
|
+
* uninstantiated types, so the instantiation is dropped whole.
|
|
482
|
+
*
|
|
483
|
+
* The substituted defs carry a synthetic node id that is deliberately absent
|
|
484
|
+
* from `signatureContextByDefId`. Their parameter/return types come out of here
|
|
485
|
+
* ALREADY normalized — the type arguments in the context that WROTE them, the
|
|
486
|
+
* rest in the interface's own — and `normalizeSignatureType` with no context is
|
|
487
|
+
* the identity beyond whitespace, so the comparison in `signaturesCompatible`
|
|
488
|
+
* cannot re-qualify a spelling that is already fully qualified.
|
|
489
|
+
*/
|
|
490
|
+
function substituteMethodSet(required, indexByName, normalizedArgs, signatureContextByDefId) {
|
|
491
|
+
const out = new Map();
|
|
492
|
+
for (const [name, overloads] of required) {
|
|
493
|
+
const substitutedOverloads = [];
|
|
494
|
+
for (const def of overloads) {
|
|
495
|
+
const context = signatureContextByDefId.get(def.nodeId);
|
|
496
|
+
const parameterTypes = [];
|
|
497
|
+
for (const parameterType of def.parameterTypes ?? []) {
|
|
498
|
+
const substituted = substituteSignatureType(parameterType, indexByName, normalizedArgs, context);
|
|
499
|
+
if (substituted === undefined)
|
|
500
|
+
return undefined;
|
|
501
|
+
parameterTypes.push(substituted);
|
|
502
|
+
}
|
|
503
|
+
let returnType;
|
|
504
|
+
if (def.returnType !== undefined) {
|
|
505
|
+
returnType = substituteSignatureType(def.returnType, indexByName, normalizedArgs, context);
|
|
506
|
+
if (returnType === undefined)
|
|
507
|
+
return undefined;
|
|
508
|
+
}
|
|
509
|
+
substitutedOverloads.push({
|
|
510
|
+
...def,
|
|
511
|
+
nodeId: `${def.nodeId}\u0000instantiated`,
|
|
512
|
+
...(def.parameterTypes !== undefined ? { parameterTypes } : {}),
|
|
513
|
+
...(returnType !== undefined ? { returnType } : {}),
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
out.set(name, substitutedOverloads);
|
|
146
517
|
}
|
|
147
|
-
return
|
|
518
|
+
return out;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Placeholder for the type argument at position `i` while its enclosing type is
|
|
522
|
+
* normalized. NUL-delimited — the same separator `methodSetKey` already uses,
|
|
523
|
+
* and for the same reason: it cannot occur in Go source.
|
|
524
|
+
*
|
|
525
|
+
* Both halves of that choice are load-bearing. `qualifyGoSignatureTypes` rewrites
|
|
526
|
+
* only tokens matching `[A-Za-z_][A-Za-z0-9_]*`, which can start with neither NUL
|
|
527
|
+
* nor a digit, so the placeholder survives normalization untouched; and
|
|
528
|
+
* `normalizeSignatureType` strips `\s+` FIRST, so a whitespace-delimited
|
|
529
|
+
* placeholder would lose its delimiters and become indistinguishable from an
|
|
530
|
+
* array length (`[5]int`).
|
|
531
|
+
*/
|
|
532
|
+
const TYPE_PARAMETER_PLACEHOLDER = /\u0000(\d+)\u0000/g;
|
|
533
|
+
/**
|
|
534
|
+
* Substitute type arguments into one signature type, preserving Go's type
|
|
535
|
+
* identity rules for everything around them.
|
|
536
|
+
*
|
|
537
|
+
* Substitution happens BEFORE normalization and reinstatement AFTER, so the
|
|
538
|
+
* argument's own spelling is never re-qualified by the interface's package while
|
|
539
|
+
* the rest of the type still is: `[]T` in package `repo` with argument
|
|
540
|
+
* `internal/model.User` yields `[]internal/model.User`, not
|
|
541
|
+
* `[]repo.internal/model.User`. Pointer, slice, map and variadic shape survive
|
|
542
|
+
* because only the identifier token is replaced (`*T` -> `*model.User`), which is
|
|
543
|
+
* what makes `Save(x T)` and `Save(x *T)` stay different methods.
|
|
544
|
+
*/
|
|
545
|
+
function substituteSignatureType(typeName, indexByName, normalizedArgs, context) {
|
|
546
|
+
const placeheld = typeName.replace(/[A-Za-z_][A-Za-z0-9_]*/g, (token, offset, source) => {
|
|
547
|
+
// `pkg.T` names `T` in package `pkg`, never the type parameter `T`.
|
|
548
|
+
if (hasPackageQualifierDot(source, offset))
|
|
549
|
+
return token;
|
|
550
|
+
const index = indexByName.get(token);
|
|
551
|
+
return index === undefined ? token : `\u0000${index}\u0000`;
|
|
552
|
+
});
|
|
553
|
+
const normalized = normalizeSignatureType(placeheld, context);
|
|
554
|
+
if (normalized === undefined)
|
|
555
|
+
return undefined;
|
|
556
|
+
return normalized.replace(TYPE_PARAMETER_PLACEHOLDER, (_match, digits) => {
|
|
557
|
+
return normalizedArgs[Number(digits)] ?? _match;
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* The key a method occupies in a method set.
|
|
562
|
+
*
|
|
563
|
+
* Go spec, Uniqueness of identifiers: "Two identifiers are different if they are
|
|
564
|
+
* spelled differently, **or if they appear in different packages and are not
|
|
565
|
+
* exported**." So an UNEXPORTED method name is scoped to its declaring package —
|
|
566
|
+
* `seal` in package `sealed` is a different identifier from `seal` in package
|
|
567
|
+
* `foreign`, and a type outside `sealed` can never satisfy `interface { seal() }`.
|
|
568
|
+
* That is the whole basis of the sealed-interface idiom.
|
|
569
|
+
*
|
|
570
|
+
* Matching on the bare name made those types satisfy each other, which is a
|
|
571
|
+
* FALSE implementation rather than an over-approximation. Qualifying the key
|
|
572
|
+
* with the declaring package for unexported names makes the comparison exact.
|
|
573
|
+
*
|
|
574
|
+
* Exported names are deliberately left unqualified: the spec makes them the same
|
|
575
|
+
* identifier across packages, which is what allows cross-package interface
|
|
576
|
+
* satisfaction to work at all.
|
|
577
|
+
*/
|
|
578
|
+
function methodSetKey(simpleName, def, signatureContextByDefId) {
|
|
579
|
+
if (isExportedGoIdentifier(simpleName))
|
|
580
|
+
return simpleName;
|
|
581
|
+
const pkg = signatureContextByDefId.get(def.nodeId)?.packageQualifier;
|
|
582
|
+
return pkg === undefined ? simpleName : `${pkg}\u0000${simpleName}`;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Go spec, Exported identifiers: exported iff the first character is a Unicode
|
|
586
|
+
* uppercase letter (category Lu). Method names always satisfy the second clause
|
|
587
|
+
* (they are method names), so the first character is the whole test.
|
|
588
|
+
*/
|
|
589
|
+
function isExportedGoIdentifier(name) {
|
|
590
|
+
const first = name.codePointAt(0);
|
|
591
|
+
if (first === undefined)
|
|
592
|
+
return false;
|
|
593
|
+
const ch = String.fromCodePoint(first);
|
|
594
|
+
return ch !== ch.toLowerCase() && ch === ch.toUpperCase();
|
|
148
595
|
}
|
|
149
596
|
function addMethod(methodsByOwner, ownerId, methodName, def) {
|
|
150
597
|
let methods = methodsByOwner.get(ownerId);
|
|
@@ -164,42 +611,86 @@ function addStructMethodCandidate(structIdsByMethodName, methodName, structId) {
|
|
|
164
611
|
structIds.add(structId);
|
|
165
612
|
structIdsByMethodName.set(methodName, structIds);
|
|
166
613
|
}
|
|
167
|
-
function addParentStruct(parentStructIdsByStructId, structId, parentStructId) {
|
|
614
|
+
function addParentStruct(parentStructIdsByStructId, structId, parentStructId, asPointer) {
|
|
168
615
|
const parents = parentStructIdsByStructId.get(structId) ?? [];
|
|
169
|
-
parents.push(parentStructId);
|
|
616
|
+
parents.push({ structId: parentStructId, asPointer });
|
|
170
617
|
parentStructIdsByStructId.set(structId, parents);
|
|
171
618
|
}
|
|
172
619
|
function collectStructMethodSet(structId, indexes, visiting, cache) {
|
|
173
620
|
const entries = collectStructMethodEntries(structId, indexes, visiting, cache);
|
|
174
|
-
|
|
621
|
+
if (entries === undefined)
|
|
622
|
+
return undefined;
|
|
623
|
+
return {
|
|
624
|
+
value: methodEntriesToMethodSet(entries.value),
|
|
625
|
+
pointer: methodEntriesToMethodSet(entries.pointer),
|
|
626
|
+
};
|
|
175
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Build MS(T) and MS(*T) together, applying the spec's promotion table exactly
|
|
630
|
+
* (go.dev/ref/spec#Method_sets, #Struct_types):
|
|
631
|
+
*
|
|
632
|
+
* declared receiver T -> in MS(T) and MS(*T)
|
|
633
|
+
* declared receiver *T -> in MS(*T) only
|
|
634
|
+
* S embeds T (value) -> MS(S) gets P's MS(T); MS(*S) gets P's MS(*T)
|
|
635
|
+
* S embeds *T (pointer) -> MS(S) AND MS(*S) both get P's MS(*T)
|
|
636
|
+
*
|
|
637
|
+
* The last row is the one that makes the embed FORM load-bearing: with
|
|
638
|
+
* `func (b *Base) Ping()`, `struct{ Base }` does not implement a `Ping`
|
|
639
|
+
* interface by value while `struct{ *Base }` does. Collapsing the forms gives
|
|
640
|
+
* both the same answer and one of them is then wrong.
|
|
641
|
+
*/
|
|
176
642
|
function collectStructMethodEntries(structId, indexes, visiting, cache) {
|
|
177
643
|
const cached = cache.get(structId);
|
|
178
|
-
if (cached !== undefined)
|
|
179
|
-
return cloneMethodEntries(cached);
|
|
644
|
+
if (cached !== undefined) {
|
|
645
|
+
return { value: cloneMethodEntries(cached.value), pointer: cloneMethodEntries(cached.pointer) };
|
|
646
|
+
}
|
|
180
647
|
if (visiting.has(structId))
|
|
181
648
|
return undefined;
|
|
182
649
|
visiting.add(structId);
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
650
|
+
const own = indexes.methodsByOwner.get(structId);
|
|
651
|
+
// MS(*T) holds every declared method; MS(T) drops the pointer-receiver ones.
|
|
652
|
+
const pointer = directMethodEntries(own);
|
|
653
|
+
const value = directMethodEntries(filterValueReceiverMethods(own));
|
|
654
|
+
for (const parent of indexes.parentStructIdsByStructId.get(structId) ?? []) {
|
|
655
|
+
const parentEntries = collectStructMethodEntries(parent.structId, indexes, visiting, cache);
|
|
186
656
|
if (parentEntries === undefined) {
|
|
187
657
|
visiting.delete(structId);
|
|
188
658
|
return undefined;
|
|
189
659
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
depth: entry.depth + 1,
|
|
196
|
-
ambiguous: false,
|
|
197
|
-
});
|
|
198
|
-
}
|
|
660
|
+
// Embedding by POINTER lifts the parent's pointer-receiver methods into the
|
|
661
|
+
// embedder's VALUE method set; embedding by value does not.
|
|
662
|
+
const promotedIntoValue = parent.asPointer ? parentEntries.pointer : parentEntries.value;
|
|
663
|
+
promoteEntries(value, promotedIntoValue);
|
|
664
|
+
promoteEntries(pointer, parentEntries.pointer);
|
|
199
665
|
}
|
|
200
666
|
visiting.delete(structId);
|
|
201
|
-
cache.set(structId, cloneMethodEntries(
|
|
202
|
-
return
|
|
667
|
+
cache.set(structId, { value: cloneMethodEntries(value), pointer: cloneMethodEntries(pointer) });
|
|
668
|
+
return { value, pointer };
|
|
669
|
+
}
|
|
670
|
+
/** Merge one depth-level of promoted entries, preserving the shallowest-depth
|
|
671
|
+
* and ambiguity rules the selector spec defines. */
|
|
672
|
+
function promoteEntries(target, source) {
|
|
673
|
+
for (const [methodName, entry] of source) {
|
|
674
|
+
if (entry.ambiguous)
|
|
675
|
+
continue;
|
|
676
|
+
mergePromotedMethodEntry(target, methodName, {
|
|
677
|
+
overloads: entry.overloads,
|
|
678
|
+
depth: entry.depth + 1,
|
|
679
|
+
ambiguous: false,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
/** MS(T) excludes methods declared with a `*T` receiver. */
|
|
684
|
+
function filterValueReceiverMethods(methods) {
|
|
685
|
+
if (methods === undefined)
|
|
686
|
+
return undefined;
|
|
687
|
+
const out = new Map();
|
|
688
|
+
for (const [name, overloads] of methods) {
|
|
689
|
+
const valueOnly = overloads.filter((def) => def.goReceiverKind !== 'pointer');
|
|
690
|
+
if (valueOnly.length > 0)
|
|
691
|
+
out.set(name, valueOnly);
|
|
692
|
+
}
|
|
693
|
+
return out;
|
|
203
694
|
}
|
|
204
695
|
function collectInterfaceMethodSet(iface, indexes, visiting, cache) {
|
|
205
696
|
const cached = cache.get(iface.nodeId);
|
|
@@ -275,14 +766,7 @@ function resolveEmbeddedInterface(site, indexes) {
|
|
|
275
766
|
const bound = resolveInheritanceBaseInScope(site.inScope, site.name, indexes.scopeIndexes);
|
|
276
767
|
if (bound !== undefined)
|
|
277
768
|
return bound.type === 'Interface' ? bound : undefined;
|
|
278
|
-
|
|
279
|
-
const matches = [];
|
|
280
|
-
for (const iface of indexes.interfaceById.values()) {
|
|
281
|
-
if (iface.qualifiedName === site.name || iface.qualifiedName === simpleName) {
|
|
282
|
-
matches.push(iface);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return matches.length === 1 ? matches[0] : undefined;
|
|
769
|
+
return uniqueInterfaceNamed(site.name, indexes.interfacesByQualifiedName);
|
|
286
770
|
}
|
|
287
771
|
function simpleTypeName(name) {
|
|
288
772
|
const dot = name.lastIndexOf('.');
|
|
@@ -340,30 +824,50 @@ function mergeMethodSet(target, source) {
|
|
|
340
824
|
}
|
|
341
825
|
}
|
|
342
826
|
function methodSetSatisfies(actual, required, signatureContextByDefId) {
|
|
827
|
+
let undecided = false;
|
|
343
828
|
for (const [name, requiredOverloads] of required) {
|
|
344
829
|
const actualOverloads = actual.get(name);
|
|
345
830
|
if (actualOverloads === undefined)
|
|
346
|
-
return
|
|
831
|
+
return 'unsatisfied';
|
|
347
832
|
for (const requiredMethod of requiredOverloads) {
|
|
348
833
|
// Fast arity pre-filter: if the required method has a known parameter
|
|
349
834
|
// count, reject immediately when no actual overload matches it. This
|
|
350
835
|
// avoids the expensive signature normalization loop for obvious mismatches.
|
|
351
836
|
if (requiredMethod.parameterCount !== undefined) {
|
|
352
837
|
if (!actualOverloads.some((a) => a.parameterCount === requiredMethod.parameterCount)) {
|
|
353
|
-
return
|
|
838
|
+
return 'unsatisfied';
|
|
354
839
|
}
|
|
355
840
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
841
|
+
const verdict = compatibleMethodVerdict(actualOverloads, requiredMethod, signatureContextByDefId);
|
|
842
|
+
// A decided mismatch anywhere ends it — a type that provably lacks ONE
|
|
843
|
+
// required method does not implement the interface, however many other
|
|
844
|
+
// methods we could not read. Undecided keeps scanning for exactly that
|
|
845
|
+
// reason: a hard no may still be waiting, and it is the better answer.
|
|
846
|
+
if (verdict === 'unsatisfied')
|
|
847
|
+
return 'unsatisfied';
|
|
848
|
+
if (verdict === 'undecided')
|
|
849
|
+
undecided = true;
|
|
359
850
|
}
|
|
360
851
|
}
|
|
361
|
-
return
|
|
852
|
+
return undecided ? 'undecided' : 'satisfied';
|
|
362
853
|
}
|
|
363
|
-
function
|
|
854
|
+
function compatibleMethodVerdict(actualOverloads, requiredMethod, signatureContextByDefId) {
|
|
855
|
+
// Nothing in the interface's own method to compare against: this is missing
|
|
856
|
+
// information, not a difference. It was a `false` before #2873.
|
|
364
857
|
if (!hasVerifiableSignature(requiredMethod))
|
|
365
|
-
return
|
|
366
|
-
|
|
858
|
+
return 'undecided';
|
|
859
|
+
let undecided = false;
|
|
860
|
+
for (const actualMethod of actualOverloads) {
|
|
861
|
+
const verdict = signaturesCompatible(actualMethod, requiredMethod, signatureContextByDefId);
|
|
862
|
+
// One overload that provably matches settles the method — the unknowns on
|
|
863
|
+
// the others cannot unsettle it. (Pyright does the same: a resolvable path
|
|
864
|
+
// suppresses the partially-unknown diagnostic from the others.)
|
|
865
|
+
if (verdict === 'satisfied')
|
|
866
|
+
return 'satisfied';
|
|
867
|
+
if (verdict === 'undecided')
|
|
868
|
+
undecided = true;
|
|
869
|
+
}
|
|
870
|
+
return undecided ? 'undecided' : 'unsatisfied';
|
|
367
871
|
}
|
|
368
872
|
function methodSetHasVerifiableSignatures(methods) {
|
|
369
873
|
for (const overloads of methods.values()) {
|
|
@@ -372,9 +876,6 @@ function methodSetHasVerifiableSignatures(methods) {
|
|
|
372
876
|
}
|
|
373
877
|
return true;
|
|
374
878
|
}
|
|
375
|
-
function isPointerReceiverMethod(def) {
|
|
376
|
-
return def.goReceiverKind === 'pointer';
|
|
377
|
-
}
|
|
378
879
|
function hasVerifiableSignature(def) {
|
|
379
880
|
return (def.parameterCount !== undefined ||
|
|
380
881
|
def.requiredParameterCount !== undefined ||
|
|
@@ -384,34 +885,76 @@ function hasVerifiableSignature(def) {
|
|
|
384
885
|
function signaturesCompatible(actual, required, signatureContextByDefId) {
|
|
385
886
|
const actualContext = signatureContextByDefId.get(actual.nodeId);
|
|
386
887
|
const requiredContext = signatureContextByDefId.get(required.nodeId);
|
|
387
|
-
|
|
388
|
-
countsCompatible(actual.requiredParameterCount, required.requiredParameterCount)
|
|
389
|
-
|
|
390
|
-
|
|
888
|
+
if (!countsCompatible(actual.parameterCount, required.parameterCount) ||
|
|
889
|
+
!countsCompatible(actual.requiredParameterCount, required.requiredParameterCount)) {
|
|
890
|
+
return 'unsatisfied';
|
|
891
|
+
}
|
|
892
|
+
// A decided mismatch beats an unknown — it is the answer we can stand behind —
|
|
893
|
+
// so the parameter verdict only short-circuits when it is `unsatisfied`.
|
|
894
|
+
const parameters = parameterTypesVerdict(actual, required, actualContext, requiredContext);
|
|
895
|
+
if (parameters === 'unsatisfied')
|
|
896
|
+
return 'unsatisfied';
|
|
897
|
+
const returns = returnTypeVerdict(actual.returnType, required.returnType, actualContext, requiredContext);
|
|
898
|
+
if (returns === 'unsatisfied')
|
|
899
|
+
return 'unsatisfied';
|
|
900
|
+
return parameters === 'undecided' || returns === 'undecided' ? 'undecided' : 'satisfied';
|
|
391
901
|
}
|
|
392
902
|
function countsCompatible(actual, required) {
|
|
393
903
|
return actual === undefined || required === undefined || actual === required;
|
|
394
904
|
}
|
|
395
|
-
function
|
|
396
|
-
|
|
397
|
-
|
|
905
|
+
function parameterTypesVerdict(actualDef, requiredDef, actualContext, requiredContext) {
|
|
906
|
+
const actual = actualDef.parameterTypes;
|
|
907
|
+
const required = requiredDef.parameterTypes;
|
|
908
|
+
if (actual === undefined || required === undefined) {
|
|
909
|
+
// A method that takes nothing has no list to carry — that is a decided
|
|
910
|
+
// agreement, not a gap, and it is the shape of every `Close() error`.
|
|
911
|
+
if (actualDef.parameterCount === 0 && requiredDef.parameterCount === 0)
|
|
912
|
+
return 'satisfied';
|
|
913
|
+
// Otherwise the types really are unread. This is where the old code assumed
|
|
914
|
+
// `true` and called two signatures compatible without comparing them.
|
|
915
|
+
return 'undecided';
|
|
916
|
+
}
|
|
398
917
|
if (actual.length !== required.length)
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
918
|
+
return 'unsatisfied';
|
|
919
|
+
// Indexed loop, not `entries()`: this is the innermost comparison in the
|
|
920
|
+
// detection pass and runs once per parameter per candidate pair.
|
|
921
|
+
let undecided = false;
|
|
922
|
+
for (let index = 0; index < actual.length; index++) {
|
|
923
|
+
const verdict = typeVerdict(actual[index], required[index], actualContext, requiredContext);
|
|
924
|
+
if (verdict === 'unsatisfied')
|
|
925
|
+
return 'unsatisfied';
|
|
926
|
+
if (verdict === 'undecided')
|
|
927
|
+
undecided = true;
|
|
928
|
+
}
|
|
929
|
+
return undecided ? 'undecided' : 'satisfied';
|
|
405
930
|
}
|
|
406
|
-
function
|
|
931
|
+
function returnTypeVerdict(actual, required, actualContext, requiredContext) {
|
|
407
932
|
if (required === undefined)
|
|
408
|
-
return actual === undefined;
|
|
933
|
+
return actual === undefined ? 'satisfied' : 'unsatisfied';
|
|
409
934
|
if (actual === undefined)
|
|
410
|
-
return
|
|
935
|
+
return 'unsatisfied';
|
|
936
|
+
return typeVerdict(actual, required, actualContext, requiredContext);
|
|
937
|
+
}
|
|
938
|
+
/** The one place a type spelling decides anything, and the only mint site of
|
|
939
|
+
* `undecided` below the method level: `normalizeSignatureType` returns
|
|
940
|
+
* `undefined` when a package qualifier has no identity we could recover, and
|
|
941
|
+
* two spellings we could not normalize are not thereby different. */
|
|
942
|
+
function typeVerdict(actual, required, actualContext, requiredContext) {
|
|
411
943
|
const actualType = normalizeSignatureType(actual, actualContext);
|
|
412
944
|
const requiredType = normalizeSignatureType(required, requiredContext);
|
|
413
|
-
|
|
945
|
+
if (actualType === undefined || requiredType === undefined)
|
|
946
|
+
return 'undecided';
|
|
947
|
+
return actualType === requiredType ? 'satisfied' : 'unsatisfied';
|
|
414
948
|
}
|
|
949
|
+
/** Normalized form of every type spelling seen in a file, keyed by its context.
|
|
950
|
+
*
|
|
951
|
+
* Normalization is a pure function of (spelling, context), and a context is
|
|
952
|
+
* immutable once built — so this is a cache, not state. It earns its keep
|
|
953
|
+
* because #2873 removed the early bail: a parameter list that named an
|
|
954
|
+
* out-of-repo type used to normalize to `undefined` and stop the comparison at
|
|
955
|
+
* parameter 0, and now every pair of (interface method, candidate struct) walks
|
|
956
|
+
* its whole signature, re-normalizing both sides once per candidate. */
|
|
957
|
+
const normalizedTypesByContext = new WeakMap();
|
|
415
958
|
function normalizeSignatureType(typeName, context) {
|
|
416
959
|
// Go type identity includes pointer/slice/map/variadic shape and package
|
|
417
960
|
// qualifiers. Only erase whitespace and qualify bare local type names; stripping
|
|
@@ -419,7 +962,18 @@ function normalizeSignatureType(typeName, context) {
|
|
|
419
962
|
const compact = typeName.replace(/\s+/g, '');
|
|
420
963
|
if (context === undefined)
|
|
421
964
|
return compact;
|
|
422
|
-
|
|
965
|
+
let normalized = normalizedTypesByContext.get(context);
|
|
966
|
+
if (normalized === undefined) {
|
|
967
|
+
normalized = new Map();
|
|
968
|
+
normalizedTypesByContext.set(context, normalized);
|
|
969
|
+
}
|
|
970
|
+
// `has`, not a truthiness check: `undefined` — "no agreeable identity" — is
|
|
971
|
+
// itself a result worth caching, and it is the one this file mints most.
|
|
972
|
+
if (normalized.has(compact))
|
|
973
|
+
return normalized.get(compact);
|
|
974
|
+
const qualified = qualifyGoSignatureTypes(compact, context);
|
|
975
|
+
normalized.set(compact, qualified);
|
|
976
|
+
return qualified;
|
|
423
977
|
}
|
|
424
978
|
function qualifyGoSignatureTypes(typeName, context) {
|
|
425
979
|
let unresolvedQualifier = false;
|
|
@@ -445,26 +999,78 @@ function hasPackageQualifierDot(source, offset) {
|
|
|
445
999
|
return source[offset - 1] === '.' && source[offset - 2] !== '.';
|
|
446
1000
|
}
|
|
447
1001
|
function signatureContextForFile(parsed, indexes) {
|
|
1002
|
+
// A key present with an `undefined` value means "in-repo, but no directory to
|
|
1003
|
+
// name it by" — a repo-ROOT package, whose own file spells its types bare, so
|
|
1004
|
+
// no qualifier either side can agree on exists. It still has to occupy the
|
|
1005
|
+
// name, or the fallback below would label a repo package external.
|
|
448
1006
|
const importQualifiers = new Map();
|
|
449
1007
|
const importEdges = indexes.imports?.get(parsed.moduleScope) ?? [];
|
|
450
1008
|
for (const edge of importEdges) {
|
|
451
1009
|
if (edge.kind !== 'namespace' || edge.targetFile === null)
|
|
452
1010
|
continue;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
1011
|
+
importQualifiers.set(edge.localName, packageQualifierForFile(edge.targetFile));
|
|
1012
|
+
}
|
|
1013
|
+
// An import that resolves to no file in the repository — every stdlib and
|
|
1014
|
+
// third-party package — still has an identity: its import path, which the
|
|
1015
|
+
// parsed directive kept even though the finalized `ImportEdge` did not (#2873).
|
|
1016
|
+
// Without this fallback `ctx context.Context` normalized to `undefined`, and
|
|
1017
|
+
// `undefined` reads as "signatures differ" on both sides at once, so two
|
|
1018
|
+
// textually identical methods compared unequal and Go interface satisfaction
|
|
1019
|
+
// only ever succeeded for builtin-only signatures.
|
|
1020
|
+
for (const directive of parsed.parsedImports) {
|
|
1021
|
+
if (directive.kind !== 'namespace')
|
|
1022
|
+
continue;
|
|
1023
|
+
const token = goImportToken(directive.localName, directive.targetRaw);
|
|
1024
|
+
// The edges ran first, so a token an in-repo import already claimed keeps
|
|
1025
|
+
// its package directory — the fallback fills gaps, it does not compete.
|
|
1026
|
+
if (importQualifiers.has(token))
|
|
1027
|
+
continue;
|
|
1028
|
+
importQualifiers.set(token, externalPackageQualifier(directive.targetRaw));
|
|
456
1029
|
}
|
|
457
1030
|
return {
|
|
458
1031
|
packageQualifier: packageQualifierForFile(parsed.filePath),
|
|
459
1032
|
importQualifiers,
|
|
460
1033
|
};
|
|
461
1034
|
}
|
|
1035
|
+
/** Identity for a package that lives outside the repository.
|
|
1036
|
+
*
|
|
1037
|
+
* The import path is the exact identity — `net/http` and `example.com/x/http`
|
|
1038
|
+
* are different packages that both spell their qualifier `http`, so keying on
|
|
1039
|
+
* the local name would make them compare equal. The prefix keeps the result in
|
|
1040
|
+
* a namespace no in-repo qualifier can reach: no package directory can begin
|
|
1041
|
+
* with the literal `extern:`. */
|
|
1042
|
+
function externalPackageQualifier(importPath) {
|
|
1043
|
+
return `extern:${importPath}`;
|
|
1044
|
+
}
|
|
1045
|
+
/** The token Go source writes before the `.` for this import.
|
|
1046
|
+
*
|
|
1047
|
+
* An alias names its own token, so it is returned as-is. An unaliased import
|
|
1048
|
+
* arrives here spelled as the last path segment, which is right until a module
|
|
1049
|
+
* carries a major version: `github.com/foo/bar/v2` is written `bar` and
|
|
1050
|
+
* `gopkg.in/yaml.v3` is written `yaml`, per the rule the go tool applies.
|
|
1051
|
+
*
|
|
1052
|
+
* Deriving "aliased" from the path rather than from `importedName` is
|
|
1053
|
+
* deliberate — the Go extractor sets both names to the alias when there is one
|
|
1054
|
+
* (`import-decomposer.ts`), so the two fields never disagree.
|
|
1055
|
+
*
|
|
1056
|
+
* A package whose name diverges from its path for any OTHER reason cannot be
|
|
1057
|
+
* recovered without reading the dependency's own source, which is by definition
|
|
1058
|
+
* outside the repository. Those stay unresolved, which is the safe direction. */
|
|
1059
|
+
function goImportToken(localName, importPath) {
|
|
1060
|
+
const segments = importPath.split('/').filter((segment) => segment.length > 0);
|
|
1061
|
+
const leaf = segments.pop() ?? importPath;
|
|
1062
|
+
if (localName !== leaf)
|
|
1063
|
+
return localName;
|
|
1064
|
+
const name = /^v\d+$/.test(leaf) ? (segments.pop() ?? leaf) : leaf;
|
|
1065
|
+
return name.replace(/\.v\d+$/, '');
|
|
1066
|
+
}
|
|
1067
|
+
/** The package directory, or `undefined` for a repo-root file.
|
|
1068
|
+
*
|
|
1069
|
+
* Shares `goPackageDir` with the package-clause resolver rather than repeating
|
|
1070
|
+
* its normalize-and-slice (#2837): the two disagree only on how they spell "no
|
|
1071
|
+
* directory", so the difference stays here, at the one call site that cares. */
|
|
462
1072
|
function packageQualifierForFile(filePath) {
|
|
463
|
-
const
|
|
464
|
-
const slash = normalized.lastIndexOf('/');
|
|
465
|
-
if (slash === -1)
|
|
466
|
-
return undefined;
|
|
467
|
-
const packageDir = normalized.slice(0, slash);
|
|
1073
|
+
const packageDir = goPackageDir(filePath);
|
|
468
1074
|
return packageDir.length === 0 ? undefined : packageDir;
|
|
469
1075
|
}
|
|
470
1076
|
const GO_BUILTIN_TYPES = new Set([
|