diff --git a/src/services/utilities.ts b/src/services/utilities.ts index be896d9d5ca..4d94041411e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -3971,12 +3971,14 @@ export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTa /** @internal */ export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { if (needsNameFromDeclaration(symbol)) { - // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. + // Names for default exports: + // - export default foo => foo + // - export { foo as default } => foo + // - export default 0 => filename converted to camelCase return getDefaultLikeExportNameFromDeclaration(symbol) || codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, !!preferCapitalized); } return symbol.name; - } function needsNameFromDeclaration(symbol: Symbol) { @@ -3984,11 +3986,18 @@ function needsNameFromDeclaration(symbol: Symbol) { } function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string | undefined { - return firstDefined(symbol.declarations, d => - isExportAssignment(d) - ? tryCast(skipOuterExpressions(d.expression), isIdentifier)?.text - : tryCast(getNameOfDeclaration(d), isIdentifier)?.text - ); + return firstDefined(symbol.declarations, d => { + // "export default" in this case. See `ExportAssignment`for more details. + if (isExportAssignment(d)) { + return tryCast(skipOuterExpressions(d.expression), isIdentifier)?.text; + } + // "export { ~ as default }" + if (isExportSpecifier(d) && d.symbol.flags === SymbolFlags.Alias) { + return tryCast(d.propertyName, isIdentifier)?.text; + } + // GH#52694 + return tryCast(getNameOfDeclaration(d), isIdentifier)?.text; + }); } function getSymbolParentOrFail(symbol: Symbol) { @@ -4219,4 +4228,4 @@ export function fileShouldUseJavaScriptRequire(file: SourceFile | string, progra } } return preferRequire; -} \ No newline at end of file +} diff --git a/tests/cases/fourslash/importNameCodeFixExportAsDefault.ts b/tests/cases/fourslash/importNameCodeFixExportAsDefault.ts new file mode 100644 index 00000000000..5cc0b995210 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixExportAsDefault.ts @@ -0,0 +1,18 @@ +/// + +// @Filename: /foo.ts +////const foo = 'foo' +////export { foo as default } + +// @Filename: /index.ts +//// foo/**/ + +verify.applyCodeActionFromCompletion("", { + name: "foo", + source: "/foo", + description: `Add import from "./foo"`, + newFileContent: `import foo from "./foo";\n\nfoo`, + preferences: { + includeCompletionsForModuleExports: true + } +}); diff --git a/tests/cases/fourslash/importNameCodeFixExportAsDefaultExistingImport.ts b/tests/cases/fourslash/importNameCodeFixExportAsDefaultExistingImport.ts new file mode 100644 index 00000000000..cd789161798 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixExportAsDefaultExistingImport.ts @@ -0,0 +1,13 @@ +/// + +//// import [|{ v1, v2, v3 }|] from "./module"; +//// v4/*0*/(); + +// @Filename: module.ts +//// const v4 = 5; +//// export { v4 as default }; +//// export const v1 = 5; +//// export const v2 = 5; +//// export const v3 = 5; + +verify.importFixAtPosition([`v4, { v1, v2, v3 }`]);