@@ -944,28 +944,39 @@ namespace ts {
944944
945945
946946 function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean {
947- let parentClassExpression = errorLocation;
948- while (parentClassExpression) {
949- const kind = parentClassExpression.kind;
950- if (kind === SyntaxKind.Identifier || kind === SyntaxKind.PropertyAccessExpression) {
951- parentClassExpression = parentClassExpression.parent;
952- continue;
953- }
954- if (kind === SyntaxKind.ExpressionWithTypeArguments) {
955- break;
956- }
947+ const parentExpression = climbToSupportedExpressionWithTypeArguments(errorLocation);
948+ if (!parentExpression) {
957949 return false;
958950 }
959- if (!parentClassExpression) {
960- return false;
961- }
962- const expression = (<ExpressionWithTypeArguments>parentClassExpression).expression;
951+ const expression = parentExpression.expression;
952+
963953 if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
964954 error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
965955 return true;
966956 }
967957 return false;
968958 }
959+ /**
960+ * Climbs up parents to a SupportedExpressionWIthTypeArguments.
961+ * Does *not* just climb to an ExpressionWithTypeArguments; instead, ensures that this really is supported.
962+ */
963+ function climbToSupportedExpressionWithTypeArguments(node: Node): SupportedExpressionWithTypeArguments | undefined {
964+ while (node) {
965+ switch (node.kind) {
966+ case SyntaxKind.Identifier:
967+ case SyntaxKind.PropertyAccessExpression:
968+ node = node.parent;
969+ break;
970+ case SyntaxKind.ExpressionWithTypeArguments:
971+ Debug.assert(isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node));
972+ return <SupportedExpressionWithTypeArguments>node;
973+ default:
974+ return undefined;
975+ }
976+ }
977+ return undefined;
978+ }
979+
969980
970981 function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
971982 Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
@@ -1250,7 +1261,7 @@ namespace ts {
12501261 }
12511262
12521263 // Resolves a qualified name and any involved aliases
1253- function resolveEntityName(name: EntityName | Expression , meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol {
1264+ function resolveEntityName(name: EntityNameOrEntityNameExpression , meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol | undefined {
12541265 if (nodeIsMissing(name)) {
12551266 return undefined;
12561267 }
@@ -1265,7 +1276,7 @@ namespace ts {
12651276 }
12661277 }
12671278 else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
1268- const left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression >name).expression;
1279+ const left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessEntityNameExpression >name).expression;
12691280 const right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
12701281
12711282 const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
@@ -1814,7 +1825,7 @@ namespace ts {
18141825 }
18151826 }
18161827
1817- function isEntityNameVisible(entityName: EntityName | Expression , enclosingDeclaration: Node): SymbolVisibilityResult {
1828+ function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression , enclosingDeclaration: Node): SymbolVisibilityResult {
18181829 // get symbol of the first identifier of the entityName
18191830 let meaning: SymbolFlags;
18201831 if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) {
@@ -4885,7 +4896,7 @@ namespace ts {
48854896 return getDeclaredTypeOfSymbol(symbol);
48864897 }
48874898
4888- function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName {
4899+ function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined {
48894900 switch (node.kind) {
48904901 case SyntaxKind.TypeReference:
48914902 return (<TypeReferenceNode>node).typeName;
@@ -4894,8 +4905,9 @@ namespace ts {
48944905 case SyntaxKind.ExpressionWithTypeArguments:
48954906 // We only support expressions that are simple qualified names. For other
48964907 // expressions this produces undefined.
4897- if (isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node)) {
4898- return (<ExpressionWithTypeArguments>node).expression;
4908+ const expr = <ExpressionWithTypeArguments>node;
4909+ if (isSupportedExpressionWithTypeArguments(expr)) {
4910+ return expr.expression;
48994911 }
49004912
49014913 // fall through;
@@ -4906,7 +4918,7 @@ namespace ts {
49064918
49074919 function resolveTypeReferenceName(
49084920 node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
4909- typeReferenceName: LeftHandSideExpression | EntityName) {
4921+ typeReferenceName: EntityNameExpression | EntityName) {
49104922
49114923 if (!typeReferenceName) {
49124924 return unknownSymbol;
@@ -4947,15 +4959,14 @@ namespace ts {
49474959 const typeReferenceName = getTypeReferenceName(node);
49484960 symbol = resolveTypeReferenceName(node, typeReferenceName);
49494961 type = getTypeReferenceType(node, symbol);
4950-
4951- links.resolvedSymbol = symbol;
4952- links.resolvedType = type;
49534962 }
49544963 else {
49554964 // We only support expressions that are simple qualified names. For other expressions this produces undefined.
4956- const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
4957- isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
4958- undefined;
4965+ const typeNameOrExpression: EntityNameOrEntityNameExpression = node.kind === SyntaxKind.TypeReference
4966+ ? (<TypeReferenceNode>node).typeName
4967+ : isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node)
4968+ ? (<SupportedExpressionWithTypeArguments>node).expression
4969+ : undefined;
49594970 symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
49604971 type = symbol === unknownSymbol ? unknownType :
49614972 symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
@@ -16594,20 +16605,21 @@ namespace ts {
1659416605 }
1659516606 }
1659616607
16597- function getFirstIdentifier(node: EntityName | Expression): Identifier {
16598- while (true) {
16599- if (node.kind === SyntaxKind.QualifiedName) {
16600- node = (<QualifiedName>node).left;
16601- }
16602- else if (node.kind === SyntaxKind.PropertyAccessExpression) {
16603- node = (<PropertyAccessExpression>node).expression;
16604- }
16605- else {
16606- break;
16607- }
16608+ function getFirstIdentifier(node: EntityNameOrEntityNameExpression): Identifier {
16609+ switch (node.kind) {
16610+ case SyntaxKind.Identifier:
16611+ return <Identifier>node;
16612+ case SyntaxKind.QualifiedName:
16613+ do {
16614+ node = (<QualifiedName>node).left;
16615+ } while (node.kind !== SyntaxKind.Identifier);
16616+ return <Identifier>node;
16617+ case SyntaxKind.PropertyAccessExpression:
16618+ do {
16619+ node = (<PropertyAccessEntityNameExpression>node).expression;
16620+ } while (node.kind !== SyntaxKind.Identifier);
16621+ return <Identifier>node;
1660816622 }
16609- Debug.assert(node.kind === SyntaxKind.Identifier);
16610- return <Identifier>node;
1661116623 }
1661216624
1661316625 function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
@@ -17306,7 +17318,7 @@ namespace ts {
1730617318 return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
1730717319 }
1730817320
17309- function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
17321+ function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol | undefined {
1731017322 if (isDeclarationName(entityName)) {
1731117323 return getSymbolOfNode(entityName.parent);
1731217324 }
@@ -17325,8 +17337,8 @@ namespace ts {
1732517337 }
1732617338 }
1732717339
17328- if (entityName.parent.kind === SyntaxKind.ExportAssignment) {
17329- return resolveEntityName(<Identifier >entityName,
17340+ if (entityName.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(<Identifier | PropertyAccessExpression>entityName) ) {
17341+ return resolveEntityName(<EntityNameExpression >entityName,
1733017342 /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
1733117343 }
1733217344
@@ -17340,7 +17352,7 @@ namespace ts {
1734017352 }
1734117353
1734217354 if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
17343- entityName = <QualifiedName | PropertyAccessExpression >entityName.parent;
17355+ entityName = <QualifiedName | PropertyAccessEntityNameExpression >entityName.parent;
1734417356 }
1734517357
1734617358 if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
@@ -18053,7 +18065,7 @@ namespace ts {
1805318065 };
1805418066
1805518067 // defined here to avoid outer scope pollution
18056- function getTypeReferenceDirectivesForEntityName(node: EntityName | PropertyAccessExpression ): string[] {
18068+ function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression ): string[] {
1805718069 // program does not have any files with type reference directives - bail out
1805818070 if (!fileToDirective) {
1805918071 return undefined;
0 commit comments