import { type EngineIndex, type EngineSymbol } from "./engine-index.js"; export interface SymbolVerdict { name: string; found: boolean; kind?: EngineSymbol["kind"] | "member"; module?: string; /** What to put in an #include to reach it. */ include?: string; header?: string; line?: number; signature?: string; parent?: string; deprecated?: { version?: string; message?: string; }; /** Set when the header cannot be included from another module. */ privateHeader?: boolean; /** Other declarations of the same name, when there is more than one. */ alsoDeclaredIn?: string[]; /** Close spellings, when the name was not found at all. */ suggestions?: string[]; } export interface VerifyResult { engineVersion: string; checked: number; foundCount: number; /** Names that did not resolve. Empty means every symbol exists. */ missing: string[]; /** Names that resolved but are deprecated. */ deprecated: string[]; /** Every include line needed, deduplicated and sorted. */ includes: string[]; /** Every module needed, deduplicated and sorted. */ modules: string[]; symbols: SymbolVerdict[]; } /** One symbol's verdict. Accepts `Class::Member` as well as a bare name. */ export declare function verifySymbol(index: EngineIndex, name: string): SymbolVerdict; /** Verify a batch, and aggregate what the caller has to do about it. */ export declare function verifySymbols(index: EngineIndex, names: string[]): VerifyResult; export interface BuildCsDeps { path: string; publicDeps: string[]; privateDeps: string[]; } /** * The module names a Build.cs already depends on. * * A regex over the two AddRange calls, which is what every Build.cs in * practice uses. A file that builds its dependency list some other way reads * as having none, which makes a suggestion redundant rather than wrong. */ export declare function readBuildCsDeps(buildCsPath: string): BuildCsDeps; /** The Build.cs for a module directory, or for the module owning a file. */ export declare function findBuildCs(startDir: string): string | null; export interface DepSuggestion { modules: string[]; /** Modules needed that the Build.cs does not already list. */ missing: string[]; buildCs?: BuildCsDeps; /** The line to paste, when something is missing. */ edit?: string; } /** Which modules a set of symbols needs, and which are not yet depended on. */ export declare function suggestBuildDeps(index: EngineIndex, names: string[], buildCsPath?: string | null): DepSuggestion; export interface UsageSite { file: string; line: number; text: string; /** `source` is a .cpp, `header` is a .h, `project` is the user's own code. */ kind: "source" | "header" | "project"; } export interface UsageResult { symbol: string; siteCount: number; sites: UsageSite[]; /** * Whether the engine tree actually contains .cpp files. * * An engine installed from the Epic launcher ships headers and no sources * at all, which is the common case. Without this flag an empty result reads * as "nothing uses this symbol" rather than "this install cannot answer * that", and those call for opposite next steps. */ engineSourcesAvailable: boolean; /** How many files were read and searched, which is what this cost. */ filesScanned: number; /** Set when the search stopped on its time budget rather than on the tree, * so a short list is never mistaken for a complete one. */ truncated?: boolean; note?: string; } /** * Real call sites for a symbol, to answer "how is this actually used" with * code that compiles. Better than a signature for anything with a non-obvious * calling convention. * * Prefers .cpp files, because a header shows the declaration the caller * already has. But a launcher-installed engine contains no .cpp at all, so on * those this falls back to headers, where Unreal keeps a great deal of inline * code, and to the project's own sources, which are often the better example * anyway. The result says which happened. * * ## Why it is shaped the way it is * * On a launcher install the fallback has to consider every header in the * tree, because a symbol used inline could be in any of them, and the search * cannot stop early when the answer is "used nowhere in a header", which for * most symbols it is. That is roughly 11,000 files and 80 MB per call, and * three things kept it from being affordable: * * - the tree was walked twice, once to discover there were no .cpp files * and again to read the headers; * - every file was decoded from UTF-8 into a UTF-16 string before being * tested for the name, though fewer than one file in a thousand holds it, * so nearly all of that decoding was thrown away; * - the reads were issued one at a time, which on a cold filesystem cache * serialises 11,000 virus-scanner round trips. * * So: one walk, remembered; the name matched against the raw bytes and only a * matching file decoded; and reads issued in parallel batches while results * are still consumed in order. The remaining cost is bounded by `budgetMs`, * and a search cut short by it says so rather than returning a short list that * reads as a complete one. */ export declare function findExampleUsage(engineRoot: string, symbol: string, options?: { limit?: number; trees?: string[]; projectDir?: string | null; /** Wall-clock ceiling. Reached only by a tree far larger than Runtime. */ budgetMs?: number; }): Promise; export interface LintFinding { severity: "error" | "warning"; rule: string; message: string; line?: number; } export interface LintResult { file: string; findings: LintFinding[]; /** Engine symbols the header references. */ referenced: string[]; /** Include lines it should have but does not. */ missingIncludes: string[]; /** Modules its Build.cs should list but does not. */ missingModules: string[]; buildCs?: string; } /** Symbols a header references, by the engine's naming convention. */ export declare function referencedSymbols(source: string): string[]; /** * Check a header the agent just wrote against the engine it has to build * against. * * Reports what the compiler would, before the compiler runs: a symbol that * does not exist, one used without its include, one whose module is missing * from Build.cs, and one the engine has deprecated. Also the two structural * mistakes that produce baffling errors in an Unreal build - a reflected type * with no generated header include, and a UCLASS with no body macro. */ export declare function lintHeader(index: EngineIndex, headerPath: string, options?: { buildCsPath?: string | null; }): LintResult;