Support 'isSourceFileFromExternalLibrary' for source files from '/// <reference types="" />'' (#28004)

* Support 'isSourceFileFromExternalLibrary' for source files from '/// <reference types="" />''

* Calculate `isExternalLibraryImport` at the end

* Calculate isExternalLibraryImport with symlink path
This commit is contained in:
Andy
2018-10-19 18:00:45 -07:00
committed by GitHub
parent 424fcdde37
commit 72244c5b03
8 changed files with 43 additions and 27 deletions

View File

@@ -298,14 +298,12 @@ namespace ts {
let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
if (resolved) {
if (!options.preserveSymlinks) {
resolved = { ...resolved, fileName: realPath(resolved.fileName, host, traceEnabled) };
}
const { fileName, packageId } = resolved;
const resolvedFileName = options.preserveSymlinks ? fileName : realPath(fileName, host, traceEnabled);
if (traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved.fileName, primary);
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFileName, primary);
}
resolvedTypeReferenceDirective = { primary, resolvedFileName: resolved.fileName, packageId: resolved.packageId };
resolvedTypeReferenceDirective = { primary, resolvedFileName, packageId, isExternalLibraryImport: pathContainsNodeModules(fileName) };
}
return { resolvedTypeReferenceDirective, failedLookupLocations };
@@ -316,7 +314,7 @@ namespace ts {
if (traceEnabled) {
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
}
return forEach(typeRoots, typeRoot => {
return firstDefined(typeRoots, typeRoot => {
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName);
const candidateDirectory = getDirectoryPath(candidate);
const directoryExists = directoryProbablyExists(candidateDirectory, host);
@@ -343,15 +341,16 @@ namespace ts {
if (traceEnabled) {
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
}
let result: SearchResult<Resolved> | undefined;
let result: Resolved | undefined;
if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) {
result = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined);
const searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined);
result = searchResult && searchResult.value;
}
else {
const { path: candidate } = normalizePathAndParts(combinePaths(initialLocationForSecondaryLookup, typeReferenceDirectiveName));
result = toSearchResult(nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true));
result = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true);
}
const resolvedFile = resolvedTypeScriptOnly(result && result.value);
const resolvedFile = resolvedTypeScriptOnly(result);
if (!resolvedFile && traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
}
@@ -883,7 +882,7 @@ namespace ts {
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ true);
const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, state);
if (resolved) {
return toSearchResult({ resolved, isExternalLibraryImport: stringContains(resolved.path, nodeModulesPathPart) });
return toSearchResult({ resolved, isExternalLibraryImport: pathContainsNodeModules(resolved.path) });
}
if (!isExternalModuleNameRelative(moduleName)) {
@@ -960,6 +959,10 @@ namespace ts {
/*@internal*/
export const nodeModulesPathPart = "/node_modules/";
/*@internal*/
export function pathContainsNodeModules(path: string): boolean {
return stringContains(path, nodeModulesPathPart);
}
/**
* This will be called on the successfully resolved path from `loadModuleFromFile`.

View File

@@ -2345,6 +2345,8 @@ namespace ts {
}
let saveResolution = true;
if (resolvedTypeReferenceDirective) {
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth++;
if (resolvedTypeReferenceDirective.primary) {
// resolved from the primary path
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
@@ -2373,6 +2375,8 @@ namespace ts {
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
}
}
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth--;
}
else {
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217

View File

@@ -432,7 +432,7 @@ namespace ts {
function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: Path) {
// If directory path contains node module, get the most parent node_modules directory for watching
while (stringContains(dirPath, nodeModulesPathPart)) {
while (pathContainsNodeModules(dirPath)) {
dir = getDirectoryPath(dir);
dirPath = getDirectoryPath(dirPath);
}

View File

@@ -4942,6 +4942,8 @@ namespace ts {
// The location of the .d.ts file we located, or undefined if resolution failed
resolvedFileName: string | undefined;
packageId?: PackageId;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
}
export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {

View File

@@ -113,12 +113,23 @@ namespace ts {
const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, bar, barFooPackage, barFooIndex, fooPackage, fooIndex], cwd: "/" });
const program = createProgram(["/a.ts"], emptyOptions, new fakes.CompilerHost(fs, { newLine: NewLineKind.LineFeed }));
for (const file of [a, bar, barFooIndex, fooIndex]) {
const isExternalExpected = file !== a;
const isExternalActual = program.isSourceFileFromExternalLibrary(program.getSourceFile(file.file)!);
assert.equal(isExternalActual, isExternalExpected, `Expected ${file.file} isSourceFileFromExternalLibrary to be ${isExternalExpected}, got ${isExternalActual}`);
}
assertIsExternal(program, [a, bar, barFooIndex, fooIndex], f => f !== a);
});
it('works on `/// <reference types="" />`', () => {
const a = new documents.TextDocument("/a.ts", '/// <reference types="foo" />');
const fooIndex = new documents.TextDocument("/node_modules/foo/index.d.ts", "declare const foo: number;");
const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, fooIndex], cwd: "/" });
const program = createProgram(["/a.ts"], emptyOptions, new fakes.CompilerHost(fs, { newLine: NewLineKind.LineFeed }));
assertIsExternal(program, [a, fooIndex], f => f !== a);
});
function assertIsExternal(program: Program, files: ReadonlyArray<documents.TextDocument>, isExternalExpected: (file: documents.TextDocument) => boolean): void {
for (const file of files) {
const actual = program.isSourceFileFromExternalLibrary(program.getSourceFile(file.file)!);
const expected = isExternalExpected(file);
assert.equal(actual, expected, `Expected ${file.file} isSourceFileFromExternalLibrary to be ${expected}, got ${actual}`);
}
}
});
}

View File

@@ -2670,6 +2670,8 @@ declare namespace ts {
primary: boolean;
resolvedFileName: string | undefined;
packageId?: PackageId;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
}
interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;

View File

@@ -2670,6 +2670,8 @@ declare namespace ts {
primary: boolean;
resolvedFileName: string | undefined;
packageId?: PackageId;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
}
interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;

View File

@@ -32,14 +32,6 @@ import { m } from "mquery";
j + k + l + m;
//// [lquery.js]
"use strict";
exports.__esModule = true;
exports.l = 2;
//// [index.js]
"use strict";
exports.__esModule = true;
exports.m = 3;
//// [a.js]
"use strict";
exports.__esModule = true;