Skip to content

Commit bdf1c78

Browse files
committed
Report file not found error about the project and watch config file even if not present
1 parent 8a7550f commit bdf1c78

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

src/compiler/tsbuild.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,11 @@ namespace ts {
483483
function startWatching() {
484484
const graph = getGlobalDependencyGraph();
485485
for (const resolved of graph.buildQueue) {
486+
// Watch this file
487+
watchConfigFile(resolved);
488+
486489
const cfg = parseConfigFile(resolved);
487490
if (cfg) {
488-
// Watch this file
489-
watchConfigFile(resolved);
490-
491491
// Update watchers for wildcard directories
492492
watchWildCardDirectories(resolved, cfg);
493493

@@ -879,7 +879,11 @@ namespace ts {
879879
// TODO:: handle this in better way later
880880

881881
const proj = parseConfigFile(resolved);
882-
if (!proj) return; // ?
882+
if (!proj) {
883+
reportParseConfigFileDiagnostic(resolved);
884+
return;
885+
}
886+
883887
if (reloadLevel === ConfigFileProgramReloadLevel.Full) {
884888
watchConfigFile(resolved);
885889
watchWildCardDirectories(resolved, proj);
@@ -954,6 +958,11 @@ namespace ts {
954958
}
955959
}
956960

961+
function reportParseConfigFileDiagnostic(proj: ResolvedConfigFileName) {
962+
host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic);
963+
storeErrorSummary(proj, 1);
964+
}
965+
957966
function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags {
958967
if (options.dry) {
959968
reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj);
@@ -969,8 +978,7 @@ namespace ts {
969978
if (!configFile) {
970979
// Failed to read the config file
971980
resultFlags |= BuildResultFlags.ConfigFileErrors;
972-
host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic);
973-
storeErrorSummary(proj, 1);
981+
reportParseConfigFileDiagnostic(proj);
974982
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
975983
return resultFlags;
976984
}
@@ -995,10 +1003,7 @@ namespace ts {
9951003
...program.getSyntacticDiagnostics()];
9961004
if (syntaxDiagnostics.length) {
9971005
resultFlags |= BuildResultFlags.SyntaxErrors;
998-
for (const diag of syntaxDiagnostics) {
999-
host.reportDiagnostic(diag);
1000-
}
1001-
storeErrors(proj, syntaxDiagnostics);
1006+
reportErrors(proj, syntaxDiagnostics);
10021007
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
10031008
return resultFlags;
10041009
}
@@ -1008,10 +1013,7 @@ namespace ts {
10081013
const declDiagnostics = program.getDeclarationDiagnostics();
10091014
if (declDiagnostics.length) {
10101015
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
1011-
for (const diag of declDiagnostics) {
1012-
host.reportDiagnostic(diag);
1013-
}
1014-
storeErrors(proj, declDiagnostics);
1016+
reportErrors(proj, declDiagnostics);
10151017
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
10161018
return resultFlags;
10171019
}
@@ -1021,10 +1023,7 @@ namespace ts {
10211023
const semanticDiagnostics = program.getSemanticDiagnostics();
10221024
if (semanticDiagnostics.length) {
10231025
resultFlags |= BuildResultFlags.TypeErrors;
1024-
for (const diag of semanticDiagnostics) {
1025-
host.reportDiagnostic(diag);
1026-
}
1027-
storeErrors(proj, semanticDiagnostics);
1026+
reportErrors(proj, semanticDiagnostics);
10281027
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
10291028
return resultFlags;
10301029
}
@@ -1091,6 +1090,7 @@ namespace ts {
10911090
const parsed = parseConfigFile(proj);
10921091
if (parsed === undefined) {
10931092
// File has gone missing; fine to ignore here
1093+
reportParseConfigFileDiagnostic(proj);
10941094
continue;
10951095
}
10961096
const outputs = getAllProjectOutputs(parsed);
@@ -1133,6 +1133,7 @@ namespace ts {
11331133
for (const next of graph.buildQueue) {
11341134
const proj = parseConfigFile(next);
11351135
if (proj === undefined) {
1136+
reportParseConfigFileDiagnostic(next);
11361137
anyFailed = true;
11371138
break;
11381139
}
@@ -1144,7 +1145,7 @@ namespace ts {
11441145

11451146
const projName = proj.options.configFilePath!;
11461147
if (status.type === UpToDateStatusType.UpToDate && !options.force) {
1147-
reportErrors(errors);
1148+
reportErrors(next, errors);
11481149
// Up to date, skip
11491150
if (defaultOptions.dry) {
11501151
// In a dry build, inform the user of this fact
@@ -1154,20 +1155,20 @@ namespace ts {
11541155
}
11551156

11561157
if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !options.force) {
1157-
reportErrors(errors);
1158+
reportErrors(next, errors);
11581159
// Fake build
11591160
updateOutputTimestamps(proj);
11601161
continue;
11611162
}
11621163

11631164
if (status.type === UpToDateStatusType.UpstreamBlocked) {
1164-
reportErrors(errors);
1165+
reportErrors(next, errors);
11651166
if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
11661167
continue;
11671168
}
11681169

11691170
if (status.type === UpToDateStatusType.ContainerOnly) {
1170-
reportErrors(errors);
1171+
reportErrors(next, errors);
11711172
// Do nothing
11721173
continue;
11731174
}
@@ -1179,8 +1180,9 @@ namespace ts {
11791180
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
11801181
}
11811182

1182-
function reportErrors(errors: Diagnostic[]) {
1183-
errors.forEach((err) => host.reportDiagnostic(err));
1183+
function reportErrors(proj: ResolvedConfigFileName, errors: ReadonlyArray<Diagnostic>) {
1184+
errors.forEach(err => host.reportDiagnostic(err));
1185+
storeErrors(proj, errors);
11841186
}
11851187

11861188
/**

src/testRunner/unittests/tsbuildWatchMode.ts

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,21 @@ namespace ts.tscWatch {
9898
function createSolutionInWatchMode() {
9999
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
100100
createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]);
101-
checkWatchedFiles(host, testProjectExpectedWatchedFiles);
102-
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
103-
checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true);
101+
verifyWatches(host);
104102
checkOutputErrorsInitial(host, emptyArray);
105103
const outputFileStamps = getOutputFileStamps(host);
106104
for (const stamp of outputFileStamps) {
107105
assert.isDefined(stamp[1], `${stamp[0]} expected to be present`);
108106
}
109107
return host;
110108
}
109+
110+
function verifyWatches(host: WatchedSystem) {
111+
checkWatchedFiles(host, testProjectExpectedWatchedFiles);
112+
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
113+
checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true);
114+
}
115+
111116
it("creates solution in watch mode", () => {
112117
createSolutionInWatchMode();
113118
});
@@ -197,6 +202,47 @@ export class someClass2 { }`);
197202

198203
});
199204

205+
it("watches config files that are not present", () => {
206+
const allFiles = [libFile, ...core, logic[1], ...tests];
207+
const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation });
208+
createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]);
209+
checkWatchedFiles(host, [core[0], core[1], core[2], logic[0], ...tests].map(f => f.path));
210+
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
211+
checkWatchedDirectories(host, [projectPath(SubProject.core)], /*recursive*/ true);
212+
checkOutputErrorsInitial(host, [
213+
createCompilerDiagnostic(Diagnostics.File_0_not_found, logic[0].path)
214+
]);
215+
for (const f of [
216+
...getOutputFileNames(SubProject.core, "anotherModule"),
217+
...getOutputFileNames(SubProject.core, "index")
218+
]) {
219+
assert.isTrue(host.fileExists(f), `${f} expected to be present`);
220+
}
221+
for (const f of [
222+
...getOutputFileNames(SubProject.logic, "index"),
223+
...getOutputFileNames(SubProject.tests, "index")
224+
]) {
225+
assert.isFalse(host.fileExists(f), `${f} expected to be absent`);
226+
}
227+
228+
// Create tsconfig file for logic and see that build succeeds
229+
const initial = getOutputFileStamps(host);
230+
host.writeFile(logic[0].path, logic[0].content);
231+
host.checkTimeoutQueueLengthAndRun(1); // Builds logic
232+
const changedLogic = getOutputFileStamps(host);
233+
verifyChangedFiles(changedLogic, initial, [
234+
...getOutputFileNames(SubProject.logic, "index")
235+
]);
236+
host.checkTimeoutQueueLengthAndRun(1); // Builds tests
237+
const changedTests = getOutputFileStamps(host);
238+
verifyChangedFiles(changedTests, changedLogic, [
239+
...getOutputFileNames(SubProject.tests, "index")
240+
]);
241+
host.checkTimeoutQueueLength(0);
242+
checkOutputErrorsIncremental(host, emptyArray);
243+
verifyWatches(host);
244+
});
245+
200246
// TODO: write tests reporting errors but that will have more involved work since file
201247
});
202248
}

0 commit comments

Comments
 (0)