Skip to content

Commit 6208d2f

Browse files
committed
Revert "Revert "[DO NOT MERGE UNTIL 5.6] Fix re-exported defaults in ExportInfoMap (#58837)""
This reverts commit a19bf0c.
1 parent c4069c5 commit 6208d2f

File tree

5 files changed

+96
-30
lines changed

5 files changed

+96
-30
lines changed

src/services/codefixes/importFixes.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ function getNewImportFixes(
11871187
const exportEquals = checker.resolveExternalModuleSymbol(exportInfo.moduleSymbol);
11881188
let namespacePrefix;
11891189
if (exportEquals !== exportInfo.moduleSymbol) {
1190-
namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, compilerOptions, /*preferCapitalizedNames*/ false, identity)!;
1190+
namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, getEmitScriptTarget(compilerOptions), identity)!;
11911191
}
11921192
namespacePrefix ||= moduleSymbolToValidIdentifier(
11931193
exportInfo.moduleSymbol,
@@ -1544,7 +1544,7 @@ function getExportInfos(
15441544
if (
15451545
defaultInfo
15461546
&& symbolFlagsHaveMeaning(checker.getSymbolFlags(defaultInfo.symbol), currentTokenMeaning)
1547-
&& forEachNameOfDefaultExport(defaultInfo.symbol, checker, compilerOptions, isJsxTagName, name => name === symbolName)
1547+
&& forEachNameOfDefaultExport(defaultInfo.symbol, checker, getEmitScriptTarget(compilerOptions), (name, capitalizedName) => (isJsxTagName ? capitalizedName ?? name : name) === symbolName)
15481548
) {
15491549
addSymbol(moduleSymbol, sourceFile, defaultInfo.symbol, defaultInfo.exportKind, program, isFromPackageJson);
15501550
}

src/services/exportInfoMap.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
append,
55
arrayIsEqualTo,
66
CancellationToken,
7-
CompilerOptions,
87
consumesNodeCoreModules,
98
createMultiMap,
109
Debug,
@@ -18,9 +17,7 @@ import {
1817
GetCanonicalFileName,
1918
getDefaultLikeExportNameFromDeclaration,
2019
getDirectoryPath,
21-
getEmitScriptTarget,
2220
getLocalSymbolForExportDefault,
23-
getNamesForExportedSymbol,
2421
getNodeModulePathParts,
2522
getPackageNameFromTypesPackageName,
2623
getRegexFromPattern,
@@ -46,6 +43,7 @@ import {
4643
Path,
4744
pathContainsNodeModules,
4845
Program,
46+
ScriptTarget,
4947
skipAlias,
5048
SourceFile,
5149
startsWith,
@@ -198,7 +196,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost):
198196
// get a better name.
199197
const names = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol)
200198
? unescapeLeadingUnderscores(symbolTableKey)
201-
: getNamesForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined);
199+
: getNamesForExportedSymbol(namedSymbol, checker, /*scriptTarget*/ undefined);
202200

203201
const symbolName = typeof names === "string" ? names : names[0];
204202
const capitalizedSymbolName = typeof names === "string" ? undefined : names[1];
@@ -558,12 +556,21 @@ function isImportableSymbol(symbol: Symbol, checker: TypeChecker) {
558556
return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) && !isPrivateIdentifierSymbol(symbol);
559557
}
560558

