From 19af881f94c908c3da4ee6b2aecc0046499ef2d4 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 27 Sep 2018 18:26:57 -0700 Subject: [PATCH] ExpressionWithTypeArguments parent may be a JSDocAugmentsTag (#27229) --- src/compiler/checker.ts | 16 +++-------- .../transformers/declarations/diagnostics.ts | 4 +-- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 28 +++++++++---------- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 6 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d6c4cb6afeb..611b6c4d4b0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27940,24 +27940,20 @@ namespace ts { return errorType; } + const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node); + const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class)); if (isPartOfTypeNode(node)) { const typeFromTypeNode = getTypeFromTypeNode(node); - - if (isExpressionWithTypeArgumentsInClassImplementsClause(node)) { - return getTypeWithThisArgument(typeFromTypeNode, getTypeOfClassContainingHeritageClause(node).thisType); - } - - return typeFromTypeNode; + return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode; } if (isExpressionNode(node)) { return getRegularTypeOfExpression(node); } - if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) { + if (classType && !classDecl!.isImplements) { // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the // extends clause of a class. We handle that case here. - const classType = getTypeOfClassContainingHeritageClause(node); const baseType = firstOrUndefined(getBaseTypes(classType)); return baseType ? getTypeWithThisArgument(baseType, classType.thisType) : errorType; } @@ -27999,10 +27995,6 @@ namespace ts { return errorType; } - function getTypeOfClassContainingHeritageClause(node: ExpressionWithTypeArguments): InterfaceType { - return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node.parent.parent)); - } - // Gets the type of object literal or array literal of destructuring assignment. // { a } from // for ( { a } of elems) { diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 0865861414e..53b5750a1ed 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -434,7 +434,7 @@ namespace ts { // Heritage clause is written by user so it can always be named if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { // Class or Interface implemented/extended is inaccessible - diagnosticMessage = (node as ExpressionWithTypeArguments).parent.token === SyntaxKind.ImplementsKeyword ? + diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ? Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1; } @@ -446,7 +446,7 @@ namespace ts { return { diagnosticMessage, errorNode: node, - typeName: getNameOfDeclaration((node as ExpressionWithTypeArguments).parent.parent) + typeName: getNameOfDeclaration(node.parent.parent as Declaration) }; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9b1c57b2097..d5480e09796 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1708,7 +1708,7 @@ namespace ts { export interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent: HeritageClause; + parent: HeritageClause | JSDocAugmentsTag; expression: LeftHandSideExpression; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 60a7d759b68..d4c28ee94c6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3734,11 +3734,20 @@ namespace ts { /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined { - if (isExpressionWithTypeArguments(node) && - node.parent.token === SyntaxKind.ExtendsKeyword && - isClassLike(node.parent.parent)) { - return node.parent.parent; - } + const cls = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node); + return cls && !cls.isImplements ? cls.class : undefined; + } + + export interface ClassImplementingOrExtendingExpressionWithTypeArguments { + readonly class: ClassLikeDeclaration; + readonly isImplements: boolean; + } + export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node: Node): ClassImplementingOrExtendingExpressionWithTypeArguments | undefined { + return isExpressionWithTypeArguments(node) + && isHeritageClause(node.parent) + && isClassLike(node.parent.parent) + ? { class: node.parent.parent, isImplements: node.parent.token === SyntaxKind.ImplementsKeyword } + : undefined; } export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression; @@ -3765,15 +3774,6 @@ namespace ts { return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined; } - export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments { - return node.kind === SyntaxKind.ExpressionWithTypeArguments - && isEntityNameExpression((node as ExpressionWithTypeArguments).expression) - && node.parent - && (node.parent).token === SyntaxKind.ImplementsKeyword - && node.parent.parent - && isClassLike(node.parent.parent); - } - export function isEntityNameExpression(node: Node): node is EntityNameExpression { return node.kind === SyntaxKind.Identifier || isPropertyAccessEntityNameExpression(node); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a454ffe3be2..a90f40f9ac7 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1082,7 +1082,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent: HeritageClause; + parent: HeritageClause | JSDocAugmentsTag; expression: LeftHandSideExpression; } interface NewExpression extends PrimaryExpression, Declaration { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3ee556a58dd..d6bd508999d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1082,7 +1082,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent: HeritageClause; + parent: HeritageClause | JSDocAugmentsTag; expression: LeftHandSideExpression; } interface NewExpression extends PrimaryExpression, Declaration {