CommonJS imports support destructuring+property access (#40702)

* CommonJS imports support destructuring+property access

Fixes #40578 for prettier

* will I ever remember semicolons? haha no

* move code around

* move function declaration closer to use

* Add missing space after `if`

Thanks to @weswigham for noticing this. Somehow it passed the linter.
This commit is contained in:
Nathan Shively-Sanders
2020-09-24 14:42:59 -07:00
committed by GitHub
parent e6fdcce2bf
commit eac75f375d
4 changed files with 37 additions and 51 deletions

View File

@@ -2448,10 +2448,11 @@ namespace ts {
}
function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration | VariableDeclaration, dontResolveAlias: boolean): Symbol | undefined {
if (isVariableDeclaration(node) && node.initializer && isPropertyAccessExpression(node.initializer)) {
const name = (getLeftmostAccessExpression(node.initializer.expression) as CallExpression).arguments[0] as StringLiteral;
return isIdentifier(node.initializer.name)
? resolveSymbol(getPropertyOfType(resolveExternalModuleTypeByLiteral(name), node.initializer.name.escapedText))
const commonJSPropertyAccess = getCommonJSPropertyAccess(node);
if (commonJSPropertyAccess) {
const name = (getLeftmostAccessExpression(commonJSPropertyAccess.expression) as CallExpression).arguments[0] as StringLiteral;
return isIdentifier(commonJSPropertyAccess.name)
? resolveSymbol(getPropertyOfType(resolveExternalModuleTypeByLiteral(name), commonJSPropertyAccess.name.escapedText))
: undefined;
}
if (isVariableDeclaration(node) || node.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
@@ -2646,12 +2647,8 @@ namespace ts {
return result;
}
function getExportOfModule(symbol: Symbol, specifier: ImportOrExportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined {
function getExportOfModule(symbol: Symbol, name: Identifier, specifier: Declaration, dontResolveAlias: boolean): Symbol | undefined {
if (symbol.flags & SymbolFlags.Module) {
const name = specifier.propertyName ?? specifier.name;
if (!isIdentifier(name)) {
return undefined;
}
const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText);
const resolved = resolveSymbol(exportSymbol, dontResolveAlias);
markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false);
@@ -2668,10 +2665,10 @@ namespace ts {
}
}
function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement, dontResolveAlias = false): Symbol | undefined {
function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined {
const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!;
const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier)!; // TODO: GH#18217
const name = specifier.propertyName || specifier.name;
const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name;
if (!isIdentifier(name)) {
return undefined;
}
@@ -2691,10 +2688,10 @@ namespace ts {
else {
symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText);
}
// if symbolFromVariable is export - get its final target
symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias);
let symbolFromModule = getExportOfModule(targetSymbol, specifier, dontResolveAlias);
let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias);
if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) {
const file = find(moduleSymbol.declarations, isSourceFile);
if (canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias)) {
@@ -2782,11 +2779,23 @@ namespace ts {
}
function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined {
const resolved = getExternalModuleMember(isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent, node, dontResolveAlias);
const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent;
const commonJSPropertyAccess = getCommonJSPropertyAccess(root);
const resolved = getExternalModuleMember(root, commonJSPropertyAccess || node, dontResolveAlias);
const name = node.propertyName || node.name;
if (commonJSPropertyAccess && resolved && isIdentifier(name)) {
return getPropertyOfType(getTypeOfSymbol(resolved), name.escapedText);
}
markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
return resolved;
}
function getCommonJSPropertyAccess(node: Node) {
if (isVariableDeclaration(node) && node.initializer && isPropertyAccessExpression(node.initializer)) {
return node.initializer;
}
}
function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol {
const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
@@ -2940,7 +2949,7 @@ namespace ts {
finalTarget: Symbol | undefined,
overwriteEmpty: boolean,
): boolean {
if (!aliasDeclaration) return false;
if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false;
// If the declaration itself is type-only, mark it and return.
// No need to check what it resolves to.