mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-04 14:56:16 -05:00
Merge branch 'master' into tsbuild
This commit is contained in:
123
src/compiler/program.ts
Executable file → Normal file
123
src/compiler/program.ts
Executable file → Normal 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) {
|
||||
|
||||
Reference in New Issue
Block a user