codesift-mcp 0.13.1 → 0.15.0
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 +5 -1
- package/dist/cli/commands-admin.d.ts +18 -0
- package/dist/cli/commands-admin.d.ts.map +1 -0
- package/dist/cli/commands-admin.js +187 -0
- package/dist/cli/commands-admin.js.map +1 -0
- package/dist/cli/commands-daemon.d.ts +42 -0
- package/dist/cli/commands-daemon.d.ts.map +1 -0
- package/dist/cli/commands-daemon.js +163 -0
- package/dist/cli/commands-daemon.js.map +1 -0
- package/dist/cli/commands-index.d.ts +12 -0
- package/dist/cli/commands-index.d.ts.map +1 -0
- package/dist/cli/commands-index.js +133 -0
- package/dist/cli/commands-index.js.map +1 -0
- package/dist/cli/commands-maintenance.d.ts +12 -0
- package/dist/cli/commands-maintenance.d.ts.map +1 -0
- package/dist/cli/commands-maintenance.js +409 -0
- package/dist/cli/commands-maintenance.js.map +1 -0
- package/dist/cli/commands-query.d.ts +21 -0
- package/dist/cli/commands-query.d.ts.map +1 -0
- package/dist/cli/commands-query.js +270 -0
- package/dist/cli/commands-query.js.map +1 -0
- package/dist/cli/commands.d.ts +2 -36
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +8 -854
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/embed-child.js +13 -2
- package/dist/cli/embed-child.js.map +1 -1
- package/dist/cli/hooks/pre-tool-use.d.ts +1 -0
- package/dist/cli/hooks/pre-tool-use.d.ts.map +1 -1
- package/dist/cli/hooks/pre-tool-use.js +11 -2
- package/dist/cli/hooks/pre-tool-use.js.map +1 -1
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -0
- package/dist/config.js.map +1 -1
- package/dist/formatters-core.d.ts +7 -0
- package/dist/formatters-core.d.ts.map +1 -1
- package/dist/formatters-core.js +14 -3
- package/dist/formatters-core.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +5 -2
- package/dist/instructions.js.map +1 -1
- package/dist/parser/extractors/hono-inline-analyzer.js +2 -2
- package/dist/parser/extractors/hono-inline-analyzer.js.map +1 -1
- package/dist/parser/extractors/php-class-metadata.d.ts +10 -0
- package/dist/parser/extractors/php-class-metadata.d.ts.map +1 -0
- package/dist/parser/extractors/php-class-metadata.js +65 -0
- package/dist/parser/extractors/php-class-metadata.js.map +1 -0
- package/dist/parser/extractors/php-doc.d.ts +13 -0
- package/dist/parser/extractors/php-doc.d.ts.map +1 -0
- package/dist/parser/extractors/php-doc.js +39 -0
- package/dist/parser/extractors/php-doc.js.map +1 -0
- package/dist/parser/extractors/php-node-metadata.d.ts +26 -0
- package/dist/parser/extractors/php-node-metadata.d.ts.map +1 -0
- package/dist/parser/extractors/php-node-metadata.js +132 -0
- package/dist/parser/extractors/php-node-metadata.js.map +1 -0
- package/dist/parser/extractors/php-symbol-builders.d.ts +13 -0
- package/dist/parser/extractors/php-symbol-builders.d.ts.map +1 -0
- package/dist/parser/extractors/php-symbol-builders.js +58 -0
- package/dist/parser/extractors/php-symbol-builders.js.map +1 -0
- package/dist/parser/extractors/php-walker.d.ts +4 -0
- package/dist/parser/extractors/php-walker.d.ts.map +1 -0
- package/dist/parser/extractors/php-walker.js +238 -0
- package/dist/parser/extractors/php-walker.js.map +1 -0
- package/dist/parser/extractors/php.d.ts +2 -33
- package/dist/parser/extractors/php.d.ts.map +1 -1
- package/dist/parser/extractors/php.js +2 -747
- package/dist/parser/extractors/php.js.map +1 -1
- package/dist/register-tool-groups/core/search.d.ts.map +1 -1
- package/dist/register-tool-groups/core/search.js +14 -0
- package/dist/register-tool-groups/core/search.js.map +1 -1
- package/dist/register-tool-groups/core/symbols.d.ts.map +1 -1
- package/dist/register-tool-groups/core/symbols.js +50 -5
- package/dist/register-tool-groups/core/symbols.js.map +1 -1
- package/dist/register-tool-loaders.d.ts +11 -11
- package/dist/register-tool-loaders.d.ts.map +1 -1
- package/dist/register-tools/runtime.d.ts +11 -0
- package/dist/register-tools/runtime.d.ts.map +1 -1
- package/dist/register-tools/runtime.js +40 -0
- package/dist/register-tools/runtime.js.map +1 -1
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +5 -1
- package/dist/register-tools.js.map +1 -1
- package/dist/retrieval/semantic-handlers.d.ts.map +1 -1
- package/dist/retrieval/semantic-handlers.js +10 -3
- package/dist/retrieval/semantic-handlers.js.map +1 -1
- package/dist/search/semantic.d.ts +2 -0
- package/dist/search/semantic.d.ts.map +1 -1
- package/dist/search/semantic.js +41 -9
- package/dist/search/semantic.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +54 -2
- package/dist/server.js.map +1 -1
- package/dist/storage/_shared.d.ts +21 -0
- package/dist/storage/_shared.d.ts.map +1 -1
- package/dist/storage/_shared.js +36 -0
- package/dist/storage/_shared.js.map +1 -1
- package/dist/storage/chunk-store.d.ts +14 -2
- package/dist/storage/chunk-store.d.ts.map +1 -1
- package/dist/storage/chunk-store.js +214 -34
- package/dist/storage/chunk-store.js.map +1 -1
- package/dist/storage/embedding-store.d.ts +0 -12
- package/dist/storage/embedding-store.d.ts.map +1 -1
- package/dist/storage/embedding-store.js +69 -9
- package/dist/storage/embedding-store.js.map +1 -1
- package/dist/storage/index-cache.d.ts +12 -0
- package/dist/storage/index-cache.d.ts.map +1 -0
- package/dist/storage/index-cache.js +89 -0
- package/dist/storage/index-cache.js.map +1 -0
- package/dist/storage/index-footprint.d.ts +12 -0
- package/dist/storage/index-footprint.d.ts.map +1 -0
- package/dist/storage/index-footprint.js +41 -0
- package/dist/storage/index-footprint.js.map +1 -0
- package/dist/storage/index-json-mutations.d.ts +11 -0
- package/dist/storage/index-json-mutations.d.ts.map +1 -0
- package/dist/storage/index-json-mutations.js +93 -0
- package/dist/storage/index-json-mutations.js.map +1 -0
- package/dist/storage/index-migration.d.ts +22 -0
- package/dist/storage/index-migration.d.ts.map +1 -0
- package/dist/storage/index-migration.js +80 -0
- package/dist/storage/index-migration.js.map +1 -0
- package/dist/storage/index-store.d.ts +26 -55
- package/dist/storage/index-store.d.ts.map +1 -1
- package/dist/storage/index-store.js +82 -350
- package/dist/storage/index-store.js.map +1 -1
- package/dist/storage/index-version.d.ts +39 -0
- package/dist/storage/index-version.d.ts.map +1 -0
- package/dist/storage/index-version.js +87 -0
- package/dist/storage/index-version.js.map +1 -0
- package/dist/storage/registry.d.ts +9 -1
- package/dist/storage/registry.d.ts.map +1 -1
- package/dist/storage/registry.js +233 -9
- package/dist/storage/registry.js.map +1 -1
- package/dist/storage/shared-embedding-cache.d.ts +23 -3
- package/dist/storage/shared-embedding-cache.d.ts.map +1 -1
- package/dist/storage/shared-embedding-cache.js +300 -45
- package/dist/storage/shared-embedding-cache.js.map +1 -1
- package/dist/storage/sqlite/accessors.d.ts +34 -0
- package/dist/storage/sqlite/accessors.d.ts.map +1 -0
- package/dist/storage/sqlite/accessors.js +178 -0
- package/dist/storage/sqlite/accessors.js.map +1 -0
- package/dist/storage/sqlite/connection.d.ts +43 -0
- package/dist/storage/sqlite/connection.d.ts.map +1 -0
- package/dist/storage/sqlite/connection.js +241 -0
- package/dist/storage/sqlite/connection.js.map +1 -0
- package/dist/storage/sqlite/errors.d.ts +38 -0
- package/dist/storage/sqlite/errors.d.ts.map +1 -0
- package/dist/storage/sqlite/errors.js +150 -0
- package/dist/storage/sqlite/errors.js.map +1 -0
- package/dist/storage/sqlite/index-io.d.ts +49 -0
- package/dist/storage/sqlite/index-io.d.ts.map +1 -0
- package/dist/storage/sqlite/index-io.js +268 -0
- package/dist/storage/sqlite/index-io.js.map +1 -0
- package/dist/storage/sqlite/meta.d.ts +41 -0
- package/dist/storage/sqlite/meta.d.ts.map +1 -0
- package/dist/storage/sqlite/meta.js +28 -0
- package/dist/storage/sqlite/meta.js.map +1 -0
- package/dist/storage/sqlite/rows.d.ts +64 -0
- package/dist/storage/sqlite/rows.d.ts.map +1 -0
- package/dist/storage/sqlite/rows.js +186 -0
- package/dist/storage/sqlite/rows.js.map +1 -0
- package/dist/storage/sqlite/runtime.d.ts +6 -0
- package/dist/storage/sqlite/runtime.d.ts.map +1 -0
- package/dist/storage/sqlite/runtime.js +31 -0
- package/dist/storage/sqlite/runtime.js.map +1 -0
- package/dist/storage/sqlite/schema.d.ts +34 -0
- package/dist/storage/sqlite/schema.d.ts.map +1 -0
- package/dist/storage/sqlite/schema.js +98 -0
- package/dist/storage/sqlite/schema.js.map +1 -0
- package/dist/storage/sqlite-index-store.d.ts +40 -80
- package/dist/storage/sqlite-index-store.d.ts.map +1 -1
- package/dist/storage/sqlite-index-store.js +32 -577
- package/dist/storage/sqlite-index-store.js.map +1 -1
- package/dist/storage/telemetry/config.d.ts.map +1 -1
- package/dist/storage/telemetry/config.js +15 -3
- package/dist/storage/telemetry/config.js.map +1 -1
- package/dist/storage/telemetry/payload.d.ts.map +1 -1
- package/dist/storage/telemetry/payload.js +4 -1
- package/dist/storage/telemetry/payload.js.map +1 -1
- package/dist/storage/telemetry/retro-aggregator.d.ts +48 -0
- package/dist/storage/telemetry/retro-aggregator.d.ts.map +1 -0
- package/dist/storage/telemetry/retro-aggregator.js +221 -0
- package/dist/storage/telemetry/retro-aggregator.js.map +1 -0
- package/dist/storage/telemetry/sanitizer.d.ts +46 -0
- package/dist/storage/telemetry/sanitizer.d.ts.map +1 -1
- package/dist/storage/telemetry/sanitizer.js +25 -0
- package/dist/storage/telemetry/sanitizer.js.map +1 -1
- package/dist/storage/telemetry/uploader.d.ts +3 -1
- package/dist/storage/telemetry/uploader.d.ts.map +1 -1
- package/dist/storage/telemetry/uploader.js +161 -18
- package/dist/storage/telemetry/uploader.js.map +1 -1
- package/dist/storage/workspace-resolver.js +1 -1
- package/dist/storage/workspace-resolver.js.map +1 -1
- package/dist/tools/cross-repo-contract-adapters.d.ts +39 -0
- package/dist/tools/cross-repo-contract-adapters.d.ts.map +1 -0
- package/dist/tools/cross-repo-contract-adapters.js +70 -0
- package/dist/tools/cross-repo-contract-adapters.js.map +1 -0
- package/dist/tools/cross-repo-contract-group.d.ts +17 -0
- package/dist/tools/cross-repo-contract-group.d.ts.map +1 -0
- package/dist/tools/cross-repo-contract-group.js +89 -0
- package/dist/tools/cross-repo-contract-group.js.map +1 -0
- package/dist/tools/cross-repo-contract-matcher.d.ts +24 -0
- package/dist/tools/cross-repo-contract-matcher.d.ts.map +1 -0
- package/dist/tools/cross-repo-contract-matcher.js +134 -0
- package/dist/tools/cross-repo-contract-matcher.js.map +1 -0
- package/dist/tools/cross-repo-contract-resolver.d.ts +9 -0
- package/dist/tools/cross-repo-contract-resolver.d.ts.map +1 -0
- package/dist/tools/cross-repo-contract-resolver.js +86 -0
- package/dist/tools/cross-repo-contract-resolver.js.map +1 -0
- package/dist/tools/cross-repo-contract-tools.d.ts +12 -135
- package/dist/tools/cross-repo-contract-tools.d.ts.map +1 -1
- package/dist/tools/cross-repo-contract-tools.js +8 -589
- package/dist/tools/cross-repo-contract-tools.js.map +1 -1
- package/dist/tools/cross-repo-contract-types.d.ts +30 -0
- package/dist/tools/cross-repo-contract-types.d.ts.map +1 -0
- package/dist/tools/cross-repo-contract-types.js +3 -0
- package/dist/tools/cross-repo-contract-types.js.map +1 -0
- package/dist/tools/cross-repo-outbound-calls.d.ts +28 -0
- package/dist/tools/cross-repo-outbound-calls.d.ts.map +1 -0
- package/dist/tools/cross-repo-outbound-calls.js +347 -0
- package/dist/tools/cross-repo-outbound-calls.js.map +1 -0
- package/dist/tools/cross-repo-outbound-lexer/call-detectors.d.ts.map +1 -1
- package/dist/tools/cross-repo-outbound-lexer/call-detectors.js +2 -0
- package/dist/tools/cross-repo-outbound-lexer/call-detectors.js.map +1 -1
- package/dist/tools/cross-repo-outbound-lexer/types.d.ts +2 -0
- package/dist/tools/cross-repo-outbound-lexer/types.d.ts.map +1 -1
- package/dist/tools/index-tools/file-indexer.js +3 -3
- package/dist/tools/index-tools/file-indexer.js.map +1 -1
- package/dist/tools/index-tools/folder-indexer.d.ts.map +1 -1
- package/dist/tools/index-tools/folder-indexer.js +51 -3
- package/dist/tools/index-tools/folder-indexer.js.map +1 -1
- package/dist/tools/index-tools/parse.d.ts +12 -3
- package/dist/tools/index-tools/parse.d.ts.map +1 -1
- package/dist/tools/index-tools/parse.js +33 -8
- package/dist/tools/index-tools/parse.js.map +1 -1
- package/dist/tools/index-tools/registry.d.ts +35 -0
- package/dist/tools/index-tools/registry.d.ts.map +1 -1
- package/dist/tools/index-tools/registry.js +167 -3
- package/dist/tools/index-tools/registry.js.map +1 -1
- package/dist/tools/index-tools/state.d.ts +31 -0
- package/dist/tools/index-tools/state.d.ts.map +1 -1
- package/dist/tools/index-tools/state.js +53 -0
- package/dist/tools/index-tools/state.js.map +1 -1
- package/dist/tools/index-tools/types.d.ts +9 -0
- package/dist/tools/index-tools/types.d.ts.map +1 -1
- package/dist/tools/index-tools/watcher.js +3 -3
- package/dist/tools/index-tools/watcher.js.map +1 -1
- package/dist/tools/index-tools/worktree-seed.d.ts +44 -0
- package/dist/tools/index-tools/worktree-seed.d.ts.map +1 -0
- package/dist/tools/index-tools/worktree-seed.js +302 -0
- package/dist/tools/index-tools/worktree-seed.js.map +1 -0
- package/dist/tools/index-tools.d.ts +2 -2
- package/dist/tools/index-tools.d.ts.map +1 -1
- package/dist/tools/index-tools.js +5 -3
- package/dist/tools/index-tools.js.map +1 -1
- package/dist/tools/nest-ext-tools/graphql.d.ts +17 -0
- package/dist/tools/nest-ext-tools/graphql.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/graphql.js +54 -0
- package/dist/tools/nest-ext-tools/graphql.js.map +1 -0
- package/dist/tools/nest-ext-tools/microservice.d.ts +17 -0
- package/dist/tools/nest-ext-tools/microservice.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/microservice.js +51 -0
- package/dist/tools/nest-ext-tools/microservice.js.map +1 -0
- package/dist/tools/nest-ext-tools/openapi.d.ts +81 -0
- package/dist/tools/nest-ext-tools/openapi.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/openapi.js +254 -0
- package/dist/tools/nest-ext-tools/openapi.js.map +1 -0
- package/dist/tools/nest-ext-tools/queue.d.ts +27 -0
- package/dist/tools/nest-ext-tools/queue.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/queue.js +95 -0
- package/dist/tools/nest-ext-tools/queue.js.map +1 -0
- package/dist/tools/nest-ext-tools/schedule.d.ts +19 -0
- package/dist/tools/nest-ext-tools/schedule.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/schedule.js +89 -0
- package/dist/tools/nest-ext-tools/schedule.js.map +1 -0
- package/dist/tools/nest-ext-tools/scope.d.ts +19 -0
- package/dist/tools/nest-ext-tools/scope.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/scope.js +151 -0
- package/dist/tools/nest-ext-tools/scope.js.map +1 -0
- package/dist/tools/nest-ext-tools/shared.d.ts +33 -0
- package/dist/tools/nest-ext-tools/shared.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/shared.js +279 -0
- package/dist/tools/nest-ext-tools/shared.js.map +1 -0
- package/dist/tools/nest-ext-tools/typeorm.d.ts +22 -0
- package/dist/tools/nest-ext-tools/typeorm.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/typeorm.js +59 -0
- package/dist/tools/nest-ext-tools/typeorm.js.map +1 -0
- package/dist/tools/nest-ext-tools/websocket.d.ts +21 -0
- package/dist/tools/nest-ext-tools/websocket.d.ts.map +1 -0
- package/dist/tools/nest-ext-tools/websocket.js +70 -0
- package/dist/tools/nest-ext-tools/websocket.js.map +1 -0
- package/dist/tools/nest-ext-tools.d.ts +10 -204
- package/dist/tools/nest-ext-tools.d.ts.map +1 -1
- package/dist/tools/nest-ext-tools.js +10 -749
- package/dist/tools/nest-ext-tools.js.map +1 -1
- package/dist/tools/perf-tools.js +2 -2
- package/dist/tools/plan-turn/stale-index.d.ts +32 -0
- package/dist/tools/plan-turn/stale-index.d.ts.map +1 -1
- package/dist/tools/plan-turn/stale-index.js +42 -5
- package/dist/tools/plan-turn/stale-index.js.map +1 -1
- package/dist/tools/python-audit/checks/dead-code.d.ts +1 -1
- package/dist/tools/python-audit/checks/dead-code.d.ts.map +1 -1
- package/dist/tools/python-constants/constant-match.d.ts +5 -0
- package/dist/tools/python-constants/constant-match.d.ts.map +1 -0
- package/dist/tools/python-constants/constant-match.js +24 -0
- package/dist/tools/python-constants/constant-match.js.map +1 -0
- package/dist/tools/python-constants/file-context.d.ts +5 -0
- package/dist/tools/python-constants/file-context.d.ts.map +1 -0
- package/dist/tools/python-constants/file-context.js +91 -0
- package/dist/tools/python-constants/file-context.js.map +1 -0
- package/dist/tools/python-constants/function-defaults.d.ts +5 -0
- package/dist/tools/python-constants/function-defaults.d.ts.map +1 -0
- package/dist/tools/python-constants/function-defaults.js +98 -0
- package/dist/tools/python-constants/function-defaults.js.map +1 -0
- package/dist/tools/python-constants/model.d.ts +78 -0
- package/dist/tools/python-constants/model.d.ts.map +1 -0
- package/dist/tools/python-constants/model.js +2 -0
- package/dist/tools/python-constants/model.js.map +1 -0
- package/dist/tools/python-constants/syntax.d.ts +22 -0
- package/dist/tools/python-constants/syntax.d.ts.map +1 -0
- package/dist/tools/python-constants/syntax.js +93 -0
- package/dist/tools/python-constants/syntax.js.map +1 -0
- package/dist/tools/python-constants/value-resolver.d.ts +6 -0
- package/dist/tools/python-constants/value-resolver.d.ts.map +1 -0
- package/dist/tools/python-constants/value-resolver.js +320 -0
- package/dist/tools/python-constants/value-resolver.js.map +1 -0
- package/dist/tools/python-constants-tools.d.ts +3 -45
- package/dist/tools/python-constants-tools.d.ts.map +1 -1
- package/dist/tools/python-constants-tools.js +2 -505
- package/dist/tools/python-constants-tools.js.map +1 -1
- package/dist/tools/route-tools/django.d.ts +8 -0
- package/dist/tools/route-tools/django.d.ts.map +1 -0
- package/dist/tools/route-tools/django.js +52 -0
- package/dist/tools/route-tools/django.js.map +1 -0
- package/dist/tools/route-tools/express.d.ts +5 -0
- package/dist/tools/route-tools/express.d.ts.map +1 -0
- package/dist/tools/route-tools/express.js +33 -0
- package/dist/tools/route-tools/express.js.map +1 -0
- package/dist/tools/route-tools/file-sources.d.ts +7 -0
- package/dist/tools/route-tools/file-sources.d.ts.map +1 -0
- package/dist/tools/route-tools/file-sources.js +15 -0
- package/dist/tools/route-tools/file-sources.js.map +1 -0
- package/dist/tools/route-tools/handler-discovery.d.ts +4 -0
- package/dist/tools/route-tools/handler-discovery.d.ts.map +1 -0
- package/dist/tools/route-tools/handler-discovery.js +38 -0
- package/dist/tools/route-tools/handler-discovery.js.map +1 -0
- package/dist/tools/route-tools/hono.d.ts +5 -0
- package/dist/tools/route-tools/hono.d.ts.map +1 -0
- package/dist/tools/route-tools/hono.js +61 -0
- package/dist/tools/route-tools/hono.js.map +1 -0
- package/dist/tools/route-tools/ktor.d.ts +5 -0
- package/dist/tools/route-tools/ktor.d.ts.map +1 -0
- package/dist/tools/route-tools/ktor.js +76 -0
- package/dist/tools/route-tools/ktor.js.map +1 -0
- package/dist/tools/route-tools/laravel.d.ts +5 -0
- package/dist/tools/route-tools/laravel.d.ts.map +1 -0
- package/dist/tools/route-tools/laravel.js +45 -0
- package/dist/tools/route-tools/laravel.js.map +1 -0
- package/dist/tools/route-tools/mermaid-call-chain.d.ts +3 -0
- package/dist/tools/route-tools/mermaid-call-chain.d.ts.map +1 -0
- package/dist/tools/route-tools/mermaid-call-chain.js +50 -0
- package/dist/tools/route-tools/mermaid-call-chain.js.map +1 -0
- package/dist/tools/route-tools/nest.d.ts +5 -0
- package/dist/tools/route-tools/nest.d.ts.map +1 -0
- package/dist/tools/route-tools/nest.js +75 -0
- package/dist/tools/route-tools/nest.js.map +1 -0
- package/dist/tools/route-tools/next-trace.d.ts +4 -0
- package/dist/tools/route-tools/next-trace.d.ts.map +1 -0
- package/dist/tools/route-tools/next-trace.js +48 -0
- package/dist/tools/route-tools/next-trace.js.map +1 -0
- package/dist/tools/route-tools/next.d.ts +7 -0
- package/dist/tools/route-tools/next.d.ts.map +1 -0
- package/dist/tools/route-tools/next.js +77 -0
- package/dist/tools/route-tools/next.js.map +1 -0
- package/dist/tools/route-tools/python-decorators.d.ts +7 -0
- package/dist/tools/route-tools/python-decorators.d.ts.map +1 -0
- package/dist/tools/route-tools/python-decorators.js +53 -0
- package/dist/tools/route-tools/python-decorators.js.map +1 -0
- package/dist/tools/route-tools/route-mermaid.d.ts +4 -0
- package/dist/tools/route-tools/route-mermaid.d.ts.map +1 -0
- package/dist/tools/route-tools/route-mermaid.js +53 -0
- package/dist/tools/route-tools/route-mermaid.js.map +1 -0
- package/dist/tools/route-tools/spring-kotlin.d.ts +5 -0
- package/dist/tools/route-tools/spring-kotlin.d.ts.map +1 -0
- package/dist/tools/route-tools/spring-kotlin.js +52 -0
- package/dist/tools/route-tools/spring-kotlin.js.map +1 -0
- package/dist/tools/route-tools/trace-analysis.d.ts +4 -0
- package/dist/tools/route-tools/trace-analysis.d.ts.map +1 -0
- package/dist/tools/route-tools/trace-analysis.js +37 -0
- package/dist/tools/route-tools/trace-analysis.js.map +1 -0
- package/dist/tools/route-tools/trace-route.d.ts +6 -0
- package/dist/tools/route-tools/trace-route.d.ts.map +1 -0
- package/dist/tools/route-tools/trace-route.js +53 -0
- package/dist/tools/route-tools/trace-route.js.map +1 -0
- package/dist/tools/route-tools/types.d.ts +35 -0
- package/dist/tools/route-tools/types.d.ts.map +1 -0
- package/dist/tools/route-tools/types.js +2 -0
- package/dist/tools/route-tools/types.js.map +1 -0
- package/dist/tools/route-tools/yii2.d.ts +5 -0
- package/dist/tools/route-tools/yii2.d.ts.map +1 -0
- package/dist/tools/route-tools/yii2.js +73 -0
- package/dist/tools/route-tools/yii2.js.map +1 -0
- package/dist/tools/route-tools.d.ts +7 -49
- package/dist/tools/route-tools.d.ts.map +1 -1
- package/dist/tools/route-tools.js +5 -978
- package/dist/tools/route-tools.js.map +1 -1
- package/dist/tools/search-tools/types.d.ts +20 -0
- package/dist/tools/search-tools/types.d.ts.map +1 -1
- package/dist/tools/search-tools/zero-hit.d.ts.map +1 -1
- package/dist/tools/search-tools/zero-hit.js +0 -0
- package/dist/tools/search-tools/zero-hit.js.map +1 -1
- package/dist/tools/status-tools.d.ts +10 -0
- package/dist/tools/status-tools.d.ts.map +1 -1
- package/dist/tools/status-tools.js +14 -4
- package/dist/tools/status-tools.js.map +1 -1
- package/dist/tools/symbol-analysis-tools.d.ts +81 -0
- package/dist/tools/symbol-analysis-tools.d.ts.map +1 -0
- package/dist/tools/symbol-analysis-tools.js +327 -0
- package/dist/tools/symbol-analysis-tools.js.map +1 -0
- package/dist/tools/symbol-context-tools.d.ts +68 -0
- package/dist/tools/symbol-context-tools.d.ts.map +1 -0
- package/dist/tools/symbol-context-tools.js +232 -0
- package/dist/tools/symbol-context-tools.js.map +1 -0
- package/dist/tools/symbol-lookup-tools.d.ts +77 -0
- package/dist/tools/symbol-lookup-tools.d.ts.map +1 -0
- package/dist/tools/symbol-lookup-tools.js +305 -0
- package/dist/tools/symbol-lookup-tools.js.map +1 -0
- package/dist/tools/symbol-reference-tools.d.ts +38 -0
- package/dist/tools/symbol-reference-tools.d.ts.map +1 -0
- package/dist/tools/symbol-reference-tools.js +253 -0
- package/dist/tools/symbol-reference-tools.js.map +1 -0
- package/dist/tools/symbol-tool-internals.d.ts +9 -0
- package/dist/tools/symbol-tool-internals.d.ts.map +1 -0
- package/dist/tools/symbol-tool-internals.js +47 -0
- package/dist/tools/symbol-tool-internals.js.map +1 -0
- package/dist/tools/symbol-tools.d.ts +11 -176
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +7 -975
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/taint/python-context.d.ts +10 -0
- package/dist/tools/taint/python-context.d.ts.map +1 -0
- package/dist/tools/taint/python-context.js +150 -0
- package/dist/tools/taint/python-context.js.map +1 -0
- package/dist/tools/taint/taint-analyzer.d.ts +2 -0
- package/dist/tools/taint/taint-analyzer.d.ts.map +1 -0
- package/dist/tools/taint/taint-analyzer.js +2 -0
- package/dist/tools/taint/taint-analyzer.js.map +1 -0
- package/dist/tools/taint/taint-expression.d.ts +18 -0
- package/dist/tools/taint/taint-expression.d.ts.map +1 -0
- package/dist/tools/taint/taint-expression.js +265 -0
- package/dist/tools/taint/taint-expression.js.map +1 -0
- package/dist/tools/taint/taint-flow.d.ts +10 -0
- package/dist/tools/taint/taint-flow.d.ts.map +1 -0
- package/dist/tools/taint/taint-flow.js +178 -0
- package/dist/tools/taint/taint-flow.js.map +1 -0
- package/dist/tools/taint/taint-model.d.ts +113 -0
- package/dist/tools/taint/taint-model.d.ts.map +1 -0
- package/dist/tools/taint/taint-model.js +277 -0
- package/dist/tools/taint/taint-model.js.map +1 -0
- package/dist/tools/taint-tools.d.ts +2 -34
- package/dist/tools/taint-tools.d.ts.map +1 -1
- package/dist/tools/taint-tools.js +2 -852
- package/dist/tools/taint-tools.js.map +1 -1
- package/dist/tools/typescript-constants/file-context.d.ts +7 -0
- package/dist/tools/typescript-constants/file-context.d.ts.map +1 -0
- package/dist/tools/typescript-constants/file-context.js +219 -0
- package/dist/tools/typescript-constants/file-context.js.map +1 -0
- package/dist/tools/typescript-constants/symbol-resolver.d.ts +7 -0
- package/dist/tools/typescript-constants/symbol-resolver.d.ts.map +1 -0
- package/dist/tools/typescript-constants/symbol-resolver.js +165 -0
- package/dist/tools/typescript-constants/symbol-resolver.js.map +1 -0
- package/dist/tools/typescript-constants/types.d.ts +44 -0
- package/dist/tools/typescript-constants/types.d.ts.map +1 -0
- package/dist/tools/typescript-constants/types.js +2 -0
- package/dist/tools/typescript-constants/types.js.map +1 -0
- package/dist/tools/typescript-constants/value-evaluator.d.ts +8 -0
- package/dist/tools/typescript-constants/value-evaluator.d.ts.map +1 -0
- package/dist/tools/typescript-constants/value-evaluator.js +404 -0
- package/dist/tools/typescript-constants/value-evaluator.js.map +1 -0
- package/dist/tools/typescript-constants-tools.d.ts.map +1 -1
- package/dist/tools/typescript-constants-tools.js +19 -709
- package/dist/tools/typescript-constants-tools.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/git-head.d.ts +12 -0
- package/dist/utils/git-head.d.ts.map +1 -1
- package/dist/utils/git-head.js +25 -0
- package/dist/utils/git-head.js.map +1 -1
- package/dist/utils/import-graph/collect.d.ts +5 -0
- package/dist/utils/import-graph/collect.d.ts.map +1 -0
- package/dist/utils/import-graph/collect.js +47 -0
- package/dist/utils/import-graph/collect.js.map +1 -0
- package/dist/utils/import-graph/edge-accumulator.d.ts +7 -0
- package/dist/utils/import-graph/edge-accumulator.d.ts.map +1 -0
- package/dist/utils/import-graph/edge-accumulator.js +47 -0
- package/dist/utils/import-graph/edge-accumulator.js.map +1 -0
- package/dist/utils/import-graph/language-imports.d.ts +6 -0
- package/dist/utils/import-graph/language-imports.d.ts.map +1 -0
- package/dist/utils/import-graph/language-imports.js +84 -0
- package/dist/utils/import-graph/language-imports.js.map +1 -0
- package/dist/utils/import-graph/metrics.d.ts +6 -0
- package/dist/utils/import-graph/metrics.d.ts.map +1 -0
- package/dist/utils/import-graph/metrics.js +51 -0
- package/dist/utils/import-graph/metrics.js.map +1 -0
- package/dist/utils/import-graph/path-map.d.ts +7 -0
- package/dist/utils/import-graph/path-map.d.ts.map +1 -0
- package/dist/utils/import-graph/path-map.js +56 -0
- package/dist/utils/import-graph/path-map.js.map +1 -0
- package/dist/utils/import-graph/python-php-edge-collectors.d.ts +5 -0
- package/dist/utils/import-graph/python-php-edge-collectors.d.ts.map +1 -0
- package/dist/utils/import-graph/python-php-edge-collectors.js +56 -0
- package/dist/utils/import-graph/python-php-edge-collectors.js.map +1 -0
- package/dist/utils/import-graph/source-edge-collector.d.ts +13 -0
- package/dist/utils/import-graph/source-edge-collector.d.ts.map +1 -0
- package/dist/utils/import-graph/source-edge-collector.js +42 -0
- package/dist/utils/import-graph/source-edge-collector.js.map +1 -0
- package/dist/utils/import-graph/source-imports.d.ts +5 -0
- package/dist/utils/import-graph/source-imports.d.ts.map +1 -0
- package/dist/utils/import-graph/source-imports.js +33 -0
- package/dist/utils/import-graph/source-imports.js.map +1 -0
- package/dist/utils/import-graph/types.d.ts +15 -0
- package/dist/utils/import-graph/types.d.ts.map +1 -0
- package/dist/utils/import-graph/types.js +2 -0
- package/dist/utils/import-graph/types.js.map +1 -0
- package/dist/utils/import-graph/typescript-edge-collector.d.ts +7 -0
- package/dist/utils/import-graph/typescript-edge-collector.d.ts.map +1 -0
- package/dist/utils/import-graph/typescript-edge-collector.js +58 -0
- package/dist/utils/import-graph/typescript-edge-collector.js.map +1 -0
- package/dist/utils/import-graph/workspace-alias.d.ts +7 -0
- package/dist/utils/import-graph/workspace-alias.d.ts.map +1 -0
- package/dist/utils/import-graph/workspace-alias.js +95 -0
- package/dist/utils/import-graph/workspace-alias.js.map +1 -0
- package/dist/utils/import-graph/workspace-entry.d.ts +3 -0
- package/dist/utils/import-graph/workspace-entry.d.ts.map +1 -0
- package/dist/utils/import-graph/workspace-entry.js +81 -0
- package/dist/utils/import-graph/workspace-entry.js.map +1 -0
- package/dist/utils/import-graph.d.ts +10 -94
- package/dist/utils/import-graph.d.ts.map +1 -1
- package/dist/utils/import-graph.js +6 -702
- package/dist/utils/import-graph.js.map +1 -1
- package/package.json +6 -4
- package/rules/codesift.md +11 -2
- package/rules/codesift.mdc +11 -2
- package/rules/codex.md +11 -2
- package/rules/gemini.md +11 -2
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { detectFrameworks, isFrameworkEntryPoint, } from "../utils/framework-detect.js";
|
|
4
|
+
import { isTestFileStrict as isTestFile } from "../utils/test-file.js";
|
|
5
|
+
import { requireCodeIndex } from "./symbol-tool-internals.js";
|
|
6
|
+
const MAX_DEAD_CODE_RESULTS = 100;
|
|
7
|
+
// Kinds that are typically exported and should have external references
|
|
8
|
+
const EXPORTABLE_KINDS = new Set([
|
|
9
|
+
"function", "class", "interface", "type", "variable", "constant", "enum",
|
|
10
|
+
"component", "hook",
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* Collect top-level symbols of exportable kinds, filtered by test/pattern options.
|
|
14
|
+
*/
|
|
15
|
+
function collectExportedSymbols(symbols, options) {
|
|
16
|
+
return symbols.filter((s) => {
|
|
17
|
+
if (!EXPORTABLE_KINDS.has(s.kind))
|
|
18
|
+
return false;
|
|
19
|
+
if (s.parent)
|
|
20
|
+
return false;
|
|
21
|
+
if (!options.includeTests && isTestFile(s.file))
|
|
22
|
+
return false;
|
|
23
|
+
if (options.filePattern && !s.file.includes(options.filePattern))
|
|
24
|
+
return false;
|
|
25
|
+
if (s.name.length < 3)
|
|
26
|
+
return false;
|
|
27
|
+
if (s.kind === "variable" && s.name === "default")
|
|
28
|
+
return false;
|
|
29
|
+
return true;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// Bumped from 2000 → 5000 (F14: prior cap silently dropped references in
|
|
33
|
+
// medium-large repos, producing false-positive dead-code candidates whose
|
|
34
|
+
// real callers lived in unscanned files). Memory cost: roughly one file
|
|
35
|
+
// content string per entry — at 5K average-sized source files this is on
|
|
36
|
+
// the order of 50–200 MB peak, well within limits for analysis flows.
|
|
37
|
+
const MAX_SCAN_FILES = 5000;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a relative import path against a source file's directory. Handles
|
|
40
|
+
* the standard TS/Node extensions plus barrel-style `index` resolution.
|
|
41
|
+
* Returns the candidate file path that exists in `allFiles`, or null.
|
|
42
|
+
*
|
|
43
|
+
* Intentionally narrow: only resolves `./` and `../` paths. Aliased imports
|
|
44
|
+
* (tsconfig paths, package-json `imports`) are out of scope here — they show
|
|
45
|
+
* up textually in scanned content anyway, so they don't drive false positives.
|
|
46
|
+
*/
|
|
47
|
+
function resolveRelativeImport(fromFile, importPath, allFiles) {
|
|
48
|
+
if (!importPath.startsWith("."))
|
|
49
|
+
return null;
|
|
50
|
+
const lastSlash = fromFile.lastIndexOf("/");
|
|
51
|
+
const fromDir = lastSlash >= 0 ? fromFile.slice(0, lastSlash) : "";
|
|
52
|
+
const segments = (fromDir + "/" + importPath).split("/");
|
|
53
|
+
const stack = [];
|
|
54
|
+
for (const seg of segments) {
|
|
55
|
+
if (!seg || seg === ".")
|
|
56
|
+
continue;
|
|
57
|
+
if (seg === "..")
|
|
58
|
+
stack.pop();
|
|
59
|
+
else
|
|
60
|
+
stack.push(seg);
|
|
61
|
+
}
|
|
62
|
+
const base = stack.join("/");
|
|
63
|
+
if (allFiles.has(base))
|
|
64
|
+
return base;
|
|
65
|
+
// TS allows `import './x.js'` to resolve to `x.ts` — strip then re-extend.
|
|
66
|
+
const stripped = base.replace(/\.(m?js|jsx)$/, "");
|
|
67
|
+
const candidates = [
|
|
68
|
+
stripped + ".ts",
|
|
69
|
+
stripped + ".tsx",
|
|
70
|
+
stripped + ".mjs",
|
|
71
|
+
stripped + ".js",
|
|
72
|
+
stripped + ".jsx",
|
|
73
|
+
stripped + "/index.ts",
|
|
74
|
+
stripped + "/index.tsx",
|
|
75
|
+
stripped + "/index.js",
|
|
76
|
+
stripped + "/index.jsx",
|
|
77
|
+
];
|
|
78
|
+
for (const c of candidates) {
|
|
79
|
+
if (allFiles.has(c))
|
|
80
|
+
return c;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Pre-scan content for re-export edges. A symbol re-exported from another
|
|
86
|
+
* file isn't textually referenced in the barrel — without this pass barrel
|
|
87
|
+
* patterns like `export * from './foo'` cause every symbol in `./foo` to be
|
|
88
|
+
* misclassified as dead.
|
|
89
|
+
*
|
|
90
|
+
* Returns a set of file paths that are reached via at least one re-export
|
|
91
|
+
* (named or star). Callers treat any candidate whose defining file lands in
|
|
92
|
+
* this set as live.
|
|
93
|
+
*/
|
|
94
|
+
function collectReExportedFiles(fileContents, allFiles) {
|
|
95
|
+
const reExported = new Set();
|
|
96
|
+
// Matches: export * from "./x"; export { A, B } from "./x"; export type { T } from "./x";
|
|
97
|
+
// Anchor dropped (`^\s*` removed) so block-comment-prefixed exports
|
|
98
|
+
// (`/** doc */ export { Y } from "./x"`) and continuation-line exports
|
|
99
|
+
// (`...; export * from "./x"`) are detected too.
|
|
100
|
+
const RE = /\bexport\s+(?:\*|type\s+\*|\{[^}]*\}|type\s+\{[^}]*\})\s+from\s+['"]([^'"]+)['"]/gm;
|
|
101
|
+
for (const [filePath, content] of fileContents) {
|
|
102
|
+
RE.lastIndex = 0;
|
|
103
|
+
let m;
|
|
104
|
+
while ((m = RE.exec(content)) !== null) {
|
|
105
|
+
const target = resolveRelativeImport(filePath, m[1], allFiles);
|
|
106
|
+
if (target)
|
|
107
|
+
reExported.add(target);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return reExported;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Find potentially dead code: exported symbols with 0 references outside their own file.
|
|
114
|
+
* Scans all indexed files for word-boundary matches of each exported symbol name.
|
|
115
|
+
*
|
|
116
|
+
* F14 fixes (2026-05-05):
|
|
117
|
+
* - Test files are now ALWAYS scanned for references regardless of
|
|
118
|
+
* `include_tests`. The flag now gates only candidate selection (whether
|
|
119
|
+
* test-internal exports can themselves be flagged dead). Symbols used
|
|
120
|
+
* only in tests are no longer false-positive dead.
|
|
121
|
+
* - Re-exports via `export * from './x'` and `export { Y } from './x'`
|
|
122
|
+
* now mark `./x` as live; previously the lack of textual mention in the
|
|
123
|
+
* barrel made every barrel-forwarded symbol look dead.
|
|
124
|
+
* - MAX_SCAN_FILES raised 2000 → 5000; truncation now surfaces in the
|
|
125
|
+
* `truncated` field so callers can react.
|
|
126
|
+
*/
|
|
127
|
+
export async function findDeadCode(repo, options) {
|
|
128
|
+
const index = await requireCodeIndex(repo);
|
|
129
|
+
const includeTests = options?.include_tests ?? false;
|
|
130
|
+
const filePattern = options?.file_pattern;
|
|
131
|
+
const exportedSymbols = collectExportedSymbols(index.symbols, { includeTests, filePattern });
|
|
132
|
+
const frameworks = detectFrameworks(index);
|
|
133
|
+
// Read EVERY indexed file (incl. tests) for reference scanning. The previous
|
|
134
|
+
// version honored `includeTests` here, which meant a symbol referenced only
|
|
135
|
+
// from tests was misclassified as dead. Candidate selection still uses
|
|
136
|
+
// `includeTests` (above) so test-only helpers don't appear in the result list.
|
|
137
|
+
const fileContents = new Map();
|
|
138
|
+
let scanTruncated = false;
|
|
139
|
+
let filesSkippedByCap = 0;
|
|
140
|
+
let filesUnreadable = 0;
|
|
141
|
+
for (const file of index.files) {
|
|
142
|
+
if (fileContents.size >= MAX_SCAN_FILES) {
|
|
143
|
+
scanTruncated = true;
|
|
144
|
+
filesSkippedByCap = index.files.length - fileContents.size - filesUnreadable;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
fileContents.set(file.path, await readFile(join(index.root, file.path), "utf-8"));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Deleted, unreadable, or raced with a write. Counted rather than merely skipped: a
|
|
152
|
+
// reference living only in a file we could not read is invisible to the scan below, and
|
|
153
|
+
// the symbol it points at then looks dead.
|
|
154
|
+
filesUnreadable++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Build set of files that are forwarded via re-exports (barrel chains).
|
|
158
|
+
// Symbols defined in such files are reachable even without textual mention.
|
|
159
|
+
const allFilePaths = new Set(fileContents.keys());
|
|
160
|
+
const reExportedFiles = collectReExportedFiles(fileContents, allFilePaths);
|
|
161
|
+
// Reference index, built in ONE pass over file contents. Previously this scan
|
|
162
|
+
// was O(exportedSymbols x files): a `\b<name>\b` regex over every file's full
|
|
163
|
+
// text for every exported symbol. On a healthy repo (few dead symbols) the
|
|
164
|
+
// early-exit never fires, so the full product ran — telemetry (2026-07-20)
|
|
165
|
+
// measured a 1,066,401 ms (~17.8 min) p95 for find_dead_code.
|
|
166
|
+
//
|
|
167
|
+
// Tokenising on [^A-Za-z0-9_]+ mirrors the \b\w boundary semantics of the old
|
|
168
|
+
// regex. Per token we only need "is it mentioned outside its defining file",
|
|
169
|
+
// so we keep the first file that mentioned it plus a multi-file flag — O(1)
|
|
170
|
+
// memory per unique token instead of a file set, and O(1) lookup per symbol.
|
|
171
|
+
const tokenIndex = new Map();
|
|
172
|
+
for (const [filePath, content] of fileContents) {
|
|
173
|
+
for (const token of new Set(content.split(/[^A-Za-z0-9_]+/))) {
|
|
174
|
+
if (!token)
|
|
175
|
+
continue;
|
|
176
|
+
const entry = tokenIndex.get(token);
|
|
177
|
+
if (!entry)
|
|
178
|
+
tokenIndex.set(token, { first: filePath, multi: false });
|
|
179
|
+
else if (!entry.multi && entry.first !== filePath)
|
|
180
|
+
entry.multi = true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const candidates = [];
|
|
184
|
+
for (const sym of exportedSymbols) {
|
|
185
|
+
if (candidates.length >= MAX_DEAD_CODE_RESULTS)
|
|
186
|
+
break;
|
|
187
|
+
if (isFrameworkEntryPoint(sym, frameworks))
|
|
188
|
+
continue;
|
|
189
|
+
// Re-export reachability — barrel forwards skip the textual-mention check.
|
|
190
|
+
if (reExportedFiles.has(sym.file))
|
|
191
|
+
continue;
|
|
192
|
+
// Mentioned in any file other than the one defining it => not dead.
|
|
193
|
+
const seen = tokenIndex.get(sym.name);
|
|
194
|
+
const hasExternalRef = !!seen && (seen.multi || seen.first !== sym.file);
|
|
195
|
+
if (!hasExternalRef) {
|
|
196
|
+
candidates.push({
|
|
197
|
+
name: sym.name,
|
|
198
|
+
kind: sym.kind,
|
|
199
|
+
file: sym.file,
|
|
200
|
+
start_line: sym.start_line,
|
|
201
|
+
end_line: sym.end_line,
|
|
202
|
+
reason: "exported but no references found outside defining file",
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const scanComplete = !scanTruncated && filesUnreadable === 0;
|
|
207
|
+
const coverage = {
|
|
208
|
+
status: scanComplete ? "complete" : "partial",
|
|
209
|
+
files_indexed: index.files.length,
|
|
210
|
+
files_read: fileContents.size,
|
|
211
|
+
...(filesSkippedByCap > 0 ? { files_skipped_by_cap: filesSkippedByCap } : {}),
|
|
212
|
+
...(filesUnreadable > 0 ? { files_unreadable: filesUnreadable } : {}),
|
|
213
|
+
...(scanComplete
|
|
214
|
+
? {}
|
|
215
|
+
: {
|
|
216
|
+
detail: `reference scan read ${fileContents.size} of ${index.files.length} indexed files` +
|
|
217
|
+
(filesSkippedByCap > 0 ? ` (${filesSkippedByCap} beyond the ${MAX_SCAN_FILES}-file cap)` : "") +
|
|
218
|
+
(filesUnreadable > 0 ? ` (${filesUnreadable} unreadable)` : "") +
|
|
219
|
+
" — a symbol referenced only from an unread file is indistinguishable from a dead one," +
|
|
220
|
+
" so do NOT delete on this result alone; narrow with file_pattern to get a complete scan",
|
|
221
|
+
}),
|
|
222
|
+
};
|
|
223
|
+
return {
|
|
224
|
+
candidates,
|
|
225
|
+
scanned_symbols: exportedSymbols.length,
|
|
226
|
+
scanned_files: fileContents.size,
|
|
227
|
+
// Deliberately ONLY about list length now. Scan completeness lives in `coverage`, because
|
|
228
|
+
// the two have opposite implications: a cut-off list means "there are more", a short scan
|
|
229
|
+
// means "these may be wrong".
|
|
230
|
+
...(candidates.length >= MAX_DEAD_CODE_RESULTS ? { truncated: true } : {}),
|
|
231
|
+
coverage,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Unused import detection
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
const MAX_UNUSED_IMPORTS = 200;
|
|
238
|
+
/**
|
|
239
|
+
* Find imports whose imported names are never referenced in the file body.
|
|
240
|
+
* Supports ES module named imports: import { A, B } from '...'
|
|
241
|
+
*/
|
|
242
|
+
export async function findUnusedImports(repo, options) {
|
|
243
|
+
const index = await requireCodeIndex(repo);
|
|
244
|
+
const includeTests = options?.include_tests ?? false;
|
|
245
|
+
const unused = [];
|
|
246
|
+
let scannedFiles = 0;
|
|
247
|
+
for (const file of index.files) {
|
|
248
|
+
if (unused.length >= MAX_UNUSED_IMPORTS)
|
|
249
|
+
break;
|
|
250
|
+
if (!includeTests && isTestFile(file.path))
|
|
251
|
+
continue;
|
|
252
|
+
if (options?.file_pattern && !file.path.includes(options.file_pattern))
|
|
253
|
+
continue;
|
|
254
|
+
// Only analyze JS/TS/Kotlin files
|
|
255
|
+
if (!/\.(ts|tsx|js|jsx|mjs|kt|kts)$/.test(file.path))
|
|
256
|
+
continue;
|
|
257
|
+
let source;
|
|
258
|
+
try {
|
|
259
|
+
source = await readFile(join(index.root, file.path), "utf-8");
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
scannedFiles++;
|
|
265
|
+
const lines = source.split("\n");
|
|
266
|
+
// Find named import lines: import { A, B, C } from '...'
|
|
267
|
+
// Also: import A from '...' and import * as A from '...'
|
|
268
|
+
const importRegex = /^import\s+(?:type\s+)?(?:\{([^}]+)\}|(\*\s+as\s+\w+)|(\w+)).*from\s+['"][^'"]+['"]/;
|
|
269
|
+
for (let i = 0; i < lines.length; i++) {
|
|
270
|
+
const line = lines[i].trim();
|
|
271
|
+
if (!line.startsWith("import "))
|
|
272
|
+
continue;
|
|
273
|
+
// Stop scanning imports when we hit non-import code
|
|
274
|
+
if (i > 0 && !line.startsWith("import") && !line.startsWith("//") && !line.startsWith("/*") && line.length > 0 && !lines[i].trim().startsWith("*") && !lines[i].trim().startsWith("}")) {
|
|
275
|
+
// Could be multi-line import continuation, keep going
|
|
276
|
+
}
|
|
277
|
+
const match = importRegex.exec(line);
|
|
278
|
+
if (!match)
|
|
279
|
+
continue;
|
|
280
|
+
const names = [];
|
|
281
|
+
if (match[1]) {
|
|
282
|
+
// Named imports: { A, B as C, type D }
|
|
283
|
+
for (const part of match[1].split(",")) {
|
|
284
|
+
const trimmed = part.trim().replace(/^type\s+/, "");
|
|
285
|
+
if (!trimmed)
|
|
286
|
+
continue;
|
|
287
|
+
// Handle "A as B" — the local name is B
|
|
288
|
+
const asMatch = /(\w+)\s+as\s+(\w+)/.exec(trimmed);
|
|
289
|
+
names.push(asMatch ? asMatch[2] : trimmed);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else if (match[2]) {
|
|
293
|
+
// Namespace import: * as A
|
|
294
|
+
const nsMatch = /\*\s+as\s+(\w+)/.exec(match[2]);
|
|
295
|
+
if (nsMatch)
|
|
296
|
+
names.push(nsMatch[1]);
|
|
297
|
+
}
|
|
298
|
+
else if (match[3]) {
|
|
299
|
+
// Default import: import A
|
|
300
|
+
names.push(match[3]);
|
|
301
|
+
}
|
|
302
|
+
// Check each imported name against rest of file
|
|
303
|
+
const bodyAfterImports = lines.slice(i + 1).join("\n");
|
|
304
|
+
for (const name of names) {
|
|
305
|
+
if (name.length < 2)
|
|
306
|
+
continue;
|
|
307
|
+
const nameRegex = new RegExp(`\\b${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`);
|
|
308
|
+
if (!nameRegex.test(bodyAfterImports)) {
|
|
309
|
+
unused.push({
|
|
310
|
+
file: file.path,
|
|
311
|
+
line: i + 1,
|
|
312
|
+
import_text: line,
|
|
313
|
+
imported_name: name,
|
|
314
|
+
});
|
|
315
|
+
if (unused.length >= MAX_UNUSED_IMPORTS)
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
unused,
|
|
323
|
+
scanned_files: scannedFiles,
|
|
324
|
+
...(unused.length >= MAX_UNUSED_IMPORTS ? { truncated: true } : {}),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=symbol-analysis-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-analysis-tools.js","sourceRoot":"","sources":["../../src/tools/symbol-analysis-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { CodeSymbol, Reference, SymbolKind } from "../types.js";
|
|
2
|
+
import { type SymbolIdAmbiguity } from "./symbol-lookup-tools.js";
|
|
3
|
+
/** Format references as compact string for MCP output. Groups by file to avoid repeating paths. */
|
|
4
|
+
export declare function formatRefsCompact(refs: Reference[]): string;
|
|
5
|
+
/** Format a CodeSymbol as compact text: header line + source. ~70% less tokens than JSON. */
|
|
6
|
+
export declare function formatSymbolCompact(sym: CodeSymbol): string;
|
|
7
|
+
/** Format multiple CodeSymbols as compact text, separated by blank lines. */
|
|
8
|
+
export declare function formatSymbolsCompact(syms: CodeSymbol[]): string;
|
|
9
|
+
/** Format ContextBundle as compact text. */
|
|
10
|
+
export declare function formatBundleCompact(bundle: {
|
|
11
|
+
symbol: CodeSymbol;
|
|
12
|
+
imports: string[];
|
|
13
|
+
siblings: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
kind: string;
|
|
16
|
+
start_line: number;
|
|
17
|
+
end_line: number;
|
|
18
|
+
}>;
|
|
19
|
+
types_used: string[];
|
|
20
|
+
}): string;
|
|
21
|
+
/**
|
|
22
|
+
* Search for a symbol by query and return it with full source.
|
|
23
|
+
* Optionally includes references across the codebase.
|
|
24
|
+
*/
|
|
25
|
+
export declare function findAndShow(repo: string, query: string, includeRefs?: boolean): Promise<{
|
|
26
|
+
symbol: CodeSymbol;
|
|
27
|
+
references?: Reference[];
|
|
28
|
+
id_ambiguity: SymbolIdAmbiguity;
|
|
29
|
+
} | null>;
|
|
30
|
+
export interface ReactContext {
|
|
31
|
+
/** Props type name extracted from the component's parameter type annotation */
|
|
32
|
+
props_type: string | null;
|
|
33
|
+
/** Source of the props interface/type declaration when found in the index (Tier 4 — Item 16) */
|
|
34
|
+
props_interface_source: string | null;
|
|
35
|
+
/** React hooks called inside this component (use*() patterns) */
|
|
36
|
+
hooks_used: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
is_stdlib: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
/** Child components rendered via JSX (<PascalCase>) */
|
|
41
|
+
child_components: string[];
|
|
42
|
+
/** Parent components that render this one via JSX */
|
|
43
|
+
parent_components: string[];
|
|
44
|
+
/** Detected wrapper pattern (memo, forwardRef, lazy) or null */
|
|
45
|
+
wrapper: "memo" | "forwardRef" | "lazy" | null;
|
|
46
|
+
}
|
|
47
|
+
export interface ContextBundle {
|
|
48
|
+
symbol: CodeSymbol;
|
|
49
|
+
imports: string[];
|
|
50
|
+
siblings: Array<{
|
|
51
|
+
name: string;
|
|
52
|
+
kind: SymbolKind;
|
|
53
|
+
start_line: number;
|
|
54
|
+
end_line: number;
|
|
55
|
+
}>;
|
|
56
|
+
types_used: string[];
|
|
57
|
+
/** Only populated when symbol.kind === "component" */
|
|
58
|
+
react_context?: ReactContext;
|
|
59
|
+
/** Always present. Says whether `symbol` is a unique resolution or the search's top hit among
|
|
60
|
+
* several sharing one id — a distinction the caller cannot otherwise make from the result. */
|
|
61
|
+
id_ambiguity: SymbolIdAmbiguity;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get a symbol with its file's imports and sibling symbols in one call.
|
|
65
|
+
* Saves 2-3 round-trips vs get_symbol + search_text(imports) + get_file_outline.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getContextBundle(repo: string, symbolName: string): Promise<ContextBundle | null>;
|
|
68
|
+
//# sourceMappingURL=symbol-context-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-context-tools.d.ts","sourceRoot":"","sources":["../../src/tools/symbol-context-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAOlC,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,CAkB3D;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAM3D;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,CAE/D;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,CAc1M;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CACR;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAAC,YAAY,EAAE,iBAAiB,CAAA;CAAE,GAAG,IAAI,CACzF,CAkBA;AAaD,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gGAAgG;IAChG,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iEAAiE;IACjE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxD,uDAAuD;IACvD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,qDAAqD;IACrD,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1F,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,sDAAsD;IACtD,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B;mGAC+F;IAC/F,YAAY,EAAE,iBAAiB,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAwD/B"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { loadConfig } from "../config.js";
|
|
4
|
+
import { searchBM25 } from "../search/bm25.js";
|
|
5
|
+
import { extractHookNames, REACT_STDLIB_HOOKS } from "./react-tools.js";
|
|
6
|
+
import { resolveSearchHit, } from "./symbol-lookup-tools.js";
|
|
7
|
+
import { findReferences } from "./symbol-reference-tools.js";
|
|
8
|
+
import { requireBM25Index, requireCodeIndex, } from "./symbol-tool-internals.js";
|
|
9
|
+
/** Format references as compact string for MCP output. Groups by file to avoid repeating paths. */
|
|
10
|
+
export function formatRefsCompact(refs) {
|
|
11
|
+
if (refs.length === 0)
|
|
12
|
+
return "";
|
|
13
|
+
// Group by file
|
|
14
|
+
const groups = new Map();
|
|
15
|
+
for (const r of refs) {
|
|
16
|
+
let g = groups.get(r.file);
|
|
17
|
+
if (!g) {
|
|
18
|
+
g = [];
|
|
19
|
+
groups.set(r.file, g);
|
|
20
|
+
}
|
|
21
|
+
g.push(` ${r.line}: ${r.context}`);
|
|
22
|
+
}
|
|
23
|
+
if (groups.size === refs.length) {
|
|
24
|
+
// Each file has 1 ref — flat is fine
|
|
25
|
+
return refs.map((r) => `${r.file}:${r.line}: ${r.context}`).join("\n");
|
|
26
|
+
}
|
|
27
|
+
const parts = [];
|
|
28
|
+
for (const [file, lines] of groups) {
|
|
29
|
+
parts.push(`${file}\n${lines.join("\n")}`);
|
|
30
|
+
}
|
|
31
|
+
return parts.join("\n");
|
|
32
|
+
}
|
|
33
|
+
/** Format a CodeSymbol as compact text: header line + source. ~70% less tokens than JSON. */
|
|
34
|
+
export function formatSymbolCompact(sym) {
|
|
35
|
+
const loc = `${sym.file}:${sym.start_line}-${sym.end_line}`;
|
|
36
|
+
const sig = sym.signature ? ` ${sym.signature}` : "";
|
|
37
|
+
const header = `${loc} ${sym.kind} ${sym.name}${sig}`;
|
|
38
|
+
if (!sym.source)
|
|
39
|
+
return header;
|
|
40
|
+
return `${header}\n${sym.source}`;
|
|
41
|
+
}
|
|
42
|
+
/** Format multiple CodeSymbols as compact text, separated by blank lines. */
|
|
43
|
+
export function formatSymbolsCompact(syms) {
|
|
44
|
+
return syms.map(formatSymbolCompact).join("\n\n");
|
|
45
|
+
}
|
|
46
|
+
/** Format ContextBundle as compact text. */
|
|
47
|
+
export function formatBundleCompact(bundle) {
|
|
48
|
+
const parts = [];
|
|
49
|
+
parts.push(formatSymbolCompact(bundle.symbol));
|
|
50
|
+
if (bundle.imports.length > 0) {
|
|
51
|
+
parts.push(`\n--- imports ---\n${bundle.imports.join("\n")}`);
|
|
52
|
+
}
|
|
53
|
+
if (bundle.siblings.length > 0) {
|
|
54
|
+
const sibLines = bundle.siblings.map((s) => ` ${s.kind} ${s.name} :${s.start_line}-${s.end_line}`);
|
|
55
|
+
parts.push(`\n--- siblings ---\n${sibLines.join("\n")}`);
|
|
56
|
+
}
|
|
57
|
+
if (bundle.types_used.length > 0) {
|
|
58
|
+
parts.push(`\n--- types used ---\n${bundle.types_used.join(", ")}`);
|
|
59
|
+
}
|
|
60
|
+
return parts.join("");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Search for a symbol by query and return it with full source.
|
|
64
|
+
* Optionally includes references across the codebase.
|
|
65
|
+
*/
|
|
66
|
+
export async function findAndShow(repo, query, includeRefs) {
|
|
67
|
+
const bm25Index = await requireBM25Index(repo);
|
|
68
|
+
const config = loadConfig();
|
|
69
|
+
const results = searchBM25(bm25Index, query, 1, config.bm25FieldWeights);
|
|
70
|
+
const topResult = results[0];
|
|
71
|
+
if (!topResult)
|
|
72
|
+
return null;
|
|
73
|
+
const resolved = await resolveSearchHit(repo, topResult.symbol);
|
|
74
|
+
if (!resolved)
|
|
75
|
+
return null;
|
|
76
|
+
const { symbol: fullSymbol, ambiguity } = resolved;
|
|
77
|
+
if (includeRefs) {
|
|
78
|
+
const references = await findReferences(repo, fullSymbol.name);
|
|
79
|
+
return { symbol: fullSymbol, references, id_ambiguity: ambiguity };
|
|
80
|
+
}
|
|
81
|
+
return { symbol: fullSymbol, id_ambiguity: ambiguity };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Extract full import lines from file source.
|
|
85
|
+
*/
|
|
86
|
+
function extractImportLines(source) {
|
|
87
|
+
const lines = source.split("\n");
|
|
88
|
+
return lines.filter((line) => {
|
|
89
|
+
const trimmed = line.trim();
|
|
90
|
+
return trimmed.startsWith("import ") || (trimmed.startsWith("const ") && trimmed.includes("require("));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get a symbol with its file's imports and sibling symbols in one call.
|
|
95
|
+
* Saves 2-3 round-trips vs get_symbol + search_text(imports) + get_file_outline.
|
|
96
|
+
*/
|
|
97
|
+
export async function getContextBundle(repo, symbolName) {
|
|
98
|
+
const bm25Index = await requireBM25Index(repo);
|
|
99
|
+
const config = loadConfig();
|
|
100
|
+
const results = searchBM25(bm25Index, symbolName, 1, config.bm25FieldWeights);
|
|
101
|
+
const topResult = results[0];
|
|
102
|
+
if (!topResult)
|
|
103
|
+
return null;
|
|
104
|
+
const index = await requireCodeIndex(repo);
|
|
105
|
+
// Get full symbol with source
|
|
106
|
+
const resolved = await resolveSearchHit(repo, topResult.symbol);
|
|
107
|
+
if (!resolved)
|
|
108
|
+
return null;
|
|
109
|
+
const { symbol: fullSymbol, ambiguity } = resolved;
|
|
110
|
+
// Read the file to extract imports
|
|
111
|
+
let fileSource;
|
|
112
|
+
try {
|
|
113
|
+
fileSource = await readFile(join(index.root, fullSymbol.file), "utf-8");
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return {
|
|
117
|
+
symbol: fullSymbol,
|
|
118
|
+
imports: [],
|
|
119
|
+
siblings: [],
|
|
120
|
+
types_used: [],
|
|
121
|
+
id_ambiguity: ambiguity,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const imports = extractImportLines(fileSource);
|
|
125
|
+
// Get sibling symbols (other symbols in the same file)
|
|
126
|
+
const siblings = index.symbols
|
|
127
|
+
.filter((s) => s.file === fullSymbol.file && s.id !== fullSymbol.id)
|
|
128
|
+
.map((s) => ({
|
|
129
|
+
name: s.name,
|
|
130
|
+
kind: s.kind,
|
|
131
|
+
start_line: s.start_line,
|
|
132
|
+
end_line: s.end_line,
|
|
133
|
+
}));
|
|
134
|
+
// Extract type names used in the symbol's source
|
|
135
|
+
const typesUsed = extractTypesUsed(fullSymbol.source ?? "", index.symbols);
|
|
136
|
+
// React-specific enrichment for components
|
|
137
|
+
const bundle = {
|
|
138
|
+
symbol: fullSymbol,
|
|
139
|
+
imports,
|
|
140
|
+
siblings,
|
|
141
|
+
types_used: typesUsed,
|
|
142
|
+
id_ambiguity: ambiguity,
|
|
143
|
+
};
|
|
144
|
+
if (fullSymbol.kind === "component") {
|
|
145
|
+
bundle.react_context = buildReactContext(fullSymbol, index.symbols);
|
|
146
|
+
}
|
|
147
|
+
return bundle;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build React-specific context for a component symbol:
|
|
151
|
+
* hooks used, child/parent components via JSX, wrapper pattern.
|
|
152
|
+
*
|
|
153
|
+
* Uses REACT_STDLIB_HOOKS imported from react-tools.js as the single source
|
|
154
|
+
* of truth for stdlib hook detection (CQ14 — no duplication).
|
|
155
|
+
*/
|
|
156
|
+
function buildReactContext(component, allSymbols) {
|
|
157
|
+
const source = component.source ?? "";
|
|
158
|
+
// Extract hooks used (uses shared extractHookNames from react-tools.ts — CQ14)
|
|
159
|
+
const hooks_used = [...extractHookNames(source)].map((name) => ({
|
|
160
|
+
name,
|
|
161
|
+
is_stdlib: REACT_STDLIB_HOOKS.has(name),
|
|
162
|
+
}));
|
|
163
|
+
// Extract child components from JSX (<PascalCase>)
|
|
164
|
+
const childSet = new Set();
|
|
165
|
+
const jsxPattern = /<([A-Z][a-zA-Z0-9_$]*)\b/g;
|
|
166
|
+
let m;
|
|
167
|
+
while ((m = jsxPattern.exec(source)) !== null) {
|
|
168
|
+
const name = m[1];
|
|
169
|
+
if (name !== component.name)
|
|
170
|
+
childSet.add(name);
|
|
171
|
+
}
|
|
172
|
+
const child_components = [...childSet].sort();
|
|
173
|
+
// Extract parent components: find other components whose source uses <ThisComponent>
|
|
174
|
+
const escapedComponentName = component.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
175
|
+
const ownPattern = new RegExp(`<${escapedComponentName}\\b`);
|
|
176
|
+
const parent_components = allSymbols
|
|
177
|
+
.filter((s) => s.kind === "component" &&
|
|
178
|
+
s.id !== component.id &&
|
|
179
|
+
s.name !== component.name &&
|
|
180
|
+
s.source &&
|
|
181
|
+
ownPattern.test(s.source))
|
|
182
|
+
.map((s) => s.name);
|
|
183
|
+
// Detect wrapper pattern from source — supports TypeScript generics:
|
|
184
|
+
// forwardRef<HTMLDivElement, Props>(...), memo<Props>(...) (Item 9)
|
|
185
|
+
let wrapper = null;
|
|
186
|
+
if (/\b(?:React\.)?memo\s*(?:<[^>]+>)?\s*\(/.test(source))
|
|
187
|
+
wrapper = "memo";
|
|
188
|
+
else if (/\b(?:React\.)?forwardRef\s*(?:<[^>]+>)?\s*\(/.test(source))
|
|
189
|
+
wrapper = "forwardRef";
|
|
190
|
+
else if (/\b(?:React\.)?lazy\s*(?:<[^>]+>)?\s*\(/.test(source))
|
|
191
|
+
wrapper = "lazy";
|
|
192
|
+
// Extract props type from signature: (props: MyProps) or ({ a, b }: Props)
|
|
193
|
+
let props_type = null;
|
|
194
|
+
const sig = component.signature ?? "";
|
|
195
|
+
// Pattern: (props: TypeName) or (arg: TypeName) or ({ ... }: TypeName)
|
|
196
|
+
const propsMatch = sig.match(/\(\s*(?:\{[^}]*\}|\w+)\s*:\s*([A-Z]\w*)/);
|
|
197
|
+
if (propsMatch) {
|
|
198
|
+
props_type = propsMatch[1];
|
|
199
|
+
}
|
|
200
|
+
// Resolve props interface body when type name found in the index (Tier 4 — Item 16).
|
|
201
|
+
// Look for an interface or type alias with the same name as props_type.
|
|
202
|
+
let props_interface_source = null;
|
|
203
|
+
if (props_type) {
|
|
204
|
+
const declarations = allSymbols.filter((s) => (s.kind === "interface" || s.kind === "type") && s.name === props_type);
|
|
205
|
+
const decl = declarations.find((s) => s.file === component.file) ?? declarations[0];
|
|
206
|
+
if (decl?.source) {
|
|
207
|
+
// Cap to 800 chars to keep bundle compact
|
|
208
|
+
props_interface_source = decl.source.length > 800
|
|
209
|
+
? decl.source.slice(0, 800) + "..."
|
|
210
|
+
: decl.source;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return { props_type, props_interface_source, hooks_used, child_components, parent_components, wrapper };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Extract type/interface names referenced in source by matching against known symbols.
|
|
217
|
+
*/
|
|
218
|
+
function extractTypesUsed(source, allSymbols) {
|
|
219
|
+
const typeNames = new Set(allSymbols
|
|
220
|
+
.filter((s) => (s.kind === "interface" || s.kind === "type" || s.kind === "enum") && s.name.length >= 3)
|
|
221
|
+
.map((s) => s.name));
|
|
222
|
+
if (typeNames.size === 0)
|
|
223
|
+
return [];
|
|
224
|
+
const used = new Set();
|
|
225
|
+
for (const match of source.matchAll(/[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/gu)) {
|
|
226
|
+
const name = match[0];
|
|
227
|
+
if (typeNames.has(name))
|
|
228
|
+
used.add(name);
|
|
229
|
+
}
|
|
230
|
+
return [...used].sort();
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=symbol-context-tools.js.map
|