Merge branch 'master' into tsbuild

This commit is contained in:
Ryan Cavanaugh
2018-06-05 14:55:51 -07:00
1932 changed files with 64966 additions and 53048 deletions

123
src/compiler/program.ts Executable file → Normal file
View File

@@ -491,6 +491,17 @@ namespace ts {
};
}
/**
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
* that represent a compilation unit.
*
* Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and
* triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in.
*
* @param createProgramOptions - The options for creating a program.
* @returns A 'Program' object.
*/
export function createProgram(createProgramOptions: CreateProgramOptions): Program;
/**
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
* that represent a compilation unit.
@@ -505,7 +516,6 @@ namespace ts {
* @param configFileParsingDiagnostics - error during config file parsing
* @returns A 'Program' object.
*/
export function createProgram(createProgramOptions: CreateProgramOptions): Program;
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
export function createProgram(rootNamesOrOptions: ReadonlyArray<string> | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program {
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217
@@ -513,7 +523,9 @@ namespace ts {
let { oldProgram } = createProgramOptions;
let program: Program;
let files: SourceFile[] = [];
let processingDefaultLibFiles: SourceFile[] | undefined;
let processingOtherFiles: SourceFile[] | undefined;
let files: SourceFile[];
let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
@@ -613,7 +625,7 @@ namespace ts {
if (parsedRef) {
if (parsedRef.commandLine.options.outFile) {
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*packageId*/ undefined);
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
}
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
}
@@ -623,7 +635,9 @@ namespace ts {
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
if (structuralIsReused !== StructureIsReused.Completely) {
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
processingDefaultLibFiles = [];
processingOtherFiles = [];
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false));
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
@@ -647,16 +661,19 @@ namespace ts {
// otherwise, using options specified in '--lib' instead of '--target' default library file
const defaultLibraryFileName = getDefaultLibraryFileName();
if (!options.lib && defaultLibraryFileName) {
processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true);
processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false);
}
else {
forEach(options.lib, libFileName => {
processRootFile(combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true);
processRootFile(combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false);
});
}
}
missingFilePaths = arrayFrom(filesByName.keys(), p => <Path>p).filter(p => !filesByName.get(p));
files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles);
processingDefaultLibFiles = undefined;
processingOtherFiles = undefined;
}
Debug.assert(!!missingFilePaths);
@@ -686,6 +703,7 @@ namespace ts {
getOptionsDiagnostics,
getGlobalDiagnostics,
getSemanticDiagnostics,
getSuggestionDiagnostics,
getDeclarationDiagnostics,
getTypeChecker,
getClassifiableNames,
@@ -703,6 +721,7 @@ namespace ts {
isSourceFileDefaultLibrary,
dropDiagnosticsProducingTypeChecker,
getSourceFileFromReference,
getLibFileFromReference,
sourceFileToPackageName,
redirectTargetsSet,
isEmittedFile,
@@ -717,6 +736,21 @@ namespace ts {
return program;
function compareDefaultLibFiles(a: SourceFile, b: SourceFile) {
return compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b));
}
function getDefaultLibFilePriority(a: SourceFile) {
if (containsPath(defaultLibraryPath, a.fileName, /*ignoreCase*/ false)) {
const basename = getBaseFileName(a.fileName);
if (basename === "lib.d.ts" || basename === "lib.es6.d.ts") return 0;
const name = removeSuffix(removePrefix(basename, "lib."), ".d.ts");
const index = libs.indexOf(name);
if (index !== -1) return index + 1;
}
return libs.length + 2;
}
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined {
return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache);
}
@@ -1039,6 +1073,11 @@ namespace ts {
if (fileChanged) {
// The `newSourceFile` object was created for the new program.
if (!arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) {
// 'lib' references has changed. Matches behavior in changesAffectModuleResolution
return oldProgram.structureIsReused = StructureIsReused.Not;
}
if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) {
// value of no-default-lib has changed
// this will affect if default library is injected into the list of files
@@ -1171,6 +1210,9 @@ namespace ts {
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
readFile: f => host.readFile(f),
fileExists: f => host.fileExists(f),
...(host.directoryExists ? { directoryExists: f => host.directoryExists!(f) } : {}),
};
}
@@ -1427,6 +1469,12 @@ namespace ts {
});
}
function getSuggestionDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
return runWithCancellationToken(() => {
return getDiagnosticsProducingTypeChecker().getSuggestionDiagnostics(sourceFile, cancellationToken);
});
}
/**
* Skip errors if previous line start with '// @ts-ignore' comment, not counting non-empty non-comment lines
*/
@@ -1696,8 +1744,8 @@ namespace ts {
return configFileParsingDiagnostics || emptyArray;
}
function processRootFile(fileName: string, isDefaultLib: boolean) {
processSourceFile(normalizePath(fileName), isDefaultLib, /*packageId*/ undefined);
function processRootFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean) {
processSourceFile(normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined);
}
function fileReferenceIsEqualTo(a: FileReference, b: FileReference): boolean {
@@ -1807,11 +1855,9 @@ namespace ts {
else if (isLiteralImportTypeNode(node)) {
imports = append(imports, node.argument.literal);
}
else {
collectDynamicImportOrRequireCallsForEachChild(node);
if (hasJSDocNodes(node)) {
forEach(node.jsDoc, collectDynamicImportOrRequireCallsForEachChild);
}
collectDynamicImportOrRequireCallsForEachChild(node);
if (hasJSDocNodes(node)) {
forEach(node.jsDoc, collectDynamicImportOrRequireCallsForEachChild);
}
}
@@ -1820,6 +1866,14 @@ namespace ts {
}
}
function getLibFileFromReference(ref: FileReference) {
const libName = ref.fileName.toLocaleLowerCase();
const libFileName = libMap.get(libName);
if (libFileName) {
return getSourceFile(combinePaths(defaultLibraryPath, libFileName));
}
}
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)));
@@ -1870,9 +1924,9 @@ namespace ts {
}
/** This has side effects through `findSourceFile`. */
function processSourceFile(fileName: string, isDefaultLib: boolean, packageId: PackageId | undefined, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
getSourceFileFromReferenceWorker(fileName,
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile!, refPos!, refEnd!, packageId), // TODO: GH#18217
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile!, refPos!, refEnd!, packageId), // TODO: GH#18217
(diagnostic, ...args) => {
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
@@ -1910,7 +1964,7 @@ namespace ts {
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
if (filesByName.has(path)) {
const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
@@ -1928,6 +1982,8 @@ namespace ts {
processTypeReferenceDirectives(file);
}
processLibReferenceDirectives(file);
modulesWithElidedImports.set(file.path, false);
processImportedModules(file);
}
@@ -1978,7 +2034,7 @@ namespace ts {
redirectTargetsSet.set(fileFromPackageId.path, true);
filesByName.set(path, dupFile);
sourceFileToPackageName.set(path, packageId.name);
files.push(dupFile);
processingOtherFiles!.push(dupFile);
return dupFile;
}
else if (file) {
@@ -2010,21 +2066,23 @@ namespace ts {
}
}
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
skipDefaultLib = skipDefaultLib || (file.hasNoDefaultLib && !ignoreNoDefaultLib);
if (!options.noResolve) {
processReferencedFiles(file, isDefaultLib);
processTypeReferenceDirectives(file);
}
processLibReferenceDirectives(file);
// always process imported modules to record module name resolutions
processImportedModules(file);
if (isDefaultLib) {
files.unshift(file);
processingDefaultLibFiles!.push(file);
}
else {
files.push(file);
processingOtherFiles!.push(file);
}
}
@@ -2051,7 +2109,7 @@ namespace ts {
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
processSourceFile(referencedFileName, isDefaultLib, /*packageId*/ undefined, file, ref.pos, ref.end);
processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end);
});
}
@@ -2086,7 +2144,7 @@ namespace ts {
if (resolvedTypeReferenceDirective) {
if (resolvedTypeReferenceDirective.primary) {
// resolved from the primary path
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
}
else {
// If we already resolved to this file, it must have been a secondary reference. Check file contents
@@ -2109,7 +2167,7 @@ namespace ts {
}
else {
// First resolution of this library
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
}
}
}
@@ -2122,6 +2180,23 @@ namespace ts {
}
}
function processLibReferenceDirectives(file: SourceFile) {
forEach(file.libReferenceDirectives, libReference => {
const libName = libReference.fileName.toLocaleLowerCase();
const libFileName = libMap.get(libName);
if (libFileName) {
// we ignore any 'no-default-lib' reference set on this file.
processRootFile(combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true);
}
else {
const unqualifiedLibName = removeSuffix(removePrefix(libName, "lib."), ".d.ts");
const suggestion = getSpellingSuggestion(unqualifiedLibName, libs, identity);
const message = suggestion ? Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 : Diagnostics.Cannot_find_lib_definition_for_0;
fileProcessingDiagnostics.add(createDiagnostic(file, libReference.pos, libReference.end, message, libName, suggestion));
}
});
}
function createDiagnostic(refFile: SourceFile, refPos: number, refEnd: number, message: DiagnosticMessage, ...args: any[]): Diagnostic {
if (refFile === undefined || refPos === undefined || refEnd === undefined) {
return createCompilerDiagnostic(message, ...args);
@@ -2182,7 +2257,7 @@ namespace ts {
else if (shouldAddFile) {
const path = toPath(resolvedFileName);
const pos = skipTrivia(file.text, file.imports[i].pos);
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId);
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId);
}
if (isFromNodeModulesSearch) {