import type { Mapping } from '@volar/source-map';
import type { LinkedCodeMap } from './linkedCodeMap';
export interface Mapper {
    mappings: Mapping<CodeInformation>[];
    toSourceRange(start: number, end: number, fallbackToAnyMatch: boolean, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, number, Mapping<CodeInformation>, Mapping<CodeInformation>]>;
    toGeneratedRange(start: number, end: number, fallbackToAnyMatch: boolean, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, number, Mapping<CodeInformation>, Mapping<CodeInformation>]>;
    toSourceLocation(generatedOffset: number, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, Mapping<CodeInformation>]>;
    toGeneratedLocation(sourceOffset: number, filter?: (data: CodeInformation) => boolean): Generator<readonly [number, Mapping<CodeInformation>]>;
}
export type MapperFactory = (mappings: Mapping<CodeInformation>[]) => Mapper;
export interface Language<T = unknown> {
    mapperFactory: MapperFactory;
    plugins: LanguagePlugin<T>[];
    scripts: {
        get(id: T, includeFsFiles?: boolean, shouldRegister?: boolean): SourceScript<T> | undefined;
        set(id: T, snapshot: IScriptSnapshot, languageId?: string, plugins?: LanguagePlugin<T>[]): SourceScript<T> | undefined;
        delete(id: T): void;
        fromVirtualCode(virtualCode: VirtualCode): SourceScript<T>;
    };
    maps: {
        get(virtualCode: VirtualCode, sourceScript: SourceScript<T>): Mapper;
        forEach(virtualCode: VirtualCode): Generator<[sourceScript: SourceScript<T>, map: Mapper]>;
    };
    linkedCodeMaps: {
        get(virtualCode: VirtualCode): LinkedCodeMap | undefined;
    };
}
export interface SourceScript<T = unknown> {
    id: T;
    languageId: string;
    snapshot: IScriptSnapshot;
    targetIds: Set<T>;
    associatedIds: Set<T>;
    associatedOnly: boolean;
    isAssociationDirty?: boolean;
    generated?: {
        root: VirtualCode;
        languagePlugin: LanguagePlugin<T>;
        embeddedCodes: Map<string, VirtualCode>;
    };
}
export type CodeMapping = Mapping<CodeInformation>;
export interface VirtualCode {
    id: string;
    languageId: string;
    snapshot: IScriptSnapshot;
    mappings: CodeMapping[];
    associatedScriptMappings?: Map<unknown, CodeMapping[]>;
    embeddedCodes?: VirtualCode[];
    linkedCodeMappings?: Mapping[];
}
export interface CodeInformation {
    /** virtual code is expected to support verification */
    verification?: boolean | {
        shouldReport?(source: string | undefined, code: string | number | undefined): boolean;
    };
    /** virtual code is expected to support assisted completion */
    completion?: boolean | {
        isAdditional?: boolean;
        onlyImport?: boolean;
    };
    /** virtual code is expected correctly reflect semantic of the source code */
    semantic?: boolean | {
        shouldHighlight?(): boolean;
    };
    /** virtual code is expected correctly reflect reference relationships of the source code */
    navigation?: boolean | {
        shouldRename?(): boolean;
        resolveRenameNewName?(newName: string): string;
        resolveRenameEditText?(newText: string): string;
    };
    /** virtual code is expected correctly reflect the structural information of the source code */
    structure?: boolean;
    /** virtual code is expected correctly reflect the format information of the source code */
    format?: boolean;
}
export interface LanguagePlugin<T = unknown, K extends VirtualCode = VirtualCode> {
    /**
     * For files that are not opened in the IDE, the language ID will not be synchronized to the language server, so a hook is needed to parse the language ID of files that are known extension but not opened in the IDE.
     */
    getLanguageId(scriptId: T): string | undefined;
    /**
     * Generate a virtual code.
     */
    createVirtualCode?(scriptId: T, languageId: string, snapshot: IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
    /**
     * Incremental update a virtual code. If not provide, call createVirtualCode again.
     */
    updateVirtualCode?(scriptId: T, virtualCode: K, newSnapshot: IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
    /**
     * Cleanup a virtual code.
     */
    disposeVirtualCode?(scriptId: T, virtualCode: K): void;
    /**
     * Some file types should not be parsed or processed as TypeScript files,
     * as they are used only as sources for generated files.
     *
     * This functionality is required only in TS plugin mode.
     */
    isAssociatedFileOnly?(scriptId: T, languageId: string): boolean;
}
export interface CodegenContext<T = unknown> {
    getAssociatedScript(scriptId: T): SourceScript<T> | undefined;
}
export interface IScriptSnapshot {
    /** Gets a portion of the script snapshot specified by [start, end). */
    getText(start: number, end: number): string;
    /** Gets the length of this script snapshot. */
    getLength(): number;
    /**
     * Gets the TextChangeRange that describe how the text changed between this text and
     * an older version.  This information is used by the incremental parser to determine
     * what sections of the script need to be re-parsed.  'undefined' can be returned if the
     * change range cannot be determined.  However, in that case, incremental parsing will
     * not happen and the entire document will be re - parsed.
     */
    getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined;
    /** Releases all resources held by this script snapshot */
    dispose?(): void;
}
export interface TextChangeRange {
    span: TextSpan;
    newLength: number;
}
export interface TextSpan {
    start: number;
    length: number;
}
