/** * Resolve an import specifier to the indexed file it refers to. * * Runs once, after indexing, filling `refs.to_file`. Doing it here rather than * in the graph readers is what makes the Code Atlas language-agnostic: the * readers only ever see "this ref points at that file", and never need to know * that Go import paths come from `go.mod` while Python's come from a directory * chain — knowledge that is not in the database and cannot be recovered from it. * * Resolution is best-effort by design. An unresolved specifier (a stdlib or * third-party module, or an ecosystem whose layout we don't model) simply * leaves `to_file` NULL, and the graph readers fall back to the ref's resolved * symbol id. Guessing would draw edges that aren't there. */ import { type ProjectStructure } from './module-roots.js'; import type { SymbolLang } from './schema.js'; export declare class ModuleResolver { private readonly structure; /** Lowercased portable path → the path as indexed (case is preserved). */ private readonly byPath; /** Lowercased portable directory → files directly inside it, as indexed. */ private readonly byDir; /** Normalized namespace → the file declaring it (first by path, stable). */ private readonly byNamespace; constructor(structure: ProjectStructure, files: readonly string[], namespaces?: ReadonlyArray<{ name: string; file: string; }>); /** * Resolve `specifier` as written in `fromFile`. * Returns the indexed target path, or `undefined` when it is external or * cannot be located. */ resolve(fromFile: string, lang: SymbolLang, specifier: string): string | undefined; /** * Resolve a namespace specifier to the file declaring it. * * Tried whole first, then with the trailing segment dropped: `using Foo.Bar` * names a namespace outright, while PHP's `use App\Models\User` names a * *class* inside `App\Models`, so the prefix is what was declared. */ private resolveNamespace; private lookup; /** * Try `base` verbatim, then `base` + each extension, then each directory * entry point inside `base`. */ private lookupWithExtensions; /** * A representative indexed file inside `dir`, for ecosystems whose import * unit is a directory rather than a file (Go packages, JVM wildcard imports). * * The choice is deterministic — a file named after the directory, else the * first by name — so the same import always produces the same edge. Package * grouping is unaffected either way: every file in the directory carries the * same package label, so the package-level edge is exact regardless of which * member represents it. */ private representativeIn; /** Relative specifiers, then workspace package names and their subpaths. */ private resolveJs; /** Go import paths are absolute module paths; a package is a directory. */ private resolveGo; /** * `import a.b.c` / `from a.b import c`, plus PEP 328 relative imports whose * leading dots the extractor preserves (`.sibling`, `..parent.mod`). */ private resolvePython; /** * `use crate::a::b`, `use super::x`, `use self::y`, `use other_crate::z`, * and `mod x;` declarations. * * Paths are resolved from the declaring file's MODULE directory, which is * only its filesystem directory for `mod.rs`/`lib.rs`/`main.rs`. A plain * `src/net.rs` owns `src/net/`: its `mod http;` is `src/net/http.rs`, its * `super` is the crate root. Using the file's directory put every * `self::`/`super::`/`mod` path from such a file one level too high, so * those edges silently resolved to nothing (or to an unrelated file). */ private resolveRust; /** * Longest module prefix of `segments` under `base` that is an indexed file. * The trailing segments of a `use` are usually items (`net::http::Client::new`), * so each is dropped in turn until a module file matches. */ private lookupRustPath; /** The file defining the module whose children live in `dir`. */ private lookupRustModuleFile; /** A crate's root file: the library root, else the binary root. */ private lookupRustCrateRoot; /** `com.example.Thing` and `com.example.*` against JVM source roots. */ private resolveJvm; /** `#include "foo/bar.h"` — quoted form only; `<…>` is a system header. */ private resolveInclude; /** `require_relative 'x'` is relative; `require 'x'` is looked up under lib/. */ private resolveRuby; } //# sourceMappingURL=module-resolver.d.ts.map