Improve handling of container projects and issue relative filename messages

This commit is contained in:
Ryan Cavanaugh 2018-06-06 13:47:59 -07:00
parent 291289f8c2
commit b107849a3a
2 changed files with 103 additions and 47 deletions

View file

@ -3632,78 +3632,82 @@
"category": "Message", "category": "Message",
"code": 6352 "code": 6352
}, },
"Project '{0}' is out of date because its dependency '{1}' is out of date": {
"Project '{0}' is up to date with .d.ts files from its dependencies": {
"category": "Message", "category": "Message",
"code": 6353 "code": 6353
}, },
"Projects in this build: {0}": {
"Project '{0}' is up to date with .d.ts files from its dependencies": {
"category": "Message", "category": "Message",
"code": 6354 "code": 6354
}, },
"A non-dry build would delete the following files: {0}": { "Projects in this build: {0}": {
"category": "Message", "category": "Message",
"code": 6355 "code": 6355
}, },
"A non-dry build would build project '{0}'": { "A non-dry build would delete the following files: {0}": {
"category": "Message", "category": "Message",
"code": 6356 "code": 6356
}, },
"Building project '{0}'...": { "A non-dry build would build project '{0}'": {
"category": "Message", "category": "Message",
"code": 6357 "code": 6357
}, },
"Updating output timestamps of project '{0}'...": { "Building project '{0}'...": {
"category": "Message", "category": "Message",
"code": 6358 "code": 6358
}, },
"delete this - Project '{0}' is up to date because it was previously built": { "Updating output timestamps of project '{0}'...": {
"category": "Message", "category": "Message",
"code": 6359 "code": 6359
}, },
"Project '{0}' is up to date": { "delete this - Project '{0}' is up to date because it was previously built": {
"category": "Message", "category": "Message",
"code": 6360 "code": 6360
}, },
"Skipping build of project '{0}' because its dependency '{1}' has errors": { "Project '{0}' is up to date": {
"category": "Message", "category": "Message",
"code": 6361 "code": 6361
}, },
"Project '{0}' can't be built because its dependency '{1}' has errors": { "Skipping build of project '{0}' because its dependency '{1}' has errors": {
"category": "Message", "category": "Message",
"code": 6362 "code": 6362
}, },
"Build one or more projects and their dependencies, if out of date": { "Project '{0}' can't be built because its dependency '{1}' has errors": {
"category": "Message", "category": "Message",
"code": 6363 "code": 6363
}, },
"Delete the outputs of all projects": { "Build one or more projects and their dependencies, if out of date": {
"category": "Message", "category": "Message",
"code": 6364 "code": 6364
}, },
"Enable verbose logging": { "Delete the outputs of all projects": {
"category": "Message", "category": "Message",
"code": 6365 "code": 6365
}, },
"Show what would be built (or deleted, if specified with '--clean')": { "Enable verbose logging": {
"category": "Message", "category": "Message",
"code": 6366 "code": 6366
}, },
"Build all projects, including those that appear to be up to date": { "Show what would be built (or deleted, if specified with '--clean')": {
"category": "Message", "category": "Message",
"code": 6367 "code": 6367
}, },
"Option '--build' must be the first command line argument.": { "Build all projects, including those that appear to be up to date": {
"category": "Error", "category": "Message",
"code": 6368 "code": 6368
}, },
"Options '{0}' and '{1}' cannot be combined.": { "Option '--build' must be the first command line argument.": {
"category": "Error", "category": "Error",
"code": 6369 "code": 6369
}, },
"Options '{0}' and '{1}' cannot be combined.": {
"category": "Error",
"code": 6370
},
"Skipping clean because not all projects could be located": { "Skipping clean because not all projects could be located": {
"category": "Error", "category": "Error",
"code": 6340 "code": 6371
}, },
"Variable '{0}' implicitly has an '{1}' type.": { "Variable '{0}' implicitly has an '{1}' type.": {

View file

@ -90,7 +90,12 @@ namespace ts {
OutOfDateWithSelf, OutOfDateWithSelf,
OutOfDateWithUpstream, OutOfDateWithUpstream,
UpstreamOutOfDate, UpstreamOutOfDate,
UpstreamBlocked UpstreamBlocked,
/**
* Projects with no outputs (i.e. "solution" files)
*/
ContainerOnly
} }
export type UpToDateStatus = export type UpToDateStatus =
@ -100,7 +105,8 @@ namespace ts {
| Status.OutOfDateWithSelf | Status.OutOfDateWithSelf
| Status.OutOfDateWithUpstream | Status.OutOfDateWithUpstream
| Status.UpstreamOutOfDate | Status.UpstreamOutOfDate
| Status.UpstreamBlocked; | Status.UpstreamBlocked
| Status.ContainerOnly;
export namespace Status { export namespace Status {
/** /**
@ -112,6 +118,13 @@ namespace ts {
reason: string; reason: string;
} }
/**
* This project doesn't have any outputs, so "is it up to date" is a meaningless question.
*/
export interface ContainerOnly {
type: UpToDateStatusType.ContainerOnly;
}
/** /**
* The project is up to date with respect to its inputs. * The project is up to date with respect to its inputs.
* We track what the newest input file is. * We track what the newest input file is.
@ -119,8 +132,11 @@ namespace ts {
export interface UpToDate { export interface UpToDate {
type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes; type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
newestInputFileTime: Date; newestInputFileTime: Date;
newestInputFileName: string;
newestDeclarationFileContentChangedTime: Date; newestDeclarationFileContentChangedTime: Date;
newestOutputFileTime: Date; newestOutputFileTime: Date;
newestOutputFileName: string;
oldestOutputFileName: string;
} }
/** /**
@ -684,12 +700,19 @@ namespace ts {
// Collect the expected outputs of this project // Collect the expected outputs of this project
const outputs = getAllProjectOutputs(project); const outputs = getAllProjectOutputs(project);
if (outputs.length === 0) {
return {
type: UpToDateStatusType.ContainerOnly
};
}
// Now see if all outputs are newer than the newest input // Now see if all outputs are newer than the newest input
let oldestOutputFileName: string | undefined; let oldestOutputFileName = "(none)";
let oldestOutputFileTime: Date = maximumDate; let oldestOutputFileTime = maximumDate;
let newestOutputFileTime: Date = minimumDate; let newestOutputFileName = "(none)";
let newestDeclarationFileContentChangedTime: Date = minimumDate; let newestOutputFileTime = minimumDate;
let missingOutputFileName: string | undefined; let missingOutputFileName: string | undefined;
let newestDeclarationFileContentChangedTime = minimumDate;
let isOutOfDateWithInputs = false; let isOutOfDateWithInputs = false;
for (const output of outputs) { for (const output of outputs) {
// Output is missing; can stop checking // Output is missing; can stop checking
@ -712,7 +735,10 @@ namespace ts {
break; break;
} }
newestOutputFileTime = newer(newestOutputFileTime, outputTime); if (outputTime > newestOutputFileTime) {
newestOutputFileTime = outputTime;
newestOutputFileName = output;
}
// Keep track of when the most recent time a .d.ts file was changed. // Keep track of when the most recent time a .d.ts file was changed.
// In addition to file timestamps, we also keep track of when a .d.ts file // In addition to file timestamps, we also keep track of when a .d.ts file
@ -768,7 +794,7 @@ namespace ts {
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
return { return {
type: UpToDateStatusType.OutOfDateWithUpstream, type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName!, outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: ref.path newerProjectName: ref.path
}; };
} }
@ -784,7 +810,7 @@ namespace ts {
if (isOutOfDateWithInputs) { if (isOutOfDateWithInputs) {
return { return {
type: UpToDateStatusType.OutOfDateWithSelf, type: UpToDateStatusType.OutOfDateWithSelf,
outOfDateOutputFileName: oldestOutputFileName!, outOfDateOutputFileName: oldestOutputFileName,
newerInputFileName: newestInputFileName newerInputFileName: newestInputFileName
}; };
} }
@ -794,7 +820,10 @@ namespace ts {
type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime, newestDeclarationFileContentChangedTime,
newestInputFileTime, newestInputFileTime,
newestOutputFileTime newestOutputFileTime,
newestInputFileName,
newestOutputFileName,
oldestOutputFileName
}; };
} }
@ -1087,6 +1116,11 @@ namespace ts {
continue; continue;
} }
if (status.type === UpToDateStatusType.ContainerOnly) {
// Do nothing
continue;
}
buildSingleProject(next); buildSingleProject(next);
} }
} }
@ -1101,7 +1135,11 @@ namespace ts {
for (const name of graph.buildQueue) { for (const name of graph.buildQueue) {
names.push(name); names.push(name);
} }
context.verbose(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + s).join("")); context.verbose(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join(""));
}
function relName(path: string): string {
return convertToRelativePath(path, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
} }
/** /**
@ -1111,32 +1149,46 @@ namespace ts {
if (!context.options.verbose) return; if (!context.options.verbose) return;
switch (status.type) { switch (status.type) {
case UpToDateStatusType.OutOfDateWithSelf: case UpToDateStatusType.OutOfDateWithSelf:
context.verbose(Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, configFileName, status.outOfDateOutputFileName, status.newerInputFileName); return context.verbose(Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
return; relName(configFileName),
relName(status.outOfDateOutputFileName),
relName(status.newerInputFileName));
case UpToDateStatusType.OutOfDateWithUpstream: case UpToDateStatusType.OutOfDateWithUpstream:
context.verbose(Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, configFileName, status.outOfDateOutputFileName, status.newerProjectName); return context.verbose(Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2,
return; relName(configFileName),
relName(status.outOfDateOutputFileName),
relName(status.newerProjectName));
case UpToDateStatusType.OutputMissing: case UpToDateStatusType.OutputMissing:
context.verbose(Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, configFileName, status.missingOutputFileName); return context.verbose(Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist,
return; relName(configFileName),
relName(status.missingOutputFileName));
case UpToDateStatusType.UpToDate: case UpToDateStatusType.UpToDate:
if (status.newestInputFileTime !== undefined) { if (status.newestInputFileTime !== undefined) {
context.verbose(Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFileName, status.newestInputFileTime, status.newestOutputFileTime); return context.verbose(Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2,
relName(configFileName),
relName(status.newestInputFileName),
relName(status.oldestOutputFileName));
} }
// Don't report anything for "up to date because it was already built" -- too verbose // Don't report anything for "up to date because it was already built" -- too verbose
return; break;
case UpToDateStatusType.UpToDateWithUpstreamTypes: case UpToDateStatusType.UpToDateWithUpstreamTypes:
context.verbose(Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, configFileName); return context.verbose(Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
return; relName(configFileName));
case UpToDateStatusType.UpstreamOutOfDate: case UpToDateStatusType.UpstreamOutOfDate:
context.verbose(Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, configFileName); return context.verbose(Diagnostics.Project_0_is_out_of_date_because_its_dependency_1_is_out_of_date,
return; relName(configFileName),
relName(status.upstreamProjectName));
case UpToDateStatusType.UpstreamBlocked: case UpToDateStatusType.UpstreamBlocked:
context.verbose(Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, configFileName, status.upstreamProjectName); return context.verbose(Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors,
return; relName(configFileName),
relName(status.upstreamProjectName));
case UpToDateStatusType.Unbuildable: case UpToDateStatusType.Unbuildable:
context.verbose(Diagnostics.Failed_to_parse_file_0_Colon_1, configFileName, status.reason); return context.verbose(Diagnostics.Failed_to_parse_file_0_Colon_1,
return; relName(configFileName),
status.reason);
case UpToDateStatusType.ContainerOnly:
// Don't report status on "solution" projects
break;
default: default:
assertTypeIsNever(status); assertTypeIsNever(status);
} }