Check autoImportExcludePatterns against symlink paths (#57033)

This commit is contained in:
Andrew Branch 2024-01-16 09:35:26 -08:00 committed by GitHub
parent cf33fd0cde
commit a673958ccc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2288 additions and 8 deletions

View File

@ -8,6 +8,7 @@ import {
createMultiMap,
Debug,
emptyArray,
ensureTrailingDirectorySeparator,
findIndex,
firstDefined,
forEachAncestorDirectory,
@ -43,6 +44,7 @@ import {
nodeModulesPathPart,
PackageJsonImportFilter,
Path,
pathContainsNodeModules,
Program,
skipAlias,
skipOuterExpressions,
@ -427,12 +429,12 @@ export function forEachExternalModuleToImportFrom(
return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames) : undefined;
});
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), excludePatterns, (module, file) => cb(module, file, program, /*isFromPackageJson*/ false));
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), excludePatterns, host, (module, file) => cb(module, file, program, /*isFromPackageJson*/ false));
const autoImportProvider = useAutoImportProvider && host.getPackageJsonAutoImportProvider?.();
if (autoImportProvider) {
const start = timestamp();
const checker = program.getTypeChecker();
forEachExternalModule(autoImportProvider.getTypeChecker(), autoImportProvider.getSourceFiles(), excludePatterns, (module, file) => {
forEachExternalModule(autoImportProvider.getTypeChecker(), autoImportProvider.getSourceFiles(), excludePatterns, host, (module, file) => {
if (file && !program.getSourceFile(file.fileName) || !file && !checker.resolveName(module.name, /*location*/ undefined, SymbolFlags.Module, /*excludeGlobals*/ false)) {
// The AutoImportProvider filters files already in the main program out of its *root* files,
// but non-root files can still be present in both programs, and already in the export info map
@ -445,15 +447,30 @@ export function forEachExternalModuleToImportFrom(
}
}
function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly SourceFile[], excludePatterns: readonly RegExp[] | undefined, cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) {
const isExcluded = excludePatterns && ((fileName: string) => excludePatterns.some(p => p.test(fileName)));
function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly SourceFile[], excludePatterns: readonly RegExp[] | undefined, host: LanguageServiceHost, cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) {
const realpathsWithSymlinks = host.getSymlinkCache?.().getSymlinkedDirectoriesByRealpath();
const isExcluded = excludePatterns && (({ fileName, path }: SourceFile) => {
if (excludePatterns.some(p => p.test(fileName))) return true;
if (realpathsWithSymlinks?.size && pathContainsNodeModules(fileName)) {
let dir = getDirectoryPath(fileName);
return forEachAncestorDirectory(getDirectoryPath(path), dirPath => {
const symlinks = realpathsWithSymlinks.get(ensureTrailingDirectorySeparator(dirPath));
if (symlinks) {
return symlinks.some(s => excludePatterns.some(p => p.test(fileName.replace(dir, s))));
}
dir = getDirectoryPath(dir);
}) ?? false;
}
return false;
});
for (const ambient of checker.getAmbientModules()) {
if (!ambient.name.includes("*") && !(excludePatterns && ambient.declarations?.every(d => isExcluded!(d.getSourceFile().fileName)))) {
if (!ambient.name.includes("*") && !(excludePatterns && ambient.declarations?.every(d => isExcluded!(d.getSourceFile())))) {
cb(ambient, /*sourceFile*/ undefined);
}
}
for (const sourceFile of allSourceFiles) {
if (isExternalOrCommonJsModule(sourceFile) && !isExcluded?.(sourceFile.fileName)) {
if (isExternalOrCommonJsModule(sourceFile) && !isExcluded?.(sourceFile)) {
cb(checker.getMergedSymbol(sourceFile.symbol), sourceFile);
}
}

View File

@ -22,7 +22,7 @@ export * from "./clients/s3";
{ "name": "aws-sdk", "version": "2.0.0", "main": "index.js" }
//// [/project/package.json]
{ "dependencies": "aws-sdk" }
{ "dependencies": { "aws-sdk": "*" } }
Info seq [hh:mm:ss:mss] request:
@ -113,6 +113,24 @@ Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /project/package.json 250 undefined WatchType: package.json file
Info seq [hh:mm:ss:mss] AutoImportProviderProject: found 1 root files in 1 dependencies in * ms
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /project/node_modules/aws-sdk/index.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/autoImportProviderProject1*
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /project/node_modules/aws-sdk/package.json 2000 undefined Project: /dev/null/autoImportProviderProject1* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /project/node_modules/aws-sdk/clients/s3.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/autoImportProviderProject1* Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info seq [hh:mm:ss:mss] Files (2)
/project/node_modules/aws-sdk/clients/s3.d.ts Text-1 "export declare class S3 {}"
/project/node_modules/aws-sdk/index.d.ts Text-1 "export * from \"./clients/s3\";"
node_modules/aws-sdk/clients/s3.d.ts
Imported via "./clients/s3" from file 'node_modules/aws-sdk/index.d.ts' with packageId 'aws-sdk/clients/s3.d.ts@2.0.0'
node_modules/aws-sdk/index.d.ts
Root file specified for compilation
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
@ -120,6 +138,10 @@ Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject2*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info seq [hh:mm:ss:mss] Files (2)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /project/node_modules/aws-sdk/package.json ProjectRootPath: undefined
@ -134,6 +156,12 @@ watchedFiles::
{"pollingInterval":500}
/lib.decorators.legacy.d.ts:
{"pollingInterval":500}
/project/node_modules/aws-sdk/clients/s3.d.ts: *new*
{"pollingInterval":500}
/project/node_modules/aws-sdk/index.d.ts: *new*
{"pollingInterval":500}
/project/node_modules/aws-sdk/package.json: *new*
{"pollingInterval":2000}
/project/package.json: *new*
{"pollingInterval":250}
@ -984,6 +1012,7 @@ Info seq [hh:mm:ss:mss] request:
},
"command": "getCodeFixes"
}
Info seq [hh:mm:ss:mss] forEachExternalModuleToImportFrom autoImportProvider: *
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,

View File

@ -12,7 +12,7 @@
//// export declare class S3 {}
// @Filename: /project/package.json
//// { "dependencies": "aws-sdk" }
//// { "dependencies": { "aws-sdk": "*" } }
// @Filename: /project/index.ts
//// S3/**/

View File

@ -0,0 +1,34 @@
/// <reference path="../fourslash.ts"/>
// @module: commonjs
// @Filename: /project/node_modules/.store/@remix-run-server-runtime-virtual-c72daf0d/package/package.json
//// {
//// "name": "@remix-run/server-runtime",
//// "version": "0.0.0",
//// "main": "index.js"
//// }
// @Filename: /project/node_modules/.store/@remix-run-server-runtime-virtual-c72daf0d/package/index.d.ts
//// export declare function ServerRuntimeMetaFunction(): void;
// @Filename: /project/package.json
//// { "dependencies": { "@remix-run/server-runtime": "*" } }
// @link: /project/node_modules/.store/@remix-run-server-runtime-virtual-c72daf0d/package -> /project/node_modules/@remix-run/server-runtime
// @Filename: /project/index.ts
//// ServerRuntimeMetaFunction/**/
const autoImportFileExcludePatterns = ["/**/@remix-run/server-runtime"];
verify.completions({
marker: "",
excludes: "ServerRuntimeMetaFunction",
preferences: {
includeCompletionsForModuleExports: true,
autoImportFileExcludePatterns,
}
});
verify.importFixAtPosition([], /*errorCode*/ undefined, { autoImportFileExcludePatterns });

View File

@ -0,0 +1,40 @@
/// <reference path="../fourslash.ts"/>
// @module: commonjs
// @Filename: c:/project/node_modules/.store/aws-sdk-virtual-adfe098/package/package.json
//// { "name": "aws-sdk", "version": "2.0.0", "main": "index.js" }
// @Filename: c:/project/node_modules/.store/aws-sdk-virtual-adfe098/package/index.d.ts
//// export {};
// @Filename: c:/project/node_modules/@remix-run/server-runtime/package.json
//// {
//// "name": "@remix-run/server-runtime",
//// "version": "0.0.0",
//// "main": "index.js"
//// }
// @Filename: c:/project/node_modules/@remix-run/server-runtime/index.d.ts
//// export declare function ServerRuntimeMetaFunction(): void;
// @Filename: c:/project/package.json
//// { "dependencies": { "aws-sdk": "*", "@remix-run/server-runtime": "*" } }
// @link: c:/project/node_modules/.store/aws-sdk-virtual-adfe098/package -> c:/project/node_modules/aws-sdk
// @Filename: c:/project/index.ts
//// ServerRuntimeMetaFunction/**/
const autoImportFileExcludePatterns = ["c:/**/@remix-run/server-runtime"];
verify.completions({
marker: "",
excludes: "ServerRuntimeMetaFunction",
preferences: {
includeCompletionsForModuleExports: true,
autoImportFileExcludePatterns,
}
});
verify.importFixAtPosition([], /*errorCode*/ undefined, { autoImportFileExcludePatterns });