mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Fix auto import crash on weird JS aliasing (#46490)
* Fix auto import crash on weird JS aliasing * Comment up the weird test * Fix setting members on union/intersection type, happens later
This commit is contained in:
@@ -3656,8 +3656,8 @@ namespace ts {
|
||||
if (exportEquals !== moduleSymbol) {
|
||||
const type = getTypeOfSymbol(exportEquals);
|
||||
if (shouldTreatPropertiesOfExternalModuleAsExports(type)) {
|
||||
getPropertiesOfType(type).forEach(symbol => {
|
||||
cb(symbol, symbol.escapedName);
|
||||
forEachPropertyOfType(type, (symbol, escapedName) => {
|
||||
cb(symbol, escapedName);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4033,13 +4033,17 @@ namespace ts {
|
||||
function getNamedMembers(members: SymbolTable): Symbol[] {
|
||||
let result: Symbol[] | undefined;
|
||||
members.forEach((symbol, id) => {
|
||||
if (!isReservedMemberName(id) && symbolIsValue(symbol)) {
|
||||
if (isNamedMember(symbol, id)) {
|
||||
(result || (result = [])).push(symbol);
|
||||
}
|
||||
});
|
||||
return result || emptyArray;
|
||||
}
|
||||
|
||||
function isNamedMember(member: Symbol, escapedName: __String) {
|
||||
return !isReservedMemberName(escapedName) && symbolIsValue(member);
|
||||
}
|
||||
|
||||
function getNamedOrIndexSignatureMembers(members: SymbolTable): Symbol[] {
|
||||
const result = getNamedMembers(members);
|
||||
const index = getIndexSymbolFromSymbolTable(members);
|
||||
@@ -11571,6 +11575,17 @@ namespace ts {
|
||||
getPropertiesOfObjectType(type);
|
||||
}
|
||||
|
||||
function forEachPropertyOfType(type: Type, action: (symbol: Symbol, escapedName: __String) => void): void {
|
||||
type = getReducedApparentType(type);
|
||||
if (type.flags & TypeFlags.StructuredType) {
|
||||
resolveStructuredTypeMembers(type as StructuredType).members.forEach((symbol, escapedName) => {
|
||||
if (isNamedMember(symbol, escapedName)) {
|
||||
action(symbol, escapedName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean {
|
||||
const list = obj.properties as NodeArray<ObjectLiteralElementLike | JsxAttributeLike>;
|
||||
return list.some(property => {
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
export function getImportCompletionAction(
|
||||
exportedSymbol: Symbol,
|
||||
targetSymbol: Symbol,
|
||||
moduleSymbol: Symbol,
|
||||
sourceFile: SourceFile,
|
||||
symbolName: string,
|
||||
@@ -280,8 +280,8 @@ namespace ts.codefix {
|
||||
): { readonly moduleSpecifier: string, readonly codeAction: CodeAction } {
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
const exportInfos = pathIsBareSpecifier(stripQuotes(moduleSymbol.name))
|
||||
? [getSymbolExportInfoForSymbol(exportedSymbol, moduleSymbol, program, host)]
|
||||
: getAllReExportingModules(sourceFile, exportedSymbol, moduleSymbol, symbolName, host, program, preferences, /*useAutoImportProvider*/ true);
|
||||
? [getSymbolExportInfoForSymbol(targetSymbol, moduleSymbol, program, host)]
|
||||
: getAllReExportingModules(sourceFile, targetSymbol, moduleSymbol, symbolName, host, program, preferences, /*useAutoImportProvider*/ true);
|
||||
const useRequire = shouldUseRequire(sourceFile, program);
|
||||
const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(getTokenAtPosition(sourceFile, position));
|
||||
const fix = Debug.checkDefined(getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, symbolName, program, position, isValidTypeOnlyUseSite, useRequire, host, preferences));
|
||||
@@ -326,7 +326,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllReExportingModules(importingFile: SourceFile, exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, host: LanguageServiceHost, program: Program, preferences: UserPreferences, useAutoImportProvider: boolean): readonly SymbolExportInfo[] {
|
||||
function getAllReExportingModules(importingFile: SourceFile, targetSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, host: LanguageServiceHost, program: Program, preferences: UserPreferences, useAutoImportProvider: boolean): readonly SymbolExportInfo[] {
|
||||
const result: SymbolExportInfo[] = [];
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
const getModuleSpecifierResolutionHost = memoizeOne((isFromPackageJson: boolean) => {
|
||||
@@ -341,12 +341,12 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions);
|
||||
if (defaultInfo && (defaultInfo.name === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, getEmitScriptTarget(compilerOptions)) === symbolName) && skipAlias(defaultInfo.symbol, checker) === exportedSymbol && isImportable(program, moduleFile, isFromPackageJson)) {
|
||||
if (defaultInfo && (defaultInfo.name === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, getEmitScriptTarget(compilerOptions)) === symbolName) && skipAlias(defaultInfo.symbol, checker) === targetSymbol && isImportable(program, moduleFile, isFromPackageJson)) {
|
||||
result.push({ symbol: defaultInfo.symbol, moduleSymbol, moduleFileName: moduleFile?.fileName, exportKind: defaultInfo.exportKind, targetFlags: skipAlias(defaultInfo.symbol, checker).flags, isFromPackageJson });
|
||||
}
|
||||
|
||||
for (const exported of checker.getExportsAndPropertiesOfModule(moduleSymbol)) {
|
||||
if (exported.name === symbolName && skipAlias(exported, checker) === exportedSymbol && isImportable(program, moduleFile, isFromPackageJson)) {
|
||||
if (exported.name === symbolName && checker.getMergedSymbol(skipAlias(exported, checker)) === targetSymbol && isImportable(program, moduleFile, isFromPackageJson)) {
|
||||
result.push({ symbol: exported, moduleSymbol, moduleFileName: moduleFile?.fileName, exportKind: ExportKind.Named, targetFlags: skipAlias(exported, checker).flags, isFromPackageJson });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1183,9 +1183,9 @@ namespace ts.Completions {
|
||||
|
||||
const checker = origin.isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker();
|
||||
const { moduleSymbol } = origin;
|
||||
const exportedSymbol = checker.getMergedSymbol(skipAlias(symbol.exportSymbol || symbol, checker));
|
||||
const targetSymbol = checker.getMergedSymbol(skipAlias(symbol.exportSymbol || symbol, checker));
|
||||
const { moduleSpecifier, codeAction } = codefix.getImportCompletionAction(
|
||||
exportedSymbol,
|
||||
targetSymbol,
|
||||
moduleSymbol,
|
||||
sourceFile,
|
||||
getNameForExportedSymbol(symbol, getEmitScriptTarget(compilerOptions)),
|
||||
|
||||
@@ -79,10 +79,14 @@ namespace ts {
|
||||
}
|
||||
const isDefault = exportKind === ExportKind.Default;
|
||||
const namedSymbol = isDefault && getLocalSymbolForExportDefault(symbol) || symbol;
|
||||
// A re-export merged with an export from a module augmentation can result in `symbol`
|
||||
// being an external module symbol; the name it is re-exported by will be `symbolTableKey`
|
||||
// (which comes from the keys of `moduleSymbol.exports`.)
|
||||
const importedName = isExternalModuleSymbol(namedSymbol)
|
||||
// 1. A named export must be imported by its key in `moduleSymbol.exports` or `moduleSymbol.members`.
|
||||
// 2. A re-export merged with an export from a module augmentation can result in `symbol`
|
||||
// being an external module symbol; the name it is re-exported by will be `symbolTableKey`
|
||||
// (which comes from the keys of `moduleSymbol.exports`.)
|
||||
// 3. Otherwise, we have a default/namespace import that can be imported by any name, and
|
||||
// `symbolTableKey` will be something undesirable like `export=` or `default`, so we try to
|
||||
// get a better name.
|
||||
const importedName = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol)
|
||||
? unescapeLeadingUnderscores(symbolTableKey)
|
||||
: getNameForExportedSymbol(namedSymbol, scriptTarget);
|
||||
const moduleName = stripQuotes(moduleSymbol.name);
|
||||
@@ -321,7 +325,7 @@ namespace ts {
|
||||
let moduleCount = 0;
|
||||
forEachExternalModuleToImportFrom(program, host, /*useAutoImportProvider*/ true, (moduleSymbol, moduleFile, program, isFromPackageJson) => {
|
||||
if (++moduleCount % 100 === 0) cancellationToken?.throwIfCancellationRequested();
|
||||
const seenExports = new Map<Symbol, true>();
|
||||
const seenExports = new Map<__String, true>();
|
||||
const checker = program.getTypeChecker();
|
||||
const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions);
|
||||
// Note: I think we shouldn't actually see resolved module symbols here, but weird merges
|
||||
@@ -339,7 +343,7 @@ namespace ts {
|
||||
checker);
|
||||
}
|
||||
checker.forEachExportAndPropertyOfModule(moduleSymbol, (exported, key) => {
|
||||
if (exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) && addToSeen(seenExports, exported)) {
|
||||
if (exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) && addToSeen(seenExports, key)) {
|
||||
cache.add(
|
||||
importingFile.path,
|
||||
exported,
|
||||
|
||||
Reference in New Issue
Block a user