559+
function getNamesForExportedSymbol(defaultExport: Symbol, checker: TypeChecker, scriptTarget: ScriptTarget | undefined) {
560+
let names: string | string[] | undefined;
561+
forEachNameOfDefaultExport(defaultExport, checker, scriptTarget, (name, capitalizedName) => {
562+
names = capitalizedName ? [name, capitalizedName] : name;
563+
return true;
564+
});
565+
return Debug.checkDefined(names);
566+
}
567+
561568
/**
562569
* @internal
563570
* May call `cb` multiple times with the same name.
564571
* Terminates when `cb` returns a truthy value.
565572
*/
566-
export function forEachNameOfDefaultExport<T>(defaultExport: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions, preferCapitalizedNames: boolean, cb: (name: string) => T | undefined): T | undefined {
573+
export function forEachNameOfDefaultExport<T>(defaultExport: Symbol, checker: TypeChecker, scriptTarget: ScriptTarget | undefined, cb: (name: string, capitalizedName?: string) => T | undefined): T | undefined {
567574
let chain: Symbol[] | undefined;
568575
let current: Symbol | undefined = defaultExport;
569576

@@ -588,7 +595,10 @@ export function forEachNameOfDefaultExport<T>(defaultExport: Symbol, checker: Ty
588595

589596
for (const symbol of chain ?? emptyArray) {
590597
if (symbol.parent && isExternalModuleSymbol(symbol.parent)) {
591-
const final = cb(moduleSymbolToValidIdentifier(symbol.parent, getEmitScriptTarget(compilerOptions), preferCapitalizedNames));
598+
const final = cb(
599+
moduleSymbolToValidIdentifier(symbol.parent, scriptTarget, /*forceCapitalize*/ false),
600+
moduleSymbolToValidIdentifier(symbol.parent, scriptTarget, /*forceCapitalize*/ true),
601+
);
592602
if (final) return final;
593603
}
594604
}

src/services/utilities.ts

+11-20
Original file line numberDiff line numberDiff line change
@@ -4024,22 +4024,13 @@ export function firstOrOnly<T>(valueOrArray: T | readonly T[]): T {
40244024
return isArray(valueOrArray) ? first(valueOrArray) : valueOrArray;
40254025
}
40264026

4027-
/** @internal */
4028-
export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined): string | [lowercase: string, capitalized: string] {
4029-
if (needsNameFromDeclaration(symbol)) {
4030-
const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol);
4031-
if (fromDeclaration) return fromDeclaration;
4032-
const fileNameCase = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ false);
4033-
const capitalized = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ true);
4034-
if (fileNameCase === capitalized) return fileNameCase;
4035-
return [fileNameCase, capitalized];
4036-
}
4037-
return symbol.name;
4038-
}
4039-
4040-
/** @internal */
4027+
/**
4028+
* If a type checker and multiple files are available, consider using `forEachNameOfDefaultExport`
4029+
* instead, which searches for names of re-exported defaults/namespaces in target files.
4030+
* @internal
4031+
*/
40414032
export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) {
4042-
if (needsNameFromDeclaration(symbol)) {
4033+
if (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default) {
40434034
// Names for default exports:
40444035
// - export default foo => foo
40454036
// - export { foo as default } => foo
@@ -4050,11 +4041,11 @@ export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTar
40504041
return symbol.name;
40514042
}
40524043

4053-
function needsNameFromDeclaration(symbol: Symbol) {
4054-
return !(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default);
4055-
}
4056-
4057-
/** @internal */
4044+
/**
4045+
* If a type checker and multiple files are available, consider using `forEachNameOfDefaultExport`
4046+
* instead, which searches for names of re-exported defaults/namespaces in target files.
4047+
* @internal
4048+
*/
40584049
export function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string | undefined {
40594050
return firstDefined(symbol.declarations, d => {
40604051
// "export default" in this case. See `ExportAssignment`for more details.

tests/baselines/reference/tsserver/fourslashServer/completionsImport_jsModuleExportsAssignment.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: *
376376
Info seq [hh:mm:ss:mss] getCompletionData: Get previous token: *
377377
Info seq [hh:mm:ss:mss] getExportInfoMap: cache miss or empty; calculating new results
378378
Info seq [hh:mm:ss:mss] getExportInfoMap: done in * ms
379-
Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 3 from cache
379+
Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 4 from cache
380380
Info seq [hh:mm:ss:mss] collectAutoImports: response is incomplete
381381
Info seq [hh:mm:ss:mss] collectAutoImports: *
382382
Info seq [hh:mm:ss:mss] getCompletionData: Semantic work: *
@@ -1049,6 +1049,19 @@ Info seq [hh:mm:ss:mss] response:
10491049
"fileName": "/third_party/marked/src/defaults.js"
10501050
}
10511051
},
1052+
{
1053+
"name": "defaults",
1054+
"kind": "property",
1055+
"kindModifiers": "",
1056+
"sortText": "16",
1057+
"hasAction": true,
1058+
"source": "/third_party/marked/src/defaults",
1059+
"data": {
1060+
"exportName": "export=",
1061+
"exportMapKey": "8 * defaults ",
1062+
"fileName": "/third_party/marked/src/defaults.js"
1063+
}
1064+
},
10521065
{
10531066
"name": "defaults",
10541067
"kind": "alias",
@@ -1253,7 +1266,7 @@ Info seq [hh:mm:ss:mss] getCompletionData: Get current token: *
12531266
Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: *
12541267
Info seq [hh:mm:ss:mss] getCompletionData: Get previous token: *
12551268
Info seq [hh:mm:ss:mss] getExportInfoMap: cache hit
1256-
Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 3 from cache
1269+
Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 4 from cache
12571270
Info seq [hh:mm:ss:mss] collectAutoImports: response is incomplete
12581271
Info seq [hh:mm:ss:mss] collectAutoImports: *
12591272
Info seq [hh:mm:ss:mss] getCompletionData: Semantic work: *
@@ -1939,6 +1952,19 @@ Info seq [hh:mm:ss:mss] response:
19391952
"fileName": "/third_party/marked/src/defaults.js"
19401953
}
19411954
},
1955+
{
1956+
"name": "defaults",
1957+
"kind": "property",
1958+
"kindModifiers": "",
1959+
"sortText": "16",
1960+
"hasAction": true,
1961+
"source": "/third_party/marked/src/defaults",
1962+
"data": {
1963+
"exportName": "export=",
1964+
"exportMapKey": "8 * defaults ",
1965+
"fileName": "/third_party/marked/src/defaults.js"
1966+
}
1967+
},
19421968
{
19431969
"name": "defaults",
19441970
"kind": "alias",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @module: preserve
4+
// @checkJs: true
5+
6+
// @Filename: /node_modules/example/package.json
7+
//// { "name": "example", "version": "1.0.0", "main": "dist/index.js" }
8+
9+
// @Filename: /node_modules/example/dist/nested/module.d.ts
10+
//// declare const defaultExport: () => void;
11+
//// declare const namedExport: () => void;
12+
////
13+
//// export default defaultExport;
14+
//// export { namedExport };
15+
16+
// @Filename: /node_modules/example/dist/index.d.ts
17+
//// export { default, namedExport } from "./nested/module";
18+
19+
// @Filename: /index.mjs
20+
//// import { namedExport } from "example";
21+
//// defaultExp/**/
22+
23+
verify.completions({
24+
marker: "",
25+
exact: completion.globalsInJsPlus([
26+
"namedExport",
27+
{
28+
name: "defaultExport",
29+
source: "example",
30+
sourceDisplay: "example",
31+
hasAction: true,
32+
sortText: completion.SortText.AutoImportSuggestions
33+
},
34+
]),
35+
preferences: {
36+
includeCompletionsForModuleExports: true,
37+
allowIncompleteCompletions: true,
38+
},
39+
});

0 commit comments

Comments
 (0)