Skip to content

Commit a4f83b0

Browse files
author
Josh Goldberg
committed
Added console clearing with a message to --watch starts
I advocated against immediately clearing the console when starting --watch in microsoft#17756 because it was confusing to have the console suddenly become blank, wait a while, and _then_ give output. After using the feature for a little while, I think it's a little disorienting how the console will only start clearing after the first recompile. This change clears the console and immediately prints a new "Starting compilation in watch mode..." message.
1 parent 49a48ff commit a4f83b0

File tree

3 files changed

+74
-43
lines changed

3 files changed

+74
-43
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,6 +2828,10 @@
28282828
"category": "Message",
28292829
"code": 6030
28302830
},
2831+
"Starting compilation in watch mode...": {
2832+
"category": "Message",
2833+
"code": 6031
2834+
},
28312835
"File change detected. Starting incremental compilation...": {
28322836
"category": "Message",
28332837
"code": 6032

src/compiler/watch.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ namespace ts {
302302
// There is no extra check needed since we can just rely on the program to decide emit
303303
const builder = createBuilder({ getCanonicalFileName, computeHash });
304304

305+
if (watchingHost.system.clearScreen) {
306+
watchingHost.system.clearScreen();
307+
}
308+
reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Starting_compilation_in_watch_mode));
305309
synchronizeProgram();
306310

307311
// Update the wild card directory watch

src/harness/unittests/tscWatchMode.ts

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,38 @@ namespace ts.tscWatch {
8080
checkOutputDoesNotContain(host, expectedNonAffectedFiles);
8181
}
8282

