diff --git a/lib/enu/diagnosticMessages.generated.json.lcg b/lib/enu/diagnosticMessages.generated.json.lcg
index a3f7dd8da25..d5c7c994b8c 100644
--- a/lib/enu/diagnosticMessages.generated.json.lcg
+++ b/lib/enu/diagnosticMessages.generated.json.lcg
@@ -5937,6 +5937,12 @@
+ -
+
+
+
+
+
-
diff --git a/lib/tsc.js b/lib/tsc.js
index 4485db040ee..ffa48aa025d 100644
--- a/lib/tsc.js
+++ b/lib/tsc.js
@@ -3394,6 +3394,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -9403,7 +9404,7 @@ var ts;
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -9415,9 +9416,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1:
- return undefined;
+ break;
case 193: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -9425,10 +9424,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -18520,20 +18517,20 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
}
@@ -18672,6 +18669,10 @@ var ts;
}
ts.parseCommandLine = parseCommandLine;
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -18683,7 +18684,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -35257,7 +35258,7 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
+ if (flowDepth === 2000) {
flowAnalysisDisabled = true;
reportFlowControlError(reference);
return errorType;
@@ -35374,7 +35375,7 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -40786,9 +40787,13 @@ var ts;
return cache ? checkExpressionCached(node) : checkExpression(node);
}
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1);
node.contextualType = saveContextualType;
return type;
}
@@ -66658,15 +66663,20 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -66682,7 +66692,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -66692,7 +66702,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -66700,8 +66710,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data);
- var mtimeBefore = ts.sys.getModifiedTime(fileName);
+ var hash = system.createHash(data);
+ var mtimeBefore = system.getModifiedTime(fileName);
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
if (fingerprint &&
@@ -66711,8 +66721,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName);
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime;
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -66723,11 +66733,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -66739,33 +66749,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -70153,16 +70160,12 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
function clearScreenIfNotWatchingForFileChanges(system, diagnostic, options) {
if (system.clearScreen &&
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -70247,6 +70250,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
function createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) {
if (system === void 0) { system = ts.sys; }
if (!createProgram) {
@@ -70255,7 +70277,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -70269,17 +70291,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -70784,7 +70799,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -70811,6 +70827,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -70922,145 +70941,97 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts");
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- addProject(arg);
- }
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
- }
- ts.performBuild = performBuild;
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
- var context = createBuildContext(defaultOptions);
- var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
};
+ }
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
+ var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
+ var existingWatchersForWildcards = ts.createMap();
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -71069,16 +71040,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
return;
@@ -71086,20 +71078,20 @@ var ts;
var _loop_12 = function (resolved) {
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1));
});
}
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -71109,11 +71101,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -71132,7 +71124,143 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -71140,28 +71268,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -71182,7 +71322,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -71213,7 +71353,7 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -71243,16 +71383,17 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -71261,7 +71402,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -71271,8 +71412,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -71282,8 +71424,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -71293,8 +71436,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -71302,16 +71446,16 @@ var ts;
var anyDtsChanged = false;
program.emit(undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -71326,19 +71470,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -71357,9 +71502,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -71378,37 +71523,34 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -71424,9 +71566,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -71442,7 +71589,7 @@ var ts;
var projName = proj.options.configFilePath;
if (status.type === UpToDateStatusType.UpToDate && !context.options.force) {
if (defaultOptions.dry) {
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -71452,7 +71599,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -71461,6 +71608,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
function reportBuildQueue(graph) {
@@ -71472,166 +71620,18 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);
@@ -71695,7 +71695,7 @@ var ts;
return !!ts.sys.writeOutputIsTTY && ts.sys.writeOutputIsTTY();
}
function shouldBePretty(options) {
- if (typeof options.pretty === "undefined") {
+ if (!options || typeof options.pretty === "undefined") {
return defaultIsPretty();
}
return options.pretty;
@@ -71720,21 +71720,7 @@ var ts;
}
function executeCommandLine(args) {
if (args.length > 0 && ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b"))) {
- var reportDiag_1 = ts.createDiagnosticReporter(ts.sys, defaultIsPretty());
- var report = function (message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- return reportDiag_1(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
- };
- var buildHost = {
- error: report,
- verbose: report,
- message: report,
- errorDiagnostic: function (d) { return reportDiag_1(d); }
- };
- var result = ts.performBuild(args.slice(1), ts.createCompilerHost({}), buildHost, ts.sys);
+ var result = performBuild(args.slice(1));
// undefined = in watch mode, do not exit
if (result !== undefined) {
return ts.sys.exit(result);
@@ -71832,6 +71818,136 @@ var ts;
ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
}
+ function performBuild(args) {
+ var buildOpts = [
+ {
+ name: "help",
+ shortName: "h",
+ type: "boolean",
+ showInSimplifiedHelpView: true,
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Print_this_message,
+ },
+ {
+ name: "help",
+ shortName: "?",
+ type: "boolean"
+ },
+ {
+ name: "verbose",
+ shortName: "v",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Enable_verbose_logging,
+ type: "boolean"
+ },
+ {
+ name: "dry",
+ shortName: "d",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
+ type: "boolean"
+ },
+ {
+ name: "force",
+ shortName: "f",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
+ type: "boolean"
+ },
+ {
+ name: "clean",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
+ type: "boolean"
+ },
+ {
+ name: "watch",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Watch_input_files,
+ type: "boolean"
+ },
+ {
+ name: "preserveWatchOutput",
+ type: "boolean",
+ category: ts.Diagnostics.Command_line_Options,
+ description: ts.Diagnostics.Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen,
+ },
+ ];
+ var buildOptionNameMap;
+ var returnBuildOptionNameMap = function () { return (buildOptionNameMap || (buildOptionNameMap = ts.createOptionNameMap(buildOpts))); };
+ var buildOptions = {};
+ var projects = [];
+ for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
+ var arg = args_1[_i];
+ if (arg.charCodeAt(0) === 45 /* minus */) {
+ var opt = ts.getOptionDeclarationFromName(returnBuildOptionNameMap, arg.slice(arg.charCodeAt(1) === 45 /* minus */ ? 2 : 1), /*allowShort*/ true);
+ if (opt) {
+ buildOptions[opt.name] = true;
+ }
+ else {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_build_option_0, arg));
+ }
+ }
+ else {
+ // Not a flag, parse as filename
+ addProject(arg);
+ }
+ }
+ if (buildOptions.help) {
+ ts.printVersion();
+ ts.printHelp(buildOpts, "--build ");
+ return ts.ExitStatus.Success;
+ }
+ // Update to pretty if host supports it
+ updateReportDiagnostic();
+ if (!ts.sys.getModifiedTime || !ts.sys.setModifiedTime || (buildOptions.clean && !ts.sys.deleteFile)) {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--build"));
+ return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
+ if (buildOptions.watch) {
+ reportWatchModeWithoutSysSupport();
+ }
+ // Nonsensical combinations
+ if (buildOptions.clean && buildOptions.force) {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"));
+ return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
+ if (buildOptions.clean && buildOptions.verbose) {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"));
+ return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
+ if (buildOptions.clean && buildOptions.watch) {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"));
+ return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
+ if (buildOptions.watch && buildOptions.dry) {
+ reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"));
+ return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
+ if (projects.length === 0) {
+ // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
+ addProject(".");
+ }
+ // TODO: change this to host if watch => watchHost otherwiue without wathc
+ var builder = ts.createSolutionBuilder(ts.createSolutionBuilderWithWatchHost(ts.sys, reportDiagnostic, ts.createBuilderStatusReporter(ts.sys, shouldBePretty()), createWatchStatusReporter()), projects, buildOptions);
+ if (buildOptions.clean) {
+ return builder.cleanAllProjects();
+ }
+ if (buildOptions.watch) {
+ builder.buildAllProjects();
+ builder.startWatching();
+ return undefined;
+ }
+ return builder.buildAllProjects();
+ function addProject(projectSpecification) {
+ var fileName = ts.resolvePath(ts.sys.getCurrentDirectory(), projectSpecification);
+ var refPath = ts.resolveProjectReferencePath(ts.sys, { path: fileName });
+ if (!ts.sys.fileExists(refPath)) {
+ return reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_does_not_exist, fileName));
+ }
+ projects.push(refPath);
+ }
+ }
function performCompilation(rootNames, projectReferences, options, configFileParsingDiagnostics) {
var host = ts.createCompilerHost(options);
enableStatistics(options);
diff --git a/lib/tsserver.js b/lib/tsserver.js
index e1b2674c296..034294039ef 100644
--- a/lib/tsserver.js
+++ b/lib/tsserver.js
@@ -5260,6 +5260,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -12035,13 +12036,13 @@ var ts;
if (ts.isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
- // Covers remaining cases
+ // Covers remaining cases (returning undefined if none match).
switch (hostNode.kind) {
case 217 /* VariableStatement */:
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219 /* ExpressionStatement */:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -12053,9 +12054,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1 /* EndOfFileToken */:
- return undefined;
+ break;
case 193 /* ParenthesizedExpression */: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -12063,10 +12062,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -22930,20 +22927,21 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ /*@internal*/
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
/* @internal */
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
@@ -23090,6 +23088,11 @@ var ts;
ts.parseCommandLine = parseCommandLine;
/** @internal */
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ /*@internal*/
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -23102,7 +23105,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -42306,8 +42309,8 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
- // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
+ if (flowDepth === 2000) {
+ // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
@@ -42443,7 +42446,8 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -49100,9 +49104,13 @@ var ts;
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */);
node.contextualType = saveContextualType;
return type;
}
@@ -82171,17 +82179,24 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ /*@internal*/
+ // TODO(shkamat): update this after reworking ts build API
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -82197,7 +82212,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -82207,7 +82222,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -82215,8 +82230,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data); // TODO: GH#18217
- var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ var hash = system.createHash(data); // TODO: GH#18217
+ var mtimeBefore = system.getModifiedTime(fileName); // TODO: GH#18217
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
@@ -82227,8 +82242,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; // TODO: GH#18217
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -82239,11 +82254,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -82255,33 +82270,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -86273,11 +86285,6 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- /** @internal */
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
/**
* @returns Whether the screen was cleared.
*/
@@ -86286,7 +86293,7 @@ var ts;
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -86386,6 +86393,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@@ -86397,7 +86423,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -86411,17 +86437,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -86996,7 +87015,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -87023,6 +87043,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -87135,152 +87158,108 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */);
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ // Mark all downstream projects of this one needing to be built "later"
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ // Can skip circular references
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- // Not a flag, parse as filename
- addProject(arg);
- }
- // Nonsensical combinations
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
+ /**
+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
+ */
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
+ };
}
- ts.performBuild = performBuild;
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, /*setParentNodes*/ undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
+ * TODO: use SolutionBuilderWithWatchHost => watchedSolution
+ * use SolutionBuilderHost => Solution
*/
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
- };
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -87289,16 +87268,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
// Everything is broken - we don't even know what to watch. Give up.
@@ -87308,14 +87308,14 @@ var ts;
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
// Watch this file
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
// Update watchers for wildcard directories
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1 /* Recursive */));
});
@@ -87323,7 +87323,7 @@ var ts;
// Watch input files
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -87333,11 +87333,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -87356,7 +87356,162 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ // Get timestamps of input files
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ // Collect the expected outputs of this project
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ // Now see if all outputs are newer than the newest input
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ // Output is missing; can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ // If an output is older than the newest input, we can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ // 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
+ // had its file touched but not had its contents changed - this allows us
+ // to skip a downstream typecheck
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ // An upstream project is blocked
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project's newest file is older than our oldest output, we
+ // can't be out of date because of it
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ // We have an output older than an upstream output - we are out of date
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ // Up to date
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -87368,30 +87523,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- // Mark all downstream projects of this one needing to be built "later"
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- // Can skip circular references
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -87412,7 +87577,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -87445,7 +87610,8 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ // TODO(shkamat): Account for this error
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -87475,17 +87641,18 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
// Failed to read the config file
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -87495,7 +87662,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -87506,8 +87673,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -87518,8 +87686,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -87530,8 +87699,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -87539,17 +87709,17 @@ var ts;
var anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
// Check for unchanged .d.ts files
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -87564,19 +87734,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -87597,9 +87768,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -87618,38 +87789,35 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- // Do this check later to allow --clean --dry to function even if the host can't delete files
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -87665,9 +87833,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -87685,7 +87858,7 @@ var ts;
// Up to date, skip
if (defaultOptions.dry) {
// In a dry build, inform the user of this fact
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -87696,7 +87869,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -87706,6 +87879,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
/**
@@ -87720,17 +87894,10 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
/**
* Report the up-to-date status of a project if we're in verbose mode
@@ -87738,173 +87905,10 @@ var ts;
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- /**
- * Gets the UpToDateStatus for a project
- */
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- // Get timestamps of input files
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- // Collect the expected outputs of this project
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- // Now see if all outputs are newer than the newest input
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- // Output is missing; can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- // If an output is older than the newest input, we can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- // 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
- // had its file touched but not had its contents changed - this allows us
- // to skip a downstream typecheck
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- // An upstream project is blocked
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project's newest file is older than our oldest output, we
- // can't be out of date because of it
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- // If the upstream project has only change .d.ts files, and we've built
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- // We have an output older than an upstream output - we are out of date
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- // Up to date
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);
diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts
index b16026b18a8..7221c99f9ef 100644
--- a/lib/tsserverlibrary.d.ts
+++ b/lib/tsserverlibrary.d.ts
@@ -2677,9 +2677,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
- getModifiedTime?(fileName: string): Date;
- setModifiedTime?(fileName: string, date: Date): void;
- deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -4295,15 +4292,26 @@ declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T;
- interface WatchCompilerHost {
+ /** Host that has watch functionality used in --watch mode */
+ interface WatchHost {
+ /** If provided, called with Diagnostic message that informs about change in watch status */
+ onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
+ /** Used to watch changes in source files, missing files needed to update the program or config file */
+ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
+ /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
+ watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
+ /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
+ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
+ /** If provided, will be used to reset existing delayed compilation */
+ clearTimeout?(timeoutId: any): void;
+ }
+ interface WatchCompilerHost extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
- /** If provided, called with Diagnostic message that informs about change in watch status */
- onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4336,14 +4344,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
- /** Used to watch changes in source files, missing files needed to update the program or config file */
- watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
- /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
- watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
- /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
- setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
- /** If provided, will be used to reset existing delayed compilation */
- clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js
index 6eabbce765d..37121cd7f6e 100644
--- a/lib/tsserverlibrary.js
+++ b/lib/tsserverlibrary.js
@@ -5247,6 +5247,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -12022,13 +12023,13 @@ var ts;
if (ts.isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
- // Covers remaining cases
+ // Covers remaining cases (returning undefined if none match).
switch (hostNode.kind) {
case 217 /* VariableStatement */:
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219 /* ExpressionStatement */:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -12040,9 +12041,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1 /* EndOfFileToken */:
- return undefined;
+ break;
case 193 /* ParenthesizedExpression */: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -12050,10 +12049,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -22917,20 +22914,21 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ /*@internal*/
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
/* @internal */
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
@@ -23077,6 +23075,11 @@ var ts;
ts.parseCommandLine = parseCommandLine;
/** @internal */
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ /*@internal*/
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -23089,7 +23092,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -42293,8 +42296,8 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
- // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
+ if (flowDepth === 2000) {
+ // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
@@ -42430,7 +42433,8 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -49087,9 +49091,13 @@ var ts;
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */);
node.contextualType = saveContextualType;
return type;
}
@@ -82158,17 +82166,24 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ /*@internal*/
+ // TODO(shkamat): update this after reworking ts build API
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -82184,7 +82199,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -82194,7 +82209,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -82202,8 +82217,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data); // TODO: GH#18217
- var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ var hash = system.createHash(data); // TODO: GH#18217
+ var mtimeBefore = system.getModifiedTime(fileName); // TODO: GH#18217
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
@@ -82214,8 +82229,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; // TODO: GH#18217
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -82226,11 +82241,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -82242,33 +82257,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -86260,11 +86272,6 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- /** @internal */
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
/**
* @returns Whether the screen was cleared.
*/
@@ -86273,7 +86280,7 @@ var ts;
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -86373,6 +86380,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@@ -86384,7 +86410,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -86398,17 +86424,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -86983,7 +87002,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -87010,6 +87030,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -87122,152 +87145,108 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */);
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ // Mark all downstream projects of this one needing to be built "later"
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ // Can skip circular references
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- // Not a flag, parse as filename
- addProject(arg);
- }
- // Nonsensical combinations
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
+ /**
+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
+ */
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
+ };
}
- ts.performBuild = performBuild;
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, /*setParentNodes*/ undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
+ * TODO: use SolutionBuilderWithWatchHost => watchedSolution
+ * use SolutionBuilderHost => Solution
*/
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
- };
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -87276,16 +87255,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
// Everything is broken - we don't even know what to watch. Give up.
@@ -87295,14 +87295,14 @@ var ts;
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
// Watch this file
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
// Update watchers for wildcard directories
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1 /* Recursive */));
});
@@ -87310,7 +87310,7 @@ var ts;
// Watch input files
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -87320,11 +87320,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -87343,7 +87343,162 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ // Get timestamps of input files
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ // Collect the expected outputs of this project
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ // Now see if all outputs are newer than the newest input
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ // Output is missing; can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ // If an output is older than the newest input, we can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ // 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
+ // had its file touched but not had its contents changed - this allows us
+ // to skip a downstream typecheck
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ // An upstream project is blocked
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project's newest file is older than our oldest output, we
+ // can't be out of date because of it
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ // We have an output older than an upstream output - we are out of date
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ // Up to date
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -87355,30 +87510,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- // Mark all downstream projects of this one needing to be built "later"
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- // Can skip circular references
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -87399,7 +87564,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -87432,7 +87597,8 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ // TODO(shkamat): Account for this error
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -87462,17 +87628,18 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
// Failed to read the config file
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -87482,7 +87649,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -87493,8 +87660,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -87505,8 +87673,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -87517,8 +87686,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -87526,17 +87696,17 @@ var ts;
var anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
// Check for unchanged .d.ts files
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -87551,19 +87721,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -87584,9 +87755,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -87605,38 +87776,35 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- // Do this check later to allow --clean --dry to function even if the host can't delete files
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -87652,9 +87820,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -87672,7 +87845,7 @@ var ts;
// Up to date, skip
if (defaultOptions.dry) {
// In a dry build, inform the user of this fact
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -87683,7 +87856,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -87693,6 +87866,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
/**
@@ -87707,17 +87881,10 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
/**
* Report the up-to-date status of a project if we're in verbose mode
@@ -87725,173 +87892,10 @@ var ts;
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- /**
- * Gets the UpToDateStatus for a project
- */
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- // Get timestamps of input files
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- // Collect the expected outputs of this project
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- // Now see if all outputs are newer than the newest input
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- // Output is missing; can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- // If an output is older than the newest input, we can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- // 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
- // had its file touched but not had its contents changed - this allows us
- // to skip a downstream typecheck
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- // An upstream project is blocked
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project's newest file is older than our oldest output, we
- // can't be out of date because of it
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- // If the upstream project has only change .d.ts files, and we've built
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- // We have an output older than an upstream output - we are out of date
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- // Up to date
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);
diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts
index bb03f59ceb8..f7ab36b4702 100644
--- a/lib/typescript.d.ts
+++ b/lib/typescript.d.ts
@@ -2677,9 +2677,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
- getModifiedTime?(fileName: string): Date;
- setModifiedTime?(fileName: string, date: Date): void;
- deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -4295,15 +4292,26 @@ declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T;
- interface WatchCompilerHost {
+ /** Host that has watch functionality used in --watch mode */
+ interface WatchHost {
+ /** If provided, called with Diagnostic message that informs about change in watch status */
+ onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
+ /** Used to watch changes in source files, missing files needed to update the program or config file */
+ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
+ /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
+ watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
+ /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
+ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
+ /** If provided, will be used to reset existing delayed compilation */
+ clearTimeout?(timeoutId: any): void;
+ }
+ interface WatchCompilerHost extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
- /** If provided, called with Diagnostic message that informs about change in watch status */
- onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4336,14 +4344,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
- /** Used to watch changes in source files, missing files needed to update the program or config file */
- watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
- /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
- watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
- /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
- setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
- /** If provided, will be used to reset existing delayed compilation */
- clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
diff --git a/lib/typescript.js b/lib/typescript.js
index 0506f341189..c80cb8e0938 100644
--- a/lib/typescript.js
+++ b/lib/typescript.js
@@ -5247,6 +5247,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -12022,13 +12023,13 @@ var ts;
if (ts.isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
- // Covers remaining cases
+ // Covers remaining cases (returning undefined if none match).
switch (hostNode.kind) {
case 217 /* VariableStatement */:
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219 /* ExpressionStatement */:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -12040,9 +12041,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1 /* EndOfFileToken */:
- return undefined;
+ break;
case 193 /* ParenthesizedExpression */: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -12050,10 +12049,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -22917,20 +22914,21 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ /*@internal*/
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
/* @internal */
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
@@ -23077,6 +23075,11 @@ var ts;
ts.parseCommandLine = parseCommandLine;
/** @internal */
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ /*@internal*/
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -23089,7 +23092,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -42293,8 +42296,8 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
- // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
+ if (flowDepth === 2000) {
+ // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
@@ -42430,7 +42433,8 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -49087,9 +49091,13 @@ var ts;
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */);
node.contextualType = saveContextualType;
return type;
}
@@ -82158,17 +82166,24 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ /*@internal*/
+ // TODO(shkamat): update this after reworking ts build API
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -82184,7 +82199,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -82194,7 +82209,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -82202,8 +82217,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data); // TODO: GH#18217
- var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ var hash = system.createHash(data); // TODO: GH#18217
+ var mtimeBefore = system.getModifiedTime(fileName); // TODO: GH#18217
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
@@ -82214,8 +82229,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; // TODO: GH#18217
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -82226,11 +82241,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -82242,33 +82257,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -86260,11 +86272,6 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- /** @internal */
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
/**
* @returns Whether the screen was cleared.
*/
@@ -86273,7 +86280,7 @@ var ts;
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -86373,6 +86380,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@@ -86384,7 +86410,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -86398,17 +86424,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -86983,7 +87002,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -87010,6 +87030,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -87122,152 +87145,108 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */);
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ // Mark all downstream projects of this one needing to be built "later"
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ // Can skip circular references
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- // Not a flag, parse as filename
- addProject(arg);
- }
- // Nonsensical combinations
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
+ /**
+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
+ */
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
+ };
}
- ts.performBuild = performBuild;
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, /*setParentNodes*/ undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
+ * TODO: use SolutionBuilderWithWatchHost => watchedSolution
+ * use SolutionBuilderHost => Solution
*/
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
- };
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -87276,16 +87255,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
// Everything is broken - we don't even know what to watch. Give up.
@@ -87295,14 +87295,14 @@ var ts;
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
// Watch this file
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
// Update watchers for wildcard directories
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1 /* Recursive */));
});
@@ -87310,7 +87310,7 @@ var ts;
// Watch input files
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -87320,11 +87320,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -87343,7 +87343,162 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ // Get timestamps of input files
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ // Collect the expected outputs of this project
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ // Now see if all outputs are newer than the newest input
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ // Output is missing; can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ // If an output is older than the newest input, we can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ // 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
+ // had its file touched but not had its contents changed - this allows us
+ // to skip a downstream typecheck
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ // An upstream project is blocked
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project's newest file is older than our oldest output, we
+ // can't be out of date because of it
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ // We have an output older than an upstream output - we are out of date
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ // Up to date
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -87355,30 +87510,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- // Mark all downstream projects of this one needing to be built "later"
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- // Can skip circular references
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -87399,7 +87564,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -87432,7 +87597,8 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ // TODO(shkamat): Account for this error
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -87462,17 +87628,18 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
// Failed to read the config file
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -87482,7 +87649,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -87493,8 +87660,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -87505,8 +87673,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -87517,8 +87686,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -87526,17 +87696,17 @@ var ts;
var anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
// Check for unchanged .d.ts files
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -87551,19 +87721,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -87584,9 +87755,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -87605,38 +87776,35 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- // Do this check later to allow --clean --dry to function even if the host can't delete files
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -87652,9 +87820,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -87672,7 +87845,7 @@ var ts;
// Up to date, skip
if (defaultOptions.dry) {
// In a dry build, inform the user of this fact
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -87683,7 +87856,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -87693,6 +87866,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
/**
@@ -87707,17 +87881,10 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
/**
* Report the up-to-date status of a project if we're in verbose mode
@@ -87725,173 +87892,10 @@ var ts;
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- /**
- * Gets the UpToDateStatus for a project
- */
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- // Get timestamps of input files
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- // Collect the expected outputs of this project
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- // Now see if all outputs are newer than the newest input
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- // Output is missing; can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- // If an output is older than the newest input, we can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- // 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
- // had its file touched but not had its contents changed - this allows us
- // to skip a downstream typecheck
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- // An upstream project is blocked
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project's newest file is older than our oldest output, we
- // can't be out of date because of it
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- // If the upstream project has only change .d.ts files, and we've built
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- // We have an output older than an upstream output - we are out of date
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- // Up to date
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);
diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts
index 1a135690baa..a725b10a275 100644
--- a/lib/typescriptServices.d.ts
+++ b/lib/typescriptServices.d.ts
@@ -2677,9 +2677,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
- getModifiedTime?(fileName: string): Date;
- setModifiedTime?(fileName: string, date: Date): void;
- deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -4295,15 +4292,26 @@ declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T;
- interface WatchCompilerHost {
+ /** Host that has watch functionality used in --watch mode */
+ interface WatchHost {
+ /** If provided, called with Diagnostic message that informs about change in watch status */
+ onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
+ /** Used to watch changes in source files, missing files needed to update the program or config file */
+ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
+ /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
+ watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
+ /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
+ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
+ /** If provided, will be used to reset existing delayed compilation */
+ clearTimeout?(timeoutId: any): void;
+ }
+ interface WatchCompilerHost extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
- /** If provided, called with Diagnostic message that informs about change in watch status */
- onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4336,14 +4344,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
- /** Used to watch changes in source files, missing files needed to update the program or config file */
- watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
- /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
- watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
- /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
- setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
- /** If provided, will be used to reset existing delayed compilation */
- clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js
index 0506f341189..c80cb8e0938 100644
--- a/lib/typescriptServices.js
+++ b/lib/typescriptServices.js
@@ -5247,6 +5247,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -12022,13 +12023,13 @@ var ts;
if (ts.isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
- // Covers remaining cases
+ // Covers remaining cases (returning undefined if none match).
switch (hostNode.kind) {
case 217 /* VariableStatement */:
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219 /* ExpressionStatement */:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -12040,9 +12041,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1 /* EndOfFileToken */:
- return undefined;
+ break;
case 193 /* ParenthesizedExpression */: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -12050,10 +12049,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -22917,20 +22914,21 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ /*@internal*/
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
/* @internal */
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
@@ -23077,6 +23075,11 @@ var ts;
ts.parseCommandLine = parseCommandLine;
/** @internal */
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ /*@internal*/
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -23089,7 +23092,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -42293,8 +42296,8 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
- // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
+ if (flowDepth === 2000) {
+ // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
@@ -42430,7 +42433,8 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -49087,9 +49091,13 @@ var ts;
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */);
node.contextualType = saveContextualType;
return type;
}
@@ -82158,17 +82166,24 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ /*@internal*/
+ // TODO(shkamat): update this after reworking ts build API
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -82184,7 +82199,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -82194,7 +82209,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -82202,8 +82217,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data); // TODO: GH#18217
- var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ var hash = system.createHash(data); // TODO: GH#18217
+ var mtimeBefore = system.getModifiedTime(fileName); // TODO: GH#18217
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
@@ -82214,8 +82229,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; // TODO: GH#18217
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -82226,11 +82241,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -82242,33 +82257,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -86260,11 +86272,6 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- /** @internal */
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
/**
* @returns Whether the screen was cleared.
*/
@@ -86273,7 +86280,7 @@ var ts;
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -86373,6 +86380,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@@ -86384,7 +86410,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -86398,17 +86424,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -86983,7 +87002,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -87010,6 +87030,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -87122,152 +87145,108 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */);
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ // Mark all downstream projects of this one needing to be built "later"
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ // Can skip circular references
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- // Not a flag, parse as filename
- addProject(arg);
- }
- // Nonsensical combinations
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
+ /**
+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
+ */
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
+ };
}
- ts.performBuild = performBuild;
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, /*setParentNodes*/ undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
+ * TODO: use SolutionBuilderWithWatchHost => watchedSolution
+ * use SolutionBuilderHost => Solution
*/
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
- };
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -87276,16 +87255,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
// Everything is broken - we don't even know what to watch. Give up.
@@ -87295,14 +87295,14 @@ var ts;
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
// Watch this file
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
// Update watchers for wildcard directories
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1 /* Recursive */));
});
@@ -87310,7 +87310,7 @@ var ts;
// Watch input files
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -87320,11 +87320,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -87343,7 +87343,162 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ // Get timestamps of input files
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ // Collect the expected outputs of this project
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ // Now see if all outputs are newer than the newest input
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ // Output is missing; can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ // If an output is older than the newest input, we can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ // 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
+ // had its file touched but not had its contents changed - this allows us
+ // to skip a downstream typecheck
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ // An upstream project is blocked
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project's newest file is older than our oldest output, we
+ // can't be out of date because of it
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ // We have an output older than an upstream output - we are out of date
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ // Up to date
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -87355,30 +87510,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- // Mark all downstream projects of this one needing to be built "later"
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- // Can skip circular references
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -87399,7 +87564,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -87432,7 +87597,8 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ // TODO(shkamat): Account for this error
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -87462,17 +87628,18 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
// Failed to read the config file
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -87482,7 +87649,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -87493,8 +87660,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -87505,8 +87673,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -87517,8 +87686,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -87526,17 +87696,17 @@ var ts;
var anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
// Check for unchanged .d.ts files
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -87551,19 +87721,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -87584,9 +87755,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -87605,38 +87776,35 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- // Do this check later to allow --clean --dry to function even if the host can't delete files
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -87652,9 +87820,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -87672,7 +87845,7 @@ var ts;
// Up to date, skip
if (defaultOptions.dry) {
// In a dry build, inform the user of this fact
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -87683,7 +87856,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -87693,6 +87866,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
/**
@@ -87707,17 +87881,10 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
/**
* Report the up-to-date status of a project if we're in verbose mode
@@ -87725,173 +87892,10 @@ var ts;
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- /**
- * Gets the UpToDateStatus for a project
- */
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- // Get timestamps of input files
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- // Collect the expected outputs of this project
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- // Now see if all outputs are newer than the newest input
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- // Output is missing; can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- // If an output is older than the newest input, we can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- // 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
- // had its file touched but not had its contents changed - this allows us
- // to skip a downstream typecheck
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- // An upstream project is blocked
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project's newest file is older than our oldest output, we
- // can't be out of date because of it
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- // If the upstream project has only change .d.ts files, and we've built
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- // We have an output older than an upstream output - we are out of date
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- // Up to date
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);
diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js
index 79fc01aff1f..d9dcdfe2d88 100644
--- a/lib/typingsInstaller.js
+++ b/lib/typingsInstaller.js
@@ -5260,6 +5260,7 @@ var ts;
Option_0_cannot_be_specified_without_specifying_option_1_or_option_2: diag(5069, ts.DiagnosticCategory.Error, "Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069", "Option '{0}' cannot be specified without specifying option '{1}' or option '{2}'."),
Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy: diag(5070, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070", "Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy."),
Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs: diag(5071, ts.DiagnosticCategory.Error, "Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071", "Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'."),
+ Unknown_build_option_0: diag(5072, ts.DiagnosticCategory.Error, "Unknown_build_option_0_5072", "Unknown build option '{0}'."),
Generates_a_sourcemap_for_each_corresponding_d_ts_file: diag(6000, ts.DiagnosticCategory.Message, "Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000", "Generates a sourcemap for each corresponding '.d.ts' file."),
Concatenate_and_emit_output_to_single_file: diag(6001, ts.DiagnosticCategory.Message, "Concatenate_and_emit_output_to_single_file_6001", "Concatenate and emit output to single file."),
Generates_corresponding_d_ts_file: diag(6002, ts.DiagnosticCategory.Message, "Generates_corresponding_d_ts_file_6002", "Generates corresponding '.d.ts' file."),
@@ -12035,13 +12036,13 @@ var ts;
if (ts.isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
- // Covers remaining cases
+ // Covers remaining cases (returning undefined if none match).
switch (hostNode.kind) {
case 217 /* VariableStatement */:
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
- return undefined;
+ break;
case 219 /* ExpressionStatement */:
var expr = hostNode.expression;
switch (expr.kind) {
@@ -12053,9 +12054,7 @@ var ts;
return arg;
}
}
- return undefined;
- case 1 /* EndOfFileToken */:
- return undefined;
+ break;
case 193 /* ParenthesizedExpression */: {
return getDeclarationIdentifier(hostNode.expression);
}
@@ -12063,10 +12062,8 @@ var ts;
if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
- return undefined;
+ break;
}
- default:
- ts.Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node) {
@@ -22930,20 +22927,21 @@ var ts;
}
ts.convertEnableAutoDiscoveryToEnable = convertEnableAutoDiscoveryToEnable;
function getOptionNameMap() {
- if (optionNameMapCache) {
- return optionNameMapCache;
- }
+ return optionNameMapCache || (optionNameMapCache = createOptionNameMap(ts.optionDeclarations));
+ }
+ /*@internal*/
+ function createOptionNameMap(optionDeclarations) {
var optionNameMap = ts.createMap();
var shortOptionNames = ts.createMap();
- ts.forEach(ts.optionDeclarations, function (option) {
+ ts.forEach(optionDeclarations, function (option) {
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames.set(option.shortName, option.name);
}
});
- optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
- return optionNameMapCache;
+ return { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames };
}
+ ts.createOptionNameMap = createOptionNameMap;
/* @internal */
function createCompilerDiagnosticForInvalidCustomType(opt) {
return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic);
@@ -23090,6 +23088,11 @@ var ts;
ts.parseCommandLine = parseCommandLine;
/** @internal */
function getOptionFromName(optionName, allowShort) {
+ return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
+ }
+ ts.getOptionFromName = getOptionFromName;
+ /*@internal*/
+ function getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort) {
if (allowShort === void 0) { allowShort = false; }
optionName = optionName.toLowerCase();
var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames;
@@ -23102,7 +23105,7 @@ var ts;
}
return optionNameMap.get(optionName);
}
- ts.getOptionFromName = getOptionFromName;
+ ts.getOptionDeclarationFromName = getOptionDeclarationFromName;
function getDiagnosticText(_message) {
var _args = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -42306,8 +42309,8 @@ var ts;
}
return resultType;
function getTypeAtFlowNode(flow) {
- if (flowDepth === 2500) {
- // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error
+ if (flowDepth === 2000) {
+ // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
// and disable further control flow analysis in the containing function or module body.
flowAnalysisDisabled = true;
reportFlowControlError(reference);
@@ -42443,7 +42446,8 @@ var ts;
}
}
else {
- var indexType = getTypeOfExpression(node.left.argumentExpression);
+ // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
+ var indexType = getContextFreeTypeOfExpression(node.left.argumentExpression);
if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) {
evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right);
}
@@ -49100,9 +49104,13 @@ var ts;
* It sets the contextual type of the node to any before calling getTypeOfExpression.
*/
function getContextFreeTypeOfExpression(node) {
+ var links = getNodeLinks(node);
+ if (links.contextFreeType) {
+ return links.contextFreeType;
+ }
var saveContextualType = node.contextualType;
node.contextualType = anyType;
- var type = getTypeOfExpression(node);
+ var type = links.contextFreeType = checkExpression(node, 1 /* SkipContextSensitive */);
node.contextualType = saveContextualType;
return type;
}
@@ -82171,17 +82179,24 @@ var ts;
}
ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames;
function createCompilerHost(options, setParentNodes) {
+ return createCompilerHostWorker(options, setParentNodes);
+ }
+ ts.createCompilerHost = createCompilerHost;
+ /*@internal*/
+ // TODO(shkamat): update this after reworking ts build API
+ function createCompilerHostWorker(options, setParentNodes, system) {
+ if (system === void 0) { system = ts.sys; }
var existingDirectories = ts.createMap();
function getCanonicalFileName(fileName) {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
- return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+ return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName, languageVersion, onError) {
var text;
try {
ts.performance.mark("beforeIORead");
- text = ts.sys.readFile(fileName, options.charset);
+ text = system.readFile(fileName, options.charset);
ts.performance.mark("afterIORead");
ts.performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -82197,7 +82212,7 @@ var ts;
if (existingDirectories.has(directoryPath)) {
return true;
}
- if (ts.sys.directoryExists(directoryPath)) {
+ if (system.directoryExists(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
@@ -82207,7 +82222,7 @@ var ts;
if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = ts.getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
- ts.sys.createDirectory(directoryPath);
+ system.createDirectory(directoryPath);
}
}
var outputFingerprints;
@@ -82215,8 +82230,8 @@ var ts;
if (!outputFingerprints) {
outputFingerprints = ts.createMap();
}
- var hash = ts.sys.createHash(data); // TODO: GH#18217
- var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ var hash = system.createHash(data); // TODO: GH#18217
+ var mtimeBefore = system.getModifiedTime(fileName); // TODO: GH#18217
if (mtimeBefore) {
var fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
@@ -82227,8 +82242,8 @@ var ts;
return;
}
}
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
- var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217
+ system.writeFile(fileName, data, writeByteOrderMark);
+ var mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; // TODO: GH#18217
outputFingerprints.set(fileName, {
hash: hash,
byteOrderMark: writeByteOrderMark,
@@ -82239,11 +82254,11 @@ var ts;
try {
ts.performance.mark("beforeIOWrite");
ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
- if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) {
+ if (ts.isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
- ts.sys.writeFile(fileName, data, writeByteOrderMark);
+ system.writeFile(fileName, data, writeByteOrderMark);
}
ts.performance.mark("afterIOWrite");
ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
@@ -82255,33 +82270,30 @@ var ts;
}
}
function getDefaultLibLocation() {
- return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath()));
+ return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath()));
}
- var newLine = ts.getNewLineCharacter(options);
- var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); });
+ var newLine = ts.getNewLineCharacter(options, function () { return system.newLine; });
+ var realpath = system.realpath && (function (path) { return system.realpath(path); });
return {
getSourceFile: getSourceFile,
getDefaultLibLocation: getDefaultLibLocation,
getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); },
writeFile: writeFile,
- getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }),
- useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+ getCurrentDirectory: ts.memoize(function () { return system.getCurrentDirectory(); }),
+ useCaseSensitiveFileNames: function () { return system.useCaseSensitiveFileNames; },
getCanonicalFileName: getCanonicalFileName,
getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return ts.sys.fileExists(fileName); },
- readFile: function (fileName) { return ts.sys.readFile(fileName); },
- trace: function (s) { return ts.sys.write(s + newLine); },
- directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); },
- getEnvironmentVariable: function (name) { return ts.sys.getEnvironmentVariable ? ts.sys.getEnvironmentVariable(name) : ""; },
- getDirectories: function (path) { return ts.sys.getDirectories(path); },
+ fileExists: function (fileName) { return system.fileExists(fileName); },
+ readFile: function (fileName) { return system.readFile(fileName); },
+ trace: function (s) { return system.write(s + newLine); },
+ directoryExists: function (directoryName) { return system.directoryExists(directoryName); },
+ getEnvironmentVariable: function (name) { return system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : ""; },
+ getDirectories: function (path) { return system.getDirectories(path); },
realpath: realpath,
- readDirectory: function (path, extensions, include, exclude, depth) { return ts.sys.readDirectory(path, extensions, include, exclude, depth); },
- getModifiedTime: ts.sys.getModifiedTime && (function (path) { return ts.sys.getModifiedTime(path); }),
- setModifiedTime: ts.sys.setModifiedTime && (function (path, date) { return ts.sys.setModifiedTime(path, date); }),
- deleteFile: ts.sys.deleteFile && (function (path) { return ts.sys.deleteFile(path); })
+ readDirectory: function (path, extensions, include, exclude, depth) { return system.readDirectory(path, extensions, include, exclude, depth); }
};
}
- ts.createCompilerHost = createCompilerHost;
+ ts.createCompilerHostWorker = createCompilerHostWorker;
function getPreEmitDiagnostics(program, sourceFile, cancellationToken) {
var diagnostics = program.getConfigFileParsingDiagnostics().concat(program.getOptionsDiagnostics(cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
@@ -86273,11 +86285,6 @@ var ts;
};
}
ts.createDiagnosticReporter = createDiagnosticReporter;
- /** @internal */
- ts.nonClearingMessageCodes = [
- ts.Diagnostics.Found_1_error_Watching_for_file_changes.code,
- ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code
- ];
/**
* @returns Whether the screen was cleared.
*/
@@ -86286,7 +86293,7 @@ var ts;
!options.preserveWatchOutput &&
!options.extendedDiagnostics &&
!options.diagnostics &&
- !ts.contains(ts.nonClearingMessageCodes, diagnostic.code)) {
+ ts.contains(ts.screenStartingMessageCodes, diagnostic.code)) {
system.clearScreen();
return true;
}
@@ -86386,6 +86393,25 @@ var ts;
}
ts.emitFilesAndReportErrors = emitFilesAndReportErrors;
var noopFileWatcher = { close: ts.noop };
+ function createWatchHost(system, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ return {
+ onWatchStatusChange: onWatchStatusChange,
+ watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
+ watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
+ setTimeout: system.setTimeout ? (function (callback, ms) {
+ var args = [];
+ for (var _i = 2; _i < arguments.length; _i++) {
+ args[_i - 2] = arguments[_i];
+ }
+ var _a;
+ return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
+ }) : ts.noop,
+ clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop
+ };
+ }
+ ts.createWatchHost = createWatchHost;
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@@ -86397,7 +86423,7 @@ var ts;
var host = system;
var useCaseSensitiveFileNames = function () { return system.useCaseSensitiveFileNames; };
var writeFileName = function (s) { return system.write(s + system.newLine); };
- var onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
+ var _a = createWatchHost(system, reportWatchStatus), onWatchStatusChange = _a.onWatchStatusChange, watchFile = _a.watchFile, watchDirectory = _a.watchDirectory, setTimeout = _a.setTimeout, clearTimeout = _a.clearTimeout;
return {
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
getNewLine: function () { return system.newLine; },
@@ -86411,17 +86437,10 @@ var ts;
readDirectory: function (path, extensions, exclude, include, depth) { return system.readDirectory(path, extensions, exclude, include, depth); },
realpath: system.realpath && (function (path) { return system.realpath(path); }),
getEnvironmentVariable: system.getEnvironmentVariable && (function (name) { return system.getEnvironmentVariable(name); }),
- watchFile: system.watchFile ? (function (path, callback, pollingInterval) { return system.watchFile(path, callback, pollingInterval); }) : function () { return noopFileWatcher; },
- watchDirectory: system.watchDirectory ? (function (path, callback, recursive) { return system.watchDirectory(path, callback, recursive); }) : function () { return noopFileWatcher; },
- setTimeout: system.setTimeout ? (function (callback, ms) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- var _a;
- return (_a = system.setTimeout).call.apply(_a, [system, callback, ms].concat(args));
- }) : ts.noop,
- clearTimeout: system.clearTimeout ? (function (timeoutId) { return system.clearTimeout(timeoutId); }) : ts.noop,
+ watchFile: watchFile,
+ watchDirectory: watchDirectory,
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
trace: function (s) { return system.write(s); },
onWatchStatusChange: onWatchStatusChange,
createDirectory: function (path) { return system.createDirectory(path); },
@@ -86996,7 +87015,8 @@ var ts;
getValueOrUndefined: getValueOrUndefined,
removeKey: removeKey,
getKeys: getKeys,
- hasKey: hasKey
+ hasKey: hasKey,
+ getSize: getSize
};
function getKeys() {
return Object.keys(lookup);
@@ -87023,6 +87043,9 @@ var ts;
var f = ts.normalizePath(fileName);
return lookup.get(f);
}
+ function getSize() {
+ return lookup.size;
+ }
}
function createDependencyMapper() {
var childToParents = createFileMap();
@@ -87135,152 +87158,108 @@ var ts;
return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */);
}
function createBuildContext(options) {
- var invalidatedProjects = createFileMap();
- var queuedProjects = createFileMap();
+ var invalidatedProjectQueue = [];
+ var nextIndex = 0;
+ var projectPendingBuild = createFileMap();
var missingRoots = ts.createMap();
+ var diagnostics = options.watch ? createFileMap() : undefined;
return {
options: options,
projectStatus: createFileMap(),
+ diagnostics: diagnostics,
unchangedOutputs: createFileMap(),
- invalidatedProjects: invalidatedProjects,
- missingRoots: missingRoots,
- queuedProjects: queuedProjects
+ invalidateProject: invalidateProject,
+ getNextInvalidatedProject: getNextInvalidatedProject,
+ hasPendingInvalidatedProjects: hasPendingInvalidatedProjects,
+ missingRoots: missingRoots
};
+ function invalidateProject(proj, dependencyGraph) {
+ if (!projectPendingBuild.hasKey(proj)) {
+ addProjToQueue(proj);
+ if (dependencyGraph) {
+ queueBuildForDownstreamReferences(proj, dependencyGraph);
+ }
+ }
+ }
+ function addProjToQueue(proj) {
+ ts.Debug.assert(!projectPendingBuild.hasKey(proj));
+ projectPendingBuild.setValue(proj, true);
+ invalidatedProjectQueue.push(proj);
+ }
+ function getNextInvalidatedProject() {
+ if (nextIndex < invalidatedProjectQueue.length) {
+ var proj = invalidatedProjectQueue[nextIndex];
+ nextIndex++;
+ projectPendingBuild.removeKey(proj);
+ if (!projectPendingBuild.getSize()) {
+ invalidatedProjectQueue.length = 0;
+ }
+ return proj;
+ }
+ }
+ function hasPendingInvalidatedProjects() {
+ return !!projectPendingBuild.getSize();
+ }
+ // Mark all downstream projects of this one needing to be built "later"
+ function queueBuildForDownstreamReferences(root, dependencyGraph) {
+ var deps = dependencyGraph.dependencyMap.getReferencesTo(root);
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
+ var ref = deps_1[_i];
+ // Can skip circular references
+ if (!projectPendingBuild.hasKey(ref)) {
+ addProjToQueue(ref);
+ queueBuildForDownstreamReferences(ref, dependencyGraph);
+ }
+ }
+ }
}
ts.createBuildContext = createBuildContext;
- var buildOpts = [
- {
- name: "verbose",
- shortName: "v",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Enable_verbose_logging,
- type: "boolean"
- },
- {
- name: "dry",
- shortName: "d",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
- type: "boolean"
- },
- {
- name: "force",
- shortName: "f",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
- type: "boolean"
- },
- {
- name: "clean",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Delete_the_outputs_of_all_projects,
- type: "boolean"
- },
- {
- name: "watch",
- category: ts.Diagnostics.Command_line_Options,
- description: ts.Diagnostics.Watch_input_files,
- type: "boolean"
- }
- ];
- function performBuild(args, compilerHost, buildHost, system) {
- var verbose = false;
- var dry = false;
- var force = false;
- var clean = false;
- var watch = false;
- var projects = [];
- for (var _i = 0, args_6 = args; _i < args_6.length; _i++) {
- var arg = args_6[_i];
- switch (arg.toLowerCase()) {
- case "-v":
- case "--verbose":
- verbose = true;
- continue;
- case "-d":
- case "--dry":
- dry = true;
- continue;
- case "-f":
- case "--force":
- force = true;
- continue;
- case "--clean":
- clean = true;
- continue;
- case "--watch":
- case "-w":
- watch = true;
- continue;
- case "--?":
- case "-?":
- case "--help":
- ts.printHelp(buildOpts, "--build ");
- return ts.ExitStatus.Success;
- }
- // Not a flag, parse as filename
- addProject(arg);
- }
- // Nonsensical combinations
- if (clean && force) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && verbose) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (clean && watch) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (watch && dry) {
- buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
- return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
- }
- if (projects.length === 0) {
- // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
- addProject(".");
- }
- var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system);
- if (clean) {
- return builder.cleanAllProjects();
- }
- if (watch) {
- builder.buildAllProjects();
- builder.startWatching();
- return undefined;
- }
- return builder.buildAllProjects();
- function addProject(projectSpecification) {
- var fileName = ts.resolvePath(compilerHost.getCurrentDirectory(), projectSpecification);
- var refPath = ts.resolveProjectReferencePath(compilerHost, { path: fileName });
- if (!compilerHost.fileExists(refPath)) {
- return buildHost.error(ts.Diagnostics.File_0_does_not_exist, fileName);
- }
- projects.push(refPath);
- }
+ /**
+ * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
+ */
+ function createBuilderStatusReporter(system, pretty) {
+ return function (diagnostic) {
+ var output = pretty ? "[" + ts.formatColorAndReset(new Date().toLocaleTimeString(), ts.ForegroundColorEscapeSequences.Grey) + "] " : new Date().toLocaleTimeString() + " - ";
+ output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, system.newLine) + (system.newLine + system.newLine);
+ system.write(output);
+ };
}
- ts.performBuild = performBuild;
+ ts.createBuilderStatusReporter = createBuilderStatusReporter;
+ function createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = ts.createCompilerHostWorker({}, /*setParentNodes*/ undefined, system);
+ host.getModifiedTime = system.getModifiedTime ? function (path) { return system.getModifiedTime(path); } : function () { return undefined; };
+ host.setModifiedTime = system.setModifiedTime ? function (path, date) { return system.setModifiedTime(path, date); } : ts.noop;
+ host.deleteFile = system.deleteFile ? function (path) { return system.deleteFile(path); } : ts.noop;
+ host.reportDiagnostic = reportDiagnostic || ts.createDiagnosticReporter(system);
+ host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
+ return host;
+ }
+ ts.createSolutionBuilderHost = createSolutionBuilderHost;
+ function createSolutionBuilderWithWatchHost(system, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus) {
+ if (system === void 0) { system = ts.sys; }
+ var host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus);
+ var watchHost = ts.createWatchHost(system, reportWatchStatus);
+ host.onWatchStatusChange = watchHost.onWatchStatusChange;
+ host.watchFile = watchHost.watchFile;
+ host.watchDirectory = watchHost.watchDirectory;
+ host.setTimeout = watchHost.setTimeout;
+ host.clearTimeout = watchHost.clearTimeout;
+ return host;
+ }
+ ts.createSolutionBuilderWithWatchHost = createSolutionBuilderWithWatchHost;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
+ * TODO: use SolutionBuilderWithWatchHost => watchedSolution
+ * use SolutionBuilderHost => Solution
*/
- function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) {
- if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) {
- throw new Error("Host must support timestamp APIs");
- }
- var configFileCache = createConfigFileCache(compilerHost);
+ function createSolutionBuilder(host, rootNames, defaultOptions) {
+ var hostWithWatch = host;
+ var configFileCache = createConfigFileCache(host);
var context = createBuildContext(defaultOptions);
+ var timerToBuildInvalidatedProject;
var existingWatchersForWildcards = ts.createMap();
- var upToDateHost = {
- fileExists: function (fileName) { return compilerHost.fileExists(fileName); },
- getModifiedTime: function (fileName) { return compilerHost.getModifiedTime(fileName); },
- getUnchangedTime: function (fileName) { return context.unchangedOutputs.getValueOrUndefined(fileName); },
- getLastStatus: function (fileName) { return context.projectStatus.getValueOrUndefined(fileName); },
- setLastStatus: function (fileName, status) { return context.projectStatus.setValue(fileName, status); },
- parseConfigFile: function (configFilePath) { return configFileCache.parseConfigFile(configFilePath); }
- };
return {
buildAllProjects: buildAllProjects,
getUpToDateStatus: getUpToDateStatus,
@@ -87289,16 +87268,37 @@ var ts;
resetBuildContext: resetBuildContext,
getBuildGraph: getBuildGraph,
invalidateProject: invalidateProject,
- buildInvalidatedProjects: buildInvalidatedProjects,
- buildDependentInvalidatedProjects: buildDependentInvalidatedProjects,
+ buildInvalidatedProject: buildInvalidatedProject,
resolveProjectName: resolveProjectName,
startWatching: startWatching
};
+ function reportStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ host.reportSolutionBuilderStatus(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)));
+ }
+ function storeErrors(proj, diagnostics) {
+ if (context.options.watch) {
+ storeErrorSummary(proj, diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length);
+ }
+ }
+ function storeErrorSummary(proj, errorCount) {
+ if (context.options.watch) {
+ context.diagnostics.setValue(proj, errorCount);
+ }
+ }
+ function reportWatchStatus(message) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ if (hostWithWatch.onWatchStatusChange) {
+ hostWithWatch.onWatchStatusChange(ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput });
+ }
+ }
function startWatching() {
- if (!system)
- throw new Error("System host must be provided if using --watch");
- if (!system.watchFile || !system.watchDirectory || !system.setTimeout)
- throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch");
var graph = getGlobalDependencyGraph();
if (!graph.buildQueue) {
// Everything is broken - we don't even know what to watch. Give up.
@@ -87308,14 +87308,14 @@ var ts;
var cfg = configFileCache.parseConfigFile(resolved);
if (cfg) {
// Watch this file
- system.watchFile(resolved, function () {
+ hostWithWatch.watchFile(resolved, function () {
configFileCache.removeKey(resolved);
invalidateProjectAndScheduleBuilds(resolved);
});
// Update watchers for wildcard directories
if (cfg.configFileSpecs) {
ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) {
- return system.watchDirectory(dir, function () {
+ return hostWithWatch.watchDirectory(dir, function () {
invalidateProjectAndScheduleBuilds(resolved);
}, !!(flags & 1 /* Recursive */));
});
@@ -87323,7 +87323,7 @@ var ts;
// Watch input files
for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) {
var input = _a[_i];
- system.watchFile(input, function () {
+ hostWithWatch.watchFile(input, function () {
invalidateProjectAndScheduleBuilds(resolved);
});
}
@@ -87333,11 +87333,11 @@ var ts;
var resolved = _a[_i];
_loop_12(resolved);
}
- function invalidateProjectAndScheduleBuilds(resolved) {
- invalidateProject(resolved);
- system.setTimeout(buildInvalidatedProjects, 100);
- system.setTimeout(buildDependentInvalidatedProjects, 3000);
- }
+ }
+ function invalidateProjectAndScheduleBuilds(resolved) {
+ reportWatchStatus(ts.Diagnostics.File_change_detected_Starting_incremental_compilation);
+ invalidateProject(resolved);
+ scheduleBuildInvalidatedProject();
}
function resetBuildContext(opts) {
if (opts === void 0) { opts = defaultOptions; }
@@ -87356,7 +87356,162 @@ var ts;
return getBuildGraph(rootNames);
}
function getUpToDateStatus(project) {
- return ts.getUpToDateStatus(upToDateHost, project);
+ if (project === undefined) {
+ return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
+ }
+ var prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath);
+ if (prior !== undefined) {
+ return prior;
+ }
+ var actual = getUpToDateStatusWorker(project);
+ context.projectStatus.setValue(project.options.configFilePath, actual);
+ return actual;
+ }
+ function getUpToDateStatusWorker(project) {
+ var newestInputFileName = undefined;
+ var newestInputFileTime = minimumDate;
+ // Get timestamps of input files
+ for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
+ var inputFile = _a[_i];
+ if (!host.fileExists(inputFile)) {
+ return {
+ type: UpToDateStatusType.Unbuildable,
+ reason: inputFile + " does not exist"
+ };
+ }
+ var inputTime = host.getModifiedTime(inputFile) || ts.missingFileModifiedTime;
+ if (inputTime > newestInputFileTime) {
+ newestInputFileName = inputFile;
+ newestInputFileTime = inputTime;
+ }
+ }
+ // Collect the expected outputs of this project
+ var outputs = getAllProjectOutputs(project);
+ if (outputs.length === 0) {
+ return {
+ type: UpToDateStatusType.ContainerOnly
+ };
+ }
+ // Now see if all outputs are newer than the newest input
+ var oldestOutputFileName = "(none)";
+ var oldestOutputFileTime = maximumDate;
+ var newestOutputFileName = "(none)";
+ var newestOutputFileTime = minimumDate;
+ var missingOutputFileName;
+ var newestDeclarationFileContentChangedTime = minimumDate;
+ var isOutOfDateWithInputs = false;
+ for (var _b = 0, outputs_1 = outputs; _b < outputs_1.length; _b++) {
+ var output = outputs_1[_b];
+ // Output is missing; can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (!host.fileExists(output)) {
+ missingOutputFileName = output;
+ break;
+ }
+ var outputTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ if (outputTime < oldestOutputFileTime) {
+ oldestOutputFileTime = outputTime;
+ oldestOutputFileName = output;
+ }
+ // If an output is older than the newest input, we can stop checking
+ // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
+ if (outputTime < newestInputFileTime) {
+ isOutOfDateWithInputs = true;
+ break;
+ }
+ if (outputTime > newestOutputFileTime) {
+ newestOutputFileTime = outputTime;
+ newestOutputFileName = output;
+ }
+ // 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
+ // had its file touched but not had its contents changed - this allows us
+ // to skip a downstream typecheck
+ if (isDeclarationFile(output)) {
+ var unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
+ if (unchangedTime !== undefined) {
+ newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
+ }
+ else {
+ var outputModifiedTime = host.getModifiedTime(output) || ts.missingFileModifiedTime;
+ newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
+ }
+ }
+ }
+ var pseudoUpToDate = false;
+ var usesPrepend = false;
+ var upstreamChangedProject;
+ if (project.projectReferences) {
+ for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
+ var ref = _d[_c];
+ usesPrepend = usesPrepend || !!(ref.prepend);
+ var resolvedRef = ts.resolveProjectReferencePath(host, ref);
+ var refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
+ // An upstream project is blocked
+ if (refStatus.type === UpToDateStatusType.Unbuildable) {
+ return {
+ type: UpToDateStatusType.UpstreamBlocked,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
+ if (refStatus.type !== UpToDateStatusType.UpToDate) {
+ return {
+ type: UpToDateStatusType.UpstreamOutOfDate,
+ upstreamProjectName: ref.path
+ };
+ }
+ // If the upstream project's newest file is older than our oldest output, we
+ // can't be out of date because of it
+ if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
+ continue;
+ }
+ // If the upstream project has only change .d.ts files, and we've built
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
+ if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
+ pseudoUpToDate = true;
+ upstreamChangedProject = ref.path;
+ continue;
+ }
+ // We have an output older than an upstream output - we are out of date
+ ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: ref.path
+ };
+ }
+ }
+ if (missingOutputFileName !== undefined) {
+ return {
+ type: UpToDateStatusType.OutputMissing,
+ missingOutputFileName: missingOutputFileName
+ };
+ }
+ if (isOutOfDateWithInputs) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithSelf,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerInputFileName: newestInputFileName
+ };
+ }
+ if (usesPrepend && pseudoUpToDate) {
+ return {
+ type: UpToDateStatusType.OutOfDateWithUpstream,
+ outOfDateOutputFileName: oldestOutputFileName,
+ newerProjectName: upstreamChangedProject
+ };
+ }
+ // Up to date
+ return {
+ type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
+ newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
+ newestInputFileTime: newestInputFileTime,
+ newestOutputFileTime: newestOutputFileTime,
+ newestInputFileName: newestInputFileName,
+ newestOutputFileName: newestOutputFileName,
+ oldestOutputFileName: oldestOutputFileName
+ };
}
function invalidateProject(configFileName) {
var resolved = resolveProjectName(configFileName);
@@ -87368,30 +87523,40 @@ var ts;
return;
}
configFileCache.removeKey(resolved);
- context.invalidatedProjects.setValue(resolved, true);
context.projectStatus.removeKey(resolved);
- var graph = getGlobalDependencyGraph();
- if (graph) {
- queueBuildForDownstreamReferences(resolved);
+ if (context.options.watch) {
+ context.diagnostics.removeKey(resolved);
}
- // Mark all downstream projects of this one needing to be built "later"
- function queueBuildForDownstreamReferences(root) {
- var deps = graph.dependencyMap.getReferencesTo(root);
- for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
- var ref = deps_1[_i];
- // Can skip circular references
- if (!context.queuedProjects.hasKey(ref)) {
- context.queuedProjects.setValue(ref, true);
- queueBuildForDownstreamReferences(ref);
- }
+ context.invalidateProject(resolved, getGlobalDependencyGraph());
+ }
+ function scheduleBuildInvalidatedProject() {
+ if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) {
+ return;
+ }
+ if (timerToBuildInvalidatedProject) {
+ hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
+ }
+ timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
+ }
+ function buildInvalidatedProject() {
+ timerToBuildInvalidatedProject = undefined;
+ var buildProject = context.getNextInvalidatedProject();
+ buildSomeProjects(function (p) { return p === buildProject; });
+ if (context.hasPendingInvalidatedProjects()) {
+ if (!timerToBuildInvalidatedProject) {
+ scheduleBuildInvalidatedProject();
}
}
+ else {
+ reportErrorSummary();
+ }
}
- function buildInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.invalidatedProjects.hasKey(p); });
- }
- function buildDependentInvalidatedProjects() {
- buildSomeProjects(function (p) { return context.queuedProjects.hasKey(p); });
+ function reportErrorSummary() {
+ if (context.options.watch) {
+ var errorCount_1 = 0;
+ context.diagnostics.getKeys().forEach(function (resolved) { return errorCount_1 += context.diagnostics.getValue(resolved); });
+ reportWatchStatus(errorCount_1 === 1 ? ts.Diagnostics.Found_1_error_Watching_for_file_changes : ts.Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount_1);
+ }
}
function buildSomeProjects(predicate) {
var resolvedNames = resolveProjectNames(rootNames);
@@ -87412,7 +87577,7 @@ var ts;
verboseReportProjectStatus(next, status);
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName);
continue;
}
buildSingleProject(next);
@@ -87445,7 +87610,8 @@ var ts;
if (temporaryMarks[projPath]) {
if (!inCircularContext) {
hadError = true;
- buildHost.error(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
+ // TODO(shkamat): Account for this error
+ reportStatus(ts.Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n"));
return;
}
}
@@ -87475,17 +87641,18 @@ var ts;
}
function buildSingleProject(proj) {
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj);
return BuildResultFlags.Success;
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Building_project_0, proj);
+ reportStatus(ts.Diagnostics.Building_project_0, proj);
var resultFlags = BuildResultFlags.None;
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
var configFile = configFileCache.parseConfigFile(proj);
if (!configFile) {
// Failed to read the config file
resultFlags |= BuildResultFlags.ConfigFileErrors;
+ storeErrorSummary(proj, 1);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" });
return resultFlags;
}
@@ -87495,7 +87662,7 @@ var ts;
}
var programOptions = {
projectReferences: configFile.projectReferences,
- host: compilerHost,
+ host: host,
rootNames: configFile.fileNames,
options: configFile.options
};
@@ -87506,8 +87673,9 @@ var ts;
resultFlags |= BuildResultFlags.SyntaxErrors;
for (var _i = 0, syntaxDiagnostics_1 = syntaxDiagnostics; _i < syntaxDiagnostics_1.length; _i++) {
var diag = syntaxDiagnostics_1[_i];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, syntaxDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" });
return resultFlags;
}
@@ -87518,8 +87686,9 @@ var ts;
resultFlags |= BuildResultFlags.DeclarationEmitErrors;
for (var _a = 0, declDiagnostics_1 = declDiagnostics; _a < declDiagnostics_1.length; _a++) {
var diag = declDiagnostics_1[_a];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, declDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" });
return resultFlags;
}
@@ -87530,8 +87699,9 @@ var ts;
resultFlags |= BuildResultFlags.TypeErrors;
for (var _b = 0, semanticDiagnostics_1 = semanticDiagnostics; _b < semanticDiagnostics_1.length; _b++) {
var diag = semanticDiagnostics_1[_b];
- buildHost.errorDiagnostic(diag);
+ host.reportDiagnostic(diag);
}
+ storeErrors(proj, semanticDiagnostics);
context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" });
return resultFlags;
}
@@ -87539,17 +87709,17 @@ var ts;
var anyDtsChanged = false;
program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) {
var priorChangeTime;
- if (!anyDtsChanged && isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) {
- if (compilerHost.readFile(fileName) === content) {
+ if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) {
+ if (host.readFile(fileName) === content) {
// Check for unchanged .d.ts files
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
- priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName);
+ priorChangeTime = host.getModifiedTime(fileName);
}
else {
anyDtsChanged = true;
}
}
- compilerHost.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
+ host.writeFile(fileName, content, writeBom, onError, ts.emptyArray);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
context.unchangedOutputs.setValue(fileName, priorChangeTime);
@@ -87564,19 +87734,20 @@ var ts;
}
function updateOutputTimestamps(proj) {
if (context.options.dry) {
- return buildHost.message(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ return reportStatus(ts.Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath);
+ }
+ if (context.options.verbose) {
+ reportStatus(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
}
- if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath);
var now = new Date();
var outputs = getAllProjectOutputs(proj);
var priorNewestUpdateTime = minimumDate;
- for (var _i = 0, outputs_1 = outputs; _i < outputs_1.length; _i++) {
- var file = outputs_1[_i];
+ for (var _i = 0, outputs_2 = outputs; _i < outputs_2.length; _i++) {
+ var file = outputs_2[_i];
if (isDeclarationFile(file)) {
- priorNewestUpdateTime = newer(priorNewestUpdateTime, compilerHost.getModifiedTime(file));
+ priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || ts.missingFileModifiedTime);
}
- compilerHost.setModifiedTime(file, now);
+ host.setModifiedTime(file, now);
}
context.projectStatus.setValue(proj.options.configFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime });
}
@@ -87597,9 +87768,9 @@ var ts;
continue;
}
var outputs = getAllProjectOutputs(parsed);
- for (var _b = 0, outputs_2 = outputs; _b < outputs_2.length; _b++) {
- var output = outputs_2[_b];
- if (compilerHost.fileExists(output)) {
+ for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
+ var output = outputs_3[_b];
+ if (host.fileExists(output)) {
filesToDelete.push(output);
}
}
@@ -87618,38 +87789,35 @@ var ts;
function cleanAllProjects() {
var resolvedNames = getAllProjectsInScope();
if (resolvedNames === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
var filesToDelete = getFilesToClean(resolvedNames);
if (filesToDelete === undefined) {
- buildHost.message(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
+ reportStatus(ts.Diagnostics.Skipping_clean_because_not_all_projects_could_be_located);
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
if (context.options.dry) {
- buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
+ reportStatus(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join(""));
return ts.ExitStatus.Success;
}
- // Do this check later to allow --clean --dry to function even if the host can't delete files
- if (!compilerHost.deleteFile) {
- throw new Error("Host does not support deleting files");
- }
for (var _i = 0, filesToDelete_1 = filesToDelete; _i < filesToDelete_1.length; _i++) {
var output = filesToDelete_1[_i];
- compilerHost.deleteFile(output);
+ host.deleteFile(output);
}
return ts.ExitStatus.Success;
}
function resolveProjectName(name) {
- var fullPath = ts.resolvePath(compilerHost.getCurrentDirectory(), name);
- if (compilerHost.fileExists(fullPath)) {
+ var fullPath = ts.resolvePath(host.getCurrentDirectory(), name);
+ if (host.fileExists(fullPath)) {
return fullPath;
}
var fullPathWithTsconfig = ts.combinePaths(fullPath, "tsconfig.json");
- if (compilerHost.fileExists(fullPathWithTsconfig)) {
+ if (host.fileExists(fullPathWithTsconfig)) {
return fullPathWithTsconfig;
}
- buildHost.error(ts.Diagnostics.File_0_not_found, relName(fullPath));
+ // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better
+ host.reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, relName(fullPath)));
return undefined;
}
function resolveProjectNames(configFileNames) {
@@ -87665,9 +87833,14 @@ var ts;
return resolvedNames;
}
function buildAllProjects() {
+ if (context.options.watch) {
+ reportWatchStatus(ts.Diagnostics.Starting_compilation_in_watch_mode);
+ }
var graph = getGlobalDependencyGraph();
- if (graph === undefined)
+ if (graph === undefined) {
+ reportErrorSummary();
return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+ }
var queue = graph.buildQueue;
reportBuildQueue(graph);
var anyFailed = false;
@@ -87685,7 +87858,7 @@ var ts;
// Up to date, skip
if (defaultOptions.dry) {
// In a dry build, inform the user of this fact
- buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName);
+ reportStatus(ts.Diagnostics.Project_0_is_up_to_date, projName);
}
continue;
}
@@ -87696,7 +87869,7 @@ var ts;
}
if (status.type === UpToDateStatusType.UpstreamBlocked) {
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
+ reportStatus(ts.Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName);
continue;
}
if (status.type === UpToDateStatusType.ContainerOnly) {
@@ -87706,6 +87879,7 @@ var ts;
var buildResult = buildSingleProject(next);
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
+ reportErrorSummary();
return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success;
}
/**
@@ -87720,17 +87894,10 @@ var ts;
names.push(name);
}
if (context.options.verbose)
- buildHost.verbose(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
+ reportStatus(ts.Diagnostics.Projects_in_this_build_Colon_0, names.map(function (s) { return "\r\n * " + relName(s); }).join(""));
}
function relName(path) {
- return ts.convertToRelativePath(path, compilerHost.getCurrentDirectory(), function (f) { return compilerHost.getCanonicalFileName(f); });
- }
- function reportVerbose(message) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- buildHost.verbose.apply(buildHost, [message].concat(args));
+ return ts.convertToRelativePath(path, host.getCurrentDirectory(), function (f) { return host.getCanonicalFileName(f); });
}
/**
* Report the up-to-date status of a project if we're in verbose mode
@@ -87738,173 +87905,10 @@ var ts;
function verboseReportProjectStatus(configFileName, status) {
if (!context.options.verbose)
return;
- return formatUpToDateStatus(configFileName, status, relName, reportVerbose);
+ return formatUpToDateStatus(configFileName, status, relName, reportStatus);
}
}
ts.createSolutionBuilder = createSolutionBuilder;
- /**
- * Gets the UpToDateStatus for a project
- */
- function getUpToDateStatus(host, project) {
- if (project === undefined) {
- return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
- }
- var prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
- if (prior !== undefined) {
- return prior;
- }
- var actual = getUpToDateStatusWorker(host, project);
- if (host.setLastStatus) {
- host.setLastStatus(project.options.configFilePath, actual);
- }
- return actual;
- }
- ts.getUpToDateStatus = getUpToDateStatus;
- function getUpToDateStatusWorker(host, project) {
- var newestInputFileName = undefined;
- var newestInputFileTime = minimumDate;
- // Get timestamps of input files
- for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) {
- var inputFile = _a[_i];
- if (!host.fileExists(inputFile)) {
- return {
- type: UpToDateStatusType.Unbuildable,
- reason: inputFile + " does not exist"
- };
- }
- var inputTime = host.getModifiedTime(inputFile);
- if (inputTime > newestInputFileTime) {
- newestInputFileName = inputFile;
- newestInputFileTime = inputTime;
- }
- }
- // Collect the expected outputs of this project
- var outputs = getAllProjectOutputs(project);
- if (outputs.length === 0) {
- return {
- type: UpToDateStatusType.ContainerOnly
- };
- }
- // Now see if all outputs are newer than the newest input
- var oldestOutputFileName = "(none)";
- var oldestOutputFileTime = maximumDate;
- var newestOutputFileName = "(none)";
- var newestOutputFileTime = minimumDate;
- var missingOutputFileName;
- var newestDeclarationFileContentChangedTime = minimumDate;
- var isOutOfDateWithInputs = false;
- for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) {
- var output = outputs_3[_b];
- // Output is missing; can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (!host.fileExists(output)) {
- missingOutputFileName = output;
- break;
- }
- var outputTime = host.getModifiedTime(output);
- if (outputTime < oldestOutputFileTime) {
- oldestOutputFileTime = outputTime;
- oldestOutputFileName = output;
- }
- // If an output is older than the newest input, we can stop checking
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
- if (outputTime < newestInputFileTime) {
- isOutOfDateWithInputs = true;
- break;
- }
- if (outputTime > newestOutputFileTime) {
- newestOutputFileTime = outputTime;
- newestOutputFileName = output;
- }
- // 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
- // had its file touched but not had its contents changed - this allows us
- // to skip a downstream typecheck
- if (isDeclarationFile(output)) {
- var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
- if (unchangedTime !== undefined) {
- newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
- }
- else {
- newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, host.getModifiedTime(output));
- }
- }
- }
- var pseudoUpToDate = false;
- var usesPrepend = false;
- var upstreamChangedProject;
- if (project.projectReferences && host.parseConfigFile) {
- for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) {
- var ref = _d[_c];
- usesPrepend = usesPrepend || !!(ref.prepend);
- var resolvedRef = ts.resolveProjectReferencePath(host, ref);
- var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
- // An upstream project is blocked
- if (refStatus.type === UpToDateStatusType.Unbuildable) {
- return {
- type: UpToDateStatusType.UpstreamBlocked,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
- if (refStatus.type !== UpToDateStatusType.UpToDate) {
- return {
- type: UpToDateStatusType.UpstreamOutOfDate,
- upstreamProjectName: ref.path
- };
- }
- // If the upstream project's newest file is older than our oldest output, we
- // can't be out of date because of it
- if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
- continue;
- }
- // If the upstream project has only change .d.ts files, and we've built
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
- if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
- pseudoUpToDate = true;
- upstreamChangedProject = ref.path;
- continue;
- }
- // We have an output older than an upstream output - we are out of date
- ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: ref.path
- };
- }
- }
- if (missingOutputFileName !== undefined) {
- return {
- type: UpToDateStatusType.OutputMissing,
- missingOutputFileName: missingOutputFileName
- };
- }
- if (isOutOfDateWithInputs) {
- return {
- type: UpToDateStatusType.OutOfDateWithSelf,
- outOfDateOutputFileName: oldestOutputFileName,
- newerInputFileName: newestInputFileName
- };
- }
- if (usesPrepend && pseudoUpToDate) {
- return {
- type: UpToDateStatusType.OutOfDateWithUpstream,
- outOfDateOutputFileName: oldestOutputFileName,
- newerProjectName: upstreamChangedProject
- };
- }
- // Up to date
- return {
- type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
- newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime,
- newestInputFileTime: newestInputFileTime,
- newestOutputFileTime: newestOutputFileTime,
- newestInputFileName: newestInputFileName,
- newestOutputFileName: newestOutputFileName,
- oldestOutputFileName: oldestOutputFileName
- };
- }
function getAllProjectOutputs(project) {
if (project.options.outFile) {
return getOutFileOutputs(project);