Skip to content

Commit 520a437

Browse files
committed
Bunch of LS fixes via eliminating resolveExternalModuleSymbol, some JS fixes
1 parent d670c28 commit 520a437

6 files changed

Lines changed: 48 additions & 62 deletions

File tree

src/compiler/checker.ts

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
18781878
const moduleSpecifier = getParseTreeNode(moduleSpecifierIn, isExpression);
18791879
return moduleSpecifier && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true);
18801880
},
1881-
resolveExternalModuleSymbol,
18821881
tryGetThisTypeAt: (nodeIn, includeGlobalThis, container) => {
18831882
const node = getParseTreeNode(nodeIn);
18841883
return node && tryGetThisTypeAt(node, includeGlobalThis, container);
@@ -2850,8 +2849,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
28502849
if (!mainModule) {
28512850
return;
28522851
}
2853-
// obtain item referenced by 'export='
2854-
mainModule = resolveExternalModuleSymbol(mainModule);
2852+
mainModule = resolveSymbol(mainModule);
28552853
if (mainModule.flags & SymbolFlags.Namespace) {
28562854
// If we're merging an augmentation to a pattern ambient module, we want to
28572855
// perform the merge unidirectionally from the augmentation ('a.foo') to
@@ -3701,7 +3699,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37013699
node,
37023700
getExternalModuleRequireArgument(node) || getExternalModuleImportEqualsDeclarationExpression(node),
37033701
);
3704-
const resolved = resolveExternalModuleSymbol(immediate);
3702+
const resolved = resolveSymbol(immediate);
37053703
if (resolved && ModuleKind.Node20 <= moduleKind && moduleKind <= ModuleKind.NodeNext) {
37063704
const moduleExports = getExportOfModule(resolved, "module.exports" as __String, node, dontResolveAlias);
37073705
if (moduleExports) {
@@ -3894,7 +3892,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
38943892
}
38953893
else if (hasSyntheticDefault || hasDefaultOnly) {
38963894
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
3897-
const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
3895+
const resolved = resolveSymbol(moduleSymbol, dontResolveAlias);
38983896
markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteEmpty*/ false);
38993897
return resolved;
39003898
}
@@ -4035,7 +4033,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
40354033
if (symbolFromModule === undefined && nameText === InternalSymbolName.Default) {
40364034
const file = moduleSymbol.declarations?.find(isSourceFile);
40374035
if (isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) {
4038-
symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
4036+
symbolFromModule = resolveSymbol(moduleSymbol, dontResolveAlias);
40394037
}
40404038
}
40414039

@@ -4150,7 +4148,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
41504148

41514149
function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol | undefined {
41524150
if (canHaveSymbol(node.parent)) {
4153-
const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
4151+
const resolved = resolveSymbol(node.parent.symbol, dontResolveAlias);
41544152
markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
41554153
return resolved;
41564154
}
@@ -4539,7 +4537,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45394537
const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral;
45404538
const moduleSym = resolveExternalModuleName(moduleName, moduleName);
45414539
if (moduleSym) {
4542-
const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
4540+
const resolvedModuleSymbol = resolveSymbol(moduleSym);
45434541
if (resolvedModuleSymbol) {
45444542
namespace = resolvedModuleSymbol;
45454543
}
@@ -4958,17 +4956,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49584956
);
49594957
}
49604958

4961-
function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol;
4962-
function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined;
4963-
function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined {
4964-
return resolveSymbol(moduleSymbol, dontResolveAlias)
4965-
}
4966-
49674959
// An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
49684960
// references a symbol that is at least declared as a module or a variable. The target of the 'export =' may
49694961
// combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
49704962
function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean, suppressInteropError: boolean): Symbol | undefined {
4971-
const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias);
4963+
const symbol = resolveSymbol(moduleSymbol, dontResolveAlias);
49724964

