UNPKG

socraticode

Version:

SocratiCode — MCP server for local codebase indexing, semantic search, and code dependency graphs. All private, all local via Docker.

186 lines • 7.82 kB
import { Lang } from "@ast-grep/napi"; export interface ImportInfo { moduleSpecifier: string; isDynamic: boolean; /** CommonJS require uses a different conditional-export branch from import. */ isRequire?: boolean; isCssImport?: boolean; /** * Fallback specifier when the primary moduleSpecifier cannot be resolved. * Used by Godot .tscn/.tres ext_resource: when both uid:// and path are * present, uid is the primary specifier and path is the fallback, so the * resolver can try the path if UID resolution misses. */ fallbackSpecifier?: string; /** * True when the specifier comes from a declaration that brings a file into * the module tree — a Rust `mod foo;` — rather than from a path that merely * names something. Rust needs the difference: a module has to be declared * before an unanchored path can reach it, and the declaration is the only * evidence of that in the file. */ isModuleDeclaration?: boolean; /** * The name a module declaration puts in the declaring file's own scope. * Absent when the declaration is written inside an inline `mod` block, * where the name belongs to the block rather than to the file. * * It is not the specifier: `#[path = "custom.rs"] mod foo;` travels as the * path it declares, while the name it brings into scope is `foo`, and it is * `foo` an unanchored `use foo::Item;` in that file may reach. */ declaredName?: string; /** * True when the path was written inside an inline `mod { … }` block and its * head is not a module that block declares. Such a head cannot reach a module * the *file* declares: rustc asks for an anchor first. Checked on cargo * 1.98.0 — `pub mod corelib;` at file level with `use corelib::marker;` * inside `pub mod block { … }` is E0432, "a similar path exists: use * crate::corelib::marker" (`super::` where the block sits deeper). * * It is the mirror of the case already handled the other way round, where a * declaration written inside a block does not count at file level. */ fromInlineBlock?: boolean; /** Distinguishes Godot path semantics for extends, preload, and runtime load. */ godotImportKind?: "extends" | "preload" | "load"; } /** * Reset the per-language dedupe set. Intended for tests that want to assert * deterministically on extraction warnings. */ export declare function resetImportExtractionWarnings(): void; /** * Decode a GDScript string literal from its raw source text. * * GDScript supports: * - Single-quoted: 'hello', '''triple single''' * - Double-quoted: "hello", \"\"\"triple double\"\\"\" * - Raw strings: r"no escapes", r'no escapes', r\"\"\"triple\"\" * * In raw strings, escape sequences are not processed — the content is * taken literally. In non-raw strings, \\n, \\t, \\\\, \\", \\', \\uXXXX * are decoded. * * Returns the decoded string value, or null if the text is not a valid * GDScript string literal. */ export declare function decodeGdscriptString(raw: string): string | null; /** * Parse a TSCN/.tres section header line into its resource type and * key-value attributes. * * TSCN whitespace is insignificant outside strings. Headings are: * [<resource_type> key1=value1 key2=value2 ...] * * This tokenizer handles: * - Leading whitespace before [ * - Spaces around = in key=value pairs * - Quoted values with escapes * - Arbitrary attribute order * - Comments (lines starting with ; outside a section) * * Returns { type, attrs } or null if the line is not a section header. */ export declare function parseTscnSectionHeader(line: string): { type: string; attrs: Map<string, string>; } | null; /** * Syntax-aware GDScript import fallback for hosts where the optional native * parser cannot load. The lightweight lexer excludes comments and string * bodies before recognizing direct preload/load arguments and extends forms. */ export declare function extractGdscriptImportsRegex(source: string): ImportInfo[]; /** * Tokenizer-based import extraction for Godot resource files (.tscn/.tres). * * These are text-based INI-like files with no tree-sitter grammar. * Dependencies are declared via `[ext_resource path="..."]` lines. * * The path can be: * - A `res://` path (absolute within the Godot project) * - A relative path (relative to the .tscn/.tres file's directory) * - A `uid://` path (resolved via .uid sidecar files) * * TSCN whitespace is insignificant outside strings, so the tokenizer handles * leading whitespace, spaces around =, arbitrary attribute order, and quoted * values with escapes. See the TSCN documentation: * https://docs.godotengine.org/en/stable/engine_details/file_formats/tscn.html * * Scene-to-scene composition is represented by PackedScene entries in * ext_resource, not a separate [instance] section. The `instance` keyword * is an attribute of a [node] declaration, not a section heading. * * Both `uid` and `path` attributes are extracted. When both are present, * Godot prefers the UID and falls back to the text path only when the UID * cannot be resolved. The resolver handles this priority. */ export declare function extractGodotResourceImports(source: string): ImportInfo[]; /** The subset of the ast-grep node API this module reads. */ interface SgNodeLike { kind(): string; text(): string; parent(): SgNodeLike | null; prev(): SgNodeLike | null; field(name: string): SgNodeLike | null; findAll(matcher: { rule: { kind: string; }; }): SgNodeLike[]; children(): SgNodeLike[]; range(): { start: { index: number; }; end: { index: number; }; }; } /** * Flatten one `use` tree into the module paths it names, one per leaf: * * crate::config::Config → ["crate::config::Config"] * crate::{a::Thing, b} → ["crate::a::Thing", "crate::b"] * crate::a::{self, b as c} → ["crate::a", "crate::a::b"] * crate::a::* → ["crate::a"] * * A braced group is not a module path and never resolved to one; recording the * leaves instead is what lets `use crate::{parser, printer}` draw an edge to * each of the two files rather than to their parent module — or, in a flat * crate with no parent module file, to nothing at all. */ export declare function expandRustUseTree(tree: string): string[]; /** A half-open range of character indexes in a source. */ interface Span { start: number; end: number; } interface UnwrappedSource { /** The rewritten Rust source. */ source: string; /** Its tree, already built by the check that accepted it. */ root: SgNodeLike; /** * Every ERROR node that tree holds — each inside a macro unwrapped in this * pass or an earlier one, or the check would not have accepted it. The next * pass forgives exactly these, and nothing else. */ errors: Span[]; } /** * Extract import statements from source code using ast-grep. * Returns raw module specifiers for each language's import syntax. * * `unwrapped` is internal, and only the Rust macro pass passes it: the tree it * had to build to accept the source it rewrote, so the same text is not parsed * twice, and the regions it blanked, which the next pass needs to tell its own * damage from the last pass's leftovers. Nothing else should pass it — it * describes one particular `source` and would be read as if it described this * one. */ export declare function extractImports(source: string, lang: Lang | string, ext: string, unwrapPassesLeft?: number, unwrapped?: UnwrappedSource): ImportInfo[]; export {}; //# sourceMappingURL=graph-imports.d.ts.map