refactor(scope-resolution): drop dead exports surfaced by knip

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.
This commit is contained in:
Gergo Magyar 2026-04-21 14:32:11 +01:00
parent 97e1a05a51
commit 103dbe669b
13 changed files with 17 additions and 116 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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';

View file

@ -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

View file

@ -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);
}

View file

@ -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 };

View file

@ -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<string>;
type ReferenceSiteSkipSet = ReadonlySet<string>;
export function emitReferencesViaLookup(
graph: KnowledgeGraph,

View file

@ -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';

View file

@ -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--) {

View file

@ -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,

View file

@ -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'
>;

View file

@ -21,7 +21,3 @@ export const SCOPE_RESOLVERS: ReadonlyMap<SupportedLanguages, ScopeResolver> = n
SupportedLanguages,
ScopeResolver
>([[SupportedLanguages.Python, pythonScopeResolver]]);
export function getScopeResolver(lang: SupportedLanguages): ScopeResolver | undefined {
return SCOPE_RESOLVERS.get(lang);
}

View file

@ -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;