gitnexus 1.6.11-rc.8 → 1.6.11
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 +95 -26
- package/dist/_shared/graph/types.d.ts +81 -2
- package/dist/_shared/graph/types.d.ts.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.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +2 -1
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +1 -0
- package/dist/_shared/languages.js.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 +4 -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.js +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts +3 -0
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +4 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +10 -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/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/types.d.ts +15 -0
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +4 -0
- package/dist/cli/ai-context.js +90 -14
- package/dist/cli/analyze-config.js +14 -0
- package/dist/cli/analyze-options.d.ts +14 -0
- package/dist/cli/analyze-watch.d.ts +20 -0
- package/dist/cli/analyze-watch.js +434 -0
- package/dist/cli/analyze.js +27 -9
- package/dist/cli/auto-sync.d.ts +1 -0
- package/dist/cli/auto-sync.js +107 -0
- package/dist/cli/command-banner.d.ts +15 -0
- package/dist/cli/command-banner.js +42 -0
- package/dist/cli/detect-changes-format.js +21 -0
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +14 -0
- package/dist/cli/group.js +7 -1
- package/dist/cli/help-i18n.js +4 -0
- package/dist/cli/i18n/en.d.ts +18 -3
- package/dist/cli/i18n/en.js +18 -3
- package/dist/cli/i18n/resources.d.ts +33 -3
- package/dist/cli/i18n/zh-CN.d.ts +15 -0
- package/dist/cli/i18n/zh-CN.js +18 -3
- package/dist/cli/index.js +34 -7
- package/dist/cli/mcp.d.ts +15 -0
- package/dist/cli/mcp.js +44 -0
- package/dist/cli/optional-grammars.d.ts +3 -2
- package/dist/cli/optional-grammars.js +19 -3
- package/dist/cli/setup.js +41 -15
- package/dist/cli/update-notice.d.ts +34 -0
- package/dist/cli/update-notice.js +91 -0
- package/dist/cli/update.d.ts +21 -0
- package/dist/cli/update.js +93 -0
- package/dist/cli/watch.d.ts +1 -20
- package/dist/cli/watch.js +5 -371
- package/dist/core/analysis-feature-registry.d.ts +2 -0
- package/dist/core/analysis-feature-registry.js +15 -0
- package/dist/core/analyzer-identity.js +21 -3
- package/dist/core/auto-sync/analysis-worker-launch.d.ts +30 -0
- package/dist/core/auto-sync/analysis-worker-launch.js +166 -0
- package/dist/core/auto-sync/config.d.ts +33 -0
- package/dist/core/auto-sync/config.js +320 -0
- package/dist/core/auto-sync/index.d.ts +6 -0
- package/dist/core/auto-sync/index.js +6 -0
- package/dist/core/auto-sync/path-security.d.ts +9 -0
- package/dist/core/auto-sync/path-security.js +251 -0
- package/dist/core/auto-sync/repo.d.ts +1 -0
- package/dist/core/auto-sync/repo.js +6 -0
- package/dist/core/auto-sync/runner.d.ts +44 -0
- package/dist/core/auto-sync/runner.js +428 -0
- package/dist/core/auto-sync/starter.d.ts +50 -0
- package/dist/core/auto-sync/starter.js +497 -0
- package/dist/core/auto-sync/state.d.ts +37 -0
- package/dist/core/auto-sync/state.js +119 -0
- package/dist/core/group/config-parser.js +8 -1
- package/dist/core/group/cross-impact.d.ts +3 -0
- package/dist/core/group/cross-impact.js +36 -4
- package/dist/core/group/extractors/http-patterns/java.js +22 -8
- package/dist/core/group/extractors/http-patterns/kotlin.js +86 -31
- package/dist/core/group/extractors/http-patterns/node.js +145 -8
- package/dist/core/group/extractors/http-patterns/python.js +11 -7
- package/dist/core/group/extractors/http-route-extractor.js +63 -17
- package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
- package/dist/core/group/group-lock.js +5 -6
- package/dist/core/group/normalization.d.ts +38 -1
- package/dist/core/group/normalization.js +59 -3
- package/dist/core/group/service.d.ts +11 -0
- package/dist/core/group/service.js +13 -1
- package/dist/core/group/storage.js +2 -2
- package/dist/core/group/sync.d.ts +24 -1
- package/dist/core/group/sync.js +46 -8
- package/dist/core/group/types.d.ts +13 -0
- package/dist/core/incremental/derived-writeback.d.ts +36 -0
- package/dist/core/incremental/derived-writeback.js +68 -0
- package/dist/core/incremental/spring-config-drift.d.ts +12 -0
- package/dist/core/incremental/spring-config-drift.js +46 -0
- package/dist/core/incremental/subgraph-extract.d.ts +7 -4
- package/dist/core/incremental/subgraph-extract.js +30 -5
- package/dist/core/ingestion/asyncapi/document.d.ts +226 -0
- package/dist/core/ingestion/asyncapi/document.js +758 -0
- package/dist/core/ingestion/asyncapi/protocol.d.ts +79 -0
- package/dist/core/ingestion/asyncapi/protocol.js +203 -0
- package/dist/core/ingestion/call-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/call-extractors/configs/zig.js +4 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +100 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.js +319 -0
- package/dist/core/ingestion/call-processor.js +3 -1
- package/dist/core/ingestion/class-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/class-extractors/configs/zig.js +32 -0
- package/dist/core/ingestion/class-extractors/generic.js +4 -1
- package/dist/core/ingestion/class-types.d.ts +6 -2
- package/dist/core/ingestion/destination-key.d.ts +59 -0
- package/dist/core/ingestion/destination-key.js +61 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +6 -2
- package/dist/core/ingestion/entry-point-scoring.js +8 -44
- package/dist/core/ingestion/export-detection.d.ts +37 -0
- package/dist/core/ingestion/export-detection.js +60 -0
- package/dist/core/ingestion/field-extractors/configs/zig.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/zig.js +49 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +1 -1
- package/dist/core/ingestion/field-extractors/generic.js +12 -1
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +5 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +9 -0
- package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +8 -1
- package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
- package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
- package/dist/core/ingestion/frameworks/spring/destinations.d.ts +539 -0
- package/dist/core/ingestion/frameworks/spring/destinations.js +840 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
- package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.d.ts +7 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.js +22 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.d.ts +13 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.js +26 -0
- package/dist/core/ingestion/import-resolvers/zig.d.ts +34 -0
- package/dist/core/ingestion/import-resolvers/zig.js +193 -0
- package/dist/core/ingestion/language-config.d.ts +177 -0
- package/dist/core/ingestion/language-config.js +719 -0
- package/dist/core/ingestion/language-provider.d.ts +178 -1
- package/dist/core/ingestion/language-provider.js +22 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +1 -1
- package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
- package/dist/core/ingestion/languages/java/captures.js +22 -1
- package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
- package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
- package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
- package/dist/core/ingestion/languages/java/spring-di.js +44 -2
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
- package/dist/core/ingestion/languages/java.js +18 -8
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
- package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
- package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
- package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
- package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
- package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
- package/dist/core/ingestion/languages/kotlin.js +24 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/rust/query.js +8 -8
- package/dist/core/ingestion/languages/zig/captures.d.ts +260 -0
- package/dist/core/ingestion/languages/zig/captures.js +2070 -0
- package/dist/core/ingestion/languages/zig/index.d.ts +4 -0
- package/dist/core/ingestion/languages/zig/index.js +4 -0
- package/dist/core/ingestion/languages/zig/interpret.d.ts +36 -0
- package/dist/core/ingestion/languages/zig/interpret.js +176 -0
- package/dist/core/ingestion/languages/zig/query.d.ts +3 -0
- package/dist/core/ingestion/languages/zig/query.js +426 -0
- package/dist/core/ingestion/languages/zig/range-binding.d.ts +37 -0
- package/dist/core/ingestion/languages/zig/range-binding.js +373 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.d.ts +12 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.js +58 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.d.ts +25 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.js +143 -0
- package/dist/core/ingestion/languages/zig.d.ts +32 -0
- package/dist/core/ingestion/languages/zig.js +130 -0
- package/dist/core/ingestion/method-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/zig.js +120 -0
- package/dist/core/ingestion/method-extractors/generic.js +16 -4
- package/dist/core/ingestion/method-types.d.ts +10 -4
- package/dist/core/ingestion/model/field-registry.d.ts +3 -3
- package/dist/core/ingestion/model/field-registry.js +11 -7
- package/dist/core/ingestion/model/method-registry.d.ts +3 -3
- package/dist/core/ingestion/model/method-registry.js +13 -8
- package/dist/core/ingestion/model/registration-table.js +3 -0
- package/dist/core/ingestion/model/type-registry.js +8 -4
- package/dist/core/ingestion/pipeline-phases/di.js +47 -14
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +7 -1
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +79 -91
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
- package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
- package/dist/core/ingestion/pipeline-phases/routes.js +27 -18
- package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
- package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
- package/dist/core/ingestion/pipeline-phases/scan.js +82 -1
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.d.ts +123 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.js +688 -0
- package/dist/core/ingestion/pipeline.d.ts +30 -1
- package/dist/core/ingestion/pipeline.js +52 -14
- package/dist/core/ingestion/resolve-references.js +5 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
- package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
- package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +12 -18
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +214 -33
- package/dist/core/ingestion/route-extractors/kotlin-spring.d.ts +13 -0
- package/dist/core/ingestion/route-extractors/kotlin-spring.js +259 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.d.ts +6 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.js +16 -0
- package/dist/core/ingestion/route-extractors/spring-shared.d.ts +30 -1
- package/dist/core/ingestion/route-extractors/spring-shared.js +77 -9
- package/dist/core/ingestion/route-extractors/spring.js +9 -5
- package/dist/core/ingestion/scope-extractor.js +8 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +62 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +2 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +11 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +23 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +24 -3
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +11 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +29 -3
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +8 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +35 -9
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -4
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +277 -9
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +7 -3
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +43 -9
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +71 -10
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -0
- package/dist/core/ingestion/tree-sitter-queries.js +161 -0
- package/dist/core/ingestion/type-extractors/zig.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/zig.js +17 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +40 -1
- package/dist/core/ingestion/utils/ast-helpers.js +124 -6
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +9 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +75 -14
- package/dist/core/ingestion/utils/test-file-path.d.ts +28 -0
- package/dist/core/ingestion/utils/test-file-path.js +87 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.js +71 -0
- package/dist/core/ingestion/workers/parse-worker.js +85 -14
- package/dist/core/install-context.d.ts +4 -0
- package/dist/core/install-context.js +152 -0
- package/dist/core/lbug/csv-generator.d.ts +10 -1
- package/dist/core/lbug/csv-generator.js +92 -22
- package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
- package/dist/core/lbug/graph-emit-sink.js +4 -2
- package/dist/core/lbug/lbug-adapter.d.ts +100 -5
- package/dist/core/lbug/lbug-adapter.js +236 -24
- package/dist/core/lbug/schema.d.ts +6 -5
- package/dist/core/lbug/schema.js +84 -22
- package/dist/core/net/url-guard.d.ts +6 -0
- package/dist/core/net/url-guard.js +147 -0
- package/dist/core/package-version.d.ts +5 -0
- package/dist/core/package-version.js +10 -0
- package/dist/core/run-analyze.d.ts +21 -4
- package/dist/core/run-analyze.js +426 -117
- package/dist/core/search/fts-indexes.d.ts +19 -1
- package/dist/core/search/fts-indexes.js +28 -1
- package/dist/core/tree-sitter/parser-loader.js +16 -0
- package/dist/core/update-cache.d.ts +39 -0
- package/dist/core/update-cache.js +141 -0
- package/dist/core/update-check.d.ts +31 -0
- package/dist/core/update-check.js +274 -0
- package/dist/mcp/local/local-backend.d.ts +27 -13
- package/dist/mcp/local/local-backend.js +148 -60
- package/dist/mcp/repository-policy.d.ts +5 -1
- package/dist/mcp/repository-policy.js +48 -4
- package/dist/mcp/resources.js +10 -1
- package/dist/mcp/server.js +8 -9
- package/dist/mcp/tools.js +32 -22
- package/dist/server/analyze-launch.d.ts +2 -0
- package/dist/server/analyze-launch.js +2 -0
- package/dist/server/analyze-worker-protocol.d.ts +6 -1
- package/dist/server/analyze-worker.d.ts +1 -0
- package/dist/server/analyze-worker.js +38 -20
- package/dist/server/api.d.ts +5 -1
- package/dist/server/api.js +105 -88
- package/dist/server/git-clone.d.ts +40 -16
- package/dist/server/git-clone.js +253 -199
- package/dist/server/grep-params.d.ts +18 -0
- package/dist/server/grep-params.js +83 -0
- package/dist/server/grep-scan.d.ts +23 -0
- package/dist/server/grep-scan.js +107 -0
- package/dist/server/grep-worker.d.ts +1 -0
- package/dist/server/grep-worker.js +12 -0
- package/dist/server/mcp-http.d.ts +8 -0
- package/dist/server/mcp-http.js +16 -1
- package/dist/server/update-controller.d.ts +29 -0
- package/dist/server/update-controller.js +82 -0
- package/dist/storage/file-lock.d.ts +15 -0
- package/dist/storage/file-lock.js +155 -0
- package/dist/storage/fs-atomic.d.ts +24 -0
- package/dist/storage/fs-atomic.js +86 -2
- package/dist/storage/global-dir.d.ts +2 -0
- package/dist/storage/global-dir.js +6 -0
- package/dist/storage/parse-cache.d.ts +45 -7
- package/dist/storage/parse-cache.js +189 -42
- package/dist/storage/parsedfile-store.d.ts +41 -60
- package/dist/storage/parsedfile-store.js +247 -171
- package/dist/storage/repo-manager.d.ts +10 -4
- package/dist/storage/repo-manager.js +35 -25
- package/dist/storage/repo-meta.d.ts +34 -0
- package/dist/storage/v8-sidecar.d.ts +48 -0
- package/dist/storage/v8-sidecar.js +347 -0
- package/dist/types/pipeline.d.ts +14 -0
- package/dist/utils/process-identity.d.ts +2 -0
- package/dist/utils/process-identity.js +35 -0
- package/package.json +10 -4
- package/scripts/assert-web-assets.mjs +35 -0
- package/scripts/build-web.js +72 -0
- package/scripts/build.js +31 -28
- package/scripts/cross-platform-tests.ts +5 -0
- package/skills/gitnexus-cli.md +5 -1
- package/web/assets/ProcessFlowModal-DAeX2BHW.js +24 -0
- package/web/assets/{abnfDiagram-QNN2D4NM-Cq2djWWe.js → abnfDiagram-PAR5IXJI-J3OdeHLl.js} +1 -1
- package/web/assets/{agent-BWAXPjC5.js → agent-BMRqXorA.js} +6 -4
- package/web/assets/architecture-7GRP2DOG-M7G3SWCO-G3sWyX6M.js +1 -0
- package/web/assets/architectureDiagram-2PNWDENW-ysKcRlGT.js +36 -0
- package/web/assets/blockDiagram-PUWGUBOA-oLXTa1lY.js +129 -0
- package/web/assets/c4Diagram-3NLNHZP5-D3iu4eC0.js +38 -0
- package/web/assets/{chunk-2SREHG4O-Dip42xOq.js → chunk-2NMSUPJH-B24w-wng.js} +1 -1
- package/web/assets/{chunk-VJFVEZTB-CX66F2ep.js → chunk-32MCUW2P-ByUyt0Sa.js} +3 -3
- package/web/assets/{chunk-4RFN2BYJ-DHHWuC-n.js → chunk-3NPNU5GP-DocZ07Sg.js} +1 -1
- package/web/assets/{chunk-XNMVGMAZ-Cg_LnPtj.js → chunk-3SMGFRGC-CAu4JRLv.js} +1 -1
- package/web/assets/{chunk-W44A43WB-BN8EQc_u.js → chunk-4CAJECRU-DRYMwG9z.js} +1 -1
- package/web/assets/chunk-4OADUZ5Q-CxrSvOwZ.js +10 -0
- package/web/assets/{chunk-DMV4VAQV-Bn6WXDSX.js → chunk-5IQCK5RY-CCMhl4so.js} +2 -2
- package/web/assets/{chunk-RRFMTAIC-CMN0wcYA.js → chunk-5MVFYWFU-Db9KvrYO.js} +1 -1
- package/web/assets/chunk-CLS4B6BI-Uvx5QNsu.js +168 -0
- package/web/assets/chunk-DZP67EKU-B3Mt380j.js +70 -0
- package/web/assets/{chunk-6L755F7B-CMhLBxi2.js → chunk-EICP7K5X-CqwE9hui.js} +1 -1
- package/web/assets/{chunk-BI6VK774-D0oaWk8V.js → chunk-GDY2UAB4-CtQQR0a8.js} +1 -1
- package/web/assets/chunk-H7VHZCWX-CE1nAmt6.js +1 -0
- package/web/assets/chunk-IJBDOHL6-BUKtY6oF.js +1 -0
- package/web/assets/{chunk-OIYT25JQ-CQ6KOZGX.js → chunk-JFFVMJIA-0fJenqia.js} +1 -1
- package/web/assets/{chunk-HNC4WDU7-DoU3KnA7.js → chunk-JZGDI5JK-BeTMSSkJ.js} +1 -1
- package/web/assets/{chunk-EQFTRU2I-1ix7TzW9.js → chunk-KD6SPIPN-Qp1Pflah.js} +1 -1
- package/web/assets/chunk-NF366YI6-CpSpya3n.js +231 -0
- package/web/assets/chunk-NUDPKBEF-CU1-BQIW.js +34 -0
- package/web/assets/{chunk-SATU7PGQ-B1zhgOvc.js → chunk-OJINMHTS-zOCQe4eI.js} +1 -1
- package/web/assets/{chunk-E5QJAATJ-dh-5CtIV.js → chunk-Q6NGPIAH-yyBomb63.js} +1 -1
- package/web/assets/chunk-QJSWEUOL-D_rf9gPD.js +128 -0
- package/web/assets/chunk-R7JDMUKV-CRoqKpD6.js +1 -0
- package/web/assets/{chunk-VE5CLXGZ-C1vB7wpY.js → chunk-RCXAM2GK-CUqrWQDV.js} +1 -1
- package/web/assets/{chunk-66DQ2XMT-CM0xjFAN.js → chunk-RT4MAWR3-zXy9-Lvt.js} +1 -1
- package/web/assets/{chunk-TZUXEDM2-B7p9AcTw.js → chunk-SFMINX4W-J2UrvMpD.js} +1 -1
- package/web/assets/{chunk-LORZLZWG-B57uGw2N.js → chunk-SLDQ463B-CHY6e_bQ.js} +2 -2
- package/web/assets/{chunk-FWYVLQTC-BgDItRzJ.js → chunk-TCEHX7R3-CXPDEVbm.js} +1 -1
- package/web/assets/{chunk-224SPVON-B8gxtXpy.js → chunk-VQC2EELJ-Dc8fIy4R.js} +1 -1
- package/web/assets/chunk-VRZKL3EH-DB3KixTQ.js +1 -0
- package/web/assets/{chunk-A7VWPJGB-B4O3oQdQ.js → chunk-VTHDQ7BV-b7FsPQZO.js} +1 -1
- package/web/assets/chunk-VY2OSTJR-Dkgc3Brg.js +2 -0
- package/web/assets/chunk-WUBWJARI-7FwILJ3k.js +2 -0
- package/web/assets/{chunk-D6VWDJW2-BxcBdZ9c.js → chunk-YBMQ5JGJ-BSnyWZmd.js} +1 -1
- package/web/assets/chunk-YDMLL4PJ-IHhMngTz.js +2 -0
- package/web/assets/chunk-Z6V44ARX-BjCEsF0Q.js +62 -0
- package/web/assets/chunk-ZJJ7VQJP-Dz089b-K.js +321 -0
- package/web/assets/chunk-ZNLK7HRR-B0iFpmW4.js +1 -0
- package/web/assets/chunk-ZQN7UHIL-Cy7KAjQt.js +1 -0
- package/web/assets/{chunk-L5GCOVLC-CE2w8Nm_.js → chunk-ZS6VBONO-DBjJO0w9.js} +2 -2
- package/web/assets/{chunk-NV3KIAZN-5yvcpMiu.js → chunk-ZUNWM646-DNRJyNPe.js} +1 -1
- package/web/assets/classDiagram-FGAMPOII-C5Ibyode.js +1 -0
- package/web/assets/classDiagram-v2-AI5RJEK4-C5Ibyode.js +1 -0
- package/web/assets/{cose-bilkent-RZA4XIPR-BHpK4Crp.js → cose-bilkent-Q72C2OJ3-DMeFXnK8.js} +1 -1
- package/web/assets/cynefin-OW5HDTMX-6OCTWOGG-vlqakYcO.js +1 -0
- package/web/assets/{cynefinDiagram-TR7LZUCG-C3Iar9lZ.js → cynefinDiagram-2OOWUY4M-BY6DZkTt.js} +1 -1
- package/web/assets/dagre-MPVFI544-DWO70fy_.js +4 -0
- package/web/assets/diagram-AE4NWXFW-f7JRVRUL.js +24 -0
- package/web/assets/{diagram-L7DVE3PN-GIRyVUtt.js → diagram-BUJID5UG-BXZv1rCS.js} +2 -2
- package/web/assets/{diagram-JCD7PQ7C-DC5-9FRr.js → diagram-C44CZ5NI-CRNfvjCq.js} +1 -1
- package/web/assets/diagram-EYOLEXXS-DZOjKQVE.js +30 -0
- package/web/assets/diagram-P7B6PWOJ-D3SQmw3_.js +3 -0
- package/web/assets/{ebnfDiagram-DRHRQJWO-D8_CI4ZF.js → ebnfDiagram-FTPZ3PV6-jKWpIDN2.js} +1 -1
- package/web/assets/erDiagram-H3ERR26V-BqJntEuJ.js +99 -0
- package/web/assets/eventmodeling-NTZA5JFV-WKSWQHFS-Bq4FqtBL.js +1 -0
- package/web/assets/flowDiagram-YHGXBVSY-Dnlk2bEu.js +1 -0
- package/web/assets/ganttDiagram-RWFTB7ED-Bl6Y1K5T.js +292 -0
- package/web/assets/gitGraph-4MIJSDKK-JH2HKYUO-B3yc4GkH.js +1 -0
- package/web/assets/gitGraphDiagram-MAR6GKOP-CkNvsrdw.js +106 -0
- package/web/assets/{index-CJDpyH-n.css → index-C2_aej58.css} +1 -1
- package/web/assets/{index-DDRie6_8.js → index-Dj3vQOHK.js} +51 -51
- package/web/assets/info-A6RAGUB7-3TX3OFWW-BM3N5_Dv.js +1 -0
- package/web/assets/infoDiagram-LV547AFH-COkFutAf.js +2 -0
- package/web/assets/{ishikawaDiagram-4JDSWWDM-DmqWtjkl.js → ishikawaDiagram-PUJQGNDS-Bb8FylSR.js} +2 -2
- package/web/assets/{journeyDiagram-QUS3FAKT-XAzVzrQW.js → journeyDiagram-EW5QJT4W-BzoHUBhM.js} +4 -4
- package/web/assets/{kanban-definition-D4L7SQKK-YurRnmYn.js → kanban-definition-JSQERAZB-Uy2Pi0yQ.js} +4 -4
- package/web/assets/katex-CZ4GXH2S-C0Fcou7U.js +257 -0
- package/web/assets/{mindmap-definition-66QP5TD6-ChrWWnil.js → mindmap-definition-VBJCLQLM-B-CnOnt_.js} +3 -3
- package/web/assets/packet-AYTQ26CC-MKII6P3Y-Bd52ZE3V.js +1 -0
- package/web/assets/{pegDiagram-YKIO5C6U-QGeQLEq2.js → pegDiagram-7WILOQTJ-D9sneKXg.js} +1 -1
- package/web/assets/pie-WAS4IAKB-6B4OPMJ5-DW5Xy69Z.js +1 -0
- package/web/assets/pieDiagram-EFA7CBSB-Dx2NQofL.js +39 -0
- package/web/assets/{quadrantDiagram-VO5QLCXA-B7098wSc.js → quadrantDiagram-WARVYA7P-DPKL9_0A.js} +3 -3
- package/web/assets/radar-RG4KPBEZ-UPTR3XUL-CkzibT2h.js +1 -0
- package/web/assets/railroad-74A4TZTK-MEFUPFMS-D9zF-mDN.js +1 -0
- package/web/assets/railroad-abnf-HS5TGJTU-R5YG2S5D-ruacjUbX.js +1 -0
- package/web/assets/railroad-ebnf-LZEXJU2U-G5QEX2L6-S1zc5OiO.js +1 -0
- package/web/assets/railroad-peg-WCYAUIDC-H5I2ZRY2-Cbcr0XzY.js +1 -0
- package/web/assets/{railroadDiagram-M77LTMSB-AXu4vxk_.js → railroadDiagram-5NIQVNLQ-DsweTo14.js} +1 -1
- package/web/assets/{requirementDiagram-RASO5HTO-B-l8InpK.js → requirementDiagram-SXREGOKZ-CXwdNSVR.js} +4 -4
- package/web/assets/{sankeyDiagram-F32LOJ6L-Kd7zjJgX.js → sankeyDiagram-VV74M2VP-CA6jtP9P.js} +3 -3
- package/web/assets/{sequenceDiagram-URATNSBD-BlcdY9DS.js → sequenceDiagram-52ZFIFDL-k_5rEbzm.js} +15 -15
- package/web/assets/src-Df5C1Nz4.js +1 -0
- package/web/assets/stateDiagram-3QAKPIVI-BejHTf31.js +1 -0
- package/web/assets/stateDiagram-v2-HN2P4RDZ-BrfoRuOc.js +1 -0
- package/web/assets/swimlanes-QLVP42QD-CQSVO5D6.js +1 -0
- package/web/assets/swimlanesDiagram-JKPDBFCN-DrWB9kcD.js +8 -0
- package/web/assets/{timeline-definition-WJXWRH4I-DUfp1R3E.js → timeline-definition-GS45XAXW-C0Ks8rPP.js} +4 -4
- package/web/assets/treeView-Q6P3EWNA-ZRJGANNQ-DmKOCo6L.js +1 -0
- package/web/assets/treemap-WGGIJYW6-K64VN5AS-DO3xY92U.js +1 -0
- package/web/assets/{vennDiagram-K3VCMQLI-Bj-FN-XS.js → vennDiagram-QIQU2ZRJ-rgPiS837.js} +3 -3
- package/web/assets/wardley-WFR3VGLG-D67OWCCH-DiDPBNft.js +1 -0
- package/web/assets/wardleyDiagram-U6YNM66N-DRVr7SPi.js +78 -0
- package/web/assets/{xychartDiagram-5VRUVLCW-CK_rbSWE.js → xychartDiagram-XJAZEDNM-COtlZzYb.js} +3 -3
- package/web/index.html +19 -17
- package/web/assets/ProcessFlowModal-Badh2Pbg.js +0 -24
- package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +0 -1
- package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +0 -36
- package/web/assets/blockDiagram-54WLDVWM-Dg_hrRWE.js +0 -132
- package/web/assets/c4Diagram-X2LASM7V-CnhoT4aV.js +0 -10
- package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +0 -127
- package/web/assets/chunk-5VCL7Z4A-CQ-2dYWj.js +0 -1
- package/web/assets/chunk-6BELYETK-ChsYtfHW.js +0 -1
- package/web/assets/chunk-7CWYLC5S-DRgGkkpF.js +0 -2
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +0 -32
- package/web/assets/chunk-KRXBNO2N-C-UNuKKf.js +0 -1
- package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +0 -321
- package/web/assets/chunk-LIEV3EAG-pyKGssV3.js +0 -1
- package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +0 -62
- package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +0 -10
- package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +0 -156
- package/web/assets/chunk-SZD42YQK-ijyKKVr1.js +0 -70
- package/web/assets/chunk-TFPGFQPA-Dj6a-0pC.js +0 -231
- package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +0 -2
- package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +0 -1
- package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +0 -1
- package/web/assets/chunk-WJBAP47W-BckNkuEN.js +0 -1
- package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +0 -1
- package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +0 -1
- package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +0 -1
- package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +0 -4
- package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +0 -30
- package/web/assets/diagram-KFBZAVDW-Dfmf_4ti.js +0 -3
- package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +0 -24
- package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +0 -85
- package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +0 -1
- package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +0 -1
- package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +0 -292
- package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +0 -1
- package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +0 -106
- package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +0 -1
- package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +0 -2
- package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +0 -257
- package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +0 -1
- package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +0 -1
- package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +0 -39
- package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +0 -1
- package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +0 -1
- package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +0 -1
- package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +0 -1
- package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +0 -1
- package/web/assets/src-C5sx_gMp.js +0 -1
- package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +0 -1
- package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +0 -1
- package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +0 -2
- package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +0 -8
- package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +0 -1
- package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +0 -1
- package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +0 -1
- package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +0 -78
- /package/web/assets/{sizeCapture-5GORAGP4-BEqQzsxs.js → sizeCapture-FGA5AGYP-BEqQzsxs.js} +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
const RUNTIME_OWNER_ALIASES = 'runtimeOwnerAliases';
|
|
3
|
+
const RUNTIME_CALLABLE_ALIASES = 'runtimeCallableAliases';
|
|
4
|
+
const KOTLIN_SUSPEND = 'kotlinSuspend';
|
|
5
|
+
const fileFacadeMetadataCache = new WeakMap();
|
|
6
|
+
function rootNode(node) {
|
|
7
|
+
let current = node;
|
|
8
|
+
while (current.parent)
|
|
9
|
+
current = current.parent;
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
function packageName(root) {
|
|
13
|
+
const header = root.namedChildren.find((child) => child.type === 'package_header');
|
|
14
|
+
return header?.text.replace(/^package\s+/, '').trim() ?? '';
|
|
15
|
+
}
|
|
16
|
+
function qualify(packageNameValue, simpleName) {
|
|
17
|
+
return packageNameValue.length === 0 ? simpleName : `${packageNameValue}.${simpleName}`;
|
|
18
|
+
}
|
|
19
|
+
function standardFacadeName(filePath) {
|
|
20
|
+
const stem = path.basename(filePath).replace(/\.(?:kt|kts)$/i, '');
|
|
21
|
+
return `${stem.charAt(0).toUpperCase()}${stem.slice(1)}Kt`;
|
|
22
|
+
}
|
|
23
|
+
function jvmNameIdentifiers(imports, allowUnqualified) {
|
|
24
|
+
const names = new Set(['kotlin.jvm.JvmName']);
|
|
25
|
+
if (allowUnqualified)
|
|
26
|
+
names.add('JvmName');
|
|
27
|
+
for (const parsedImport of imports) {
|
|
28
|
+
if (parsedImport.kind !== 'named' && parsedImport.kind !== 'alias')
|
|
29
|
+
continue;
|
|
30
|
+
if (parsedImport.importedName !== 'JvmName')
|
|
31
|
+
continue;
|
|
32
|
+
const target = parsedImport.targetRaw.replace(/\\/g, '/');
|
|
33
|
+
if (target === 'kotlin.jvm' || target === 'kotlin.jvm.JvmName') {
|
|
34
|
+
names.add(parsedImport.localName);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return [...names];
|
|
38
|
+
}
|
|
39
|
+
function annotationJvmName(source, target = '', imports = [], allowUnqualified = true) {
|
|
40
|
+
const names = jvmNameIdentifiers(imports, allowUnqualified);
|
|
41
|
+
if (names.length === 0)
|
|
42
|
+
return undefined;
|
|
43
|
+
const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
44
|
+
const prefix = target.length === 0 ? '' : `${escapedTarget}:`;
|
|
45
|
+
const namePattern = [...names]
|
|
46
|
+
.map((name) => name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
47
|
+
.join('|');
|
|
48
|
+
return new RegExp(`@${prefix}(?:${namePattern})\\s*\\(\\s*["']([^"']+)["']\\s*\\)`).exec(source)?.[1];
|
|
49
|
+
}
|
|
50
|
+
function fileFacadeMetadata(root, imports, allowUnqualified) {
|
|
51
|
+
const cached = fileFacadeMetadataCache.get(root);
|
|
52
|
+
if (cached !== undefined)
|
|
53
|
+
return cached;
|
|
54
|
+
const metadata = {
|
|
55
|
+
packageName: packageName(root),
|
|
56
|
+
customFacade: annotationJvmName(root.text, 'file', imports, allowUnqualified),
|
|
57
|
+
};
|
|
58
|
+
fileFacadeMetadataCache.set(root, metadata);
|
|
59
|
+
return metadata;
|
|
60
|
+
}
|
|
61
|
+
function hasEnclosingType(node) {
|
|
62
|
+
let current = node.parent;
|
|
63
|
+
while (current) {
|
|
64
|
+
if (current.type === 'class_declaration' ||
|
|
65
|
+
current.type === 'object_declaration' ||
|
|
66
|
+
current.type === 'companion_object') {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
current = current.parent;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
/** Transient graph metadata used only by the same analysis run's runtime import. */
|
|
74
|
+
export function extractKotlinRuntimeSymbolProperties(context) {
|
|
75
|
+
const properties = {};
|
|
76
|
+
const source = context.definitionNode.text;
|
|
77
|
+
const root = rootNode(context.definitionNode);
|
|
78
|
+
const allowUnqualifiedJvmName = !/\bannotation\s+class\s+JvmName\b/.test(root.text);
|
|
79
|
+
if ((context.nodeLabel === 'Function' || context.nodeLabel === 'Method') &&
|
|
80
|
+
context.definitionNode.type === 'function_declaration') {
|
|
81
|
+
if (/\bsuspend\b/.test(source.slice(0, source.indexOf('fun') + 3))) {
|
|
82
|
+
properties[KOTLIN_SUSPEND] = true;
|
|
83
|
+
}
|
|
84
|
+
const callableJvmName = annotationJvmName(source, '', context.parsedImports, allowUnqualifiedJvmName);
|
|
85
|
+
if (callableJvmName !== undefined) {
|
|
86
|
+
properties[RUNTIME_CALLABLE_ALIASES] = [callableJvmName];
|
|
87
|
+
}
|
|
88
|
+
if (!hasEnclosingType(context.definitionNode)) {
|
|
89
|
+
const facade = fileFacadeMetadata(root, context.parsedImports, allowUnqualifiedJvmName);
|
|
90
|
+
properties[RUNTIME_OWNER_ALIASES] = [
|
|
91
|
+
qualify(facade.packageName, facade.customFacade ?? standardFacadeName(context.filePath)),
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (context.nodeLabel === 'Property') {
|
|
96
|
+
const getterJvmName = annotationJvmName(source, 'get', context.parsedImports, allowUnqualifiedJvmName);
|
|
97
|
+
if (getterJvmName !== undefined) {
|
|
98
|
+
properties[RUNTIME_CALLABLE_ALIASES] = [getterJvmName];
|
|
99
|
+
}
|
|
100
|
+
if (!hasEnclosingType(context.definitionNode)) {
|
|
101
|
+
const facade = fileFacadeMetadata(root, context.parsedImports, allowUnqualifiedJvmName);
|
|
102
|
+
properties[RUNTIME_OWNER_ALIASES] = [
|
|
103
|
+
qualify(facade.packageName, facade.customFacade ?? standardFacadeName(context.filePath)),
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return Object.keys(properties).length === 0 ? undefined : properties;
|
|
108
|
+
}
|
|
109
|
+
function stringArrayProperty(node, property) {
|
|
110
|
+
const value = node.properties[property];
|
|
111
|
+
return Array.isArray(value)
|
|
112
|
+
? value.filter((item) => typeof item === 'string')
|
|
113
|
+
: [];
|
|
114
|
+
}
|
|
115
|
+
function callableNames(node) {
|
|
116
|
+
return [String(node.properties.name), ...stringArrayProperty(node, RUNTIME_CALLABLE_ALIASES)];
|
|
117
|
+
}
|
|
118
|
+
function propertyGetterNames(node) {
|
|
119
|
+
const name = String(node.properties.name);
|
|
120
|
+
const capitalized = `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
121
|
+
return [
|
|
122
|
+
name.startsWith('is') && name.length > 2 && /[A-Z]/.test(name.charAt(2))
|
|
123
|
+
? name
|
|
124
|
+
: `get${capitalized}`,
|
|
125
|
+
...stringArrayProperty(node, RUNTIME_CALLABLE_ALIASES),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
function sourceCallableName(runtimeName) {
|
|
129
|
+
return runtimeName.endsWith('$default') ? runtimeName.slice(0, -'$default'.length) : runtimeName;
|
|
130
|
+
}
|
|
131
|
+
function matchesKotlinCallable(node, runtime) {
|
|
132
|
+
// Kotlin property declarations and their synthesized JVM accessor Methods
|
|
133
|
+
// coexist in the graph. Bind runtime getters to the source Property so the
|
|
134
|
+
// synthetic accessor cannot turn an otherwise exact match into ambiguity.
|
|
135
|
+
if (node.properties.synthetic === 'kotlin-jvm')
|
|
136
|
+
return false;
|
|
137
|
+
const runtimeName = sourceCallableName(runtime.name);
|
|
138
|
+
if (node.label === 'Property') {
|
|
139
|
+
const names = propertyGetterNames(node);
|
|
140
|
+
if (!names.includes(runtime.name) && !names.includes(runtimeName))
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
else if (!callableNames(node).includes(runtimeName)) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
const parameterCount = node.properties.parameterCount;
|
|
147
|
+
const descriptorTypes = runtime.descriptorParameterTypes;
|
|
148
|
+
if (typeof parameterCount !== 'number' ||
|
|
149
|
+
descriptorTypes === undefined ||
|
|
150
|
+
runtime.name.endsWith('$default')) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
if (parameterCount === descriptorTypes.length)
|
|
154
|
+
return true;
|
|
155
|
+
return (node.properties[KOTLIN_SUSPEND] === true &&
|
|
156
|
+
parameterCount + 1 === descriptorTypes.length &&
|
|
157
|
+
descriptorTypes.at(-1) === 'kotlin/coroutines/Continuation');
|
|
158
|
+
}
|
|
159
|
+
export const kotlinRuntimeSymbolStrategy = {
|
|
160
|
+
callableOwnerAliases(node, owner) {
|
|
161
|
+
const aliases = [...stringArrayProperty(node, RUNTIME_OWNER_ALIASES)];
|
|
162
|
+
const ownerName = owner?.properties.qualifiedName;
|
|
163
|
+
if (typeof ownerName === 'string') {
|
|
164
|
+
aliases.push(ownerName);
|
|
165
|
+
if (node.properties.isStatic === true && !ownerName.endsWith('.Companion')) {
|
|
166
|
+
aliases.push(`${ownerName}.Companion`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return aliases;
|
|
170
|
+
},
|
|
171
|
+
matchesCallable: matchesKotlinCallable,
|
|
172
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { KnowledgeGraph } from '../../../graph/types.js';
|
|
2
|
+
import type { GraphNodeLookup } from '../../scope-resolution/graph-bridge/node-lookup.js';
|
|
3
|
+
import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
|
|
4
|
+
import { type ParsedFile, type ScopeId } from '../../../../_shared/index.js';
|
|
5
|
+
import { type SpringConfigConsumer } from '../../frameworks/spring/config-bindings.js';
|
|
6
|
+
import { type SyntaxNode } from '../../utils/ast-helpers.js';
|
|
7
|
+
export interface KotlinSpringConfigConsumerFact {
|
|
8
|
+
readonly consumer: SpringConfigConsumer;
|
|
9
|
+
readonly annotationName: string;
|
|
10
|
+
readonly classScopeId: ScopeId;
|
|
11
|
+
}
|
|
12
|
+
/** Collect config facts from the Kotlin parser's existing AST (no reparse). */
|
|
13
|
+
export declare function captureKotlinSpringConfigConsumerFacts(root: SyntaxNode, filePath: string): KotlinSpringConfigConsumerFact[];
|
|
14
|
+
/** Parse Kotlin consumers for focused unit tests; production reuses the worker AST. */
|
|
15
|
+
export declare function extractKotlinSpringConfigConsumers(source: string): SpringConfigConsumer[];
|
|
16
|
+
export declare function extractKotlinSpringConfigConsumerFacts(source: string): KotlinSpringConfigConsumerFact[];
|
|
17
|
+
/** Kotlin ScopeResolver post-resolution hook for Spring configuration consumers. */
|
|
18
|
+
export declare function attachKotlinSpringConfigBindings(graph: KnowledgeGraph, parsedFiles: readonly ParsedFile[], _nodeLookup: GraphNodeLookup, indexes: ScopeResolutionIndexes): void;
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { makeScopeId } from '../../../../_shared/index.js';
|
|
2
|
+
import { bindSpringConfigConsumers, } from '../../frameworks/spring/config-bindings.js';
|
|
3
|
+
import { createSpringAnnotationNameResolver } from '../../frameworks/spring/bean-candidates.js';
|
|
4
|
+
import { parseSpringAnnotationArguments, parseStaticStringLiteral, } from '../../frameworks/spring/annotation-arguments.js';
|
|
5
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
6
|
+
import { nodeToCapture } from '../../utils/ast-helpers.js';
|
|
7
|
+
import { getKotlinParser } from './query.js';
|
|
8
|
+
import { getKotlinSpringConfigConsumerFacts } from './capture-side-channel.js';
|
|
9
|
+
import { isKotlinPackageSiblingVisibilityIncomplete } from './package-siblings.js';
|
|
10
|
+
const VALUE_ANNOTATION = 'org.springframework.beans.factory.annotation.Value';
|
|
11
|
+
const CONFIGURATION_PROPERTIES_ANNOTATION = 'org.springframework.boot.context.properties.ConfigurationProperties';
|
|
12
|
+
const VALUE_SIMPLE = 'Value';
|
|
13
|
+
const CONFIGURATION_PROPERTIES_SIMPLE = 'ConfigurationProperties';
|
|
14
|
+
const SKIP_USE_SITES = new Set(['get', 'property', 'file']);
|
|
15
|
+
const BIND_USE_SITES = new Set(['field', 'set', 'param']);
|
|
16
|
+
const OWNER_TYPES = new Set(['class_declaration', 'object_declaration', 'companion_object']);
|
|
17
|
+
const INTERPOLATION_TYPES = new Set([
|
|
18
|
+
'interpolated_identifier',
|
|
19
|
+
'interpolated_expression',
|
|
20
|
+
'interpolation_expression_start',
|
|
21
|
+
]);
|
|
22
|
+
const STRING_LITERAL_TYPES = new Set(['string_literal', 'character_literal']);
|
|
23
|
+
function firstDescendantOfType(node, type) {
|
|
24
|
+
const stack = [...node.namedChildren].reverse();
|
|
25
|
+
while (stack.length > 0) {
|
|
26
|
+
const current = stack.pop();
|
|
27
|
+
if (current === undefined)
|
|
28
|
+
continue;
|
|
29
|
+
if (current.type === type)
|
|
30
|
+
return current;
|
|
31
|
+
for (let index = current.namedChildren.length - 1; index >= 0; index--) {
|
|
32
|
+
const child = current.namedChildren[index];
|
|
33
|
+
if (child !== undefined)
|
|
34
|
+
stack.push(child);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
function ownerName(declaration) {
|
|
40
|
+
if (declaration.type === 'companion_object') {
|
|
41
|
+
const named = declaration.namedChildren.find((child) => child.type === 'type_identifier');
|
|
42
|
+
return named?.text.trim() || 'Companion';
|
|
43
|
+
}
|
|
44
|
+
return (declaration.namedChildren.find((child) => child.type === 'type_identifier')?.text.trim() ??
|
|
45
|
+
declaration.namedChildren.find((child) => child.type === 'simple_identifier')?.text.trim());
|
|
46
|
+
}
|
|
47
|
+
function enclosingOwner(node) {
|
|
48
|
+
let current = node.parent;
|
|
49
|
+
while (current !== null) {
|
|
50
|
+
if (OWNER_TYPES.has(current.type))
|
|
51
|
+
return current;
|
|
52
|
+
current = current.parent;
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function classScopeId(filePath, declaration) {
|
|
57
|
+
return makeScopeId({
|
|
58
|
+
filePath,
|
|
59
|
+
range: nodeToCapture('@scope.class', declaration).range,
|
|
60
|
+
kind: 'Class',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function collectKotlinImports(root) {
|
|
64
|
+
const exact = new Map();
|
|
65
|
+
const wildcard = new Set();
|
|
66
|
+
const localTypes = new Map();
|
|
67
|
+
for (const header of root.descendantsOfType('import_header')) {
|
|
68
|
+
const text = header.text.replace(/^import\s+/, '').trim();
|
|
69
|
+
const aliasMatch = text.match(/^([\w.]+)\s+as\s+(\w+)\s*$/);
|
|
70
|
+
if (aliasMatch !== null) {
|
|
71
|
+
exact.set(aliasMatch[2], aliasMatch[1]);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (text.endsWith('.*'))
|
|
75
|
+
wildcard.add(text.slice(0, -2));
|
|
76
|
+
else {
|
|
77
|
+
const simple = text.slice(text.lastIndexOf('.') + 1);
|
|
78
|
+
if (simple.length > 0)
|
|
79
|
+
exact.set(simple, text);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const type of ['class_declaration', 'object_declaration']) {
|
|
83
|
+
for (const declaration of root.descendantsOfType(type)) {
|
|
84
|
+
const name = ownerName(declaration);
|
|
85
|
+
if (name) {
|
|
86
|
+
const declarations = localTypes.get(name) ?? [];
|
|
87
|
+
declarations.push(declaration);
|
|
88
|
+
localTypes.set(name, declarations);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { exact, wildcard, localTypes };
|
|
93
|
+
}
|
|
94
|
+
function annotationFromNode(annotation) {
|
|
95
|
+
const nameNode = firstDescendantOfType(annotation, 'user_type') ??
|
|
96
|
+
firstDescendantOfType(annotation, 'type_identifier') ??
|
|
97
|
+
firstDescendantOfType(annotation, 'simple_identifier');
|
|
98
|
+
if (nameNode === undefined)
|
|
99
|
+
return null;
|
|
100
|
+
const useSiteTarget = annotation.namedChildren
|
|
101
|
+
.find((child) => child.type === 'use_site_target')
|
|
102
|
+
?.text.replace(/:\s*$/, '')
|
|
103
|
+
.trim();
|
|
104
|
+
return {
|
|
105
|
+
name: nameNode.text.trim(),
|
|
106
|
+
node: annotation,
|
|
107
|
+
...(useSiteTarget === undefined || useSiteTarget.length === 0 ? {} : { useSiteTarget }),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function annotationsOn(node) {
|
|
111
|
+
const annotations = [];
|
|
112
|
+
for (const child of node.namedChildren) {
|
|
113
|
+
if (child.type === 'annotation') {
|
|
114
|
+
const fact = annotationFromNode(child);
|
|
115
|
+
if (fact !== null)
|
|
116
|
+
annotations.push(fact);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (child.type !== 'modifiers' && child.type !== 'parameter_modifiers')
|
|
120
|
+
continue;
|
|
121
|
+
for (const nested of child.namedChildren) {
|
|
122
|
+
if (nested.type !== 'annotation')
|
|
123
|
+
continue;
|
|
124
|
+
const fact = annotationFromNode(nested);
|
|
125
|
+
if (fact !== null)
|
|
126
|
+
annotations.push(fact);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return annotations;
|
|
130
|
+
}
|
|
131
|
+
function simpleName(rawName) {
|
|
132
|
+
const parts = rawName.split('.');
|
|
133
|
+
return parts[parts.length - 1] ?? rawName;
|
|
134
|
+
}
|
|
135
|
+
function importedAs(imports, simple, fqn, wildcardPackage) {
|
|
136
|
+
if (imports.exact.get(simple) === fqn)
|
|
137
|
+
return true;
|
|
138
|
+
// An explicit import wins over a star import in Kotlin, so a conflicting
|
|
139
|
+
// binding for the same simple name rules the Spring annotation out even when
|
|
140
|
+
// its package is wildcard-imported.
|
|
141
|
+
return imports.exact.get(simple) === undefined && imports.wildcard.has(wildcardPackage);
|
|
142
|
+
}
|
|
143
|
+
function hasVisibleLocalType(imports, simple, annotation) {
|
|
144
|
+
for (const declaration of imports.localTypes.get(simple) ?? []) {
|
|
145
|
+
const declarationOwner = enclosingOwner(declaration);
|
|
146
|
+
if (declarationOwner === undefined)
|
|
147
|
+
return true;
|
|
148
|
+
let current = annotation;
|
|
149
|
+
while (current !== null) {
|
|
150
|
+
if (current.id === declarationOwner.id)
|
|
151
|
+
return true;
|
|
152
|
+
current = current.parent;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
const SIMPLE_CONFIG_ANNOTATIONS = [
|
|
158
|
+
{
|
|
159
|
+
simple: VALUE_SIMPLE,
|
|
160
|
+
kind: 'value',
|
|
161
|
+
fqn: VALUE_ANNOTATION,
|
|
162
|
+
wildcardPackage: 'org.springframework.beans.factory.annotation',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
simple: CONFIGURATION_PROPERTIES_SIMPLE,
|
|
166
|
+
kind: 'configuration-properties',
|
|
167
|
+
fqn: CONFIGURATION_PROPERTIES_ANNOTATION,
|
|
168
|
+
wildcardPackage: 'org.springframework.boot.context.properties',
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
function configAnnotationKind(annotation, imports) {
|
|
172
|
+
const rawName = annotation.name;
|
|
173
|
+
if (rawName === VALUE_ANNOTATION)
|
|
174
|
+
return 'value';
|
|
175
|
+
if (rawName === CONFIGURATION_PROPERTIES_ANNOTATION)
|
|
176
|
+
return 'configuration-properties';
|
|
177
|
+
const simple = simpleName(rawName);
|
|
178
|
+
const aliased = imports.exact.get(simple);
|
|
179
|
+
if (aliased === VALUE_ANNOTATION)
|
|
180
|
+
return 'value';
|
|
181
|
+
if (aliased === CONFIGURATION_PROPERTIES_ANNOTATION)
|
|
182
|
+
return 'configuration-properties';
|
|
183
|
+
for (const candidate of SIMPLE_CONFIG_ANNOTATIONS) {
|
|
184
|
+
if (simple !== candidate.simple)
|
|
185
|
+
continue;
|
|
186
|
+
if (hasVisibleLocalType(imports, simple, annotation.node) && !imports.exact.has(simple)) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
return importedAs(imports, simple, candidate.fqn, candidate.wildcardPackage)
|
|
190
|
+
? candidate.kind
|
|
191
|
+
: null;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
function hasInterpolation(annotation) {
|
|
196
|
+
const stack = [...annotation.namedChildren];
|
|
197
|
+
while (stack.length > 0) {
|
|
198
|
+
const current = stack.pop();
|
|
199
|
+
if (current === undefined)
|
|
200
|
+
continue;
|
|
201
|
+
if (INTERPOLATION_TYPES.has(current.type))
|
|
202
|
+
return true;
|
|
203
|
+
stack.push(...current.namedChildren);
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
function decodeKotlinStringLiteral(literal) {
|
|
208
|
+
const raw = literal.startsWith('"""') && literal.endsWith('"""');
|
|
209
|
+
const delimiterLength = raw ? 3 : 1;
|
|
210
|
+
if (literal.length < delimiterLength * 2)
|
|
211
|
+
return null;
|
|
212
|
+
const body = literal.slice(delimiterLength, -delimiterLength);
|
|
213
|
+
if (!raw && /(?<!\\)\$\{/.test(body))
|
|
214
|
+
return null;
|
|
215
|
+
if (raw)
|
|
216
|
+
return body;
|
|
217
|
+
return body
|
|
218
|
+
.replace(/\\u([0-9a-fA-F]{4})/g, (_match, hex) => String.fromCharCode(Number.parseInt(hex, 16)))
|
|
219
|
+
.replace(/\\(["'\\$btnfr])/g, (_match, escaped) => {
|
|
220
|
+
const controls = {
|
|
221
|
+
b: '\b',
|
|
222
|
+
t: '\t',
|
|
223
|
+
n: '\n',
|
|
224
|
+
f: '\f',
|
|
225
|
+
r: '\r',
|
|
226
|
+
$: '$',
|
|
227
|
+
};
|
|
228
|
+
return controls[escaped] ?? escaped;
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function kotlinStringLiterals(annotation) {
|
|
232
|
+
const literals = [];
|
|
233
|
+
const stack = [...annotation.namedChildren];
|
|
234
|
+
while (stack.length > 0) {
|
|
235
|
+
const current = stack.pop();
|
|
236
|
+
if (current === undefined)
|
|
237
|
+
continue;
|
|
238
|
+
if (STRING_LITERAL_TYPES.has(current.type)) {
|
|
239
|
+
const decoded = decodeKotlinStringLiteral(current.text);
|
|
240
|
+
if (decoded !== null)
|
|
241
|
+
literals.push(decoded);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
stack.push(...current.namedChildren);
|
|
245
|
+
}
|
|
246
|
+
return literals;
|
|
247
|
+
}
|
|
248
|
+
function parseValuePlaceholderKeys(annotation) {
|
|
249
|
+
if (hasInterpolation(annotation))
|
|
250
|
+
return [];
|
|
251
|
+
const keys = new Set();
|
|
252
|
+
for (const literal of kotlinStringLiterals(annotation)) {
|
|
253
|
+
for (const match of literal.matchAll(/\$\{([^{}]+)\}/g)) {
|
|
254
|
+
const key = match[1].split(':', 1)[0].trim();
|
|
255
|
+
if (/^[A-Za-z0-9_.-]+$/.test(key))
|
|
256
|
+
keys.add(key);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return [...keys];
|
|
260
|
+
}
|
|
261
|
+
function parseConfigurationPropertiesPrefix(annotation) {
|
|
262
|
+
if (hasInterpolation(annotation))
|
|
263
|
+
return null;
|
|
264
|
+
const argumentsList = parseSpringAnnotationArguments(annotation.text);
|
|
265
|
+
if (argumentsList !== null) {
|
|
266
|
+
const named = argumentsList.filter((argument) => argument.name === 'prefix' || argument.name === 'value');
|
|
267
|
+
const positional = argumentsList.filter((argument) => argument.name === undefined);
|
|
268
|
+
const chosen = named.length === 1 ? named[0] : named.length === 0 ? positional[0] : undefined;
|
|
269
|
+
if (chosen !== undefined) {
|
|
270
|
+
const decoded = parseStaticStringLiteral(chosen.value);
|
|
271
|
+
if (decoded === null)
|
|
272
|
+
return null;
|
|
273
|
+
const prefix = decoded.replace(/^\.+|\.+$/g, '');
|
|
274
|
+
if (/^[A-Za-z0-9_.-]+$/.test(prefix))
|
|
275
|
+
return prefix;
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
if (argumentsList.length > 0)
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
const literals = kotlinStringLiterals(annotation);
|
|
282
|
+
if (literals.length !== 1)
|
|
283
|
+
return null;
|
|
284
|
+
const prefix = literals[0].trim().replace(/^\.+|\.+$/g, '');
|
|
285
|
+
return /^[A-Za-z0-9_.-]+$/.test(prefix) ? prefix : null;
|
|
286
|
+
}
|
|
287
|
+
function allowedUseSite(useSiteTarget) {
|
|
288
|
+
if (useSiteTarget === undefined)
|
|
289
|
+
return true;
|
|
290
|
+
if (SKIP_USE_SITES.has(useSiteTarget))
|
|
291
|
+
return false;
|
|
292
|
+
return BIND_USE_SITES.has(useSiteTarget);
|
|
293
|
+
}
|
|
294
|
+
function hasBindingPattern(parameter) {
|
|
295
|
+
return parameter.namedChildren.some((child) => child.type === 'binding_pattern_kind');
|
|
296
|
+
}
|
|
297
|
+
function propertyName(node) {
|
|
298
|
+
if (node.type === 'class_parameter') {
|
|
299
|
+
return node.namedChildren.find((child) => child.type === 'simple_identifier')?.text.trim();
|
|
300
|
+
}
|
|
301
|
+
const variable = node.namedChildren.find((child) => child.type === 'variable_declaration');
|
|
302
|
+
return variable?.namedChildren.find((child) => child.type === 'simple_identifier')?.text.trim();
|
|
303
|
+
}
|
|
304
|
+
function underFileAnnotation(node) {
|
|
305
|
+
let current = node;
|
|
306
|
+
while (current !== null) {
|
|
307
|
+
if (current.type === 'file_annotation')
|
|
308
|
+
return true;
|
|
309
|
+
current = current.parent;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
function pushValueFacts(facts, member, filePath, imports) {
|
|
314
|
+
if (underFileAnnotation(member))
|
|
315
|
+
return;
|
|
316
|
+
const owner = enclosingOwner(member);
|
|
317
|
+
if (owner === undefined)
|
|
318
|
+
return;
|
|
319
|
+
const fieldName = propertyName(member);
|
|
320
|
+
if (fieldName === undefined)
|
|
321
|
+
return;
|
|
322
|
+
for (const annotation of annotationsOn(member)) {
|
|
323
|
+
if (!allowedUseSite(annotation.useSiteTarget))
|
|
324
|
+
continue;
|
|
325
|
+
if (configAnnotationKind(annotation, imports) !== 'value')
|
|
326
|
+
continue;
|
|
327
|
+
const keys = parseValuePlaceholderKeys(annotation.node);
|
|
328
|
+
if (keys.length === 0)
|
|
329
|
+
continue;
|
|
330
|
+
facts.push({
|
|
331
|
+
consumer: {
|
|
332
|
+
kind: 'value',
|
|
333
|
+
fieldName,
|
|
334
|
+
line: member.startPosition.row + 1,
|
|
335
|
+
keys,
|
|
336
|
+
},
|
|
337
|
+
annotationName: annotation.name,
|
|
338
|
+
classScopeId: classScopeId(filePath, owner),
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/** Collect config facts from the Kotlin parser's existing AST (no reparse). */
|
|
343
|
+
export function captureKotlinSpringConfigConsumerFacts(root, filePath) {
|
|
344
|
+
const imports = collectKotlinImports(root);
|
|
345
|
+
const facts = [];
|
|
346
|
+
for (const property of root.descendantsOfType('property_declaration')) {
|
|
347
|
+
pushValueFacts(facts, property, filePath, imports);
|
|
348
|
+
}
|
|
349
|
+
for (const parameter of root.descendantsOfType('class_parameter')) {
|
|
350
|
+
if (!hasBindingPattern(parameter))
|
|
351
|
+
continue;
|
|
352
|
+
pushValueFacts(facts, parameter, filePath, imports);
|
|
353
|
+
}
|
|
354
|
+
for (const type of ['class_declaration', 'object_declaration']) {
|
|
355
|
+
for (const declaration of root.descendantsOfType(type)) {
|
|
356
|
+
const className = ownerName(declaration);
|
|
357
|
+
if (className === undefined)
|
|
358
|
+
continue;
|
|
359
|
+
for (const annotation of annotationsOn(declaration)) {
|
|
360
|
+
if (configAnnotationKind(annotation, imports) !== 'configuration-properties') {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
const prefix = parseConfigurationPropertiesPrefix(annotation.node);
|
|
364
|
+
if (prefix === null)
|
|
365
|
+
continue;
|
|
366
|
+
facts.push({
|
|
367
|
+
consumer: {
|
|
368
|
+
kind: 'configuration-properties',
|
|
369
|
+
className,
|
|
370
|
+
line: declaration.startPosition.row + 1,
|
|
371
|
+
prefix,
|
|
372
|
+
},
|
|
373
|
+
annotationName: annotation.name,
|
|
374
|
+
classScopeId: classScopeId(filePath, declaration),
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return facts;
|
|
380
|
+
}
|
|
381
|
+
/** Parse Kotlin consumers for focused unit tests; production reuses the worker AST. */
|
|
382
|
+
export function extractKotlinSpringConfigConsumers(source) {
|
|
383
|
+
const tree = parseSourceSafe(getKotlinParser(), source);
|
|
384
|
+
return captureKotlinSpringConfigConsumerFacts(tree.rootNode, '<memory>').map((fact) => fact.consumer);
|
|
385
|
+
}
|
|
386
|
+
export function extractKotlinSpringConfigConsumerFacts(source) {
|
|
387
|
+
const tree = parseSourceSafe(getKotlinParser(), source);
|
|
388
|
+
return captureKotlinSpringConfigConsumerFacts(tree.rootNode, '<memory>');
|
|
389
|
+
}
|
|
390
|
+
/** Kotlin ScopeResolver post-resolution hook for Spring configuration consumers. */
|
|
391
|
+
export function attachKotlinSpringConfigBindings(graph, parsedFiles, _nodeLookup, indexes) {
|
|
392
|
+
const resolveAnnotation = createSpringAnnotationNameResolver(indexes);
|
|
393
|
+
const recognizedAnnotations = new Set([VALUE_ANNOTATION, CONFIGURATION_PROPERTIES_ANNOTATION]);
|
|
394
|
+
const batches = [];
|
|
395
|
+
for (const parsed of parsedFiles) {
|
|
396
|
+
const consumers = [];
|
|
397
|
+
for (const fact of getKotlinSpringConfigConsumerFacts(parsed.filePath)) {
|
|
398
|
+
const classScope = indexes.scopeTree.getScope(fact.classScopeId);
|
|
399
|
+
if (classScope === undefined || classScope.kind !== 'Class')
|
|
400
|
+
continue;
|
|
401
|
+
const expectedAnnotation = fact.consumer.kind === 'value' ? VALUE_ANNOTATION : CONFIGURATION_PROPERTIES_ANNOTATION;
|
|
402
|
+
const enclosingScope = fact.consumer.kind === 'value' ? classScope.id : classScope.parent;
|
|
403
|
+
const resolved = resolveAnnotation(fact.annotationName, parsed, enclosingScope, recognizedAnnotations, isKotlinPackageSiblingVisibilityIncomplete(parsed.filePath));
|
|
404
|
+
if (resolved === expectedAnnotation)
|
|
405
|
+
consumers.push(fact.consumer);
|
|
406
|
+
}
|
|
407
|
+
if (consumers.length > 0)
|
|
408
|
+
batches.push({ filePath: parsed.filePath, consumers });
|
|
409
|
+
}
|
|
410
|
+
bindSpringConfigConsumers(graph, batches);
|
|
411
|
+
}
|
|
@@ -1,14 +1,64 @@
|
|
|
1
|
+
import { type SpringArgumentFact } from '../../frameworks/spring/argument-facts.js';
|
|
1
2
|
import { type SpringDiAnnotationFact, type SpringDiClassFact, type SpringDiDependencyFact, type SpringDiInjectionSiteFact } from '../../frameworks/spring/di-metadata.js';
|
|
2
3
|
import { type SyntaxNode } from '../../utils/ast-helpers.js';
|
|
3
4
|
export interface KotlinAnnotationSyntaxFact extends SpringDiAnnotationFact {
|
|
4
5
|
readonly useSiteTarget?: string;
|
|
5
6
|
readonly line: number;
|
|
7
|
+
/** Present only for callers that opt in via `kotlinSpringAnnotationFacts`. */
|
|
8
|
+
readonly args?: readonly SpringArgumentFact[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Options for `kotlinSpringAnnotationFacts`.
|
|
12
|
+
*
|
|
13
|
+
* The STRUCTURED arguments are opt-in because DI captures every annotated
|
|
14
|
+
* constructor parameter, property, and function in the repository, and none of
|
|
15
|
+
* its consumers reads them. Note what this does and does not save: every fact
|
|
16
|
+
* already carries `text`, the annotation's full source, so the argument TEXT
|
|
17
|
+
* crosses the worker boundary either way. What the opt-in avoids is a second,
|
|
18
|
+
* parsed copy of that same text on facts that would never look at it.
|
|
19
|
+
*/
|
|
20
|
+
export interface KotlinSpringAnnotationFactOptions {
|
|
21
|
+
readonly includeArguments?: boolean;
|
|
6
22
|
}
|
|
7
23
|
export type KotlinSpringDependencyFact = SpringDiDependencyFact<KotlinAnnotationSyntaxFact>;
|
|
8
24
|
type KotlinSpringInjectionSiteKind = 'property' | 'constructor' | 'method';
|
|
9
25
|
export type KotlinSpringInjectionSiteFact = SpringDiInjectionSiteFact<KotlinAnnotationSyntaxFact, KotlinSpringInjectionSiteKind>;
|
|
10
26
|
export type KotlinSpringDiClassFact = SpringDiClassFact<KotlinAnnotationSyntaxFact, KotlinSpringInjectionSiteKind>;
|
|
11
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Kotlin writes annotation arguments and call arguments with the same
|
|
29
|
+
* `value_arguments` node, so one reader serves `@KafkaListener(topics = [...])`
|
|
30
|
+
* and `kafkaTemplate.send(topic, payload)`.
|
|
31
|
+
*
|
|
32
|
+
* A named argument keeps its key; everything else — positional values, spreads,
|
|
33
|
+
* collection literals, and interpolated strings — is kept as raw text, because
|
|
34
|
+
* evaluating it would be resolution.
|
|
35
|
+
*
|
|
36
|
+
* Returns `null` for a list tree-sitter had to recover, and the callers decide
|
|
37
|
+
* what that means: a producer call drops the whole fact, since it has no state
|
|
38
|
+
* for "published somewhere unreadable", while an annotation reports no
|
|
39
|
+
* arguments and collapses into the marker form. Both answers say "nothing here
|
|
40
|
+
* to resolve", which is true; a fabricated value would send a consumer
|
|
41
|
+
* somewhere real and wrong.
|
|
42
|
+
*
|
|
43
|
+
* The check lives HERE, not only in the callers. This function is exported and
|
|
44
|
+
* already has a caller in another module, so a guard that every future caller
|
|
45
|
+
* has to remember is the same fragility this change set exists to remove —
|
|
46
|
+
* `null` makes the decision unavoidable at the type level. Per-argument
|
|
47
|
+
* re-checks are still pointless: `hasError` propagates from any argument up to
|
|
48
|
+
* the list, so a branch behind this one could never fire.
|
|
49
|
+
*
|
|
50
|
+
* A named argument is identified by the `=` TOKEN, and the two-child shape is
|
|
51
|
+
* only a corroborating detail. Today nothing well formed reaches two children
|
|
52
|
+
* without an `=`: an annotated positional argument such as
|
|
53
|
+
* `@Suppress("UNCHECKED_CAST") "orders"` arrives as ONE `prefix_expression`, not
|
|
54
|
+
* as two children, so the token test is currently redundant. It is kept as the
|
|
55
|
+
* leading condition anyway, because the failure it prevents is asymmetric —
|
|
56
|
+
* dropping it would let any future two-child positional shape be reported under
|
|
57
|
+
* an argument key the source never wrote, which is the failure mode this whole
|
|
58
|
+
* change set is about.
|
|
59
|
+
*/
|
|
60
|
+
export declare function kotlinValueArgumentFacts(valueArguments: SyntaxNode): SpringArgumentFact[] | null;
|
|
61
|
+
export declare function kotlinSpringAnnotationFacts(node: SyntaxNode, options?: KotlinSpringAnnotationFactOptions): KotlinAnnotationSyntaxFact[];
|
|
12
62
|
/**
|
|
13
63
|
* Capture one class already surfaced by Kotlin's scope query. Kotlin-specific
|
|
14
64
|
* syntax is normalized here while import/FQN semantics remain deferred until
|