Skip to content
Merged
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
124 changes: 124 additions & 0 deletions packages/typescript/src/api/async/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,18 @@ import {
toPath,
} from "../path.ts";
import type {
BuildResponse,
CleanBuildResponse,
CompilerOptions,
ConfiguredProjectId,
CreateBuildOrchestratorResponse,
CreateProgramOptions as ProtocolCreateProgramOptions,
CreateSnapshotParams as ProtocolCreateSnapshotParams,
CreateSnapshotProgramParams as ProtocolCreateSnapshotProgramParams,
CreateSnapshotResponse,
CreateSourceFileOptions,
Diagnostic,
DiagnosticResponse,
DocumentIdentifier,
DocumentPosition,
EmitOutputResponse as ProtocolEmitOutputResponse,
Expand Down Expand Up @@ -328,6 +332,7 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
private initialized: boolean = false;
private initializing: Promise<void> | undefined;
private activeSnapshots: Map<number, Snapshot> = new Map();
private activeBuildOrchestrators: Set<BuildOrchestrator> = new Set();
private activeSourceFileLeases: Map<number, RetainedSourceFile> = new Map();
readonly printer: Printer;
readonly internal: InternalAPI;
Expand Down Expand Up @@ -399,6 +404,21 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
return "\n";
}

async createBuildOrchestrator(rootNames: readonly string[], buildOrchestratorOptions: BuildOrchestratorOptions): Promise<BuildOrchestrator> {
await this.ensureInitialized();
const orchestratorResponse = await this.client.apiRequest("createBuildOrchestrator", {
...buildOrchestratorOptions,
...buildOrchestratorOptions.overrideCompilerOptions,
rootNames,
});

const orchestrator = new BuildOrchestrator(this.client, orchestratorResponse, () => {
this.activeBuildOrchestrators.delete(orchestrator);
});
this.activeBuildOrchestrators.add(orchestrator);
return orchestrator;
}

async parseConfigFile(file: DocumentIdentifier): Promise<ParsedCommandLine> {
await this.ensureInitialized();
return this.client.apiRequest("parseConfigFile", { file });
Expand Down Expand Up @@ -652,6 +672,9 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
}
finally {
try {
for (const orchestrator of [...this.activeBuildOrchestrators]) {
await orchestrator.dispose();
}
for (const snapshot of [...this.activeSnapshots.values()]) {
await snapshot.dispose();
}
Expand Down Expand Up @@ -1961,6 +1984,107 @@ export class Program<Id extends ProjectId = ProjectId> implements FormatDiagnost
}
}

export interface BuildOrchestratorOptions {
cwd?: string | undefined;
dry?: boolean;
force?: boolean;
verbose?: boolean;
stopBuildOnErrors?: boolean;
overrideCompilerOptions?: OverrideCompilerOptions;
}

export interface OverrideCompilerOptions {
incremental?: boolean;
assumeChangesOnlyAffectDirectDependencies?: boolean;
declaration?: boolean;
declarationMap?: boolean;
emitDeclarationOnly?: boolean;
sourceMap?: boolean;
inlineSourceMap?: boolean;
traceResolution?: boolean;
Comment thread
iisaduan marked this conversation as resolved.
}

export class BuildOrchestrator {
Comment thread
iisaduan marked this conversation as resolved.
private client: Client;
private id: number;
private disposed = false;
private disposePromise: Promise<void> | undefined;
private onDispose: () => void;

constructor(
client: Client,
orchestratorResponse: CreateBuildOrchestratorResponse,
onDispose: () => void,
) {
this.client = client;
this.id = orchestratorResponse.buildOrchestratorID;
this.onDispose = onDispose;
}

[globalThis.Symbol.dispose](): void {
void this.dispose();
}
dispose(): Promise<void> {
return this.disposePromise ??= this.disposeWorker();
}

private async disposeWorker(): Promise<void> {
if (this.disposed) return;
this.disposed = true;
try {
await this.client.apiRequest("disposeBuildOrchestrator", {
buildOrchestratorID: this.id,
});
}
finally {
this.onDispose();
}
}

async build(project?: string): Promise<BuildResponse> {
this.ensureNotDisposed();
const response = await this.client.apiRequest("build", {
buildOrchestratorID: this.id,
...(project !== undefined ? { project } : {}),
});
return response;
}
async buildReferences(project: string): Promise<BuildResponse> {
this.ensureNotDisposed();
const response = await this.client.apiRequest("buildReferences", {
buildOrchestratorID: this.id,
project,
});
return response;
}
async clean(project?: string): Promise<CleanBuildResponse> {
this.ensureNotDisposed();
const response = await this.client.apiRequest("cleanBuild", {
buildOrchestratorID: this.id,
...(project !== undefined ? { project } : {}),
});
return response;
}
async cleanReferences(project?: string): Promise<CleanBuildResponse> {
this.ensureNotDisposed();
const response = await this.client.apiRequest("cleanReferences", {
buildOrchestratorID: this.id,
...(project !== undefined ? { project } : {}),
});
return response;
}

isDisposed(): boolean {
return this.disposed;
}

private ensureNotDisposed(): void {
if (this.disposed) {
throw new Error("Build orchestrator is disposed");
}
}
}

