Skip to content

Commit 8999411

Browse files
authored
Missing import code fix - include export assignment properties when looking for module exports (#17376)
* Include export assignment properties when looking for module exports * Create new API function for tryGetMemberInModuleExportsAndProperties * Cleanup based on review feedback
1 parent cc8399d commit 8999411

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ namespace ts {
212212
return node ? isOptionalParameter(node) : false;
213213
},
214214
tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol),
215+
tryGetMemberInModuleExportsAndProperties: (name, symbol) => tryGetMemberInModuleExportsAndProperties(escapeLeadingUnderscores(name), symbol),
215216
tryFindAmbientModuleWithoutAugmentations: moduleName => {
216217
// we deliberately exclude augmentations
217218
// since we are only interested in declarations of the module itself
@@ -1776,6 +1777,17 @@ namespace ts {
17761777
}
17771778
}
17781779

1780+
function tryGetMemberInModuleExportsAndProperties(memberName: __String, moduleSymbol: Symbol): Symbol | undefined {
1781+
const symbol = tryGetMemberInModuleExports(memberName, moduleSymbol);
1782+
if (!symbol) {
1783+
const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
1784+
if (exportEquals !== moduleSymbol) {
1785+
return getPropertyOfType(getTypeOfSymbol(exportEquals), memberName);
1786+
}
1787+
}
1788+
return symbol;
1789+
}
1790+
17791791
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
17801792
return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports || emptySymbols;
17811793
}

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2581,6 +2581,8 @@ namespace ts {
25812581
getAmbientModules(): Symbol[];
25822582

25832583
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
2584+
/** Unlike `tryGetMemberInModuleExports`, this includes properties of an `export =` value. */
2585+
/* @internal */ tryGetMemberInModuleExportsAndProperties(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
25842586
getApparentType(type: Type): Type;
25852587
getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined;
25862588
getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;

src/services/codefixes/importFixes.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,11 @@ namespace ts.codefix {
178178
}
179179
}
180180

181+
// "default" is a keyword and not a legal identifier for the import, so we don't expect it here
182+
Debug.assert(name !== "default");
183+
181184
// check exports with the same name
182-
const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExports(name, moduleSymbol);
185+
const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(name, moduleSymbol);
183186
if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) {
184187
const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName);
185188
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
//// [|bar/*0*/();|]
4+
5+
// @Filename: foo.ts
6+
//// interface MyStatic {
7+
//// bar(): void;
8+
//// }
9+
//// declare var x: MyStatic;
10+
//// export = x;
11+
12+
verify.importFixAtPosition([
13+
`import { bar } from "./foo";
14+
15+
bar();`
16+
]);

0 commit comments

Comments
 (0)