From 103dbe669bdb5014a2dc003c9592bacf2a583164 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Tue, 21 Apr 2026 14:32:11 +0100 Subject: [PATCH] refactor(scope-resolution): drop dead exports surfaced by knip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Knip flagged 44+ dead exports in the PR surface. Cleanup: Barrel deletion: - Remove src/core/ingestion/scope-resolution/index.ts entirely. It re-exported 30+ symbols but only one file (languages/python/scope-resolver.ts) imported from it, and only 7 symbols. Matches the project's "no barrel re-exports" preference and removes a drift surface. scope-resolver.ts now imports from concrete files (passes/mro.ts, scope/walkers.ts, contract/...). Dead functions/interfaces removed: - resolvePythonScope + ResolvePythonScopeInput + ResolvePythonScopeStats in languages/python/scope-resolver.ts — never called. pipelinePhase reaches pythonScopeResolver via SCOPE_RESOLVERS, not via a per-language entry point. - getScopeResolver in scope-resolution/pipeline/registry.ts — had zero callers. Consumers read SCOPE_RESOLVERS directly. Exports demoted to module-internal (used only within their own file): - PYTHON_SCOPE_QUERY (query.ts) + its re-export from python/index.ts - PROF (cache-stats.ts) - PythonArityMetadata (arity-metadata.ts) - ReferenceSiteSkipSet (graph-bridge/references-to-edges.ts) - ReceiverBoundProviderSubset (passes/receiver-bound-calls.ts) - ResolveCompoundReceiverOptions interface (passes/compound-receiver.ts) - matchingOpenParen function (passes/compound-receiver.ts) - followChainPostFinalize function (passes/imported-return-types.ts) - RunScopeResolutionInput + RunScopeResolutionStats (pipeline/run.ts) Also removed: - Redundant `export type { Scope }` re-export from contract/scope-resolver.ts (consumers import Scope directly from gitnexus-shared). Verification: knip reports zero dead exports in PR-touched files. 204/204 test/integration/resolvers/python.test.ts both flag paths. 335/335 scope-resolution + graph unit tests. tsc clean. --- .../languages/python/arity-metadata.ts | 2 +- .../ingestion/languages/python/cache-stats.ts | 2 +- .../core/ingestion/languages/python/index.ts | 1 - .../core/ingestion/languages/python/query.ts | 2 +- .../languages/python/scope-resolver.ts | 27 ++----- .../contract/scope-resolver.ts | 5 -- .../graph-bridge/references-to-edges.ts | 2 +- .../core/ingestion/scope-resolution/index.ts | 76 ------------------- .../passes/compound-receiver.ts | 4 +- .../passes/imported-return-types.ts | 2 +- .../passes/receiver-bound-calls.ts | 2 +- .../scope-resolution/pipeline/registry.ts | 4 - .../scope-resolution/pipeline/run.ts | 4 +- 13 files changed, 17 insertions(+), 116 deletions(-) delete mode 100644 gitnexus/src/core/ingestion/scope-resolution/index.ts diff --git a/gitnexus/src/core/ingestion/languages/python/arity-metadata.ts b/gitnexus/src/core/ingestion/languages/python/arity-metadata.ts index a997cb609..87e53f4f4 100644 --- a/gitnexus/src/core/ingestion/languages/python/arity-metadata.ts +++ b/gitnexus/src/core/ingestion/languages/python/arity-metadata.ts @@ -18,7 +18,7 @@ import type { SyntaxNode } from '../../utils/ast-helpers.js'; import { pythonMethodConfig } from '../../method-extractors/configs/python.js'; -export interface PythonArityMetadata { +interface PythonArityMetadata { readonly parameterCount: number | undefined; readonly requiredParameterCount: number | undefined; readonly parameterTypes: readonly string[] | undefined; diff --git a/gitnexus/src/core/ingestion/languages/python/cache-stats.ts b/gitnexus/src/core/ingestion/languages/python/cache-stats.ts index e423a7dba..baa1e096d 100644 --- a/gitnexus/src/core/ingestion/languages/python/cache-stats.ts +++ b/gitnexus/src/core/ingestion/languages/python/cache-stats.ts @@ -9,7 +9,7 @@ * doesn't carry a module-global counter and its reset/export surface. */ -export const PROF = process.env.PROF_SCOPE_RESOLUTION === '1'; +const PROF = process.env.PROF_SCOPE_RESOLUTION === '1'; let CACHE_HITS = 0; let CACHE_MISSES = 0; diff --git a/gitnexus/src/core/ingestion/languages/python/index.ts b/gitnexus/src/core/ingestion/languages/python/index.ts index c3e502ec0..fcb723c5c 100644 --- a/gitnexus/src/core/ingestion/languages/python/index.ts +++ b/gitnexus/src/core/ingestion/languages/python/index.ts @@ -72,7 +72,6 @@ * `test/integration/resolvers/python.test.ts`. */ -export { PYTHON_SCOPE_QUERY } from './query.js'; export { emitPythonScopeCaptures } from './captures.js'; export { getPythonCaptureCacheStats, resetPythonCaptureCacheStats } from './cache-stats.js'; export { interpretPythonImport, interpretPythonTypeBinding } from './interpret.js'; diff --git a/gitnexus/src/core/ingestion/languages/python/query.ts b/gitnexus/src/core/ingestion/languages/python/query.ts index cc45c305b..03b27f730 100644 --- a/gitnexus/src/core/ingestion/languages/python/query.ts +++ b/gitnexus/src/core/ingestion/languages/python/query.ts @@ -13,7 +13,7 @@ import Parser from 'tree-sitter'; import Python from 'tree-sitter-python'; -export const PYTHON_SCOPE_QUERY = ` +const PYTHON_SCOPE_QUERY = ` ;; Scopes (module) @scope.module (class_definition) @scope.class diff --git a/gitnexus/src/core/ingestion/languages/python/scope-resolver.ts b/gitnexus/src/core/ingestion/languages/python/scope-resolver.ts index 485845f5a..a29abfe09 100644 --- a/gitnexus/src/core/ingestion/languages/python/scope-resolver.ts +++ b/gitnexus/src/core/ingestion/languages/python/scope-resolver.ts @@ -1,28 +1,22 @@ /** - * Python `ScopeResolver` and the `resolvePythonScope` entry point. + * Python `ScopeResolver` registered in `SCOPE_RESOLVERS` and consumed + * by the generic `runScopeResolution` orchestrator. * * The provider is a thin wiring object — Python's specific bits * (super recognizer, LEGB merge precedence, Python's relative-import - * resolver, the simplified MRO walk) plug into the generic - * `runScopeResolution` orchestrator from `scope-resolution/`. + * resolver, the simplified MRO walk) plug into `runScopeResolution`. * * Migration reference: when bringing up the next language * (TypeScript / Java / Kotlin / Ruby), copy this file's structure — * implement the 6 required `ScopeResolver` fields, optionally toggle - * the 2 booleans, and call `runScopeResolution(input, provider)`. + * the 2 booleans, and register in `scope-resolution/pipeline/registry.ts`. */ import type { ParsedFile, Scope, WorkspaceIndex } from 'gitnexus-shared'; import { SupportedLanguages } from 'gitnexus-shared'; -import { - buildMro, - defaultLinearize, - populateClassOwnedMembers, - runScopeResolution, - type ScopeResolver, - type RunScopeResolutionInput, - type RunScopeResolutionStats, -} from '../../scope-resolution/index.js'; +import { buildMro, defaultLinearize } from '../../scope-resolution/passes/mro.js'; +import { populateClassOwnedMembers } from '../../scope-resolution/scope/walkers.js'; +import type { ScopeResolver } from '../../scope-resolution/contract/scope-resolver.js'; import { pythonProvider } from '../python.js'; import { pythonArityCompatibility, @@ -78,10 +72,3 @@ const pythonScopeResolver: ScopeResolver = { }; export { pythonScopeResolver }; - -export interface ResolvePythonScopeInput extends RunScopeResolutionInput {} -export interface ResolvePythonScopeStats extends RunScopeResolutionStats {} - -export function resolvePythonScope(input: ResolvePythonScopeInput): ResolvePythonScopeStats { - return runScopeResolution(input, pythonScopeResolver); -} diff --git a/gitnexus/src/core/ingestion/scope-resolution/contract/scope-resolver.ts b/gitnexus/src/core/ingestion/scope-resolution/contract/scope-resolver.ts index f721196b1..c21ef7b35 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/contract/scope-resolver.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/contract/scope-resolver.ts @@ -77,7 +77,6 @@ import type { BindingRef, Callsite, ParsedFile, - Scope, ScopeId, SupportedLanguages, SymbolDefinition, @@ -210,7 +209,3 @@ export interface ScopeResolver { */ readonly fieldFallbackOnMethodLookup?: boolean; } - -// Re-export Scope so consumers don't need to dig into `gitnexus-shared` -// for the type they're already using transitively. -export type { Scope }; diff --git a/gitnexus/src/core/ingestion/scope-resolution/graph-bridge/references-to-edges.ts b/gitnexus/src/core/ingestion/scope-resolution/graph-bridge/references-to-edges.ts index 1331f204b..eb8bfdfea 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/graph-bridge/references-to-edges.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/graph-bridge/references-to-edges.ts @@ -32,7 +32,7 @@ import type { GraphNodeLookup } from '../graph-bridge/node-lookup.js'; * fallback resolution doesn't fight the precise emission. The key is * `${filePath}:${startLine}:${startCol}`. */ -export type ReferenceSiteSkipSet = ReadonlySet; +type ReferenceSiteSkipSet = ReadonlySet; export function emitReferencesViaLookup( graph: KnowledgeGraph, diff --git a/gitnexus/src/core/ingestion/scope-resolution/index.ts b/gitnexus/src/core/ingestion/scope-resolution/index.ts deleted file mode 100644 index 7716bceb9..000000000 --- a/gitnexus/src/core/ingestion/scope-resolution/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * `scope-resolution/` — registry-primary call/reference resolution. - * - * Public surface, grouped by concern. New language migrations should - * read `contract/scope-resolver.ts` first — it lists every hook the - * generic pipeline needs from a per-language adapter. - * - * Folder layout: - * - `contract/` — `ScopeResolver` interface + shared types - * - `pipeline/` — orchestrator, registry, pipeline-phase wrapper - * - `passes/` — reference-resolution passes (receiver-bound, - * free-call fallback, compound-receiver, MRO, - * cross-file return-type propagation) - * - `graph-bridge/` — CLI-local layer that translates resolved - * references into `KnowledgeGraph` edges - * - `scope/` — generic scope-chain walkers + namespace targets - * - * The `scope/` and `passes/` content is pure logic with no graph - * dependency; if a future consumer (gitnexus-web) needs the resolver - * without the graph, those two folders are the natural promotion path - * to `gitnexus-shared/`. - */ - -// ── Contract ────────────────────────────────────────────────────────────── -export type { ArityVerdict, LinearizeStrategy, ScopeResolver } from './contract/scope-resolver.js'; - -// ── Pipeline ────────────────────────────────────────────────────────────── -export { - runScopeResolution, - type RunScopeResolutionInput, - type RunScopeResolutionStats, -} from './pipeline/run.js'; -export { SCOPE_RESOLVERS, getScopeResolver } from './pipeline/registry.js'; - -// ── Passes ──────────────────────────────────────────────────────────────── -export { emitReceiverBoundCalls } from './passes/receiver-bound-calls.js'; -export { emitFreeCallFallback } from './passes/free-call-fallback.js'; -export { - matchingOpenParen, - resolveCompoundReceiverClass, - type ResolveCompoundReceiverOptions, -} from './passes/compound-receiver.js'; -export { - followChainPostFinalize, - propagateImportedReturnTypes, -} from './passes/imported-return-types.js'; -export { buildMro, defaultLinearize } from './passes/mro.js'; - -// ── Graph bridge (CLI-local) ────────────────────────────────────────────── -export { - buildGraphNodeLookup, - isLinkableLabel, - type GraphNodeLookup, -} from './graph-bridge/node-lookup.js'; -export { - resolveCallerGraphId, - resolveDefGraphId, - simpleQualifiedName, -} from './graph-bridge/ids.js'; -export { mapReferenceKindToEdgeType, tryEmitEdge } from './graph-bridge/edges.js'; -export { emitReferencesViaLookup } from './graph-bridge/references-to-edges.js'; -export { emitImportEdges } from './graph-bridge/imports-to-edges.js'; -export { buildPopulatedMethodDispatch } from './graph-bridge/method-dispatch.js'; - -// ── Scope walkers ───────────────────────────────────────────────────────── -export { - findReceiverTypeBinding, - findClassBindingInScope, - findCallableBindingInScope, - findEnclosingClassDef, - findExportedDefByName, - findOwnedMember, - findExportedDef, - populateClassOwnedMembers, -} from './scope/walkers.js'; -export { collectNamespaceTargets } from './scope/namespace-targets.js'; diff --git a/gitnexus/src/core/ingestion/scope-resolution/passes/compound-receiver.ts b/gitnexus/src/core/ingestion/scope-resolution/passes/compound-receiver.ts index ba1223eeb..7dc0fe65a 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/passes/compound-receiver.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/passes/compound-receiver.ts @@ -34,7 +34,7 @@ import { * pathological recursion if the receiver text is malformed. */ const COMPOUND_RECEIVER_MAX_DEPTH = 4; -export interface ResolveCompoundReceiverOptions { +interface ResolveCompoundReceiverOptions { /** When true (default), if method lookup fails on the receiver's * class, walk its fields and try the lookup on each field's class. * Phase-9C "unified fixpoint" — Python-shaped heuristic. */ @@ -152,7 +152,7 @@ export function resolveCompoundReceiverClass( /** Find the index of the `(` that matches the trailing `)` of a * call-expression text. Returns -1 if unbalanced. */ -export function matchingOpenParen(text: string): number { +function matchingOpenParen(text: string): number { if (!text.endsWith(')')) return -1; let depth = 0; for (let i = text.length - 1; i >= 0; i--) { diff --git a/gitnexus/src/core/ingestion/scope-resolution/passes/imported-return-types.ts b/gitnexus/src/core/ingestion/scope-resolution/passes/imported-return-types.ts index b7d192312..80b82b0f3 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/passes/imported-return-types.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/passes/imported-return-types.ts @@ -30,7 +30,7 @@ const RECHAIN_MAX_DEPTH = 8; * `followChainedRef` but operates on post-finalize Scope objects so * it can see imported return-types propagated by * `propagateImportedReturnTypes`. */ -export function followChainPostFinalize( +function followChainPostFinalize( start: TypeRef, fromScopeId: ScopeId, scopes: ScopeResolutionIndexes, diff --git a/gitnexus/src/core/ingestion/scope-resolution/passes/receiver-bound-calls.ts b/gitnexus/src/core/ingestion/scope-resolution/passes/receiver-bound-calls.ts index fe2b476d2..fceaae8d2 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/passes/receiver-bound-calls.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/passes/receiver-bound-calls.ts @@ -49,7 +49,7 @@ import { resolveCompoundReceiverClass } from '../passes/compound-receiver.js'; /** Subset of `ScopeResolver` consumed by this pass. Accepting the * subset rather than the full provider keeps tests and partial * refactors lighter — callers only need to populate what we read. */ -export type ReceiverBoundProviderSubset = Pick< +type ReceiverBoundProviderSubset = Pick< ScopeResolver, 'isSuperReceiver' | 'fieldFallbackOnMethodLookup' >; diff --git a/gitnexus/src/core/ingestion/scope-resolution/pipeline/registry.ts b/gitnexus/src/core/ingestion/scope-resolution/pipeline/registry.ts index 2f6093b6c..baf8e75b7 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/pipeline/registry.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/pipeline/registry.ts @@ -21,7 +21,3 @@ export const SCOPE_RESOLVERS: ReadonlyMap = n SupportedLanguages, ScopeResolver >([[SupportedLanguages.Python, pythonScopeResolver]]); - -export function getScopeResolver(lang: SupportedLanguages): ScopeResolver | undefined { - return SCOPE_RESOLVERS.get(lang); -} diff --git a/gitnexus/src/core/ingestion/scope-resolution/pipeline/run.ts b/gitnexus/src/core/ingestion/scope-resolution/pipeline/run.ts index ff0974ae7..b21f6eadb 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/pipeline/run.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/pipeline/run.ts @@ -38,7 +38,7 @@ import { emitImportEdges } from '../graph-bridge/imports-to-edges.js'; import type { ScopeResolver } from '../contract/scope-resolver.js'; import { buildWorkspaceResolutionIndex } from '../workspace-index.js'; -export interface RunScopeResolutionInput { +interface RunScopeResolutionInput { readonly graph: KnowledgeGraph; readonly files: readonly { readonly path: string; readonly content: string }[]; readonly onWarn?: (message: string) => void; @@ -52,7 +52,7 @@ export interface RunScopeResolutionInput { readonly treeCache?: { get(filePath: string): unknown }; } -export interface RunScopeResolutionStats { +interface RunScopeResolutionStats { readonly filesProcessed: number; readonly filesSkipped: number; readonly importsEmitted: number;