Skip to content

Commit dc62bb9

Browse files
committed
Change builder to BuilderProgram so it is similar to operating on program
1 parent 965f40f commit dc62bb9

6 files changed

Lines changed: 411 additions & 375 deletions

File tree

src/compiler/builder.ts

Lines changed: 296 additions & 213 deletions
Large diffs are not rendered by default.

src/compiler/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"emitter.ts",
3939
"watchUtilities.ts",
4040
"program.ts",
41+
"builderState.ts",
4142
"builder.ts",
4243
"resolutionCache.ts",
4344
"watch.ts",

src/compiler/watch.ts

Lines changed: 43 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -146,62 +146,23 @@ namespace ts {
146146
return ExitStatus.Success;
147147
}
148148

149-
/**
150-
* Creates the function that emits files and reports errors when called with program
151-
*/
152-
function createEmitFilesAndReportErrorsWithBuilderUsingSystem(system: System, reportDiagnostic: DiagnosticReporter) {
153-
const emitErrorsAndReportErrorsWithBuilder = createEmitFilesAndReportErrorsWithBuilder({
154-
useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames,
155-
createHash: system.createHash && (s => system.createHash(s)),
156-
writeFile,
157-
reportDiagnostic,
158-
writeFileName: s => system.write(s + system.newLine)
159-
});
160-
let host: CachedDirectoryStructureHost | undefined;
161-
return {
162-
emitFilesAndReportError: (program: Program) => emitErrorsAndReportErrorsWithBuilder(program),
163-
setHost: (cachedDirectoryStructureHost: CachedDirectoryStructureHost) => host = cachedDirectoryStructureHost
164-
};
165-
166-
function getHost() {
167-
return host || system;
168-
}
169-
170-
function ensureDirectoriesExist(directoryPath: string) {
171-
if (directoryPath.length > getRootLength(directoryPath) && !getHost().directoryExists(directoryPath)) {
172-
const parentDirectory = getDirectoryPath(directoryPath);
173-
ensureDirectoriesExist(parentDirectory);
174-
getHost().createDirectory(directoryPath);
175-
}
176-
}
177-
178-
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
179-
try {
180-
performance.mark("beforeIOWrite");
181-
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
182-
183-
getHost().writeFile(fileName, text, writeByteOrderMark);
184-
185-
performance.mark("afterIOWrite");
186-
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
187-
}
188-
catch (e) {
189-
if (onError) {
190-
onError(e.message);
191-
}
192-
}
193-
}
194-
}
195-
196149
const noopFileWatcher: FileWatcher = { close: noop };
197150

198151
/**
199152
* Creates the watch compiler host that can be extended with config file or root file names and options host
200153
*/
201154
function createWatchCompilerHost(system = sys, reportDiagnostic: DiagnosticReporter): WatchCompilerHost {
202-
const { emitFilesAndReportError, setHost } = createEmitFilesAndReportErrorsWithBuilderUsingSystem(system, reportDiagnostic);
203-
const host: WatchCompilerHost = {
204-
useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames,
155+
let host: DirectoryStructureHost = system;
156+
const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames;
157+
const writeFileName = (s: string) => system.write(s + system.newLine);
158+
const builderProgramHost: BuilderProgramHost = {
159+
useCaseSensitiveFileNames,
160+
createHash: system.createHash && (s => system.createHash(s)),
161+
writeFile
162+
};
163+
let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined;
164+
return {
165+
useCaseSensitiveFileNames,
205166
getNewLine: () => system.newLine,
206167
getCurrentDirectory: () => system.getCurrentDirectory(),
207168
getDefaultLibLocation,
@@ -220,10 +181,9 @@ namespace ts {
220181
onWatchStatusChange,
221182
createDirectory: path => system.createDirectory(path),
222183
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
223-
onCachedDirectoryStructureHostCreate: host => setHost(host),
224-
afterProgramCreate: emitFilesAndReportError,
184+
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
185+
afterProgramCreate: emitFilesAndReportErrorUsingBuilder,
225186
};
226-
return host;
227187

228188
function getDefaultLibLocation() {
229189
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
@@ -235,6 +195,36 @@ namespace ts {
235195
}
236196
system.write(`${new Date().toLocaleTimeString()} - ${flattenDiagnosticMessageText(diagnostic.messageText, newLine)}${newLine + newLine + newLine}`);
237197
}
198+
199+
function emitFilesAndReportErrorUsingBuilder(program: Program) {
200+
builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, builderProgramHost, builderProgram);
201+
emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName);
202+
}
203+
204+
function ensureDirectoriesExist(directoryPath: string) {
205+
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists(directoryPath)) {
206+
const parentDirectory = getDirectoryPath(directoryPath);
207+
ensureDirectoriesExist(parentDirectory);
208+
host.createDirectory(directoryPath);
209+
}
210+
}
211+
212+
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
213+
try {
214+
performance.mark("beforeIOWrite");
215+
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
216+
217+
host.writeFile(fileName, text, writeByteOrderMark);
218+
219+
performance.mark("afterIOWrite");
220+
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
221+
}
222+
catch (e) {
223+
if (onError) {
224+
onError(e.message);
225+
}
226+
}
227+
}
238228
}
239229

