Skip to content

Commit 598dba7

Browse files
committed
Merge branch 'main' into lsp-mem-fix
2 parents 0375d12 + 4f5ddae commit 598dba7

34 files changed

Lines changed: 4134 additions & 84 deletions

‎.github/skills/mcfly/SKILL.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ description: Only invoke when explicitly instructed to
44
---
55

66
You need to "re-stack" your commits to match the following format:
7-
* A failing test case
7+
* Testcase(s), including at least one that demonstrate the problem - this could be a test that directly fails, baselines that show the problem, or even both
88
* A commit, or series of commits, that fixes the failing test case
9-
* (Optional) a follow-up commit that checks in any modified baselines
9+
* If needed, a follow-up commit with modified baselines
1010

1111
Since you can't force-push, start with a commit that undoes all your prior changes and gets you back to `main`.
1212

1313
Then add your test case(s) in a single commit.
14+
When you add testcases that create or modify baselines, commit the (pre-fix) baselines at the same time as the testcases themselves.
1415
A test case isn't necessarily a new file; it could be a modification to an existing test or a change in the test configuration.
1516
Ensure that at least one test in the full run fails - you might be operating on a bad PR that didn't actually introduce a failing scenario!
1617
If zero tests failed, abort and post a message explaining what you observed.
1718
Remember that baseline tests do not "fail" in the traditional sense; they are used to verify that the output matches the expected baseline.
18-
You should examine the PR description to determine what the desired passing baseline should look like.
19+
Ensure that your test demonstrates the problem that the PR is intended to fix.
1920

2021
Then, add your fix.
2122
You can break this apart into multiple commits if it's more logical to review that way; use your judgment.

‎packages/typescript/src/api/async/api.ts‎

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,18 @@ import {
6060
toPath,
6161
} from "../path.ts";
6262
import type {
63+
BuildResponse,
64+
CleanBuildResponse,
6365
CompilerOptions,
6466
ConfiguredProjectId,
67+
CreateBuildOrchestratorResponse,
6568
CreateProgramOptions as ProtocolCreateProgramOptions,
6669
CreateSnapshotParams as ProtocolCreateSnapshotParams,
6770
CreateSnapshotProgramParams as ProtocolCreateSnapshotProgramParams,
6871
CreateSnapshotResponse,
6972
CreateSourceFileOptions,
7073
Diagnostic,
74+
DiagnosticResponse,
7175
DocumentIdentifier,
7276
DocumentPosition,
7377
EmitOutputResponse as ProtocolEmitOutputResponse,
@@ -328,6 +332,7 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
328332
private initialized: boolean = false;
329333
private initializing: Promise<void> | undefined;
330334
private activeSnapshots: Map<number, Snapshot> = new Map();
335+
private activeBuildOrchestrators: Set<BuildOrchestrator> = new Set();
331336
private activeSourceFileLeases: Map<number, RetainedSourceFile> = new Map();
332337
readonly printer: Printer;
333338
readonly internal: InternalAPI;
@@ -399,6 +404,21 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
399404
return "\n";
400405
}
401406

407+
async createBuildOrchestrator(rootNames: readonly string[], buildOrchestratorOptions: BuildOrchestratorOptions): Promise<BuildOrchestrator> {
408+
await this.ensureInitialized();
409+
const orchestratorResponse = await this.client.apiRequest("createBuildOrchestrator", {
410+
...buildOrchestratorOptions,
411+
...buildOrchestratorOptions.overrideCompilerOptions,
412+
rootNames,
413+
});
414+
415+
const orchestrator = new BuildOrchestrator(this.client, orchestratorResponse, () => {
416+
this.activeBuildOrchestrators.delete(orchestrator);
417+
});
418+
this.activeBuildOrchestrators.add(orchestrator);
419+
return orchestrator;
420+
}
421+
402422
async parseConfigFile(file: DocumentIdentifier): Promise<ParsedCommandLine> {
403423
await this.ensureInitialized();
404424
return this.client.apiRequest("parseConfigFile", { file });
@@ -652,6 +672,9 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
652672
}
653673
finally {
654674
try {
675+
for (const orchestrator of [...this.activeBuildOrchestrators]) {
676+
await orchestrator.dispose();
677+
}
655678
for (const snapshot of [...this.activeSnapshots.values()]) {
656679
await snapshot.dispose();
657680
}
@@ -1961,6 +1984,107 @@ export class Program<Id extends ProjectId = ProjectId> implements FormatDiagnost
19611984
}
19621985
}
19631986

