Skip to content

Commit 021444a

Browse files
committed
Make it as api so we can test it
1 parent e28869d commit 021444a

File tree

4 files changed

+118
-49
lines changed

4 files changed

+118
-49
lines changed

src/compiler/program.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,7 @@ namespace ts {
7474
// TODO(shkamat): update this after reworking ts build API
7575
export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
7676
const existingDirectories = createMap<boolean>();
77-
function getCanonicalFileName(fileName: string): string {
78-
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
79-
// otherwise use toLowerCase as a canonical form.
80-
return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
81-
}
82-
77+
const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames);
8378
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
8479
let text: string | undefined;
8580
try {

src/compiler/watch.ts

+50
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,56 @@ namespace ts {
383383
if (!buildInfo.program) return undefined;
384384
return createBuildProgramUsingProgramBuildInfo(buildInfo.program);
385385
}
386+
387+
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
388+
const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
389+
host.createHash = maybeBind(system, system.createHash);
390+
setGetSourceFileAsHashVersioned(host, system);
391+
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
392+
return host;
393+
}
394+
395+
export interface IncrementalProgramOptions<T extends BuilderProgram> {
396+
rootNames: ReadonlyArray<string>;
397+
options: CompilerOptions;
398+
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
399+
projectReferences?: ReadonlyArray<ProjectReference>;
400+
host?: CompilerHost;
401+
createProgram?: CreateProgram<T>;
402+
}
403+
export function createIncrementalProgram<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>({
404+
rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram
405+
}: IncrementalProgramOptions<T>): T {
406+
host = host || createIncrementalCompilerHost(options);
407+
createProgram = createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
408+
const oldProgram = readBuilderProgram(options, path => host!.readFile(path)) as any as T;
409+
return createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
410+
}
411+
412+
export interface IncrementalCompilationOptions {
413+
rootNames: ReadonlyArray<string>;
414+
options: CompilerOptions;
415+
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
416+
projectReferences?: ReadonlyArray<ProjectReference>;
417+
host?: CompilerHost;
418+
reportDiagnostic?: DiagnosticReporter;
419+
reportErrorSummary?: ReportEmitErrorSummary;
420+
afterProgramEmitAndDiagnostics?(program: EmitAndSemanticDiagnosticsBuilderProgram): void;
421+
system?: System;
422+
}
423+
export function performIncrementalCompilation(input: IncrementalCompilationOptions) {
424+
const system = input.system || sys;
425+
const host = input.host || (input.host = createIncrementalCompilerHost(input.options, system));
426+
const builderProgram = createIncrementalProgram(input);
427+
const exitStatus = emitFilesAndReportErrors(
428+
builderProgram,
429+
input.reportDiagnostic || createDiagnosticReporter(system),
430+
s => host!.trace && host!.trace!(s),
431+
input.reportErrorSummary || input.options.pretty ? errorCount => system.write(getErrorSummaryText(errorCount, system.newLine)) : undefined
432+
);
433+
if (input.afterProgramEmitAndDiagnostics) input.afterProgramEmitAndDiagnostics(builderProgram);
434+
return exitStatus;
435+
}
386436
}
387437

