mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 07:13:45 -05:00
Merge branch 'master' into path_mapping_exact_extension
This commit is contained in:
@@ -193,63 +193,66 @@ namespace ts {
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
|
||||
// Check primary library paths
|
||||
if (typeRoots && typeRoots.length) {
|
||||
let resolved = primaryLookup();
|
||||
let primary = true;
|
||||
if (!resolved) {
|
||||
resolved = secondaryLookup();
|
||||
primary = false;
|
||||
}
|
||||
|
||||
let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
|
||||
if (resolved) {
|
||||
resolved = realpath(resolved, host, traceEnabled);
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, primary);
|
||||
}
|
||||
for (const typeRoot of typeRoots) {
|
||||
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName);
|
||||
const candidateDirectory = getDirectoryPath(candidate);
|
||||
resolvedTypeReferenceDirective = { primary, resolvedFileName: resolved };
|
||||
}
|
||||
|
||||
const resolved = resolvedTypeScriptOnly(
|
||||
loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, failedLookupLocations,
|
||||
!directoryProbablyExists(candidateDirectory, host), moduleResolutionState));
|
||||
return { resolvedTypeReferenceDirective, failedLookupLocations };
|
||||
|
||||
if (resolved) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, true);
|
||||
}
|
||||
return {
|
||||
resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolved },
|
||||
failedLookupLocations
|
||||
};
|
||||
function primaryLookup(): string | undefined {
|
||||
// Check primary library paths
|
||||
if (typeRoots && typeRoots.length) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
|
||||
}
|
||||
return forEach(typeRoots, typeRoot => {
|
||||
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName);
|
||||
const candidateDirectory = getDirectoryPath(candidate);
|
||||
return resolvedTypeScriptOnly(
|
||||
loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, failedLookupLocations,
|
||||
!directoryProbablyExists(candidateDirectory, host), moduleResolutionState));
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths);
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedFile: string;
|
||||
const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile);
|
||||
function secondaryLookup(): string | undefined {
|
||||
let resolvedFile: string;
|
||||
const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile);
|
||||
|
||||
if (initialLocationForSecondaryLookup !== undefined) {
|
||||
// check secondary locations
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
|
||||
}
|
||||
resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState));
|
||||
if (traceEnabled) {
|
||||
if (resolvedFile) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false);
|
||||
if (initialLocationForSecondaryLookup !== undefined) {
|
||||
// check secondary locations
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
|
||||
}
|
||||
else {
|
||||
resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState));
|
||||
if (!resolvedFile && traceEnabled) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
|
||||
}
|
||||
return resolvedFile;
|
||||
}
|
||||
else {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder);
|
||||
}
|
||||
}
|
||||
return {
|
||||
resolvedTypeReferenceDirective: resolvedFile ? { primary: false, resolvedFileName: resolvedFile } : undefined,
|
||||
failedLookupLocations
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -549,7 +552,7 @@ namespace ts {
|
||||
const result = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript);
|
||||
if (result) {
|
||||
const { resolved, isExternalLibraryImport } = result;
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved && resolvedWithRealpath(resolved, host, traceEnabled), isExternalLibraryImport, failedLookupLocations);
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved, isExternalLibraryImport, failedLookupLocations);
|
||||
}
|
||||
return { resolvedModule: undefined, failedLookupLocations };
|
||||
|
||||
@@ -564,7 +567,8 @@ namespace ts {
|
||||
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName);
|
||||
}
|
||||
const resolved = loadModuleFromNodeModules(extensions, moduleName, containingDirectory, failedLookupLocations, state);
|
||||
return resolved && { resolved, isExternalLibraryImport: true };
|
||||
// For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files.
|
||||
return resolved && { resolved: { path: realpath(resolved.path, host, traceEnabled), extension: resolved.extension }, isExternalLibraryImport: true };
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
@@ -574,16 +578,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function resolvedWithRealpath(resolved: Resolved, host: ModuleResolutionHost, traceEnabled: boolean): Resolved {
|
||||
function realpath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
|
||||
if (!host.realpath) {
|
||||
return resolved;
|
||||
return path;
|
||||
}
|
||||
|
||||
const real = normalizePath(host.realpath(resolved.path));
|
||||
const real = normalizePath(host.realpath(path));
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_real_path_for_0_result_1, resolved.path, real);
|
||||
trace(host, Diagnostics.Resolving_real_path_for_0_result_1, path, real);
|
||||
}
|
||||
return { path: real, extension: resolved.extension };
|
||||
return real;
|
||||
}
|
||||
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
|
||||
@@ -1404,14 +1404,17 @@ namespace ts {
|
||||
// If we already resolved to this file, it must have been a secondary reference. Check file contents
|
||||
// for sameness and possibly issue an error
|
||||
if (previousResolution) {
|
||||
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
|
||||
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
));
|
||||
// Don't bother reading the file again if it's the same file.
|
||||
if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) {
|
||||
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
|
||||
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
));
|
||||
}
|
||||
}
|
||||
// don't overwrite previous resolution result
|
||||
saveResolution = false;
|
||||
|
||||
@@ -958,28 +958,38 @@ namespace Harness {
|
||||
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
|
||||
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
const realPathMap: ts.FileMap<string> = ts.createFileMap<string>();
|
||||
const fileMap: ts.FileMap<() => ts.SourceFile> = ts.createFileMap<() => ts.SourceFile>();
|
||||
/** Maps a symlink name to a realpath. Used only for exposing `realpath`. */
|
||||
const realPathMap = ts.createFileMap<string>();
|
||||
/**
|
||||
* Maps a file name to a source file.
|
||||
* This will have a different SourceFile for every symlink pointing to that file;
|
||||
* if the program resolves realpaths then symlink entries will be ignored.
|
||||
*/
|
||||
const fileMap = ts.createFileMap<ts.SourceFile>();
|
||||
for (const file of inputFiles) {
|
||||
if (file.content !== undefined) {
|
||||
const fileName = ts.normalizePath(file.unitName);
|
||||
const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName);
|
||||
if (file.fileOptions && file.fileOptions["symlink"]) {
|
||||
const link = file.fileOptions["symlink"];
|
||||
const linkPath = ts.toPath(link, currentDirectory, getCanonicalFileName);
|
||||
realPathMap.set(linkPath, fileName);
|
||||
fileMap.set(path, (): ts.SourceFile => { throw new Error("Symlinks should always be resolved to a realpath first"); });
|
||||
const links = file.fileOptions["symlink"].split(",");
|
||||
for (const link of links) {
|
||||
const linkPath = ts.toPath(link, currentDirectory, getCanonicalFileName);
|
||||
realPathMap.set(linkPath, fileName);
|
||||
// Create a different SourceFile for every symlink.
|
||||
const sourceFile = createSourceFileAndAssertInvariants(linkPath, file.content, scriptTarget);
|
||||
fileMap.set(linkPath, sourceFile);
|
||||
}
|
||||
}
|
||||
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
|
||||
fileMap.set(path, () => sourceFile);
|
||||
fileMap.set(path, sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string) {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
if (fileMap.contains(path)) {
|
||||
return fileMap.get(path)();
|
||||
const fromFileMap = fileMap.get(toPath(fileName));
|
||||
if (fromFileMap) {
|
||||
return fromFileMap;
|
||||
}
|
||||
else if (fileName === fourslashFileName) {
|
||||
const tsFn = "tests/cases/fourslash/" + fourslashFileName;
|
||||
@@ -998,6 +1008,9 @@ namespace Harness {
|
||||
newLineKind === ts.NewLineKind.LineFeed ? lineFeed :
|
||||
Harness.IO.newLine();
|
||||
|
||||
function toPath(fileName: string): ts.Path {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
return {
|
||||
getCurrentDirectory: () => currentDirectory,
|
||||
@@ -1007,24 +1020,26 @@ namespace Harness {
|
||||
getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getNewLine: () => newLine,
|
||||
fileExists: fileName => {
|
||||
const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
return fileMap.contains(path) || (realPathMap && realPathMap.contains(path));
|
||||
},
|
||||
fileExists: fileName => fileMap.contains(toPath(fileName)),
|
||||
readFile: (fileName: string): string => {
|
||||
return fileMap.get(ts.toPath(fileName, currentDirectory, getCanonicalFileName))().getText();
|
||||
const file = fileMap.get(toPath(fileName));
|
||||
if (ts.endsWith(fileName, "json")) {
|
||||
// strip comments
|
||||
return file.getText();
|
||||
}
|
||||
return file.text;
|
||||
},
|
||||
realpath: (fileName: string): ts.Path => {
|
||||
const path = toPath(fileName);
|
||||
return (realPathMap.get(path) as ts.Path) || path;
|
||||
},
|
||||
realpath: realPathMap && ((f: string) => {
|
||||
const path = ts.toPath(f, currentDirectory, getCanonicalFileName);
|
||||
return realPathMap.get(path) || path;
|
||||
}),
|
||||
directoryExists: dir => {
|
||||
let path = ts.toPath(dir, currentDirectory, getCanonicalFileName);
|
||||
// Strip trailing /, which may exist if the path is a drive root
|
||||
if (path[path.length - 1] === "/") {
|
||||
path = <ts.Path>path.substr(0, path.length - 1);
|
||||
}
|
||||
return mapHasFileInDirectory(path, fileMap) || mapHasFileInDirectory(path, realPathMap);
|
||||
return mapHasFileInDirectory(path, fileMap);
|
||||
},
|
||||
getDirectories: d => {
|
||||
const path = ts.toPath(d, currentDirectory, getCanonicalFileName);
|
||||
|
||||
Reference in New Issue
Block a user