1987+
export interface BuildOrchestratorOptions {
1988+
cwd?: string | undefined;
1989+
dry?: boolean;
1990+
force?: boolean;
1991+
verbose?: boolean;
1992+
stopBuildOnErrors?: boolean;
1993+
overrideCompilerOptions?: OverrideCompilerOptions;
1994+
}
1995+
1996+
export interface OverrideCompilerOptions {
1997+
incremental?: boolean;
1998+
assumeChangesOnlyAffectDirectDependencies?: boolean;
1999+
declaration?: boolean;
2000+
declarationMap?: boolean;
2001+
emitDeclarationOnly?: boolean;
2002+
sourceMap?: boolean;
2003+
inlineSourceMap?: boolean;
2004+
traceResolution?: boolean;
2005+
}
2006+
2007+
export class BuildOrchestrator {
2008+
private client: Client;
2009+
private id: number;
2010+
private disposed = false;
2011+
private disposePromise: Promise<void> | undefined;
2012+
private onDispose: () => void;
2013+
2014+
constructor(
2015+
client: Client,
2016+
orchestratorResponse: CreateBuildOrchestratorResponse,
2017+
onDispose: () => void,
2018+
) {
2019+
this.client = client;
2020+
this.id = orchestratorResponse.buildOrchestratorID;
2021+
this.onDispose = onDispose;
2022+
}
2023+
2024+
[globalThis.Symbol.dispose](): void {
2025+
void this.dispose();
2026+
}
2027+
dispose(): Promise<void> {
2028+
return this.disposePromise ??= this.disposeWorker();
2029+
}
2030+
2031+
private async disposeWorker(): Promise<void> {
2032+
if (this.disposed) return;
2033+
this.disposed = true;
2034+
try {
2035+
await this.client.apiRequest("disposeBuildOrchestrator", {
2036+
buildOrchestratorID: this.id,
2037+
});
2038+
}
2039+
finally {
2040+
this.onDispose();
2041+
}
2042+
}
2043+
2044+
async build(project?: string): Promise<BuildResponse> {
2045+
this.ensureNotDisposed();
2046+
const response = await this.client.apiRequest("build", {
2047+
buildOrchestratorID: this.id,
2048+
...(project !== undefined ? { project } : {}),
2049+
});
2050+
return response;
2051+
}
2052+
async buildReferences(project: string): Promise<BuildResponse> {
2053+
this.ensureNotDisposed();
2054+
const response = await this.client.apiRequest("buildReferences", {
2055+
buildOrchestratorID: this.id,
2056+
project,
2057+
});
2058+
return response;
2059+
}
2060+
async clean(project?: string): Promise<CleanBuildResponse> {
2061+
this.ensureNotDisposed();
2062+
const response = await this.client.apiRequest("cleanBuild", {
2063+
buildOrchestratorID: this.id,
2064+
...(project !== undefined ? { project } : {}),
2065+
});
2066+
return response;
2067+
}
2068+
async cleanReferences(project?: string): Promise<CleanBuildResponse> {
2069+
this.ensureNotDisposed();
2070+
const response = await this.client.apiRequest("cleanReferences", {
2071+
buildOrchestratorID: this.id,
2072+
...(project !== undefined ? { project } : {}),
2073+
});
2074+
return response;
2075+
}
2076+
2077+
isDisposed(): boolean {
2078+
return this.disposed;
2079+
}
2080+
2081+
private ensureNotDisposed(): void {
2082+
if (this.disposed) {
2083+
throw new Error("Build orchestrator is disposed");
2084+
}
2085+
}
2086+
}
2087+
19642088
function toEmitOutput(response: ProtocolEmitOutputResponse): EmitOutput {
19652089
const outputFiles = new Map<string, EmitOutputFile>();
19662090
for (const { fileName, ...outputFile } of response.outputFiles) {

‎packages/typescript/src/api/fs.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export interface FileSystem {
3636
}
3737

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

4141
export interface CreateFileSystemOptions {
4242
/** Complete directory listings. Full filesystems derive these from `files` when omitted. */

‎packages/typescript/src/api/proto.generated.ts‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export interface APIMethodInfo {
2727
createSnapshot: APIMethod<CreateSnapshotParams, CreateSnapshotResponse>;
2828
updateSnapshot: APIMethod<UpdateSnapshotParams, CreateSnapshotResponse>;
2929
getCurrentLanguageServerSnapshot: APIMethod<GetCurrentLanguageServerSnapshotParams, CreateSnapshotResponse>;
30+
createBuildOrchestrator: APIMethod<CreateBuildOrchestratorParams, CreateBuildOrchestratorResponse>;
31+
disposeBuildOrchestrator: APIMethod<DisposeBuildOrchestratorParams, unknown>;
32+
build: APIMethod<BuildParams, BuildResponse>;
33+
buildReferences: APIMethod<BuildParams, BuildResponse>;
34+
cleanBuild: APIMethod<CleanBuildParams, CleanBuildResponse>;
35+
cleanReferences: APIMethod<CleanBuildParams, CleanBuildResponse>;
3036
createModuleResolver: APIMethod<CreateModuleResolverParams, number>;
3137
releaseModuleResolver: APIMethod<ReleaseModuleResolverParams, unknown>;
3238
resolveModuleName: APIMethod<ResolveModuleNameParams, ResolveModuleNameResult>;
@@ -262,6 +268,42 @@ export interface GetCurrentLanguageServerSnapshotParams {
262268
changes?: LanguageServerSnapshotChanges | undefined;
263269
}
264270

271+
export interface CreateBuildOrchestratorParams extends BuildOptions, CompilerOptions {
272+
rootNames: readonly string[] | null;
273+
cwd?: string | undefined;
274+
}
275+
276+
export interface CreateBuildOrchestratorResponse {
277+
buildOrchestratorID: number;
278+
}
279+
280+
export interface DisposeBuildOrchestratorParams {
281+
buildOrchestratorID: number;
282+
}
283+
284+
export interface BuildParams {
285+
buildOrchestratorID: number;
286+
project?: string | undefined;
287+
}
288+
289+
export interface BuildResponse {
290+
status: number;
291+
diagnostics?: DiagnosticResponse[] | undefined;
292+
statistics: Statistics;
293+
}
294+
295+
export interface CleanBuildParams {
296+
buildOrchestratorID: number;
297+
project?: string | undefined;
298+
}
299+
300+
export interface CleanBuildResponse {
301+
status: number;
302+
diagnostics?: DiagnosticResponse[] | undefined;
303+
statistics: Statistics;
304+
filesDeleted?: string[] | undefined;
305+
}
306+
265307
export interface CreateModuleResolverParams {
266308
compilerOptions: CompilerOptions;
267309
moduleResolutions?: ModuleResolutionSpec | undefined;
@@ -294,6 +336,7 @@ export interface ParseCommandLineParams {
294336
export interface ConfigFileResponse {
295337
fileNames: string[];
296338
options: CompilerOptions;
339+
buildOptions?: BuildOptions | undefined;
297340
projectReferences?: ProjectReference[] | undefined;
298341
typeAcquisition?: TypeAcquisition | undefined;
299342
compileOnSave?: boolean | undefined;
@@ -1042,10 +1085,16 @@ export interface ProfileResult {
10421085
export interface BatchRequest {
10431086
method:
10441087
| "batchRequests"
1088+
| "build"
1089+
| "buildReferences"
1090+
| "cleanBuild"
1091+
| "cleanReferences"
1092+
| "createBuildOrchestrator"
10451093
| "createModuleResolver"
10461094
| "createSnapshot"
10471095
| "createSourceFile"
10481096
| "createSourceFileFromFile"
1097+
| "disposeBuildOrchestrator"
10491098
| "emit"
10501099
| "emitToString"
10511100
| "formatNodeForInsertion"
@@ -1211,10 +1260,16 @@ export interface BatchRequest {
12111260
export interface BatchResponse {
12121261
method:
12131262
| "batchRequests"
1263+
| "build"
1264+
| "buildReferences"
1265+
| "cleanBuild"
1266+
| "cleanReferences"
1267+
| "createBuildOrchestrator"
12141268
| "createModuleResolver"
12151269
| "createSnapshot"
12161270
| "createSourceFile"
12171271
| "createSourceFileFromFile"
1272+
| "disposeBuildOrchestrator"
12181273
| "emit"
12191274
| "emitToString"
12201275
| "formatNodeForInsertion"
@@ -1482,6 +1537,16 @@ export interface SnapshotOperationResponse {
14821537
export interface LanguageServerSnapshotChanges extends SnapshotRequestChangesParams {
14831538
}
14841539

1540+
export interface BuildOptions {
1541+
dry?: boolean | undefined;
1542+
force?: boolean | undefined;
1543+
verbose?: boolean | undefined;
1544+
builders?: number | undefined;
1545+
stopBuildOnErrors?: boolean | undefined;
1546+
/** Internal fields */
1547+
clean?: boolean | undefined;
1548+
}
1549+
14851550
/** CompilerOptions contains the compiler options exposed by the API. */
14861551
export interface CompilerOptions {
14871552
allowJs?: boolean | undefined;
@@ -1590,6 +1655,12 @@ export interface CompilerOptions {
15901655
configFilePath?: string | undefined;
15911656
}
15921657

1658+
export interface Statistics {
1659+
Projects: number;
1660+
ProjectsBuilt: number;
1661+
TimestampUpdates: number;
1662+
}
1663+
15931664
export interface ModuleResolutionSpec {
15941665
fallback: "resolve" | "unresolved";
15951666
entries: ModuleResolutionEntry[];

‎packages/typescript/src/api/proto.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ export interface CreateSnapshotParams extends CoreCreateSnapshotParams {
9292
openProject?: string | undefined;
9393
}
9494

95+
export interface CreateBuildOrchestratorParams {
96+
rootNames: readonly string[] | null;
97+
}
98+
9599
/**
96100
* Builds the wire request for createSnapshot, applying the deprecated `openProject`
97101
* compatibility shim: a single `openProject` is folded into `openProjects` and is

0 commit comments

Comments
 (0)