function toEmitOutput(response: ProtocolEmitOutputResponse): EmitOutput {
const outputFiles = new Map<string, EmitOutputFile>();
for (const { fileName, ...outputFile } of response.outputFiles) {
Expand Down
2 changes: 1 addition & 1 deletion packages/typescript/src/api/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface FileSystem {
}

/** The callback names supported by the Go server for virtual FS delegation. */
export const fsCallbackNames = ["readFile", "fileExists", "directoryExists", "getAccessibleEntries", "realpath", "writeFile"] as const;
export const fsCallbackNames = ["readFile", "fileExists", "directoryExists", "getAccessibleEntries", "realpath", "writeFile", "removeFile"] as const;

export interface CreateFileSystemOptions {
/** Complete directory listings. Full filesystems derive these from `files` when omitted. */
Expand Down
71 changes: 71 additions & 0 deletions packages/typescript/src/api/proto.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export interface APIMethodInfo {
createSnapshot: APIMethod<CreateSnapshotParams, CreateSnapshotResponse>;
updateSnapshot: APIMethod<UpdateSnapshotParams, CreateSnapshotResponse>;
getCurrentLanguageServerSnapshot: APIMethod<GetCurrentLanguageServerSnapshotParams, CreateSnapshotResponse>;
createBuildOrchestrator: APIMethod<CreateBuildOrchestratorParams, CreateBuildOrchestratorResponse>;
disposeBuildOrchestrator: APIMethod<DisposeBuildOrchestratorParams, unknown>;
build: APIMethod<BuildParams, BuildResponse>;
buildReferences: APIMethod<BuildParams, BuildResponse>;
cleanBuild: APIMethod<CleanBuildParams, CleanBuildResponse>;
cleanReferences: APIMethod<CleanBuildParams, CleanBuildResponse>;
createModuleResolver: APIMethod<CreateModuleResolverParams, number>;
releaseModuleResolver: APIMethod<ReleaseModuleResolverParams, unknown>;
resolveModuleName: APIMethod<ResolveModuleNameParams, ResolveModuleNameResult>;
Expand Down Expand Up @@ -262,6 +268,42 @@ export interface GetCurrentLanguageServerSnapshotParams {
changes?: LanguageServerSnapshotChanges | undefined;
}

export interface CreateBuildOrchestratorParams extends BuildOptions, CompilerOptions {
rootNames: readonly string[] | null;
cwd?: string | undefined;
}

export interface CreateBuildOrchestratorResponse {
buildOrchestratorID: number;
}

export interface DisposeBuildOrchestratorParams {
buildOrchestratorID: number;
}

export interface BuildParams {
buildOrchestratorID: number;
project?: string | undefined;
}

export interface BuildResponse {
status: number;
diagnostics?: DiagnosticResponse[] | undefined;
statistics: Statistics;
}

export interface CleanBuildParams {
buildOrchestratorID: number;
project?: string | undefined;
}

export interface CleanBuildResponse {
status: number;
diagnostics?: DiagnosticResponse[] | undefined;
statistics: Statistics;
filesDeleted?: string[] | undefined;
}

export interface CreateModuleResolverParams {
compilerOptions: CompilerOptions;
moduleResolutions?: ModuleResolutionSpec | undefined;
Expand Down Expand Up @@ -294,6 +336,7 @@ export interface ParseCommandLineParams {
export interface ConfigFileResponse {
fileNames: string[];
options: CompilerOptions;
buildOptions?: BuildOptions | undefined;
projectReferences?: ProjectReference[] | undefined;
typeAcquisition?: TypeAcquisition | undefined;
compileOnSave?: boolean | undefined;
Expand Down Expand Up @@ -1042,10 +1085,16 @@ export interface ProfileResult {
export interface BatchRequest {
method:
| "batchRequests"
| "build"
| "buildReferences"
| "cleanBuild"
| "cleanReferences"
| "createBuildOrchestrator"
| "createModuleResolver"
| "createSnapshot"
| "createSourceFile"
| "createSourceFileFromFile"
| "disposeBuildOrchestrator"
| "emit"
| "emitToString"
| "formatNodeForInsertion"
Expand Down Expand Up @@ -1211,10 +1260,16 @@ export interface BatchRequest {
export interface BatchResponse {
method:
| "batchRequests"
| "build"
| "buildReferences"
| "cleanBuild"
| "cleanReferences"
| "createBuildOrchestrator"
| "createModuleResolver"
| "createSnapshot"
| "createSourceFile"
| "createSourceFileFromFile"
| "disposeBuildOrchestrator"
| "emit"
| "emitToString"
| "formatNodeForInsertion"
Expand Down Expand Up @@ -1482,6 +1537,16 @@ export interface SnapshotOperationResponse {
export interface LanguageServerSnapshotChanges extends SnapshotRequestChangesParams {
}

export interface BuildOptions {
dry?: boolean | undefined;
force?: boolean | undefined;
verbose?: boolean | undefined;
builders?: number | undefined;
stopBuildOnErrors?: boolean | undefined;
/** Internal fields */
clean?: boolean | undefined;
}

/** CompilerOptions contains the compiler options exposed by the API. */
export interface CompilerOptions {
allowJs?: boolean | undefined;
Expand Down Expand Up @@ -1590,6 +1655,12 @@ export interface CompilerOptions {
configFilePath?: string | undefined;
}

export interface Statistics {
Projects: number;
ProjectsBuilt: number;
TimestampUpdates: number;
}

export interface ModuleResolutionSpec {
fallback: "resolve" | "unresolved";
entries: ModuleResolutionEntry[];
Expand Down
4 changes: 4 additions & 0 deletions packages/typescript/src/api/proto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ export interface CreateSnapshotParams extends CoreCreateSnapshotParams {
openProject?: string | undefined;
}

export interface CreateBuildOrchestratorParams {
rootNames: readonly string[] | null;
}

/**
* Builds the wire request for createSnapshot, applying the deprecated `openProject`
* compatibility shim: a single `openProject` is folded into `openProjects` and is
Expand Down
Loading
Loading