388438
namespace ts {

src/testRunner/unittests/tscWatch/incremental.ts

+62-14
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,35 @@ namespace ts.tscWatch {
1515
expectedIncrementalEmit?: ReadonlyArray<File>;
1616
expectedIncrementalErrors?: ReadonlyArray<string>;
1717
}
18-
function verifyIncrementalWatchEmit({
19-
files, expectedInitialEmit, expectedInitialErrors, modifyFs, expectedIncrementalEmit, expectedIncrementalErrors
20-
}: VerifyIncrementalWatchEmitInput) {
18+
function verifyIncrementalWatchEmit(input: VerifyIncrementalWatchEmitInput) {
19+
it("with tsc --w", () => {
20+
verifyIncrementalWatchEmitWorker({
21+
input,
22+
emitAndReportErrors: createWatchOfConfigFile,
23+
verifyErrors: checkOutputErrorsInitial
24+
});
25+
});
26+
it("with tsc", () => {
27+
verifyIncrementalWatchEmitWorker({
28+
input,
29+
emitAndReportErrors: ,
30+
verifyErrors
31+
});
32+
});
33+
}
34+
35+
interface VerifyIncrementalWatchEmitWorkerInput {
36+
input: VerifyIncrementalWatchEmitInput;
37+
emitAndReportErrors: (configFile: string, host: WatchedSystem) => { close(): void; };
38+
verifyErrors: (host: WatchedSystem, errors: ReadonlyArray<string>) => void;
39+
}
40+
function verifyIncrementalWatchEmitWorker({
41+
input: {
42+
files, expectedInitialEmit, expectedInitialErrors, modifyFs, expectedIncrementalEmit, expectedIncrementalErrors
43+
},
44+
emitAndReportErrors,
45+
verifyErrors
46+
}: VerifyIncrementalWatchEmitWorkerInput) {
2147
const host = createWatchedSystem(files, { currentDirectory: project });
2248
const originalWriteFile = host.writeFile;
2349
const writtenFiles = createMap<string>();
@@ -26,18 +52,40 @@ namespace ts.tscWatch {
2652
writtenFiles.set(path, content);
2753
originalWriteFile.call(host, path, content);
2854
};
29-
verifyWatch(host, writtenFiles, expectedInitialEmit, expectedInitialErrors);
55+
verifyBuild({
56+
host,
57+
writtenFiles,
58+
emitAndReportErrors,
59+
verifyErrors,
60+
expectedEmit: expectedInitialEmit,
61+
expectedErrors: expectedInitialErrors
62+
});
3063
if (modifyFs) {
3164
modifyFs(host);
32-
verifyWatch(host, writtenFiles, Debug.assertDefined(expectedIncrementalEmit), Debug.assertDefined(expectedIncrementalErrors));
65+
verifyBuild({
66+
host,
67+
writtenFiles,
68+
emitAndReportErrors,
69+
verifyErrors,
70+
expectedEmit: Debug.assertDefined(expectedIncrementalEmit),
71+
expectedErrors: Debug.assertDefined(expectedIncrementalErrors)
72+
});
3373
}
3474
}
3575

36-
function verifyWatch(host: WatchedSystem, writtenFiles: Map<string>, expectedEmit: ReadonlyArray<File>, expectedErrors: ReadonlyArray<string>) {
76+
interface VerifyBuildWorker {
77+
host: WatchedSystem;
78+
writtenFiles: Map<string>;
79+
emitAndReportErrors: VerifyIncrementalWatchEmitWorkerInput["emitAndReportErrors"];
80+
verifyErrors: VerifyIncrementalWatchEmitWorkerInput["verifyErrors"];
81+
expectedEmit: ReadonlyArray<File>;
82+
expectedErrors: ReadonlyArray<string>;
83+
}
84+
function verifyBuild({ host, writtenFiles, emitAndReportErrors, verifyErrors, expectedEmit, expectedErrors }: VerifyBuildWorker) {
3785
writtenFiles.clear();
38-
const watch = createWatchOfConfigFile("tsconfig.json", host);
86+
const watch = emitAndReportErrors("tsconfig.json", host);
3987
checkFileEmit(writtenFiles, expectedEmit);
40-
checkOutputErrorsInitial(host, expectedErrors);
88+
verifyErrors(host, expectedErrors);
4189
watch.close();
4290
}
4391

@@ -73,7 +121,7 @@ namespace ts.tscWatch {
73121
content: "var y = 20;\n"
74122
};
75123

76-
it("own file emit without errors", () => {
124+
describe("own file emit without errors", () => {
77125
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
78126
verifyIncrementalWatchEmit({
79127
files: [libFile, file1, file2, configFile],
@@ -125,7 +173,7 @@ namespace ts.tscWatch {
125173
});
126174
});
127175

128-
it("own file emit with errors", () => {
176+
describe("own file emit with errors", () => {
129177
const fileModified: File = {
130178
path: file2.path,
131179
content: `const y: string = 20;`
@@ -208,7 +256,7 @@ namespace ts.tscWatch {
208256
});
209257
});
210258

211-
it("with --out", () => {
259+
describe("with --out", () => {
212260
const config: File = {
213261
path: configFile.path,
214262
content: JSON.stringify({ compilerOptions: { incremental: true, outFile: "out.js" } })
@@ -279,7 +327,7 @@ namespace ts.tscWatch {
279327
content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd" } })
280328
};
281329

282-
it("own file emit without errors", () => {
330+
describe("own file emit without errors", () => {
283331
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
284332
verifyIncrementalWatchEmit({
285333
files: [libFile, file1, file2, config],
@@ -330,7 +378,7 @@ namespace ts.tscWatch {
330378
});
331379
});
332380

333-
it("own file emit with errors", () => {
381+
describe("own file emit with errors", () => {
334382
const fileModified: File = {
335383
path: file2.path,
336384
content: `export const y: string = 20;`
@@ -412,7 +460,7 @@ namespace ts.tscWatch {
412460
});
413461
});
414462

415-
it("with --out", () => {
463+
describe("with --out", () => {
416464
const config: File = {
417465
path: configFile.path,
418466
content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd", outFile: "out.js" } })

src/tsc/tsc.ts

+5-29
Original file line numberDiff line numberDiff line change
@@ -260,40 +260,16 @@ namespace ts {
260260

261261
function performIncrementalCompilation(config: ParsedCommandLine) {
262262
const { options, fileNames, projectReferences } = config;
263-
const host = createCompilerHost(options);
264-
const currentDirectory = host.getCurrentDirectory();
265-
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
266-
setGetSourceFileAsHashVersioned(host, sys);
267-
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
268263
enableStatistics(options);
269-
const oldProgram = readBuilderProgram(options, path => host.readFile(path));
270-
const configFileParsingDiagnostics = getConfigFileParsingDiagnostics(config);
271-
const programOptions: CreateProgramOptions = {
264+
const exitStatus = ts.performIncrementalCompilation({
272265
rootNames: fileNames,
273266
options,
274-
projectReferences,
275-
host,
276267
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
277-
};
278-
const program = createProgram(programOptions);
279-
const builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(
280-
program,
281-
{
282-
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
283-
createHash: maybeBind(sys, sys.createHash),
284-
writeFile: (path, data, writeByteOrderMark) => sys.writeFile(path, data, writeByteOrderMark)
285-
},
286-
oldProgram,
287-
configFileParsingDiagnostics
288-
);
289-
290-
const exitStatus = emitFilesAndReportErrors(
291-
builderProgram,
268+
projectReferences,
292269
reportDiagnostic,
293-
s => sys.write(s + sys.newLine),
294-
createReportErrorSummary(options)
295-
);
296-
reportStatistics(program);
270+
reportErrorSummary: createReportErrorSummary(options),
271+
afterProgramEmitAndDiagnostics: builderProgram => reportStatistics(builderProgram.getProgram())
272+
});
297273
return sys.exit(exitStatus);
298274
}
299275

0 commit comments

Comments
 (0)