From a301001420e86acddf5526f5607efd240ec11405 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 30 Sep 2020 09:32:19 -0700 Subject: [PATCH] Use correct program when checking for reexports from AutoImportProviderProject (#40843) --- src/services/codefixes/importFixes.ts | 12 +++++----- .../fourslash/server/autoImportProvider5.ts | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/server/autoImportProvider5.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 291dbdf5514..4600dfcd9b0 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -498,7 +498,7 @@ namespace ts.codefix { const compilerOptions = program.getCompilerOptions(); const preferTypeOnlyImport = compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error && isValidTypeOnlyAliasUseSite(symbolToken); const useRequire = shouldUseRequire(sourceFile, compilerOptions); - const exportInfos = getExportInfos(symbolName, getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, checker, program, useAutoImportProvider, host); + const exportInfos = getExportInfos(symbolName, getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host); const fixes = arrayFrom(flatMapIterator(exportInfos.entries(), ([_, exportInfos]) => getFixForImport(exportInfos, symbolName, symbolToken.getStart(sourceFile), preferTypeOnlyImport, useRequire, program, sourceFile, host, preferences))); return { fixes, symbolName }; @@ -521,7 +521,6 @@ namespace ts.codefix { currentTokenMeaning: SemanticMeaning, cancellationToken: CancellationToken, sourceFile: SourceFile, - checker: TypeChecker, program: Program, useAutoImportProvider: boolean, host: LanguageServiceHost @@ -529,21 +528,22 @@ namespace ts.codefix { // For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once. // Maps symbol id to info for modules providing that symbol (original export + re-exports). const originalSymbolToExportInfos = createMultiMap(); - function addSymbol(moduleSymbol: Symbol, exportedSymbol: Symbol, importKind: ImportKind): void { + function addSymbol(moduleSymbol: Symbol, exportedSymbol: Symbol, importKind: ImportKind, checker: TypeChecker): void { originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol, importKind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exportedSymbol, checker) }); } - forEachExternalModuleToImportFrom(program, host, sourceFile, /*filterByPackageJson*/ true, useAutoImportProvider, moduleSymbol => { + forEachExternalModuleToImportFrom(program, host, sourceFile, /*filterByPackageJson*/ true, useAutoImportProvider, (moduleSymbol, _, program) => { + const checker = program.getTypeChecker(); cancellationToken.throwIfCancellationRequested(); const defaultInfo = getDefaultLikeExportInfo(sourceFile, moduleSymbol, checker, program.getCompilerOptions()); if (defaultInfo && defaultInfo.name === symbolName && symbolHasMeaning(defaultInfo.symbolForMeaning, currentTokenMeaning)) { - addSymbol(moduleSymbol, defaultInfo.symbol, defaultInfo.kind); + addSymbol(moduleSymbol, defaultInfo.symbol, defaultInfo.kind, checker); } // check exports with the same name const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); if (exportSymbolWithIdenticalName && symbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { - addSymbol(moduleSymbol, exportSymbolWithIdenticalName, ImportKind.Named); + addSymbol(moduleSymbol, exportSymbolWithIdenticalName, ImportKind.Named, checker); } }); return originalSymbolToExportInfos; diff --git a/tests/cases/fourslash/server/autoImportProvider5.ts b/tests/cases/fourslash/server/autoImportProvider5.ts new file mode 100644 index 00000000000..824666e91c9 --- /dev/null +++ b/tests/cases/fourslash/server/autoImportProvider5.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: /package.json +//// { "dependencies": { "react-hook-form": "*" } } + +// @Filename: /node_modules/react-hook-form/package.json +//// { "types": "dist/index.d.ts" } + +// @Filename: /node_modules/react-hook-form/dist/index.d.ts +//// export * from "./useForm"; + +// @Filename: /node_modules/react-hook-form/dist/useForm.d.ts +//// export declare function useForm(): void; + +// @Filename: /index.ts +//// useForm/**/ + +goTo.marker(""); +verify.importFixAtPosition([ + `import { useForm } from "react-hook-form";\r\n\r\nuseForm`, + `import { useForm } from "react-hook-form/dist/useForm";\r\n\r\nuseForm` +]);