49734965
if (!dontResolveAlias && symbol) {
49744966
if (!suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile)) {
@@ -5059,9 +5051,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
50595051

50605052
function getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[] {
50615053
const exports = getExportsOfModuleAsArray(moduleSymbol);
5062-
const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
5063-
if (exportEquals !== moduleSymbol) {
5064-
const type = getTypeOfSymbol(exportEquals);
5054+
if (hasExportAssignmentSymbol(moduleSymbol)) {
5055+
const type = getTypeOfSymbol(moduleSymbol);
50655056
if (shouldTreatPropertiesOfExternalModuleAsExports(type)) {
50665057
addRange(exports, getPropertiesOfType(type));
50675058
}
@@ -5076,9 +5067,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
50765067
cb(symbol, key);
50775068
}
50785069
});
5079-
const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
5080-
if (exportEquals !== moduleSymbol) {
5081-
const type = getTypeOfSymbol(exportEquals);
5070+
if (hasExportAssignmentSymbol(moduleSymbol)) {
5071+
const type = getTypeOfSymbol(moduleSymbol);
50825072
if (shouldTreatPropertiesOfExternalModuleAsExports(type)) {
50835073
forEachPropertyOfType(type, (symbol, escapedName) => {
50845074
cb(symbol, escapedName);
@@ -5100,12 +5090,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51005090
return symbol;
51015091
}
51025092

5103-
const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
5104-
if (exportEquals === moduleSymbol) {
5093+
if (!moduleSymbol.exports || !hasExportAssignmentSymbol(moduleSymbol)) {
51055094
return undefined;
51065095
}
51075096

5108-
const type = getTypeOfSymbol(exportEquals);
5097+
const type = getTypeOfSymbol(moduleSymbol);
51095098
return shouldTreatPropertiesOfExternalModuleAsExports(type) ? getPropertyOfType(type, memberName) : undefined;
51105099
}
51115100

@@ -5177,7 +5166,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51775166
const nonTypeOnlyNames = new Set<__String>();
51785167

51795168
// A module defined by an 'export=' consists of one export that needs to be resolved
5180-
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
5169+
moduleSymbol = resolveSymbol(moduleSymbol);
51815170
const exports = visit(moduleSymbol) || emptySymbols;
51825171

51835172
if (typeOnlyExportStarMap) {
@@ -5367,8 +5356,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
53675356
return getSymbolOfDeclaration(d.parent as Declaration);
53685357
}
53695358
// export ='d member of an ambient module
5370-
if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) {
5371-
return getSymbolOfDeclaration(d.parent.parent);
5359+
if (isModuleBlock(d.parent) && d.parent.parent) {
5360+
const container = resolveSymbol(getSymbolOfDeclaration(d.parent.parent))
5361+
if (container && container.exports && hasExportAssignmentSymbol(container) && container.exports.get(InternalSymbolName.ExportEquals) === symbol) {
5362+
return getSymbolOfDeclaration(d.parent.parent);
5363+
}
53725364
}
53735365
}
53745366
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
@@ -13021,7 +13013,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1302113013
}
1302213014

1302313015
// The outer type parameters are those defined by enclosing generic classes, methods, or functions.
13024-
function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined {
13016+
function getOuterTypeParametersOfClassOrInterface(symbol: Symbol | undefined): TypeParameter[] | undefined {
13017+
if (!symbol) {
13018+
return undefined;
13019+
}
13020+
if (symbol.exports && hasExportAssignmentSymbol(symbol)) {
13021+
return getOuterTypeParametersOfClassOrInterface(resolveSymbol(symbol.exports?.get(InternalSymbolName.ExportEquals)));
13022+
}
1302513023
const declaration = (symbol.flags & SymbolFlags.Class || symbol.flags & SymbolFlags.Function)
1302613024
? symbol.valueDeclaration
1302713025
: symbol.declarations?.find(decl => {
@@ -13040,10 +13038,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1304013038

1304113039
// The local type parameters are the combined set of type parameters from all declarations of the class,
1304213040
// interface, or type alias.
13043-
function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined {
13044-
if (!symbol.declarations) {
13041+
function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol | undefined): TypeParameter[] | undefined {
13042+
if (!symbol || !symbol.declarations) {
1304513043
return;
1304613044
}
13045+
if (symbol.exports && hasExportAssignmentSymbol(symbol)) {
13046+
return getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(resolveSymbol(symbol.exports?.get(InternalSymbolName.ExportEquals)));
13047+
}
1304713048
let result: TypeParameter[] | undefined;
1304813049
for (const node of symbol.declarations) {
1304913050
if (
@@ -16352,7 +16353,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1635216353
function resolveExternalModuleTypeByLiteral(name: StringLiteral) {
1635316354
const moduleSym = resolveExternalModuleName(name, name);
1635416355
if (moduleSym) {
16355-
const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
16356+
const resolvedModuleSymbol = resolveSymbol(moduleSym);
1635616357
if (resolvedModuleSymbol) {
1635716358
return getTypeOfSymbol(resolvedModuleSymbol);
1635816359
}
@@ -17123,6 +17124,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1712317124
if (res) {
1712417125
return checkNoTypeArguments(node, symbol) ? getRegularTypeOfLiteralType(res) : errorType;
1712517126
}
17127+
if (symbol.exports && hasExportAssignmentSymbol(symbol)) {
17128+
const res = getTypeReferenceType(node, resolveSymbol(symbol.exports.get(InternalSymbolName.ExportEquals)!));
17129+
if (res !== errorType) {
17130+
return res;
17131+
}
17132+
}
1712617133
if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) {
1712717134
const jsdocType = getTypeFromJSDocValueReference(node, symbol);
1712817135
if (jsdocType) {
@@ -17134,9 +17141,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1713417141
return getTypeOfSymbol(symbol);
1713517142
}
1713617143
}
17137-
if (symbol.exports && hasExportAssignmentSymbol(symbol)) {
17138-
return getTypeReferenceType(node, resolveSymbol(symbol.exports.get(InternalSymbolName.ExportEquals)!))
17139-
}
1714017144
return errorType;
1714117145
}
1714217146

@@ -19970,7 +19974,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1997019974
return links.resolvedType = errorType;
1997119975
}
1997219976
const isExportEquals = !!innerModuleSymbol.exports?.get(InternalSymbolName.ExportEquals);
19973-
const moduleSymbol = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false);
19977+
const moduleSymbol = resolveSymbol(innerModuleSymbol, /*dontResolveAlias*/ false);
1997419978
if (!nodeIsMissing(node.qualifier)) {
1997519979
const nameStack: Identifier[] = getIdentifierChain(node.qualifier!);
1997619980
let currentNamespace = moduleSymbol;
@@ -50539,12 +50543,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5053950543
if (!symbol) {
5054050544
return false;
5054150545
}
50542-
const container = getSourceFileOfNode(symbol.valueDeclaration);
50543-
const fileSymbol = container && getSymbolOfDeclaration(container);
50544-
// Ensures cjs export assignment is setup, since this symbol may point at, and merge with, the file itself.
50545-
// If we don't, the merge may not have yet occured, and the flags check below will be missing flags that
50546-
// are added as a result of the merge.
50547-
void resolveExternalModuleSymbol(fileSymbol);
5054850546
const target = getExportSymbolOfValueSymbolIfExported(resolveAlias(symbol));
5054950547
if (target === unknownSymbol) {
5055050548
return !excludeTypeOnlyValues || !getTypeOnlyAliasDeclaration(symbol);
@@ -51208,7 +51206,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5120851206
if (!sym) {
5120951207
return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, internalFlags, tracker);
5121051208
}
51211-
resolveExternalModuleSymbol(sym); // ensures cjs export assignment is setup
5121251209
return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, internalFlags, tracker);
5121351210
},
5121451211
isImportRequiredByAugmentation,

src/compiler/types.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5454,13 +5454,6 @@ export interface TypeChecker {
54545454
getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined;
54555455
getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined;
54565456
/** @internal */ resolveExternalModuleName(moduleSpecifier: Expression): Symbol | undefined;
5457-
/**
5458-
* An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
5459-
* and an external module with no 'export =' declaration resolves to the module itself.
5460-
*
5461-
* @internal
5462-
*/
5463-
resolveExternalModuleSymbol(symbol: Symbol): Symbol;
54645457
/**
54655458
* @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression.
54665459
*

src/services/codefixes/importFixes.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,10 +1289,9 @@ function getNewImportFixes(
12891289
//
12901290
// import fs = require("fs"); // or const in JS
12911291
// fs.writeFile
1292-
const exportEquals = checker.resolveExternalModuleSymbol(exportInfo.moduleSymbol);
12931292
let namespacePrefix;
1294-
if (exportEquals !== exportInfo.moduleSymbol) {
1295-
namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, getEmitScriptTarget(compilerOptions), identity)!;
1293+
if (exportInfo.moduleSymbol.exports?.has(InternalSymbolName.ExportEquals)) {
1294+
namespacePrefix = forEachNameOfDefaultExport(exportInfo.moduleSymbol.exports?.get(InternalSymbolName.ExportEquals)!, checker, getEmitScriptTarget(compilerOptions), identity)!;
12961295
}
12971296
namespacePrefix ||= moduleSymbolToValidIdentifier(
12981297
exportInfo.moduleSymbol,

src/services/completions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5386,7 +5386,7 @@ function getAutoImportSymbolFromCompletionEntryData(name: string, data: Completi
53865386

53875387
if (!moduleSymbol) return undefined;
53885388
let symbol = data.exportName === InternalSymbolName.ExportEquals
5389-
? checker.resolveExternalModuleSymbol(moduleSymbol)
5389+
? moduleSymbol.exports?.get(InternalSymbolName.ExportEquals)
53905390
: checker.tryGetMemberInModuleExportsAndProperties(data.exportName, moduleSymbol);
53915391
if (!symbol) return undefined;
53925392
const isDefaultExport = data.exportName === InternalSymbolName.Default;

src/services/exportInfoMap.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost):
302302
);
303303
const symbol = info.symbol || cachedSymbol || Debug.checkDefined(
304304
exportKind === ExportKind.ExportEquals
305-
? checker.resolveExternalModuleSymbol(moduleSymbol)
305+
? moduleSymbol
306306
: checker.tryGetMemberInModuleExportsAndProperties(unescapeLeadingUnderscores(info.symbolTableKey), moduleSymbol),
307307
`Could not find symbol '${info.symbolName}' by key '${info.symbolTableKey}' in module ${moduleSymbol.name}`,
308308
);
@@ -604,14 +604,11 @@ export function getDefaultLikeExportInfo(moduleSymbol: Symbol, checker: TypeChec
604604
symbol: Symbol;
605605
exportKind: ExportKind;
606606
} | undefined {
607-
const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol);
608-
if (exportEquals !== moduleSymbol) {
609-
const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, exportEquals);
610-
if (defaultExport) return { symbol: defaultExport, exportKind: ExportKind.Default };
611-
return { symbol: exportEquals, exportKind: ExportKind.ExportEquals };
612-
}
613607
const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol);
614608
if (defaultExport) return { symbol: defaultExport, exportKind: ExportKind.Default };
609+
if (moduleSymbol.exports?.has(InternalSymbolName.ExportEquals)) {
610+
return { symbol: moduleSymbol.exports.get(InternalSymbolName.ExportEquals)!, exportKind: ExportKind.ExportEquals };
611+
}
615612
}
616613

617614
function isImportableSymbol(symbol: Symbol, checker: TypeChecker) {

src/services/refactors/convertImport.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
ImportDeclaration,
2222
ImportKind,
2323
ImportSpecifier,
24+
InternalSymbolName,
2425
isExportSpecifier,
2526
isImportDeclaration,
2627
isJSDocImportTag,
@@ -281,8 +282,7 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra
281282
function isExportEqualsModule(moduleSpecifier: Expression, checker: TypeChecker) {
282283
const externalModule = checker.resolveExternalModuleName(moduleSpecifier);
283284
if (!externalModule) return false;
284-
const exportEquals = checker.resolveExternalModuleSymbol(externalModule);
285-
return externalModule !== exportEquals;
285+
return !!externalModule.exports?.has(InternalSymbolName.ExportEquals);
286286
}
287287

288288
function createImport(node: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration {

0 commit comments

Comments
 (0)