//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! THIS FILE IS AUTO-GENERATED - DO NOT EDIT !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// Source: src/api/async/api.ts
// Regenerate: npm run generate (from _packages/native-preview)
//
/// <reference path="../node/node.ts" preserve="true" />
import { CompletionItemKind } from "#enums/completionItemKind";
import { DiagnosticCategory } from "#enums/diagnosticCategory";
import { ElementFlags } from "#enums/elementFlags";
import { ModuleKind } from "#enums/moduleKind";
import { NodeBuilderFlags } from "#enums/nodeBuilderFlags";
import { ObjectFlags } from "#enums/objectFlags";
import { SignatureFlags } from "#enums/signatureFlags";
import { SignatureKind } from "#enums/signatureKind";
import { SymbolFlags } from "#enums/symbolFlags";
import { TypeFlags } from "#enums/typeFlags";
import { TypePredicateKind } from "#enums/typePredicateKind";
import { ModifierFlags, unescapeLeadingUnderscores, } from "../../ast/index.js";
import { encodeNode, uint8ArrayToBase64, } from "../node/encoder.js";
import { decodeNode, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, RemoteSourceFile, } from "../node/node.js";
import { Wtf8Decoder } from "../node/wtf8.js";
import { createGetCanonicalFileName, toPath, } from "../path.js";
import { resolveFileName, toUpdateSnapshotRequest, } from "../proto.js";
import { SourceFileCache } from "../sourceFileCache.js";
import { Client, } from "./client.js";
export { documentURIToFileName, fileNameToDocumentURI } from "../path.js";
export { CompletionItemKind, DiagnosticCategory, ElementFlags, ModifierFlags, ModuleKind, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
export class API {
    client;
    sourceFileCache;
    toPath;
    initialized = false;
    activeSnapshots = new Set();
    latestSnapshot;
    internal;
    constructor(options = {}) {
        this.client = new Client(options);
        this.sourceFileCache = new SourceFileCache();
        this.internal = new InternalAPI(this.client, () => this.ensureInitialized());
    }
    /**
     * Create an API instance from an existing LSP connection's API session.
     * Use this when connecting to an API pipe provided by an LSP server via custom/initializeAPISession.
     */
    static fromLSPConnection(options) {
        const api = new API(options);
        api.ensureInitialized();
        return api;
    }
    ensureInitialized() {
        if (!this.initialized) {
            const response = this.client.apiRequest("initialize", null);
            const getCanonicalFileName = createGetCanonicalFileName(response.useCaseSensitiveFileNames);
            const currentDirectory = response.currentDirectory;
            this.toPath = (fileName) => toPath(fileName, currentDirectory, getCanonicalFileName);
            this.initialized = true;
        }
    }
    parseConfigFile(file) {
        this.ensureInitialized();
        return this.client.apiRequest("parseConfigFile", { file });
    }
    updateSnapshot(params) {
        this.ensureInitialized();
        const requestParams = toUpdateSnapshotRequest(params);
        const data = this.client.apiRequest("updateSnapshot", requestParams);
        // Retain cached source files from previous snapshot for unchanged files
        if (this.latestSnapshot) {
            this.sourceFileCache.retainForSnapshot(data.snapshot, this.latestSnapshot.id, data.changes);
            if (this.latestSnapshot.isDisposed()) {
                this.sourceFileCache.releaseSnapshot(this.latestSnapshot.id);
            }
        }
        const snapshot = new Snapshot(data, this.client, this.sourceFileCache, this.toPath, () => {
            this.activeSnapshots.delete(snapshot);
            if (snapshot !== this.latestSnapshot) {
                this.sourceFileCache.releaseSnapshot(snapshot.id);
            }
        });
        this.latestSnapshot = snapshot;
        this.activeSnapshots.add(snapshot);
        return snapshot;
    }
    close() {
        // Dispose all active snapshots
        for (const snapshot of [...this.activeSnapshots]) {
            snapshot.dispose();
        }
        // Release the latest snapshot's cache refs if still held
        if (this.latestSnapshot) {
            this.sourceFileCache.releaseSnapshot(this.latestSnapshot.id);
            this.latestSnapshot = undefined;
        }
        this.client.close();
        this.sourceFileCache.clear();
    }
    clearSourceFileCache() {
        this.sourceFileCache.clear();
    }
    /**
     * Returns a snapshot of collected timing information for requests made
     * through this API instance: client-measured round-trip latency and bytes
     * transferred, folded together with the server's own per-request processing
     * time and an estimated transport overhead (round-trip minus server time).
     *
     * Fetching the snapshot issues a lightweight request to the server to
     * retrieve its timing collection. Collection must be enabled via the
     * `collectTiming` option; when it is not, the returned snapshot has
     * `enabled: false` and zeroed totals.
     */
    getTimingInfo() {
        return this.client.getTimingInfo();
    }
    /** Clears all accumulated timing totals and recent-request history, on both the client and the server. */
    resetTimingInfo() {
        return this.client.resetTimingInfo();
    }
}
export class InternalAPI {
    client;
    ensureInitialized;
    /** @internal */
    constructor(client, ensureInitialized) {
        this.client = client;
        this.ensureInitialized = ensureInitialized;
    }
    startCPUProfile(dir) {
        this.ensureInitialized();
        this.client.apiRequest("startCPUProfile", { dir });
    }
    stopCPUProfile() {
        this.ensureInitialized();
        const result = this.client.apiRequest("stopCPUProfile", null);
        return result.file;
    }
    saveHeapProfile(dir) {
        this.ensureInitialized();
        const result = this.client.apiRequest("saveHeapProfile", { dir });
        return result.file;
    }
}
export class Snapshot {
    id;
    projectMap;
    toPath;
    client;
    disposed = false;
    onDispose;
    snapshotRegistry;
    constructor(data, client, sourceFileCache, toPath, onDispose) {
        this.id = data.snapshot;
        this.client = client;
        this.toPath = toPath;
        this.onDispose = onDispose;
        this.projectMap = new Map();
        this.snapshotRegistry = new SnapshotObjectRegistry(client, this.id, projectId => this.projectMap.get(projectId));
        for (const projData of data.projects) {
            const project = new Project(projData, this.id, client, sourceFileCache, toPath, this.snapshotRegistry);
            this.projectMap.set(toPath(projData.configFileName), project);
        }
    }
    getProjects() {
        this.ensureNotDisposed();
        return [...this.projectMap.values()];
    }
    getProject(configFileName) {
        this.ensureNotDisposed();
        return this.projectMap.get(this.toPath(configFileName));
    }
    getDefaultProjectForFile(file) {
        this.ensureNotDisposed();
        const data = this.client.apiRequest("getDefaultProjectForFile", {
            snapshot: this.id,
            file,
        });
        if (!data)
            return undefined;
        return this.projectMap.get(this.toPath(data.configFileName));
    }
    [globalThis.Symbol.dispose]() {
        this.dispose();
    }
    dispose() {
        if (this.disposed)
            return;
        this.disposed = true;
        for (const project of this.projectMap.values()) {
            project.dispose();
        }
        this.projectMap.clear();
        this.snapshotRegistry.clear();
        this.onDispose();
        this.client.apiRequest("release", { snapshot: this.id });
    }
    isDisposed() {
        return this.disposed;
    }
    ensureNotDisposed() {
        if (this.disposed) {
            throw new Error("Snapshot is disposed");
        }
    }
}
class SnapshotObjectRegistry {
    symbols = new Map();
    client;
    snapshotId;
    resolveProject;
    constructor(client, snapshotId, resolveProject) {
        this.client = client;
        this.snapshotId = snapshotId;
        this.resolveProject = resolveProject;
    }
    /** Resolve a project id (a config file path) to its Project within this snapshot. */
    getProject(projectId) {
        return this.resolveProject(projectId);
    }
    getOrCreateSymbol(data) {
        let symbol = this.symbols.get(data.id);
        if (!symbol) {
            symbol = new Symbol(data, this);
            this.symbols.set(data.id, symbol);
        }
        else {
            // Light prefetch omits parent; full responses (and later light
            // responses that include parent) must upgrade the cached handle
            // or SymbolDisplay loses the container FQN (Indexed.prop).
            symbol.applyParentHandle(data.parent);
        }
        return symbol;
    }
    getSymbol(id) {
        return this.symbols.get(id);
    }
    clear() {
        this.symbols.clear();
    }
    /**
     * Fetch the full declaration payload for a symbol id (declarations +
     * valueDeclaration). Returns null if the symbol has no declarations. Used to
     * lazily upgrade light prefetch symbols; the registry is snapshot-scoped so
     * no project id is required.
     */
    fetchSymbolDeclarations(symbolId) {
        return this.client.apiRequest("getSymbolDeclarations", {
            snapshot: this.snapshotId,
            objectId: symbolId,
        });
    }
    /**
     * Materialize symbols the server referenced by bare id (getSymbolsInScope
     * dedup) but this registry has not seen. getSymbolsDeclarations resolves
     * ids against the server-side snapshot registry and returns full payloads.
     */
    materializeSymbols(symbolIds) {
        const data = this.client.apiRequest("getSymbolsDeclarations", {
            snapshot: this.snapshotId,
            symbols: symbolIds,
        }) ?? [];
        return data.map(d => d ? this.getOrCreateSymbol(d) : undefined);
    }
    /**
     * Batch-resolve parents for symbols whose wire payload omitted the parent
     * handle ("unfilled"). One RPC replaces a lazy getParentOfSymbol per
     * symbol; a null entry is the same confirmed "no parent" the lazy path
     * memoizes.
     */
    fetchParentsOfSymbols(symbolIds) {
        const data = this.client.apiRequest("getParentsOfSymbols", {
            snapshot: this.snapshotId,
            symbols: symbolIds,
        }) ?? [];
        return symbolIds.map((_, i) => data[i] ? this.getOrCreateSymbol(data[i]) : undefined);
    }
    /**
     * Batch-prefetch declaration payloads for every unresolved symbol in the
     * registry, WITHOUT resolving them. A single lazy `.declarations` miss
     * usually means a services loop is walking many light symbols
     * (auto-import/codefix export scans touch thousands); one batched RPC
     * replaces N per-symbol round trips. Payloads are stashed on each symbol
     * and applied only when that symbol's declarations are actually read, so
     * observable resolution state (hasDeclarationsResolved) stays identical
     * to the per-symbol lazy path — bridge-side remap gates branch on it.
     */
    stashAllUnresolvedDeclarations() {
        const needIds = [];
        for (const sym of this.symbols.values()) {
            if (!sym.hasDeclarationsResolved() && !sym.hasDeclarationStash())
                needIds.push(sym.id);
        }
        const CHUNK = 8192;
        for (let i = 0; i < needIds.length; i += CHUNK) {
            const chunk = needIds.slice(i, i + CHUNK);
            const data = this.client.apiRequest("getSymbolsDeclarations", {
                snapshot: this.snapshotId,
                symbols: chunk,
            }) ?? [];
            for (let j = 0; j < chunk.length; j++) {
                const sym = this.symbols.get(chunk[j]);
                if (sym)
                    sym.stashDeclarationPayload(data[j] ?? null);
            }
        }
    }
    /** Batch-upgrade light prefetch symbols with declaration payloads (one RPC). */
    hydrateSymbolDeclarations(symbolIds) {
        if (symbolIds.length === 0)
            return;
        const needIds = [];
        for (const id of symbolIds) {
            const sym = this.symbols.get(id);
            if (sym && !sym.hasDeclarationsResolved())
                needIds.push(id);
        }
        if (needIds.length === 0)
            return;
        const data = this.client.apiRequest("getSymbolsDeclarations", {
            snapshot: this.snapshotId,
            symbols: needIds,
        }) ?? [];
        for (let i = 0; i < needIds.length; i++) {
            const sym = this.symbols.get(needIds[i]);
            if (sym)
                sym.applyDeclarationPayload(data[i] ?? null);
        }
    }
    fetchSymbol(source, method, handle, projectId) {
        // getParentOfSymbol resolves via source.id (objectId). A missing wire
        // handle is not "no parent" — light symbols omit parent, and callers
        // still need the lazy RPC. Other methods keep the early return.
        if (!handle) {
            if (method !== "getParentOfSymbol") {
                return undefined;
            }
        }
        else {
            const cached = this.getSymbol(handle);
            if (cached)
                return cached;
        }
        const data = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: projectId,
            objectId: source.id,
        });
        if (!data) {
            // Optional relations (parent) legitimately return null.
            if (method === "getParentOfSymbol")
                return undefined;
            throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
        }
        return this.getOrCreateSymbol(data);
    }
    fetchSymbols(source, method, handles, projectId) {
        if (handles) {
            const result = new Array(handles.length);
            let allCached = true;
            for (let i = 0; i < handles.length; i++) {
                const cached = this.getSymbol(handles[i]);
                if (!cached) {
                    allCached = false;
                    break;
                }
                result[i] = cached;
            }
            if (allCached)
                return result;
        }
        const symbolData = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: projectId,
            objectId: source.id,
        });
        if (symbolData == null)
            return [];
        else
            return symbolData.map(data => this.getOrCreateSymbol(data));
    }
}
class ProjectObjectRegistry {
    client;
    snapshotId;
    project;
    snapshotRegistry;
    types = new Map();
    signatures = new Map();
    constructor(client, snapshotId, project, snapshotRegistry) {
        this.client = client;
        this.snapshotId = snapshotId;
        this.project = project;
        this.snapshotRegistry = snapshotRegistry;
    }
    getOrCreateSymbol(data) {
        return this.snapshotRegistry.getOrCreateSymbol(data);
    }
    getSymbol(id) {
        return this.snapshotRegistry.getSymbol(id);
    }
    materializeSymbols(symbolIds) {
        return this.snapshotRegistry.materializeSymbols(symbolIds);
    }
    fetchParentsOfSymbols(symbolIds) {
        return this.snapshotRegistry.fetchParentsOfSymbols(symbolIds);
    }
    hydrateSymbolDeclarations(symbolIds) {
        this.snapshotRegistry.hydrateSymbolDeclarations(symbolIds);
    }
    getOrCreateType(data) {
        let type = this.types.get(data.id);
        if (!type) {
            type = new TypeObject(data, this);
            this.types.set(data.id, type);
        }
        return type;
    }
    getType(id) {
        return this.types.get(id);
    }
    getOrCreateSignature(data) {
        let sig = this.signatures.get(data.id);
        if (!sig) {
            sig = new Signature(data, this.project, this);
            this.signatures.set(data.id, sig);
        }
        return sig;
    }
    getSignature(id) {
        return this.signatures.get(id);
    }
    clear() {
        this.types.clear();
        this.signatures.clear();
    }
    fetchType(source, method, handle) {
        if (handle !== false) {
            if (!handle)
                return undefined;
            const cached = this.getType(handle);
            if (cached)
                return cached;
        }
        const data = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: this.project.id,
            objectId: source.id,
        });
        if (!data)
            throw new Error(`${method} returned null type for ${source.constructor.name} ${source.id}`);
        return this.getOrCreateType(data);
    }
    fetchSymbol(source, method, handle) {
        return this.snapshotRegistry.fetchSymbol(source, method, handle, this.project.id);
    }
    fetchSignature(source, method, handle) {
        if (!handle)
            return undefined;
        const cached = this.getSignature(handle);
        if (cached)
            return cached;
        const data = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: this.project.id,
            objectId: source.id,
        });
        if (!data)
            throw new Error(`${method} returned null signature for ${source.constructor.name} ${source.id}`);
        return this.getOrCreateSignature(data);
    }
    fetchTypes(source, method, handles) {
        if (handles) {
            const result = new Array(handles.length);
            let allCached = true;
            for (let i = 0; i < handles.length; i++) {
                const cached = this.getType(handles[i]);
                if (!cached) {
                    allCached = false;
                    break;
                }
                result[i] = cached;
            }
            if (allCached)
                return result;
        }
        const typesData = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: this.project.id,
            objectId: source.id,
        });
        if (typesData == null)
            return [];
        else
            return typesData.map(data => this.getOrCreateType(data));
    }
    fetchSymbols(source, method, handles) {
        return this.snapshotRegistry.fetchSymbols(source, method, handles, this.project.id);
    }
    // getBaseTypes is a checker-level endpoint keyed by `type` (not `objectId`),
    // so it cannot go through fetchTypes. This helper reuses that server method.
    fetchBaseTypes(source) {
        const typesData = this.client.apiRequest("getBaseTypes", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: source.id,
        });
        if (typesData == null)
            return [];
        return typesData.map(data => this.getOrCreateType(data));
    }
    /** Stock SignatureObject.getTypeParameterAtPosition → checker.getParameterType. */
    getParameterType(signature, index) {
        const data = this.client.apiRequest("getParameterType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            index,
        });
        if (!data)
            throw new Error(`getParameterType returned null for signature ${signature.id} index ${index}`);
        return this.getOrCreateType(data);
    }
}
export class Project {
    id;
    configFileName;
    compilerOptions;
    rootFiles;
    program;
    checker;
    emitter;
    client;
    constructor(data, snapshotId, client, sourceFileCache, toPath, snapshotRegistry) {
        this.id = data.id;
        this.configFileName = data.configFileName;
        this.compilerOptions = data.compilerOptions;
        this.rootFiles = data.rootFiles;
        this.client = client;
        this.program = new Program(snapshotId, this, client, sourceFileCache, toPath);
        const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this, snapshotRegistry);
        this.checker = new Checker(snapshotId, this, client, objectRegistry);
        this.emitter = new Emitter(client);
    }
    dispose() {
        this.checker.dispose();
    }
}
export class Program {
    snapshotId;
    project;
    client;
    sourceFileCache;
    toPath;
    decoder = new Wtf8Decoder();
    sourceFileMetadataCache = new Map();
    constructor(snapshotId, project, client, sourceFileCache, toPath) {
        this.snapshotId = snapshotId;
        this.project = project;
        this.client = client;
        this.sourceFileCache = sourceFileCache;
        this.toPath = toPath;
    }
    getCompilerOptions() {
        return this.project.compilerOptions;
    }
    getSourceFile(file) {
        const fileName = resolveFileName(file);
        const path = this.toPath(fileName);
        // Check if we already have a retained cache entry for this (snapshot, project) pair
        const retained = this.sourceFileCache.getRetained(path, this.snapshotId, this.project.id);
        if (retained) {
            return retained;
        }
        // Fetch from server
        const binaryData = this.client.apiRequestBinary("getSourceFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        if (!binaryData) {
            return undefined;
        }
        const view = new DataView(binaryData.buffer, binaryData.byteOffset, binaryData.byteLength);
        const contentHash = readSourceFileHash(view);
        const parseOptionsKey = readParseOptionsKey(view);
        // Create a new RemoteSourceFile and cache it (set returns existing if hash matches)
        const sourceFile = new RemoteSourceFile(binaryData, this.decoder, this.client.getTimingCollector());
        return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.project.id);
    }
    getSourceFileNames() {
        const data = this.client.apiRequest("getSourceFileNames", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /**
     * Returns program-stored metadata for the given source file, or `undefined` if the file
     * is not part of the program. Metadata is fetched lazily per file and cached on this
     * `Program` instance.
     */
    getSourceFileMetadata(fileName) {
        return this.getSourceFileMetadataByPath(this.toPath(fileName));
    }
    /**
     * Returns program-stored metadata for the source file at the given path, or `undefined`
     * if the file is not part of the program. Like {@link getSourceFileMetadata}, but skips
     * the file name to path conversion. Metadata is fetched lazily per file and cached on
     * this `Program` instance.
     */
    getSourceFileMetadataByPath(path) {
        let metadata = this.sourceFileMetadataCache.get(path);
        if (metadata === undefined) {
            metadata = this.fetchSourceFileMetadata(path);
            this.sourceFileMetadataCache.set(path, metadata);
        }
        return metadata;
    }
    fetchSourceFileMetadata(path) {
        const data = this.client.apiRequest("getSourceFileMetadata", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file: path,
        });
        return data ?? undefined;
    }
    /**
     * Returns whether the given source file was loaded as part of an external library
     * (e.g. a dependency resolved from `node_modules`). The underlying program metadata is
     * fetched lazily per file and cached on this `Program` instance.
     */
    isSourceFileFromExternalLibrary(file) {
        const metadata = this.getSourceFileMetadataByPath(file.path);
        return metadata?.isFromExternalLibrary ?? false;
    }
    /**
     * Returns whether the given source file is a default library file (e.g. `lib.d.ts`).
     * The underlying program metadata is fetched lazily per file and cached on this
     * `Program` instance.
     */
    isSourceFileDefaultLibrary(file) {
        const metadata = this.getSourceFileMetadataByPath(file.path);
        return metadata?.isDefaultLibrary ?? false;
    }
    /**
     * Builder-state metadata for every program file in one batch: content-hash
     * version, referenced-file edges (canonical tsgo paths), global-scope
     * effect and implied module format. Computed with the same graph walk
     * tsgo's own incremental buildinfo uses; no semantic pass runs.
     */
    getBuilderFileGraph() {
        const data = this.client.apiRequest("getBuilderFileGraph", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /**
     * Per-file syntactic + semantic diagnostics for every program file in one
     * batch. Same per-file results as getSyntacticDiagnostics /
     * getSemanticDiagnostics called file-by-file; build-mode builders use this
     * to avoid ~2 RPCs per program file.
     */
    getDiagnosticsBatch() {
        const data = this.client.apiRequest("getDiagnosticsBatch", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /**
     * Get syntactic (parse) diagnostics for a specific file or all files.
     * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
     */
    getSyntacticDiagnostics(file) {
        const data = this.client.apiRequest("getSyntacticDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(file !== undefined ? { file } : {}),
        });
        return data ?? [];
    }
    /**
     * Get binder diagnostics for a specific file or all files.
     * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
     */
    getBindDiagnostics(file) {
        const data = this.client.apiRequest("getBindDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(file !== undefined ? { file } : {}),
        });
        return data ?? [];
    }
    /**
     * Get semantic (type-check) diagnostics for a specific file or all files.
     * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
     */
    getSemanticDiagnostics(file) {
        const data = this.client.apiRequest("getSemanticDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(file !== undefined ? { file } : {}),
        });
        return data ?? [];
    }
    /**
     * Emit JS/declaration output for a file (or the whole program). Output files
     * are returned for the caller to write, so --noEmit and custom writeFile hosts
     * stay in control. `emitOnly`: 0=All, 1=Js, 2=Dts, 3=ForcedDts.
     */
    emit(options) {
        const data = this.client.apiRequest("emit", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(options?.file !== undefined ? { file: options.file } : {}),
            ...(options?.emitOnly !== undefined ? { emitOnly: options.emitOnly } : {}),
            ...(options?.forceDtsEmit ? { forceDtsEmit: true } : {}),
        });
        return data ?? { emitSkipped: true };
    }
    /**
     * Emit only the .tsbuildinfo for this project. The serialized buildinfo is
     * returned in `outputFiles` for the caller to write (same contract as
     * {@link emit}); like stock Program.emitBuildInfo, the write happens
     * whenever the project has a buildinfo path — the caller owns the
     * emit-pending decision. Pass `build: true` when running under a
     * `tsc -b`-style solution build so non-incremental projects get
     * build-mode buildinfo (the flag never appears in the tsconfig itself).
     */
    emitBuildInfo(options) {
        const data = this.client.apiRequest("emitBuildInfo", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(options?.build ? { build: true } : {}),
        });
        return data ?? { emitSkipped: true };
    }
    /**
     * Get suggestion diagnostics for a specific file or all files.
     * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
     */
    getSuggestionDiagnostics(file) {
        const data = this.client.apiRequest("getSuggestionDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(file !== undefined ? { file } : {}),
        });
        return data ?? [];
    }
    /**
     * Get declaration emit diagnostics for a specific file or all files.
     * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
     */
    getDeclarationDiagnostics(file) {
        const data = this.client.apiRequest("getDeclarationDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
            ...(file !== undefined ? { file } : {}),
        });
        return data ?? [];
    }
    /**
     * Get program-wide diagnostics for the project, including compiler options diagnostics.
     */
    getProgramDiagnostics() {
        const data = this.client.apiRequest("getProgramDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /**
     * Get global (non-file-specific) semantic diagnostics for the project.
     */
    getGlobalDiagnostics() {
        const data = this.client.apiRequest("getGlobalDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /**
     * Get config file parsing diagnostics for the project.
     */
    getConfigFileParsingDiagnostics() {
        const data = this.client.apiRequest("getConfigFileParsingDiagnostics", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ?? [];
    }
    /** Effective compiler options for a file (project-reference redirect aware). */
    getCompilerOptionsForFile(file) {
        return this.client.apiRequest("getCompilerOptionsForFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        }) ?? undefined;
    }
    getImpliedNodeFormatForEmit(file) {
        const data = this.client.apiRequest("getImpliedNodeFormatForEmit", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        return data?.mode ?? undefined;
    }
    getDefaultResolutionModeForFile(file) {
        const data = this.client.apiRequest("getDefaultResolutionModeForFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        return data?.mode ?? undefined;
    }
    getEmitModuleFormatOfFile(file) {
        const data = this.client.apiRequest("getEmitModuleFormatOfFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        return data?.kind ?? 0;
    }
    getModeForUsageLocation(file, position) {
        const data = this.client.apiRequest("getModeForUsageLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            position,
        });
        return data?.mode ?? undefined;
    }
    getEmitSyntaxForUsageLocation(file, position) {
        const data = this.client.apiRequest("getEmitSyntaxForUsageLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            position,
        });
        return data?.mode ?? undefined;
    }
    getRedirectTargets(file) {
        const data = this.client.apiRequest("getRedirectTargets", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        return data?.targets ?? [];
    }
}
export class Checker {
    snapshotId;
    project;
    client;
    objectRegistry;
    wellKnownSymbols;
    constructor(snapshotId, project, client, objectRegistry) {
        this.snapshotId = snapshotId;
        this.project = project;
        this.client = client;
        this.objectRegistry = objectRegistry;
    }
    dispose() {
        this.objectRegistry.clear();
    }
    /**
     * Lightweight ambient-module index (module names + symbols only — no exports).
     * Symbols are registered in the object registry as light prefetch entries.
     */
    getAmbientModules() {
        const data = this.client.apiRequest("getAmbientModules", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        if (!data?.modules?.length) {
            return { modules: [] };
        }
        const toSymbol = (wire) => this.objectRegistry.getOrCreateSymbol(wire);
        return {
            modules: data.modules.map(mod => ({
                moduleName: mod.moduleName,
                moduleSymbol: toSymbol(mod.moduleSymbol),
            })),
        };
    }
    /**
     * Auto-import export index for every external/ambient module in one batch,
     * mirroring stock exportInfoMap populate. Symbols are registered in the
     * object registry as light prefetch entries (declarations fetched lazily).
     */
    getModuleExportMap(importingFile) {
        const data = this.client.apiRequest("getModuleExportMap", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file: importingFile,
        });
        if (!data?.modules?.length) {
            return { modules: [] };
        }
        const toSymbol = (wire) => this.objectRegistry.getOrCreateSymbol(wire);
        const modules = data.modules.map(mod => ({
            moduleFileName: mod.moduleFileName,
            moduleName: mod.moduleName,
            moduleSymbol: toSymbol(mod.moduleSymbol),
            importableFrom: mod.importableFrom,
            defaultExport: mod.defaultExport ? {
                symbol: toSymbol(mod.defaultExport.symbol),
                tableKey: mod.defaultExport.tableKey,
                exportKind: mod.defaultExport.exportKind,
                targetFlags: mod.defaultExport.targetFlags,
            } : undefined,
            namedExports: mod.namedExports.map(exp => ({
                symbol: toSymbol(exp.symbol),
                key: exp.key,
                targetFlags: exp.targetFlags,
            })),
        }));
        return { modules };
    }
    /**
     * Batch-resolve auto-import module specifiers for many module symbols in
     * one RPC, mirroring stock getModuleSpecifiersWithCacheInfo.
     */
    getModuleSpecifiersBatch(file, moduleSymbols, preferences) {
        if (moduleSymbols.length === 0) {
            return { results: [] };
        }
        const data = this.client.apiRequest("getModuleSpecifiersBatch", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            moduleSymbols: moduleSymbols.map(sym => sym.id),
            preferences,
        });
        if (!data?.results?.length) {
            return { results: [] };
        }
        return {
            results: data.results.map(entry => ({
                moduleSymbol: this.objectRegistry.getSymbol(entry.moduleSymbol)
                    ?? this.objectRegistry.getOrCreateSymbol({ id: entry.moduleSymbol, name: "", flags: 0, checkFlags: 0 }),
                kind: entry.kind,
                moduleSpecifiers: entry.moduleSpecifiers,
            })),
        };
    }
    getSymbolAtLocation(nodeOrNodes) {
        if (Array.isArray(nodeOrNodes)) {
            const data = this.client.apiRequest("getSymbolsAtLocations", {
                snapshot: this.snapshotId,
                project: this.project.id,
                locations: nodeOrNodes.map(node => getNodeId(node)),
            });
            return data.map(d => d ? this.objectRegistry.getOrCreateSymbol(d) : undefined);
        }
        const data = this.client.apiRequest("getSymbolAtLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(nodeOrNodes),
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSymbolAtPosition(file, positionOrPositions) {
        if (typeof positionOrPositions === "number") {
            const data = this.client.apiRequest("getSymbolAtPosition", {
                snapshot: this.snapshotId,
                project: this.project.id,
                file,
                position: positionOrPositions,
            });
            return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
        }
        const data = this.client.apiRequest("getSymbolsAtPositions", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            positions: positionOrPositions,
        });
        return data.map(d => d ? this.objectRegistry.getOrCreateSymbol(d) : undefined);
    }
    getTypeOfSymbol(symbolOrSymbols) {
        if (Array.isArray(symbolOrSymbols)) {
            const data = this.client.apiRequest("getTypesOfSymbols", {
                snapshot: this.snapshotId,
                project: this.project.id,
                symbols: symbolOrSymbols.map(s => s.id),
            });
            return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
        }
        const data = this.client.apiRequest("getTypeOfSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbolOrSymbols.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    /**
     * Get the declared type of a symbol. Always returns a type; for symbols whose
     * declared type cannot be determined the checker yields the error type (use
     * {@link Type.isErrorType} to detect it).
     */
    getDeclaredTypeOfSymbol(symbol) {
        const data = this.client.apiRequest("getDeclaredTypeOfSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        if (!data)
            throw new Error(`getDeclaredTypeOfSymbol returned no type for symbol ${symbol.id}`);
        return this.objectRegistry.getOrCreateType(data);
    }
    getReferencesToSymbolInFile(file, symbol) {
        const data = this.client.apiRequest("getReferencesToSymbolInFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            symbol: symbol.id,
        });
        return (data ?? []).map(h => new NodeHandle(h, this.project));
    }
    getReferencedSymbolsForNode(node, position) {
        const data = this.client.apiRequest("getReferencedSymbolsForNode", {
            snapshot: this.snapshotId,
            project: this.project.id,
            node: getNodeId(node),
            position,
        });
        return (data ?? []).map(entry => ({
            definition: new NodeHandle(entry.definition, this.project),
            symbol: entry.symbol ? this.objectRegistry.getOrCreateSymbol(entry.symbol) : undefined,
            references: (entry.references ?? []).map(h => new NodeHandle(h, this.project)),
        }));
    }
    getSignatureUsage(signatureDecl) {
        const data = this.client.apiRequest("getSignatureUsages", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signatureDecl: getNodeId(signatureDecl),
        });
        return (data ?? []).map(entry => ({
            name: new NodeHandle(entry.name, this.project),
            call: entry.call ? new NodeHandle(entry.call, this.project) : undefined,
        }));
    }
    getCompletionsAtPosition(document, position, options) {
        const data = this.client.apiRequest("getCompletionsAtPosition", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file: document,
            position,
            triggerCharacter: options?.triggerCharacter,
            includeSymbol: options?.includeSymbol,
        });
        if (!data)
            return undefined;
        return {
            isIncomplete: data.isIncomplete,
            entries: data.entries.map(e => ({
                ...e,
                symbol: e.symbol ? this.objectRegistry.getOrCreateSymbol(e.symbol) : undefined,
            })),
        };
    }
    getTypeAtLocation(nodeOrNodes) {
        if (Array.isArray(nodeOrNodes)) {
            const data = this.client.apiRequest("getTypeAtLocations", {
                snapshot: this.snapshotId,
                project: this.project.id,
                locations: nodeOrNodes.map(node => getNodeId(node)),
            });
            return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
        }
        const data = this.client.apiRequest("getTypeAtLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(nodeOrNodes),
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getSignaturesOfType(type, kind) {
        const data = this.client.apiRequest("getSignaturesOfType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            kind,
        });
        return data.map(d => this.objectRegistry.getOrCreateSignature(d));
    }
    getResolvedSignature(node) {
        const data = this.client.apiRequest("getResolvedSignature", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateSignature(data) : undefined;
    }
    /**
     * Signature-help resolution (CheckMode.IsForSignatureHelp + cache clear).
     * Returns {resolved, candidates}; argumentCount undefined → sentinel -1.
     */
    getResolvedSignatureForSignatureHelp(node, argumentCount) {
        const data = this.client.apiRequest("getResolvedSignatureForSignatureHelp", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            argumentCount: argumentCount === undefined ? -1 : argumentCount,
        });
        if (!data)
            return { resolved: undefined, candidates: [] };
        return {
            resolved: data.resolved ? this.objectRegistry.getOrCreateSignature(data.resolved) : undefined,
            candidates: (data.candidates ?? []).map(c => this.objectRegistry.getOrCreateSignature(c)),
        };
    }
    getExpandedParameters(signature, skipUnionExpanding) {
        const groups = this.client.apiRequest("getExpandedParameters", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            skipUnionExpanding: !!skipUnionExpanding,
        });
        if (!groups?.length)
            return [];
        return groups.map(ids => {
            const syms = this.objectRegistry.materializeSymbols(ids);
            return syms.map((s, i) => {
                if (!s)
                    throw new Error(`getExpandedParameters: missing symbol ${ids[i]}`);
                return s;
            });
        });
    }
    hasEffectiveRestParameter(signature) {
        return this.client.apiRequest("hasEffectiveRestParameter", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
        });
    }
    symbolToParameterDeclaration(symbol, enclosingDeclaration, flags) {
        const binaryData = this.client.apiRequestBinary("symbolToParameterDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) {
        const data = this.client.apiRequest("getLocalTypeParametersOfClassOrInterfaceOrTypeAlias", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        if (!data?.length)
            return undefined;
        return data.map(d => this.objectRegistry.getOrCreateType(d));
    }
    getContextualTypeForObjectLiteralElement(element, contextFlags) {
        const data = this.client.apiRequest("getContextualTypeForObjectLiteralElement", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(element),
            contextFlags: contextFlags ?? 0,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    isOptionalParameter(node) {
        return !!this.client.apiRequest("isOptionalParameter", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
    }
    isImplementationOfOverload(node) {
        return !!this.client.apiRequest("isImplementationOfOverload", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
    }
    getTypeAtPosition(file, positionOrPositions) {
        if (typeof positionOrPositions === "number") {
            const data = this.client.apiRequest("getTypeAtPosition", {
                snapshot: this.snapshotId,
                project: this.project.id,
                file,
                position: positionOrPositions,
            });
            return data ? this.objectRegistry.getOrCreateType(data) : undefined;
        }
        const data = this.client.apiRequest("getTypesAtPositions", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
            positions: positionOrPositions,
        });
        return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
    }
    getSymbolsInScope(location, meaning) {
        // dedup: scope results are dominated by globals identical across every
        // location — the server sends a full payload once per snapshot and bare
        // ids afterwards; the snapshot registry retains the materialized
        // symbols, so `known` ids always resolve locally.
        const data = this.client.apiRequest("getSymbolsInScope", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(location),
            meaning,
            dedup: true,
        });
        if (!data)
            return [];
        const result = [];
        if (data.symbols) {
            for (const d of data.symbols)
                result.push(this.objectRegistry.getOrCreateSymbol(d));
        }
        if (data.known) {
            // A "known" id can be missing locally when a JS Snapshot was
            // re-created for an unchanged server snapshot (same handle, same
            // server-side sent-set, fresh client registry). Batch-fetch the
            // full payloads for those in one registry-only RPC.
            let missing;
            for (const id of data.known) {
                const sym = this.objectRegistry.getSymbol(id);
                if (sym)
                    result.push(sym);
                else
                    (missing ??= []).push(id);
            }
            if (missing) {
                for (const sym of this.objectRegistry.materializeSymbols(missing)) {
                    if (sym)
                        result.push(sym);
                }
            }
        }
        return result;
    }
    resolveName(name, meaning, location, excludeGlobals) {
        // Distinguish Node (has `kind`) from DocumentPosition (has `document` and `position`)
        const isNode = location && "kind" in location;
        const data = this.client.apiRequest("resolveName", {
            snapshot: this.snapshotId,
            project: this.project.id,
            name,
            meaning,
            location: isNode ? getNodeId(location) : undefined,
            file: !isNode && location ? location.document : undefined,
            position: !isNode && location ? location.position : undefined,
            excludeGlobals,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getResolvedSymbol(node) {
        const text = node.text;
        if (!text)
            return undefined;
        return this.resolveName(text, SymbolFlags.Value | SymbolFlags.ExportValue, node);
    }
    getContextualType(node, contextFlags) {
        const data = this.client.apiRequest("getContextualType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            contextFlags: contextFlags ?? 0,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getBaseTypeOfLiteralType(type) {
        const data = this.client.apiRequest("getBaseTypeOfLiteralType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getNonNullableType(type) {
        const data = this.client.apiRequest("getNonNullableType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getNonOptionalType(type) {
        const data = this.client.apiRequest("getNonOptionalType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getTypeFromTypeNode(node) {
        const data = this.client.apiRequest("getTypeFromTypeNode", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getWidenedType(type) {
        const data = this.client.apiRequest("getWidenedType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getParameterType(signature, index) {
        const data = this.client.apiRequest("getParameterType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            index,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    isArrayLikeType(type) {
        return this.client.apiRequest("isArrayLikeType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
    }
    isTypeAssignableTo(source, target) {
        return this.client.apiRequest("isTypeAssignableTo", {
            snapshot: this.snapshotId,
            project: this.project.id,
            source: source.id,
            target: target.id,
        });
    }
    getUnionType(types, unionReduction = 1) {
        if (types.length === 0) {
            return this.getNeverType();
        }
        if (types.length === 1) {
            return types[0];
        }
        const data = this.client.apiRequest("getUnionType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            types: types.map(t => t.id),
            unionReduction,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getPromisedTypeOfPromise(type) {
        const data = this.client.apiRequest("getPromisedTypeOfPromise", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getAllPossiblePropertiesOfTypes(types) {
        if (!types.length) {
            return [];
        }
        const data = this.client.apiRequest("getAllPossiblePropertiesOfTypes", {
            snapshot: this.snapshotId,
            project: this.project.id,
            types: types.map(t => t.id),
        });
        return (data ?? []).map(d => d ? this.objectRegistry.getOrCreateSymbol(d) : undefined).filter((s) => !!s);
    }
    isTypeInvalidDueToUnionDiscriminant(type, node) {
        return !!this.client.apiRequest("isTypeInvalidDueToUnionDiscriminant", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            location: getNodeId(node),
        });
    }
    typeHasCallOrConstructSignatures(type) {
        return !!this.client.apiRequest("typeHasCallOrConstructSignatures", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
    }
    /**
     * Composite RPC: runs the stock Completions.getPropertiesForObjectExpression
     * pipeline server-side in one round trip and returns every intermediate
     * verdict so callers can answer the per-member checker calls from cache.
     */
    getPropertiesForObjectExpression(contextualType, completionsType, location) {
        const data = this.client.apiRequest("getPropertiesForObjectExpression", {
            snapshot: this.snapshotId,
            project: this.project.id,
            contextualType: contextualType.id,
            completionsType: completionsType?.id,
            location: getNodeId(location),
        });
        if (!data)
            return undefined;
        const toType = (t) => this.objectRegistry.getOrCreateType(t);
        const toSymbols = (symbols) => (symbols ?? []).map(s => this.objectRegistry.getOrCreateSymbol(s));
        const finalMembers = (data.finalMembers ?? []).map(m => ({
            type: toType(m.type),
            isArrayLike: !!m.isArrayLike,
            invalidDueToUnionDiscriminant: !!m.invalidDueToUnionDiscriminant,
            hasCallOrConstructSignatures: !!m.hasCallOrConstructSignatures,
            apparentProperties: m.apparentProperties ? toSymbols(m.apparentProperties) : undefined,
        }));
        const finalMemberById = new Map(finalMembers.map(m => [m.type.id, m.type]));
        return {
            members: data.members.map(m => ({
                type: toType(m.type),
                promisedType: m.promisedType ? toType(m.promisedType) : undefined,
            })),
            promiseFilteredType: toType(data.promiseFilteredType),
            mergedType: data.mergedType ? toType(data.mergedType) : undefined,
            finalMembers,
            filteredTypes: (data.filteredTypes ?? []).map(id => finalMemberById.get(id)).filter((t) => !!t),
            properties: toSymbols(data.properties),
        };
    }
    getShorthandAssignmentValueSymbol(node) {
        const data = this.client.apiRequest("getShorthandAssignmentValueSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    /**
     * Get the type of a symbol as narrowed at a specific location. Always returns
     * a type; for symbols whose type cannot be determined the checker yields the
     * error type (use {@link Type.isErrorType} to detect it).
     */
    getTypeOfSymbolAtLocation(symbol, location) {
        const data = this.client.apiRequest("getTypeOfSymbolAtLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            location: getNodeId(location),
        });
        if (!data)
            throw new Error(`getTypeOfSymbolAtLocation returned no type for symbol ${symbol.id}`);
        return this.objectRegistry.getOrCreateType(data);
    }
    getIntrinsicType(method) {
        const data = this.client.apiRequest(method, {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return this.objectRegistry.getOrCreateType(data);
    }
    getAnyType() {
        return this.getIntrinsicType("getAnyType");
    }
    getErrorType() {
        return this.getIntrinsicType("getErrorType");
    }
    getPromiseType() {
        return this.getIntrinsicType("getPromiseType");
    }
    getPromiseLikeType() {
        return this.getIntrinsicType("getPromiseLikeType");
    }
    getAnyAsyncIterableType() {
        const data = this.client.apiRequest("getAnyAsyncIterableType", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getStringType() {
        return this.getIntrinsicType("getStringType");
    }
    getNumberType() {
        return this.getIntrinsicType("getNumberType");
    }
    getBooleanType() {
        return this.getIntrinsicType("getBooleanType");
    }
    getVoidType() {
        return this.getIntrinsicType("getVoidType");
    }
    getUndefinedType() {
        return this.getIntrinsicType("getUndefinedType");
    }
    getNullType() {
        return this.getIntrinsicType("getNullType");
    }
    getNeverType() {
        return this.getIntrinsicType("getNeverType");
    }
    getUnknownType() {
        return this.getIntrinsicType("getUnknownType");
    }
    getBigIntType() {
        return this.getIntrinsicType("getBigIntType");
    }
    getESSymbolType() {
        return this.getIntrinsicType("getESSymbolType");
    }
    typeToTypeNode(type, enclosingDeclaration, flags) {
        const binaryData = this.client.apiRequestBinary("typeToTypeNode", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    typeParameterToDeclaration(type, enclosingDeclaration, flags) {
        const binaryData = this.client.apiRequestBinary("typeParameterToDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    symbolToTypeParameterDeclarations(symbol, enclosingDeclaration, flags) {
        const encoded = this.client.apiRequest("symbolToTypeParameterDeclarations", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!encoded?.length)
            return [];
        return encoded.map(data => decodeNode(new Uint8Array(Buffer.from(data, "base64"))));
    }
    signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags) {
        const binaryData = this.client.apiRequestBinary("signatureToSignatureDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            kind,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    signatureToString(signature, enclosingDeclaration, flags) {
        return this.client.apiRequest("signatureToString", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
    }
    typeToString(type, enclosingDeclaration, flags) {
        return this.client.apiRequest("typeToString", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
    }
    isContextSensitive(node) {
        return this.client.apiRequest("isContextSensitive", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
    }
    isArrayType(type) {
        return this.client.apiRequest("isArrayType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
    }
    isTupleType(type) {
        return this.client.apiRequest("isTupleType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
    }
    isDeclarationVisible(node) {
        return !!this.client.apiRequest("isDeclarationVisible", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
    }
    tryGetThisTypeAt(node, includeGlobalThis = true, container) {
        const data = this.client.apiRequest("tryGetThisTypeAt", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            includeGlobalThis,
            container: container ? getNodeId(container) : undefined,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    isValidPropertyAccessForCompletions(node, type, property) {
        return !!this.client.apiRequest("isValidPropertyAccessForCompletions", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            type: type.id,
            symbol: property.id,
        });
    }
    getTypeArgumentConstraint(node) {
        const data = this.client.apiRequest("getTypeArgumentConstraint", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getExportsAndPropertiesOfModule(moduleSymbol) {
        const data = this.client.apiRequest("getExportsAndPropertiesOfModule", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: moduleSymbol.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getJsxIntrinsicTagNamesAt(location) {
        const data = this.client.apiRequest("getJsxIntrinsicTagNamesAt", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(location),
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    isPropertyAccessible(node, isSuper, isWrite, containingType, property) {
        return !!this.client.apiRequest("isPropertyAccessible", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            isSuper,
            isWrite,
            type: containingType.id,
            symbol: property.id,
        });
    }
    getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing) {
        const data = this.client.apiRequest("getAccessibleSymbolChain", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            enclosingDeclaration: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            meaning,
            useOnlyExternalAliasing,
        });
        // Stock: no chain → undefined (not []). Wire may yield null or [].
        if (!data?.length)
            return undefined;
        return data.map(d => this.objectRegistry.getOrCreateSymbol(d));
    }
    getContextualTypeForArgumentAtIndex(callTarget, argIndex) {
        const data = this.client.apiRequest("getContextualTypeForArgumentAtIndex", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(callTarget),
            argIndex,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getContextualTypeForJsxAttribute(attribute) {
        const data = this.client.apiRequest("getContextualTypeForJsxAttribute", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(attribute),
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    isValidPropertyAccess(node, propertyName) {
        return !!this.client.apiRequest("isValidPropertyAccess", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
            propertyName,
        });
    }
    getCandidateSignaturesForStringLiteralCompletions(call, editingArgument) {
        const data = this.client.apiRequest("getCandidateSignaturesForStringLiteralCompletions", {
            snapshot: this.snapshotId,
            project: this.project.id,
            call: getNodeId(call),
            editingArgument: getNodeId(editingArgument),
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSignature(d)) : [];
    }
    getSymbolsOfParameterPropertyDeclaration(parameter, parameterName) {
        const data = this.client.apiRequest("getSymbolsOfParameterPropertyDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(parameter),
            parameterName,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getAwaitedType(type) {
        const data = this.client.apiRequest("getAwaitedType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getNullableType(type, flags) {
        const data = this.client.apiRequest("getNullableType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id, flags,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    isNullableType(type) {
        return !!this.client.apiRequest("isNullableType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
    }
    getElementTypeOfArrayType(type) {
        const data = this.client.apiRequest("getElementTypeOfArrayType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getIndexInfoOfType(type, kind) {
        const data = this.client.apiRequest("getIndexInfoOfType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id, kind,
        });
        return data ? this.materializeIndexInfo(data) : undefined;
    }
    getIndexTypeOfType(type, kind) {
        const data = this.client.apiRequest("getIndexTypeOfType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id, kind,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getTypeOfPropertyOfType(type, name) {
        const data = this.client.apiRequest("getTypeOfPropertyOfType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id, name,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getTypeOfPropertyOfContextualType(type, name) {
        const data = this.client.apiRequest("getTypeOfPropertyOfContextualType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id, name,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    fillMissingTypeArguments(typeArguments, typeParameters, minTypeArgumentCount, isJavaScriptImplicitAny) {
        const data = this.client.apiRequest("fillMissingTypeArguments", {
            snapshot: this.snapshotId,
            project: this.project.id,
            typeArguments: typeArguments.map(t => t.id),
            typeParameters: (typeParameters ?? []).map(t => t.id),
            minTypeArgumentCount,
            isJavaScriptImplicitAny,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
    }
    getWidenedLiteralType(type) {
        const data = this.client.apiRequest("getWidenedLiteralType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties) {
        const data = this.client.apiRequest("getUnmatchedProperties", {
            snapshot: this.snapshotId,
            project: this.project.id,
            source: source.id,
            target: target.id,
            requireOptionalProperties,
            matchDiscriminantProperties,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    isEmptyAnonymousObjectType(type) {
        return !!this.client.apiRequest("isEmptyAnonymousObjectType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
    }
    isLibType(type) {
        return !!this.client.apiRequest("isLibType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
    }
    symbolIsValue(symbol) {
        return !!this.client.apiRequest("symbolIsValue", {
            snapshot: this.snapshotId, project: this.project.id, symbol: symbol.id,
        });
    }
    requiresAddingImplicitUndefined(node) {
        return !!this.client.apiRequest("requiresAddingImplicitUndefined", {
            snapshot: this.snapshotId, project: this.project.id, location: getNodeId(node),
        });
    }
    getTypeOnlyAliasDeclaration(symbol) {
        const data = this.client.apiRequest("getTypeOnlyAliasDeclaration", {
            snapshot: this.snapshotId, project: this.project.id, symbol: symbol.id,
        });
        return data ? new NodeHandle(data, this.project) : undefined;
    }
    resolveExternalModuleName(moduleSpecifier) {
        const data = this.client.apiRequest("resolveExternalModuleName", {
            snapshot: this.snapshotId, project: this.project.id, location: getNodeId(moduleSpecifier),
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getPropertySymbolOfDestructuringAssignment(location) {
        const data = this.client.apiRequest("getPropertySymbolOfDestructuringAssignment", {
            snapshot: this.snapshotId, project: this.project.id, location: getNodeId(location),
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSuggestedSymbolForNonexistentProperty(name, containingType) {
        const data = this.client.apiRequest("getSuggestedSymbolForNonexistentProperty", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(name),
            type: containingType.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSuggestedSymbolForNonexistentClassMember(name, baseType) {
        const data = this.client.apiRequest("getSuggestedSymbolForNonexistentClassMember", {
            snapshot: this.snapshotId,
            project: this.project.id,
            name,
            type: baseType.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSuggestedSymbolForNonexistentJSXAttribute(name, containingType) {
        const data = this.client.apiRequest("getSuggestedSymbolForNonexistentJSXAttribute", {
            snapshot: this.snapshotId,
            project: this.project.id,
            name,
            type: containingType.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSuggestedSymbolForNonexistentModule(name, targetModule) {
        const data = this.client.apiRequest("getSuggestedSymbolForNonexistentModule", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(name),
            symbol: targetModule.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getSuggestedSymbolForNonexistentSymbol(location, name, meaning) {
        const data = this.client.apiRequest("getSuggestedSymbolForNonexistentSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(location),
            name,
            meaning,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    symbolToExpression(symbol, meaning, enclosingDeclaration, flags, internalFlags) {
        const binaryData = this.client.apiRequestBinary("symbolToExpression", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            meaning,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
            internalFlags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    symbolToNode(symbol, meaning, enclosingDeclaration, flags, internalFlags) {
        const binaryData = this.client.apiRequestBinary("symbolToNode", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            meaning,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
            internalFlags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    symbolToEntityName(symbol, meaning, enclosingDeclaration, flags, internalFlags) {
        const binaryData = this.client.apiRequestBinary("symbolToEntityName", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            meaning,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
            internalFlags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    typePredicateToTypePredicateNode(predicate, enclosingDeclaration, flags) {
        const binaryData = this.client.apiRequestBinary("typePredicateToTypePredicateNode", {
            snapshot: this.snapshotId,
            project: this.project.id,
            kind: predicate.kind,
            parameterIndex: predicate.parameterIndex ?? 0,
            parameterName: predicate.parameterName,
            type: predicate.type?.id,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    indexInfoToIndexSignatureDeclaration(info, enclosingDeclaration, flags) {
        const declaration = info.declaration;
        let declarationHandle;
        if (declaration) {
            if (typeof declaration.index === "number" && declaration.path != null
                && typeof declaration.id !== "string") {
                const h = declaration;
                declarationHandle = `${h.index}.${h.kind}.${h.path}`;
            }
            else {
                declarationHandle = getNodeId(declaration);
            }
        }
        const binaryData = this.client.apiRequestBinary("indexInfoToIndexSignatureDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            keyType: info.keyType.id,
            valueType: info.type?.id ?? info.valueType.id,
            isReadonly: info.isReadonly,
            declaration: declarationHandle,
            location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            flags,
        });
        if (!binaryData)
            return undefined;
        return decodeNode(binaryData);
    }
    getExactOptionalProperties(type) {
        const data = this.client.apiRequest("getExactOptionalProperties", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getJsxNamespace(location) {
        const data = this.client.apiRequest("getJsxNamespace", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: location ? getNodeId(location) : undefined,
        });
        return data ?? "";
    }
    getJsxFragmentFactory(location) {
        const data = this.client.apiRequest("getJsxFragmentFactory", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(location),
        });
        return data ?? "";
    }
    getParameterIdentifierInfoAtPosition(signature, position) {
        const data = this.client.apiRequest("getParameterIdentifierInfoAtPosition", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
            position,
        });
        if (!data)
            return undefined;
        return {
            parameter: data.parameter ? new NodeHandle(data.parameter, this.project) : undefined,
            parameterName: data.parameterName,
            isRestParameter: !!data.isRestParameter,
        };
    }
    createArrayType(elementType) {
        const data = this.client.apiRequest("createArrayType", {
            snapshot: this.snapshotId, project: this.project.id, type: elementType.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    createPromiseType(promisedType) {
        const data = this.client.apiRequest("createPromiseType", {
            snapshot: this.snapshotId, project: this.project.id, type: promisedType.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    createTransientSymbolWithType(flags, name, type) {
        const data = this.client.apiRequest("createTransientSymbolWithType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            flags,
            name,
            type: type?.id,
        });
        return this.objectRegistry.getOrCreateSymbol(data);
    }
    createSignatureFromParts(parameters, returnType, minArgumentCount, flags, typeParameters, thisParameter) {
        const data = this.client.apiRequest("createSignatureFromParts", {
            snapshot: this.snapshotId,
            project: this.project.id,
            parameters: parameters.map(p => p.id),
            returnType: returnType.id,
            minArgumentCount,
            flags,
            typeParameters: typeParameters?.length ? typeParameters.map(t => t.id) : undefined,
            thisParameter: thisParameter?.id,
        });
        return this.objectRegistry.getOrCreateSignature(data);
    }
    createAnonymousTypeFromParts(symbol, members, callSignatures, constructSignatures, indexInfos) {
        const data = this.client.apiRequest("createAnonymousTypeFromParts", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol?.id,
            members: members.map(m => m.id),
            callSignatures: callSignatures.map(s => s.id),
            constructSignatures: constructSignatures.map(s => s.id),
            indexInfos: indexInfos.map(i => ({
                keyType: i.keyType.id,
                valueType: i.valueType.id,
                isReadonly: !!i.isReadonly,
            })),
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getMemberOverrideModifierStatus(classLike, symbol, memberHasOverride, memberHasAbstract, memberIsStatic, memberHasName) {
        return this.client.apiRequest("getMemberOverrideModifierStatus", {
            snapshot: this.snapshotId,
            project: this.project.id,
            classLike: getNodeId(classLike),
            symbol: symbol.id,
            memberHasOverride,
            memberHasAbstract,
            memberIsStatic,
            memberHasName,
        }) ?? 0;
    }
    getSymbolOfExpando(location, allowDeclaration) {
        const data = this.client.apiRequest("getSymbolOfExpando", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(location),
            allowDeclaration,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    collectVisitedTypeParameters(type) {
        const data = this.client.apiRequest("collectVisitedTypeParameters", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
    }
    isSymbolAccessible(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible) {
        const data = this.client.apiRequest("isSymbolAccessible", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            enclosingDeclaration: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
            meaning,
            shouldComputeAliasesToMakeVisible,
        });
        return data ?? { accessibility: 0 };
    }
    getIndexInfosOfIndexSymbol(indexSymbol, siblingSymbols) {
        const data = this.client.apiRequest("getIndexInfosOfIndexSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: indexSymbol.id,
            siblingSymbols: siblingSymbols?.map(s => s.id),
        });
        if (!data)
            return [];
        return data.map(d => this.materializeIndexInfo(d));
    }
    containsArgumentsReference(node) {
        return !!this.client.apiRequest("containsArgumentsReference", {
            snapshot: this.snapshotId, project: this.project.id, location: getNodeId(node),
        });
    }
    getAugmentedPropertiesOfType(type) {
        const data = this.client.apiRequest("getAugmentedPropertiesOfType", {
            snapshot: this.snapshotId, project: this.project.id, type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getReturnTypeOfSignature(signature) {
        const data = this.client.apiRequest("getReturnTypeOfSignature", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getRestTypeOfSignature(signature) {
        const data = this.client.apiRequest("getRestTypeOfSignature", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getTypePredicateOfSignature(signature) {
        const data = this.client.apiRequest("getTypePredicateOfSignature", {
            snapshot: this.snapshotId,
            project: this.project.id,
            signature: signature.id,
        });
        if (!data)
            return undefined;
        return {
            kind: data.kind,
            parameterIndex: data.parameterIndex,
            parameterName: data.parameterName,
            type: data.type ? this.objectRegistry.getOrCreateType(data.type) : undefined,
        };
    }
    /**
     * Get the base types of a class or interface type. A type with no base types
     * yields an empty array.
     */
    getBaseTypes(type) {
        const data = this.client.apiRequest("getBaseTypes", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
    }
    getApparentType(type) {
        const data = this.client.apiRequest("getApparentType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getPropertiesOfType(type) {
        const data = this.client.apiRequest("getPropertiesOfType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getIndexInfosOfType(type) {
        const data = this.client.apiRequest("getIndexInfosOfType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        if (!data)
            return [];
        return data.map(d => this.materializeIndexInfo(d));
    }
    /**
     * Index infos applicable at a property-access name (stock getIndexInfosAtLocation).
     * Non-PA-name → undefined; PA-name with no matches → [].
     */
    getIndexInfosAtLocation(node) {
        const data = this.client.apiRequest("getIndexInfosAtLocation", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        if (data == null)
            return undefined;
        return data.map(d => this.materializeIndexInfo(d));
    }
    /** Attach declaration.symbol from wire (RemoteNode AST omits binder symbols). */
    materializeIndexInfo(d) {
        const declaration = d.declaration ? new NodeHandle(d.declaration, this.project) : undefined;
        const wireSym = d.symbol;
        if (declaration && wireSym) {
            const sym = this.objectRegistry.getOrCreateSymbol(wireSym);
            Object.defineProperty(declaration, "symbol", { value: sym, configurable: true });
        }
        return {
            keyType: this.objectRegistry.getOrCreateType(d.keyType),
            valueType: this.objectRegistry.getOrCreateType(d.valueType),
            isReadonly: d.isReadonly ?? false,
            declaration,
        };
    }
    /**
     * Get the constraint of a type parameter (the `T` in `<U extends T>`), or
     * undefined if it has none.
     */
    getConstraintOfTypeParameter(type) {
        const data = this.client.apiRequest("getConstraintOfTypeParameter", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getBaseConstraintOfType(type) {
        const data = this.client.apiRequest("getBaseConstraintOfType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? this.objectRegistry.getOrCreateType(data) : undefined;
    }
    getPropertyOfType(type, name) {
        const data = this.client.apiRequest("getPropertyOfType", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
            name,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getConstantValue(node) {
        const data = this.client.apiRequest("getConstantValue", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ?? undefined;
    }
    getSignatureFromDeclaration(node) {
        const data = this.client.apiRequest("getSignatureFromDeclaration", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateSignature(data) : undefined;
    }
    getExportSpecifierLocalTargetSymbol(node) {
        const data = this.client.apiRequest("getExportSpecifierLocalTargetSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            location: getNodeId(node),
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    /**
     * Follow all aliases to get the original symbol. Always returns a symbol; for
     * an unresolved alias the checker yields the unknown symbol (use
     * {@link Checker.isUnknownSymbol} to detect it).
     */
    getAliasedSymbol(symbol) {
        const data = this.client.apiRequest("getAliasedSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        if (!data)
            throw new Error(`getAliasedSymbol returned no symbol for symbol ${symbol.id}`);
        return this.objectRegistry.getOrCreateSymbol(data);
    }
    getImmediateAliasedSymbol(symbol) {
        const data = this.client.apiRequest("getImmediateAliasedSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    /**
     * Fetch (once, then cache) the handle ids of the per-checker singleton
     * symbols (unknown, undefined, arguments). These ids are stable for the life
     * of the project's checker, so identity checks against them are local after
     * the first call.
     */
    getWellKnownSymbols() {
        return this.wellKnownSymbols ??= this.client.apiRequest("getWellKnownSymbols", {
            snapshot: this.snapshotId,
            project: this.project.id,
        });
    }
    /**
     * Returns `true` if the symbol is the checker's "unknown" symbol (e.g. the
     * result of {@link Checker.getAliasedSymbol} on an unresolved alias).
     */
    isUnknownSymbol(symbol) {
        return symbol.id === (this.getWellKnownSymbols()).unknown;
    }
    /**
     * Returns `true` if the symbol is the checker's "undefined" symbol.
     */
    isUndefinedSymbol(symbol) {
        return symbol.id === (this.getWellKnownSymbols()).undefined;
    }
    /**
     * Returns `true` if the symbol is the checker's "arguments" symbol.
     */
    isArgumentsSymbol(symbol) {
        return symbol.id === (this.getWellKnownSymbols()).arguments;
    }
    getExportsOfModule(symbol) {
        const data = this.client.apiRequest("getExportsOfModule", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getModuleSymbolForSourceFile(file) {
        const data = this.client.apiRequest("getModuleSymbolForSourceFile", {
            snapshot: this.snapshotId,
            project: this.project.id,
            file,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getRootSymbols(symbol) {
        const data = this.client.apiRequest("getRootSymbols", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
    }
    getMemberInModuleExports(symbol, name) {
        const data = this.client.apiRequest("getMemberInModuleExports", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
            name,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    resolveExternalModuleSymbol(symbol) {
        const data = this.client.apiRequest("resolveExternalModuleSymbol", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
    }
    getJsDocTagsOfSymbol(symbol) {
        const data = this.client.apiRequest("getJsDocTags", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
        return data ?? [];
    }
    getDocumentationCommentOfSymbol(symbol) {
        return this.client.apiRequest("getDocumentationComment", {
            snapshot: this.snapshotId,
            project: this.project.id,
            symbol: symbol.id,
        });
    }
    /**
     * Get the type arguments of a type reference (e.g. the `string` in `Array<string>`).
     */
    getTypeArguments(type) {
        const data = this.client.apiRequest("getTypeArguments", {
            snapshot: this.snapshotId,
            project: this.project.id,
            type: type.id,
        });
        return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
    }
}
export class Emitter {
    client;
    constructor(client) {
        this.client = client;
    }
    printNode(node, options = {}) {
        const encoded = encodeNode(node);
        const base64 = uint8ArrayToBase64(encoded);
        return this.client.apiRequest("printNode", {
            data: base64,
            ...options,
        });
    }
}
// Remaps a raw tsgo SyntaxKind to the consumer's SyntaxKind. The tsgo and
// fork (drop-in `typescript`) SyntaxKind enums diverge by ~180 values, so a
// NodeHandle's kind — parsed straight from the wire handle string as the RAW
// tsgo kind — must be remapped before `ts.isXxx(handle)` type-guards (which
// compare against fork kind values) can fire correctly. RemoteNode.kind is
// already remapped via a prototype getter, but NodeHandle.kind is a
// constructor-set own property, so the remap has to happen here at
// construction time. The fork installs the hook once its remap table is built
// (see setNodeHandleKindRemap); when unset, kind passes through unchanged.
let _nodeHandleKindRemap;
/**
 * Install a kind-remap function applied to every NodeHandle's `kind` at
 * construction. Pass `undefined` to clear. Idempotent.
 */
export function setNodeHandleKindRemap(remap) {
    _nodeHandleKindRemap = remap;
}
export class NodeHandle {
    /**
     * The project this handle was produced in, used as the default for {@link resolve}.
     * Node handles are only meaningful within a project's program, so the producing project
     * is remembered so callers don't have to pass it explicitly.
     */
    canonicalProject;
    index;
    kind;
    path;
    constructor(handle, canonicalProject) {
        const parsed = parseNodeHandle(handle);
        this.index = parsed.index;
        this.kind = (_nodeHandleKindRemap ? _nodeHandleKindRemap(parsed.kind) : parsed.kind);
        this.path = parsed.path;
        this.canonicalProject = canonicalProject;
    }
    /**
     * Resolve this handle to the actual AST node by fetching the source file from a project
     * and looking up the node by index. If no project is passed, the project that produced
     * the handle is used.
     */
    resolve(project = this.canonicalProject) {
        const sourceFile = project.program.getSourceFile(this.path);
        if (!sourceFile) {
            return undefined;
        }
        return sourceFile.getOrCreateNodeAtIndex(this.index);
    }
}
export class Symbol {
    objectRegistry;
    /**
     * The project this symbol was first observed in, used as the default project for
     * lookups that need a project context (members/exports/parent). Symbols are shared
     * snapshot-wide, so these lookups can otherwise be ambiguous about which project to use.
     */
    canonicalProject;
    id;
    /** The escaped (`__String`) name, used as the key in member/export tables. */
    escapedName;
    /** The display name (escaped underscores removed). */
    name;
    flags;
    checkFlags;
    /** Wire handle for the parent symbol; `.parent` resolves it lazily. */
    parentHandle;
    exportSymbol;
    membersCache;
    exportsCache;
    // Declarations are lazy: "light" symbols (getAmbientModules,
    // getModuleExportMap) carry only id/name/flags to keep the payload small,
    // so the wire data omits the declarations entirely. When a consumer reads
    // `.declarations`
    // / `.valueDeclaration` on such a symbol (e.g. the scope manager building
    // variable defs for no-func-assign), fetch the full set on demand by id.
    // Full responses (newSymbolResponse) include the declaration fields up front,
    // in which case no follow-up request is made.
    _declarations;
    _valueDeclaration;
    _declarationsResolved;
    constructor(data, objectRegistry) {
        this.objectRegistry = objectRegistry;
        this.id = data.id;
        this.escapedName = data.name;
        this.name = unescapeLeadingUnderscores(data.name);
        this.flags = data.flags;
        this.checkFlags = data.checkFlags;
        // Canonical project: full responses always carry it (server records the
        // first-observer project); TNB light payloads (ambient modules, export
        // map, scope dedup) may omit it, in which case node resolution falls
        // back to the registry's current project.
        this.canonicalProject = (data.project ? objectRegistry.getProject(data.project) : undefined);
        // A response that carries either declaration field is "full" — record
        // the declarations and skip the lazy fetch. A light response omits both;
        // defer until first access.
        if (data.declarations !== undefined || data.valueDeclaration !== undefined) {
            this._declarations = data.declarations !== undefined ? data.declarations.map(d => new NodeHandle(d, this.canonicalProject)) : undefined;
            this._valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration, this.canonicalProject) : undefined;
            this._declarationsResolved = true;
        }
        else {
            this._declarations = undefined;
            this._valueDeclaration = undefined;
            this._declarationsResolved = false;
        }
        if (data.parent !== undefined)
            this.parentHandle = data.parent;
        if (data.exportSymbol !== undefined)
            this.exportSymbol = data.exportSymbol;
    }
    /** @internal Upgrade parent handle when a fuller SymbolResponse arrives. */
    applyParentHandle(parent) {
        if (parent !== undefined && this.parentHandle === undefined) {
            this.parentHandle = parent;
        }
    }
    /**
     * Stock services read `.parent` as the owning Symbol object (e.g.
     * SymbolDisplay's "type parameter T in C<T>" / "Indexed.prop"). Resolve
     * the wire handle lazily; if the handle was omitted (light prefetch),
     * still call getParentOfSymbol via objectId.
     */
    get parent() {
        return this.objectRegistry.fetchSymbol(this, "getParentOfSymbol", this.parentHandle, this.canonicalProject?.id);
    }
    ensureDeclarations() {
        if (this._declarationsResolved)
            return;
        this._declarationsResolved = true;
        if (this._declarationStash !== undefined) {
            const data = this._declarationStash;
            this._declarationStash = undefined;
            this.applyDeclarationPayload(data);
            return;
        }
        // One lazy miss predicts a burst (services loops over export/member
        // lists read .declarations per symbol): prefetch payloads for the whole
        // registry's unresolved set in one batched RPC instead of N fetches.
        this.objectRegistry.stashAllUnresolvedDeclarations();
        if (this._declarationStash !== undefined) {
            const data = this._declarationStash;
            this._declarationStash = undefined;
            this.applyDeclarationPayload(data);
            return;
        }
        const data = this.objectRegistry.fetchSymbolDeclarations(this.id);
        this.applyDeclarationPayload(data);
    }
    /** @internal Payload prefetched by stashAllUnresolvedDeclarations; applied on first read. */
    _declarationStash;
    /** @internal */
    hasDeclarationStash() {
        return this._declarationStash !== undefined;
    }
    /** @internal Stash a batch-prefetched payload without marking resolution. */
    stashDeclarationPayload(data) {
        if (this._declarationsResolved)
            return;
        this._declarationStash = data;
    }
    /** @internal Used by batch hydrate after prefetch. */
    hasDeclarationsResolved() {
        return this._declarationsResolved;
    }
    /** @internal Apply full or empty declaration payload from RPC. */
    applyDeclarationPayload(data) {
        this._declarationsResolved = true;
        // Stock parity: a symbol with no declarations has `declarations:
        // undefined` (transient symbols), never an empty array — consumers
        // like @typescript-eslint/no-deprecated branch on undefined.
        this._declarations = data?.declarations !== undefined ? data.declarations.map(d => new NodeHandle(d, this.canonicalProject)) : undefined;
        this._valueDeclaration = data?.valueDeclaration ? new NodeHandle(data.valueDeclaration, this.canonicalProject) : undefined;
        if (data)
            this.applyParentHandle(data.parent);
    }
    get declarations() {
        this.ensureDeclarations();
        return this._declarations;
    }
    get valueDeclaration() {
        this.ensureDeclarations();
        return this._valueDeclaration;
    }
    getParent() {
        return this.parent;
    }
    /**
     * Get this symbol's members keyed by escaped name. The result is cached on
     * the symbol, so repeated calls do not round-trip to the server.
     */
    getMembers() {
        return this.membersCache ??= this.fetchSymbolTable("getMembersOfSymbol");
    }
    /**
     * Get this symbol's exports keyed by escaped name. The result is cached on
     * the symbol, so repeated calls do not round-trip to the server.
     */
    getExports() {
        return this.exportsCache ??= this.fetchSymbolTable("getExportsOfSymbol");
    }
    fetchSymbolTable(method) {
        const symbols = this.objectRegistry.fetchSymbols(this, method, undefined, this.canonicalProject?.id);
        const table = new Map();
        for (const symbol of symbols) {
            table.set(symbol.escapedName, symbol);
        }
        return table;
    }
    getExportSymbol() {
        if (!this.exportSymbol)
            return this;
        return this.objectRegistry.fetchSymbol(this, "getExportSymbolOfSymbol", this.exportSymbol, this.canonicalProject?.id);
    }
    getJsDocTags(checker) {
        return checker.getJsDocTagsOfSymbol(this);
    }
    getDocumentationComment(checker) {
        return checker.getDocumentationCommentOfSymbol(this);
    }
}
class TypeObject {
    objectRegistry;
    id;
    flags;
    objectFlags;
    // Wire handle; stock Type.symbol is a Symbol object. Resolve lazily.
    symbolHandle;
    value;
    intrinsicName;
    isThisType;
    freshType;
    regularType;
    target;
    typeParameters;
    outerTypeParameters;
    localTypeParameters;
    aliasTypeArguments;
    aliasSymbol;
    elementFlags;
    fixedLength;
    readonly;
    texts;
    objectType;
    indexType;
    checkType;
    extendsType;
    baseType;
    substConstraint;
    trueType; // false if not yet loaded
    falseType; // false if not yet loaded
    constructor(data, objectRegistry) {
        this.objectRegistry = objectRegistry;
        this.id = data.id;
        this.flags = data.flags;
        if (data.objectFlags !== undefined)
            this.objectFlags = data.objectFlags;
        if (data.symbol !== undefined)
            this.symbolHandle = data.symbol;
        if (data.value != null) {
            // BigInt literal values are serialized as decimal strings (e.g. "-123") because
            // JSON cannot represent bigint. Decode them back into a real bigint here.
            this.value = (data.flags & TypeFlags.BigIntLiteral) ? BigInt(data.value) : data.value;
        }
        if (data.intrinsicName !== undefined)
            this.intrinsicName = data.intrinsicName;
        if (data.isThisType !== undefined)
            this.isThisType = data.isThisType;
        if (data.freshType !== undefined)
            this.freshType = data.freshType;
        if (data.regularType !== undefined)
            this.regularType = data.regularType;
        if (data.target !== undefined)
            this.target = data.target;
        this.typeParameters = data.typeParameters ?? [];
        this.outerTypeParameters = data.outerTypeParameters ?? [];
        this.localTypeParameters = data.localTypeParameters ?? [];
        this.aliasTypeArguments = data.aliasTypeArguments ?? [];
        if (data.aliasSymbol !== undefined)
            this.aliasSymbol = data.aliasSymbol;
        if (data.elementFlags !== undefined)
            this.elementFlags = data.elementFlags;
        if (data.fixedLength !== undefined)
            this.fixedLength = data.fixedLength;
        if (data.readonly !== undefined)
            this.readonly = data.readonly;
        if (data.texts !== undefined)
            this.texts = data.texts;
        if (data.objectType !== undefined)
            this.objectType = data.objectType;
        if (data.indexType !== undefined)
            this.indexType = data.indexType;
        if (data.checkType !== undefined)
            this.checkType = data.checkType;
        if (data.extendsType !== undefined)
            this.extendsType = data.extendsType;
        if (data.baseType !== undefined)
            this.baseType = data.baseType;
        if (data.substConstraint !== undefined)
            this.substConstraint = data.substConstraint;
        this.trueType = false;
        this.falseType = false;
    }
    /**
     * Stock services read `.symbol` as a Symbol object (e.g. signatureHelp
     * type-arg items: typeParameter.symbol.getDocumentationComment). Resolve
     * the wire handle lazily (same pattern as Symbol.parent).
     */
    get symbol() {
        return this.objectRegistry.fetchSymbol(this, "getSymbolOfType", this.symbolHandle);
    }
    getSymbol() {
        return this.symbol;
    }
    getAliasSymbol() {
        return this.objectRegistry.fetchSymbol(this, "getAliasSymbolOfType", this.aliasSymbol);
    }
    getTarget() {
        return this.objectRegistry.fetchType(this, "getTargetOfType", this.target);
    }
    getFreshType() {
        return this.objectRegistry.fetchType(this, "getFreshTypeOfType", this.freshType);
    }
    getRegularType() {
        return this.objectRegistry.fetchType(this, "getRegularTypeOfType", this.regularType);
    }
    getTypes() {
        // Only union, intersection, and template literal types have constituent
        // types; any other kind has none, so return undefined rather than sending
        // a request the server cannot satisfy.
        if (!(this.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral))) {
            return undefined;
        }
        return this.objectRegistry.fetchTypes(this, "getTypesOfType");
    }
    getTypeParameters() {
        return this.objectRegistry.fetchTypes(this, "getTypeParametersOfType", this.typeParameters);
    }
    getOuterTypeParameters() {
        return this.objectRegistry.fetchTypes(this, "getOuterTypeParametersOfType", this.outerTypeParameters);
    }
    getLocalTypeParameters() {
        return this.objectRegistry.fetchTypes(this, "getLocalTypeParametersOfType", this.localTypeParameters);
    }
    getAliasTypeArguments() {
        return this.objectRegistry.fetchTypes(this, "getAliasTypeArgumentsOfType", this.aliasTypeArguments);
    }
    getObjectType() {
        return this.objectRegistry.fetchType(this, "getObjectTypeOfType", this.objectType);
    }
    getIndexType() {
        return this.objectRegistry.fetchType(this, "getIndexedAccessIndexType", this.indexType);
    }
    getCheckType() {
        return this.objectRegistry.fetchType(this, "getCheckTypeOfType", this.checkType);
    }
    getExtendsType() {
        return this.objectRegistry.fetchType(this, "getExtendsTypeOfType", this.extendsType);
    }
    getBaseType() {
        return this.objectRegistry.fetchType(this, "getBaseTypeOfType", this.baseType);
    }
    getConstraint() {
        return this.objectRegistry.fetchType(this, "getConstraintOfType", this.substConstraint);
    }
    getTrueType() {
        const result = this.objectRegistry.fetchType(this, "getTrueTypeOfConditionalType", this.trueType);
        this.trueType = result.id;
        return result;
    }
    getFalseType() {
        const result = this.objectRegistry.fetchType(this, "getFalseTypeOfConditionalType", this.falseType);
        this.falseType = result.id;
        return result;
    }
    /**
     * Get the base types of this type. Returns `undefined` for any type that is
     * not a class or interface.
     */
    getBaseTypes() {
        if (!this.isClassOrInterface()) {
            return undefined;
        }
        return this.objectRegistry.fetchBaseTypes(this);
    }
    isClassOrInterface() {
        return isClassOrInterfaceType(this);
    }
    isUnionType() {
        return isUnionType(this);
    }
    isIntersectionType() {
        return isIntersectionType(this);
    }
    isObjectType() {
        return isObjectType(this);
    }
    isIntrinsicType() {
        return isIntrinsicType(this);
    }
    isErrorType() {
        return isErrorType(this);
    }
    isLiteralType() {
        return isLiteralType(this);
    }
    isStringLiteralType() {
        return isStringLiteralType(this);
    }
    isNumberLiteralType() {
        return isNumberLiteralType(this);
    }
    isBigIntLiteralType() {
        return isBigIntLiteralType(this);
    }
    isBooleanLiteralType() {
        return isBooleanLiteralType(this);
    }
    isTypeReference() {
        return isTypeReference(this);
    }
    isTupleType() {
        return isTupleType(this);
    }
    isIndexType() {
        return isIndexType(this);
    }
    isIndexedAccessType() {
        return isIndexedAccessType(this);
    }
    isConditionalType() {
        return isConditionalType(this);
    }
    isSubstitutionType() {
        return isSubstitutionType(this);
    }
    isTemplateLiteralType() {
        return isTemplateLiteralType(this);
    }
    isStringMappingType() {
        return isStringMappingType(this);
    }
    isTypeParameter() {
        return isTypeParameter(this);
    }
}
export function isUnionType(type) {
    return (type.flags & TypeFlags.Union) !== 0;
}
export function isIntersectionType(type) {
    return (type.flags & TypeFlags.Intersection) !== 0;
}
export function isObjectType(type) {
    return (type.flags & TypeFlags.Object) !== 0;
}
export function isClassOrInterfaceType(type) {
    return isObjectType(type) && (type.objectFlags & ObjectFlags.ClassOrInterface) !== 0;
}
export function isIntrinsicType(type) {
    return (type.flags & TypeFlags.Intrinsic) !== 0;
}
/**
 * Whether this is the error type — the placeholder the checker produces when a
 * type cannot be determined (e.g. an unresolved reference). It is an intrinsic
 * type named `"error"` (this covers both the singleton error type and the
 * per-alias error types manufactured for unresolved type alias references).
 */
export function isErrorType(type) {
    return isIntrinsicType(type) && type.intrinsicName === "error";
}
export function isLiteralType(type) {
    return (type.flags & TypeFlags.Literal) !== 0;
}
export function isStringLiteralType(type) {
    return (type.flags & TypeFlags.StringLiteral) !== 0;
}
export function isNumberLiteralType(type) {
    return (type.flags & TypeFlags.NumberLiteral) !== 0;
}
export function isBigIntLiteralType(type) {
    return (type.flags & TypeFlags.BigIntLiteral) !== 0;
}
export function isBooleanLiteralType(type) {
    return (type.flags & TypeFlags.BooleanLiteral) !== 0;
}
export function isTypeReference(type) {
    return isObjectType(type) && (type.objectFlags & ObjectFlags.Reference) !== 0;
}
export function isTupleType(type) {
    return isObjectType(type) && (type.objectFlags & ObjectFlags.Tuple) !== 0;
}
export function isIndexType(type) {
    return (type.flags & TypeFlags.Index) !== 0;
}
export function isIndexedAccessType(type) {
    return (type.flags & TypeFlags.IndexedAccess) !== 0;
}
export function isConditionalType(type) {
    return (type.flags & TypeFlags.Conditional) !== 0;
}
export function isSubstitutionType(type) {
    return (type.flags & TypeFlags.Substitution) !== 0;
}
export function isTemplateLiteralType(type) {
    return (type.flags & TypeFlags.TemplateLiteral) !== 0;
}
export function isStringMappingType(type) {
    return (type.flags & TypeFlags.StringMapping) !== 0;
}
export function isTypeParameter(type) {
    return (type.flags & TypeFlags.TypeParameter) !== 0;
}
export class Signature {
    flags;
    objectRegistry;
    id;
    declaration;
    // Raw wire handles — stock Signature exposes these as objects
    // (TypeParameter[] / Symbol / Signature). Resolve lazily like Symbol.parent.
    typeParameterHandles;
    _typeParameters = null;
    thisParameterHandle;
    targetHandle;
    // Raw parameter symbol ids from the wire; resolved lazily by the
    // `parameters` getter. ts.Signature.parameters is an array of Symbol
    // objects (and ts-api-utils / rules read `signature.parameters[idx]`
    // directly, then pass it to checker.getTypeOfSymbolAtLocation), so exposing
    // raw ids here makes those callers send `undefined` as the symbol id and
    // the bridge reject it as an "empty symbol handle". Resolve to Symbols.
    _parameterIds;
    _parameters;
    constructor(data, project, objectRegistry) {
        this.id = data.id;
        this.flags = data.flags;
        this.objectRegistry = objectRegistry;
        this.declaration = data.declaration ? new NodeHandle(data.declaration, project) : undefined;
        // Omit empty: stock Signature.typeParameters is undefined when none
        // (Go SignatureResponse omits typeParameters via omitempty).
        this.typeParameterHandles = data.typeParameters?.length ? data.typeParameters : undefined;
        this._parameterIds = data.parameters ?? [];
        this.thisParameterHandle = data.thisParameter;
        this.targetHandle = data.target;
    }
    get parameters() {
        if (this._parameters === undefined) {
            this._parameters = this.objectRegistry.fetchSymbols(this, "getParametersOfSignature", this._parameterIds);
        }
        return this._parameters;
    }
    /**
     * Stock services read `.typeParameters` as TypeParameter[] | undefined.
     * Resolve wire TypeIDs lazily through the registry (cached after first access).
     */
    get typeParameters() {
        if (this._typeParameters !== null)
            return this._typeParameters;
        if (!this.typeParameterHandles) {
            this._typeParameters = undefined;
            return undefined;
        }
        this._typeParameters = this.objectRegistry.fetchTypes(this, "getTypeParametersOfSignature", this.typeParameterHandles);
        return this._typeParameters;
    }
    /**
     * Stock services read `.thisParameter` as Symbol | undefined.
     */
    get thisParameter() {
        return this.objectRegistry.fetchSymbol(this, "getThisParameterOfSignature", this.thisParameterHandle);
    }
    /**
     * Stock services read `.target` as Signature | undefined.
     */
    get target() {
        return this.objectRegistry.fetchSignature(this, "getTargetOfSignature", this.targetHandle);
    }
    getTypeParameters() {
        return this.typeParameters;
    }
    getParameters() {
        return this.parameters;
    }
    getThisParameter() {
        return this.thisParameter;
    }
    getTarget() {
        return this.target;
    }
    /** Stock SignatureObject: delegate to checker.getParameterType(this, pos). */
    getTypeParameterAtPosition(pos) {
        return this.objectRegistry.getParameterType(this, pos);
    }
    get hasRestParameter() {
        return (this.flags & SignatureFlags.HasRestParameter) !== 0;
    }
    get isConstruct() {
        return (this.flags & SignatureFlags.Construct) !== 0;
    }
    get isAbstract() {
        return (this.flags & SignatureFlags.Abstract) !== 0;
    }
}
//# sourceMappingURL=api.js.map