83-
function checkOutputErrors(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>, isInitial?: true, skipWaiting?: true) {
83+
enum ExpectedOutputErrorsPosition {
84+
BeforeCompilationStarts,
85+
AfterCompilationStarting,
86+
AfterFileChangeDetected
87+
}
88+
89+
function checkOutputErrors(
90+
host: WatchedSystem,
91+
errors: ReadonlyArray<Diagnostic>,
92+
errorsPosition: ExpectedOutputErrorsPosition,
93+
skipWaiting?: true
94+
) {
8495
const outputs = host.getOutput();
85-
const expectedOutputCount = (isInitial ? 0 : 1) + errors.length + (skipWaiting ? 0 : 1);
96+
const expectedOutputCount = errors.length + (skipWaiting ? 0 : 1) + 1;
8697
assert.equal(outputs.length, expectedOutputCount, "Outputs = " + outputs.toString());
87-
let index = 0;
88-
if (!isInitial) {
89-
assertWatchDiagnosticAt(host, index, Diagnostics.File_change_detected_Starting_incremental_compilation);
90-
index++;
98+
let index: number;
99+
100+
switch (errorsPosition) {
101+
case ExpectedOutputErrorsPosition.AfterCompilationStarting:
102+
assertWatchDiagnosticAt(host, 0, Diagnostics.Starting_compilation_in_watch_mode);
103+
index = 1;
104+
break;
105+
case ExpectedOutputErrorsPosition.AfterFileChangeDetected:
106+
assertWatchDiagnosticAt(host, 0, Diagnostics.File_change_detected_Starting_incremental_compilation);
107+
index = 1;
108+
break;
109+
case ExpectedOutputErrorsPosition.BeforeCompilationStarts:
110+
assertWatchDiagnosticAt(host, errors.length, Diagnostics.Starting_compilation_in_watch_mode);
111+
index = 0;
112+
break;
91113
}
114+
92115
forEach(errors, error => {
93116
assertDiagnosticAt(host, index, error);
94117
index++;
@@ -333,13 +356,13 @@ namespace ts.tscWatch {
333356
checkOutputErrors(host, [
334357
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path),
335358
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y")
336-
], /*isInitial*/ true);
359+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
337360

338361
host.reloadFS([file1, commonFile2, libFile]);
339362
host.runQueuedTimeoutCallbacks();
340363
checkProgramRootFiles(watch(), [file1.path]);
341364
checkProgramActualFiles(watch(), [file1.path, libFile.path, commonFile2.path]);
342-
checkOutputErrors(host, emptyArray);
365+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
343366
});
344367

345368
it("should reflect change in config file", () => {
@@ -667,15 +690,15 @@ namespace ts.tscWatch {
667690
const watch = createWatchModeWithConfigFile(config.path, host);
668691

669692
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
670-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
693+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
671694

672695
host.reloadFS([file1, file2, libFile]);
673696
host.checkTimeoutQueueLengthAndRun(1);
674697

675698
assert.equal(host.exitCode, ExitStatus.DiagnosticsPresent_OutputsSkipped);
676699
checkOutputErrors(host, [
677700
getDiagnosticWithoutFile(Diagnostics.File_0_not_found, config.path)
678-
], /*isInitial*/ undefined, /*skipWaiting*/ true);
701+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected, /*skipWaiting*/ true);
679702
});
680703

681704
it("Proper errors: document is not contained in project", () => {
@@ -778,7 +801,7 @@ namespace ts.tscWatch {
778801
};
779802
const host = createWatchedSystem([moduleFile, file1, libFile]);
780803
const watch = createWatchModeWithoutConfigFile([file1.path], host);
781-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
804+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
782805

783806
const moduleFileOldPath = moduleFile.path;
784807
const moduleFileNewPath = "/a/b/moduleFile1.ts";
@@ -787,12 +810,12 @@ namespace ts.tscWatch {
787810
host.runQueuedTimeoutCallbacks();
788811
checkOutputErrors(host, [
789812
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
790-
]);
813+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
791814

792815
moduleFile.path = moduleFileOldPath;
793816
host.reloadFS([moduleFile, file1, libFile]);
794817
host.runQueuedTimeoutCallbacks();
795-
checkOutputErrors(host, emptyArray);
818+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
796819
});
797820

798821
it("rename a module file and rename back should restore the states for configured projects", () => {
@@ -810,7 +833,7 @@ namespace ts.tscWatch {
810833
};
811834
const host = createWatchedSystem([moduleFile, file1, configFile, libFile]);
812835
const watch = createWatchModeWithConfigFile(configFile.path, host);
813-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
836+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
814837

815838
const moduleFileOldPath = moduleFile.path;
816839
const moduleFileNewPath = "/a/b/moduleFile1.ts";
@@ -819,12 +842,12 @@ namespace ts.tscWatch {
819842
host.runQueuedTimeoutCallbacks();
820843
checkOutputErrors(host, [
821844
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
822-
]);
845+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
823846

824847
moduleFile.path = moduleFileOldPath;
825848
host.reloadFS([moduleFile, file1, configFile, libFile]);
826849
host.runQueuedTimeoutCallbacks();
827-
checkOutputErrors(host, emptyArray);
850+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
828851
});
829852

830853
it("types should load from config file path if config exists", () => {
@@ -863,11 +886,11 @@ namespace ts.tscWatch {
863886

864887
checkOutputErrors(host, [
865888
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
866-
], /*isInitial*/ true);
889+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
867890

868891
host.reloadFS([file1, moduleFile, libFile]);
869892
host.runQueuedTimeoutCallbacks();
870-
checkOutputErrors(host, emptyArray);
893+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
871894
});
872895

873896
it("Configure file diagnostics events are generated when the config file has errors", () => {
@@ -890,7 +913,7 @@ namespace ts.tscWatch {
890913
checkOutputErrors(host, [
891914
getUnknownCompilerOption(watch(), configFile, "foo"),
892915
getUnknownCompilerOption(watch(), configFile, "allowJS")
893-
], /*isInitial*/ true);
916+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.BeforeCompilationStarts);
894917
});
895918

896919
it("If config file doesnt have errors, they are not reported", () => {
@@ -907,7 +930,7 @@ namespace ts.tscWatch {
907930

908931
const host = createWatchedSystem([file, configFile, libFile]);
909932
createWatchModeWithConfigFile(configFile.path, host);
910-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
933+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
911934
});
912935

913936
it("Reports errors when the config file changes", () => {
@@ -924,7 +947,7 @@ namespace ts.tscWatch {
924947

925948
const host = createWatchedSystem([file, configFile, libFile]);
926949
const watch = createWatchModeWithConfigFile(configFile.path, host);
927-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
950+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
928951

929952
configFile.content = `{
930953
"compilerOptions": {
@@ -935,14 +958,14 @@ namespace ts.tscWatch {
935958
host.runQueuedTimeoutCallbacks();
936959
checkOutputErrors(host, [
937960
getUnknownCompilerOption(watch(), configFile, "haha")
938-
]);
961+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
939962

940963
configFile.content = `{
941964
"compilerOptions": {}
942965
}`;
943966
host.reloadFS([file, configFile, libFile]);
944967
host.runQueuedTimeoutCallbacks();
945-
checkOutputErrors(host, emptyArray);
968+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
946969
});
947970

948971
it("non-existing directories listed in config file input array should be tolerated without crashing the server", () => {
@@ -1030,13 +1053,13 @@ namespace ts.tscWatch {
10301053
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
10311054
];
10321055
const intialErrors = errors();
1033-
checkOutputErrors(host, intialErrors, /*isInitial*/ true);
1056+
checkOutputErrors(host, intialErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
10341057

10351058
configFile.content = configFileContentWithoutCommentLine;
10361059
host.reloadFS(files);
10371060
host.runQueuedTimeoutCallbacks();
10381061
const nowErrors = errors();
1039-
checkOutputErrors(host, nowErrors);
1062+
checkOutputErrors(host, nowErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
10401063
assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length);
10411064
assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length);
10421065
});
@@ -1667,7 +1690,7 @@ namespace ts.tscWatch {
16671690
const cannotFindFoo = getDiagnosticOfFileFromProgram(watch(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo");
16681691

16691692
// ensure that imported file was found
1670-
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*isInitial*/ true);
1693+
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
16711694

16721695
const originalFileExists = host.fileExists;
16731696
{
@@ -1687,7 +1710,7 @@ namespace ts.tscWatch {
16871710
f1IsNotModule,
16881711
getDiagnosticOfFileFromProgram(watch(), root.path, newContent.indexOf("var x") + "var ".length, "x".length, Diagnostics.Type_0_is_not_assignable_to_type_1, 1, "string"),
16891712
cannotFindFoo
1690-
]);
1713+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
16911714
}
16921715
{
16931716
let fileExistsIsCalled = false;
@@ -1709,7 +1732,7 @@ namespace ts.tscWatch {
17091732
// ensure file has correct number of errors after edit
17101733
checkOutputErrors(host, [
17111734
getDiagnosticModuleNotFoundOfFile(watch(), root, "f2")
1712-
]);
1735+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
17131736

17141737
assert.isTrue(fileExistsIsCalled);
17151738
}
@@ -1730,7 +1753,7 @@ namespace ts.tscWatch {
17301753
host.reloadFS(files);
17311754
host.runQueuedTimeoutCallbacks();
17321755

1733-
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo]);
1756+
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
17341757
assert.isTrue(fileExistsCalled);
17351758
}
17361759
});
@@ -1767,15 +1790,15 @@ namespace ts.tscWatch {
17671790
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
17681791
checkOutputErrors(host, [
17691792
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
1770-
], /*isInitial*/ true);
1793+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
17711794

17721795
fileExistsCalledForBar = false;
17731796
root.content = `import {y} from "bar"`;
17741797
host.reloadFS(files.concat(imported));
17751798

17761799
host.runQueuedTimeoutCallbacks();
17771800
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
1778-
checkOutputErrors(host, emptyArray);
1801+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
17791802
});
17801803

17811804
it("should compile correctly when resolved module goes missing and then comes back (module is not part of the root)", () => {
@@ -1807,21 +1830,21 @@ namespace ts.tscWatch {
18071830
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
18081831

18091832
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
1810-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
1833+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
18111834

18121835
fileExistsCalledForBar = false;
18131836
host.reloadFS(files);
18141837
host.runQueuedTimeoutCallbacks();
18151838
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
18161839
checkOutputErrors(host, [
18171840
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
1818-
]);
1841+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
18191842

18201843
fileExistsCalledForBar = false;
18211844
host.reloadFS(filesWithImported);
18221845
host.checkTimeoutQueueLengthAndRun(1);
18231846
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
1824-
checkOutputErrors(host, emptyArray);
1847+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
18251848
});
18261849

18271850
it("works when module resolution changes to ambient module", () => {
@@ -1857,11 +1880,11 @@ declare module "fs" {
18571880

18581881
checkOutputErrors(host, [
18591882
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
1860-
], /*isInitial*/ true);
1883+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
18611884

18621885
host.reloadFS(filesWithNodeType);
18631886
host.runQueuedTimeoutCallbacks();
1864-
checkOutputErrors(host, emptyArray);
1887+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
18651888
});
18661889

18671890
it("works when included file with ambient module changes", () => {
@@ -1899,12 +1922,12 @@ declare module "fs" {
18991922

19001923
checkOutputErrors(host, [
19011924
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
1902-
], /*isInitial*/ true);
1925+
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
19031926

19041927
file.content += fileContentWithFS;
19051928
host.reloadFS(files);
19061929
host.runQueuedTimeoutCallbacks();
1907-
checkOutputErrors(host, emptyArray);
1930+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
19081931
});
19091932

19101933
it("works when reusing program with files from external library", () => {
@@ -1939,7 +1962,7 @@ declare module "fs" {
19391962
const host = createWatchedSystem(programFiles.concat(configFile), { currentDirectory: "/a/b/projects/myProject/" });
19401963
const watch = createWatchModeWithConfigFile(configFile.path, host);
19411964
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
1942-
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
1965+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
19431966
const expectedFiles: ExpectedFile[] = [
19441967
createExpectedEmittedFile(file1),
19451968
createExpectedEmittedFile(file2),
@@ -1958,7 +1981,7 @@ declare module "fs" {
19581981
host.reloadFS(programFiles.concat(configFile));
19591982
host.runQueuedTimeoutCallbacks();
19601983
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
1961-
checkOutputErrors(host, emptyArray);
1984+
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
19621985
verifyExpectedFiles(expectedFiles);
19631986

19641987

@@ -2029,7 +2052,7 @@ declare module "fs" {
20292052
});
20302053

20312054
describe("tsc-watch console clearing", () => {
2032-
it("doesn't clear the console when it starts", () => {
2055+
it("clears the console when it starts", () => {
20332056
const file = {
20342057
path: "f.ts",
20352058
content: ""
@@ -2039,7 +2062,7 @@ declare module "fs" {
20392062
createWatchModeWithoutConfigFile([file.path], host);
20402063
host.runQueuedTimeoutCallbacks();
20412064

2042-
host.checkScreenClears(0);
2065+
host.checkScreenClears(1);
20432066
});
20442067

20452068
it("clears the console on recompile", () => {
@@ -2057,7 +2080,7 @@ declare module "fs" {
20572080
host.reloadFS([modifiedFile]);
20582081
host.runQueuedTimeoutCallbacks();
20592082

2060-
host.checkScreenClears(1);
2083+
host.checkScreenClears(2);
20612084
});
20622085
});
20632086
}

0 commit comments

Comments
 (0)