Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/typescript/src/api/async/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,13 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo

private prepareCreateSnapshotParams(params: CreateSnapshotParams | undefined): ProtocolCreateSnapshotParams {
params ??= {};
if (params.fileSystem?.kind === "snapshot") {
const sourceId = params.fileSystem.snapshot;
const source = sourceId === undefined ? undefined : this.activeSnapshots.get(sourceId);
if (!source || source.isDisposed()) {
throw new Error("Cannot use an inactive snapshot filesystem");
}
}
const prepareOptions = (options: CreateProgramOptions | undefined): ProtocolCreateProgramOptions | undefined => {
if (!options) return undefined;
const { moduleResolver, projectReferences, ...rest } = options;
Expand Down Expand Up @@ -1109,6 +1116,12 @@ export class Snapshot {
return this.getProject(projectId)?.program;
}

/**
* Creates a snapshot using this snapshot's projects and incremental state.
* Use `createFileSystemFromSnapshot(source)` from the filesystem API as `fileSystem`
* to overlay another snapshot's retained request entries without replaying
* intermediate updates. Changes and program reuse are relative to this snapshot.
*/
update<
const CreatePrograms extends CreateSnapshotParams["createPrograms"] = undefined,
const OpenFiles extends CreateSnapshotParams["openFiles"] = undefined,
Expand Down
21 changes: 21 additions & 0 deletions packages/typescript/src/api/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
RootedFilePath,
RootedPath,
} from "../ast/index.ts";
import type { Snapshot } from "./async/api.ts";
import { normalizePath } from "./path.ts";
import type {
RequestDirectoryEntries,
Expand Down Expand Up @@ -169,6 +170,26 @@ export function createFileSystemLayer(
return createRequestFileSystem("layer", files, options);
}

/**
* Reuses a snapshot's retained request filesystem without resending its contents.
* Entries take precedence over the receiving snapshot's filesystem; a full source
* filesystem remains total. Host and editor contents are not copied.
* An optional layer or full filesystem is applied over the reused filesystem.
* The source must remain active until the snapshot operation completes.
*/
export function createFileSystemFromSnapshot(
snapshot: Pick<Snapshot, "id" | "isDisposed">,
fileSystem?: RequestFileSystem | undefined,
): RequestFileSystem {
if (snapshot.isDisposed()) {
throw new Error("Cannot create a filesystem from a disposed snapshot");
}
if (fileSystem?.kind === "snapshot") {
throw new Error("Only a layer or full filesystem can be applied on top of a snapshot filesystem");
}
return { kind: "snapshot", snapshot: snapshot.id, files: {}, fileSystem };
}

function createRequestFileSystem(
kind: RequestFileSystem["kind"],
files: RequestFileEntries,
Expand Down
10 changes: 8 additions & 2 deletions packages/typescript/src/api/proto.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,9 @@ export interface CreateSnapshotParams extends SnapshotRequestChangesParams {
/**
* FileSystem supplies file contents and directory listings for the new snapshot.
* A full filesystem is canonical and total. A filesystem layer is checked
* before falling back to the base snapshot or host filesystem.
* before falling back to the base snapshot or host filesystem. A snapshot
* filesystem overlays retained request entries from another active snapshot,
* then applies an optional layer or full filesystem.
*/
fileSystem?: RequestFileSystem | undefined;
}
Expand Down Expand Up @@ -1570,7 +1572,11 @@ export interface FileNotifications {
* for a request that creates a snapshot.
*/
export interface RequestFileSystem {
kind: "full" | "layer";
kind: "full" | "layer" | "snapshot";
/** Snapshot identifies the retained snapshot supplying request entries for KindSnapshot. */
snapshot?: number | undefined;
/** FileSystem is an optional layer or full filesystem applied on top of KindSnapshot. */
fileSystem?: RequestFileSystem | undefined;
/** Files maps file names to their complete contents. */
files: Record<string, string>;
/**
Expand Down
13 changes: 13 additions & 0 deletions packages/typescript/src/api/sync/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,13 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo

private prepareCreateSnapshotParams(params: CreateSnapshotParams | undefined): ProtocolCreateSnapshotParams {
params ??= {};
if (params.fileSystem?.kind === "snapshot") {
const sourceId = params.fileSystem.snapshot;
const source = sourceId === undefined ? undefined : this.activeSnapshots.get(sourceId);
if (!source || source.isDisposed()) {
throw new Error("Cannot use an inactive snapshot filesystem");
}
}
const prepareOptions = (options: CreateProgramOptions | undefined): ProtocolCreateProgramOptions | undefined => {
if (!options) return undefined;
const { moduleResolver, projectReferences, ...rest } = options;
Expand Down Expand Up @@ -1737,6 +1744,12 @@ export class Snapshot {
return this.getProject(projectId)?.program;
}

/**
* Creates a snapshot using this snapshot's projects and incremental state.
* Use `createFileSystemFromSnapshot(source)` from the filesystem API as `fileSystem`
* to overlay another snapshot's retained request entries without replaying
* intermediate updates. Changes and program reuse are relative to this snapshot.
*/
get update(): {
<const CreatePrograms extends CreateSnapshotParams["createPrograms"] = undefined, const OpenFiles extends CreateSnapshotParams["openFiles"] = undefined>(params: SnapshotOperationParams<CreateSnapshotParams, CreatePrograms, OpenFiles>): SnapshotForOperationResults<CreatePrograms, OpenFiles>;
(params: CreateSnapshotParams): Snapshot;
Expand Down
Loading
Loading