Skip to content

Commit

Permalink
Fixed errors in DTE when enums are accessed through a dotted identifier.
Browse files Browse the repository at this point in the history
Signed-off-by: Titian Cernicova-Dragomir <tcernicovad1@bloomberg.net>
  • Loading branch information
dragomirtitian committed Nov 27, 2023
1 parent 867e100 commit 3403de2
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 1,100 deletions.
17 changes: 1 addition & 16 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
and,
AnonymousType,
AnyImportOrReExport,
AnyImportSyntax,
append,
appendIfUnique,
ArrayBindingPattern,
Expand Down Expand Up @@ -241,6 +240,7 @@ import {
getAllJSDocTags,
getAllowSyntheticDefaultImports,
getAncestor,
getAnyImportSyntax,
getAssignedExpandoInitializer,
getAssignmentDeclarationKind,
getAssignmentDeclarationPropertyAccessKind,
Expand Down Expand Up @@ -3927,21 +3927,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|| (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || (getFunctionFlags(n) & FunctionFlags.AsyncGenerator)) ? "quit" : false));
}

function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return node as ImportEqualsDeclaration;
case SyntaxKind.ImportClause:
return (node as ImportClause).parent;
case SyntaxKind.NamespaceImport:
return (node as NamespaceImport).parent.parent;
case SyntaxKind.ImportSpecifier:
return (node as ImportSpecifier).parent.parent.parent;
default:
return undefined;
}
}

function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
return symbol.declarations && findLast<Declaration>(symbol.declarations, isAliasSymbolDeclaration);
}
Expand Down
63 changes: 33 additions & 30 deletions src/compiler/transformers/declarations/emitResolver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
AnyImportSyntax,
appendIfUnique,
ComputedPropertyName,
createEvaluator,
Expand All @@ -19,6 +18,7 @@ import {
findAncestor,
FunctionDeclaration,
FunctionLikeDeclaration,
getAnyImportSyntax,
getFirstIdentifier,
getNameOfDeclaration,
getParseTreeNode,
Expand All @@ -27,11 +27,7 @@ import {
hasProperty,
hasSyntacticModifier,
Identifier,
ImportClause,
ImportEqualsDeclaration,
ImportSpecifier,
isAccessor,
isArrowFunction,
isBigIntLiteral,
isBinaryExpression,
isBindingElement,
Expand All @@ -42,7 +38,7 @@ import {
isEnumMember,
isExpressionStatement,
isFunctionDeclaration,
isFunctionExpression,
isFunctionExpressionOrArrowFunction,
isFunctionLike,
isGetAccessor,
isGetAccessorDeclaration,
Expand All @@ -54,6 +50,7 @@ import {
isPartOfTypeNode,
isPrefixUnaryExpression,
isPropertyAccessExpression,
isPropertyName,
isSetAccessor,
isSetAccessorDeclaration,
isStringLiteralLike,
Expand All @@ -65,7 +62,6 @@ import {
LateBoundDeclaration,
LateVisibilityPaintedStatement,
ModifierFlags,
NamespaceImport,
Node,
NodeArray,
NodeFlags,
Expand Down Expand Up @@ -122,13 +118,39 @@ export function createEmitDeclarationResolver(file: SourceFile): IsolatedEmitRes
}
return undefined;
}

function resolveEntityName(location: Node, node: Expression, meaning: SymbolFlags): EmitDeclarationSymbol | undefined {
if (isIdentifier(node)) {
return resolveName(location, node.escapedText, meaning);
}
else if (isPropertyAccessExpression(node) || isElementAccessExpression(node)) {
const symbol = resolveEntityName(location, node.expression, meaning);
if (symbol === undefined) return undefined;

const name = isElementAccessExpression(node) ? node.argumentExpression : node.name;
if (!isPropertyName(name)) return;

const memberSymbol = symbol.exports?.get(getMemberKey(name));
if (!memberSymbol || !(memberSymbol.flags & meaning)) {
return undefined;
}
return memberSymbol;
}
else {
return undefined;
}
}
function isTargetEnumDeclaration(target: Expression, location: EnumDeclaration) {
const symbol = resolveEntityName(location, target, SymbolFlags.Namespace);

return !!symbol?.declarations.some(d => d === location);
}
const evaluate = createEvaluator({
evaluateElementAccessExpression(expr, location) {
// We only resolve names in the current enum declaration
if (!location || !isEnumDeclaration(location)) return undefined;
if (
isIdentifier(expr.expression)
&& expr.expression.escapedText === location.name.escapedText
isTargetEnumDeclaration(expr.expression, location)
&& isStringLiteralLike(expr.argumentExpression)
) {
return getEnumValueFromName(expr.argumentExpression, location);
Expand All @@ -148,9 +170,8 @@ export function createEmitDeclarationResolver(file: SourceFile): IsolatedEmitRes
return getEnumValueFromName(expr, location);
}
if (
isPropertyAccessExpression(expr)
&& isIdentifier(expr.expression)
&& expr.expression.escapedText === location.name.escapedText
isEntityNameExpression(expr.expression)
&& isTargetEnumDeclaration(expr.expression, location)
) {
return getEnumValueFromName(expr.name, location);
}
Expand Down Expand Up @@ -640,24 +661,6 @@ export function createEmitDeclarationResolver(file: SourceFile): IsolatedEmitRes
}
}

function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return node as ImportEqualsDeclaration;
case SyntaxKind.ImportClause:
return (node as ImportClause).parent;
case SyntaxKind.NamespaceImport:
return (node as NamespaceImport).parent.parent;
case SyntaxKind.ImportSpecifier:
return (node as ImportSpecifier).parent.parent.parent;
default:
return undefined;
}
}
function isFunctionExpressionOrArrowFunction(node: Expression) {
return isFunctionExpression(node) || isArrowFunction(node);
}

function getParentScope(declaration: VariableDeclaration | FunctionDeclaration):
| undefined
| Node & {
Expand Down
17 changes: 17 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10519,6 +10519,23 @@ export function getDeclarationContainer(node: Node): Node {
})!.parent;
}

/** @internal */
export function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return node as ImportEqualsDeclaration;
case SyntaxKind.ImportClause:
return (node as ImportClause).parent;
case SyntaxKind.NamespaceImport:
return (node as NamespaceImport).parent.parent;
case SyntaxKind.ImportSpecifier:
return (node as ImportSpecifier).parent.parent.parent;
default:
return undefined;
}
}


/** @internal */
export function isGlobalSourceFile(node: Node) {
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node as SourceFile);
Expand Down

This file was deleted.

Loading

0 comments on commit 3403de2

Please sign in to comment.