240230
/**
@@ -272,73 +262,6 @@ namespace ts {
272262
namespace ts {
273263
export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
274264

275-
interface BuilderProgram extends ProgramToEmitFilesAndReportErrors {
276-
updateProgram(program: Program): void;
277-
}
278-
279-
function createBuilderProgram(host: BuilderEmitHost): BuilderProgram {
280-
const builder = createEmitAndSemanticDiagnosticsBuilder(host);
281-
let program: Program;
282-
return {
283-
getCurrentDirectory: () => program.getCurrentDirectory(),
284-
getCompilerOptions: () => program.getCompilerOptions(),
285-
getSourceFiles: () => program.getSourceFiles(),
286-
getSyntacticDiagnostics: () => program.getSyntacticDiagnostics(),
287-
getOptionsDiagnostics: () => program.getOptionsDiagnostics(),
288-
getGlobalDiagnostics: () => program.getGlobalDiagnostics(),
289-
getSemanticDiagnostics: () => builder.getSemanticDiagnostics(program),
290-
emit,
291-
updateProgram
292-
};
293-
294-
function updateProgram(p: Program) {
295-
program = p;
296-
builder.updateProgram(p);
297-
}
298-
299-
function emit(): EmitResult {
300-
// Emit and report any errors we ran into.
301-
let sourceMaps: SourceMapData[];
302-
let emitSkipped: boolean;
303-
let diagnostics: Diagnostic[];
304-
let emittedFiles: string[];
305-
306-
let affectedEmitResult: AffectedFileResult<EmitResult>;
307-
while (affectedEmitResult = builder.emitNextAffectedFile(program, host.writeFile)) {
308-
emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped;
309-
diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics);
310-
emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles);
311-
sourceMaps = addRange(sourceMaps, affectedEmitResult.result.sourceMaps);
312-
}
313-
return {
314-
emitSkipped,
315-
diagnostics,
316-
emittedFiles,
317-
sourceMaps
318-
};
319-
}
320-
}
321-
322-
/**
323-
* Host needed to emit files and report errors using builder
324-
*/
325-
export interface BuilderEmitHost extends BuilderHost {
326-
writeFile: WriteFileCallback;
327-
reportDiagnostic: DiagnosticReporter;
328-
writeFileName?: (s: string) => void;
329-
}
330-
331-
/**
332-
* Creates the function that reports the program errors and emit files every time it is called with argument as program
333-
*/
334-
export function createEmitFilesAndReportErrorsWithBuilder(host: BuilderEmitHost) {
335-
const builderProgram = createBuilderProgram(host);
336-
return (program: Program) => {
337-
builderProgram.updateProgram(program);
338-
emitFilesAndReportErrors(builderProgram, host.reportDiagnostic, host.writeFileName);
339-
};
340-
}
341-
342265
export interface WatchCompilerHost {
343266
/** If provided, callback to invoke before each program creation */
344267
beforeProgramCreate?(compilerOptions: CompilerOptions): void;

src/harness/unittests/builder.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,22 @@ namespace ts {
8181
});
8282

8383
function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray<string>) => void {
84-
const builder = createEmitAndSemanticDiagnosticsBuilder({ useCaseSensitiveFileNames: returnTrue, });
84+
const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue };
85+
let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined;
8586
return fileNames => {
8687
const program = getProgram();
87-
builder.updateProgram(program);
88+
builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram);
8889
const outputFileNames: string[] = [];
8990
// tslint:disable-next-line no-empty
90-
while (builder.emitNextAffectedFile(program, fileName => outputFileNames.push(fileName))) {
91+
while (builderProgram.emitNextAffectedFile(fileName => outputFileNames.push(fileName))) {
9192
}
9293
assert.deepEqual(outputFileNames, fileNames);
9394
};
9495
}
9596

9697
function makeAssertChangesWithCancellationToken(getProgram: () => Program): (fileNames: ReadonlyArray<string>, cancelAfterEmitLength?: number) => void {
97-
const builder = createEmitAndSemanticDiagnosticsBuilder({ useCaseSensitiveFileNames: returnTrue, });
98+
const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue };
99+
let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined;
98100
let cancel = false;
99101
const cancellationToken: CancellationToken = {
100102
isCancellationRequested: () => cancel,
@@ -108,7 +110,7 @@ namespace ts {
108110
cancel = false;
109111
let operationWasCancelled = false;
110112
const program = getProgram();
111-
builder.updateProgram(program);
113+
builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram);
112114
const outputFileNames: string[] = [];
113115
try {
114116
// tslint:disable-next-line no-empty
@@ -117,7 +119,7 @@ namespace ts {
117119
if (outputFileNames.length === cancelAfterEmitLength) {
118120
cancel = true;
119121
}
120-
} while (builder.emitNextAffectedFile(program, fileName => outputFileNames.push(fileName), cancellationToken));
122+
} while (builderProgram.emitNextAffectedFile(fileName => outputFileNames.push(fileName), cancellationToken));
121123
}
122124
catch (e) {
123125
assert.isFalse(operationWasCancelled);

src/services/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"../compiler/declarationEmitter.ts",
3838
"../compiler/emitter.ts",
3939
"../compiler/program.ts",
40+
"../compiler/builderState.ts",
4041
"../compiler/builder.ts",
4142
"../compiler/resolutionCache.ts",
4243
"../compiler/watch.ts",

0 commit comments

Comments
 (0)