@@ -968,28 +968,39 @@ namespace ts {
968968
969969
970970 function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean {
971- let parentClassExpression = errorLocation;
972- while (parentClassExpression) {
973- const kind = parentClassExpression.kind;
974- if (kind === SyntaxKind.Identifier || kind === SyntaxKind.PropertyAccessExpression) {
975- parentClassExpression = parentClassExpression.parent;
976- continue;
977- }
978- if (kind === SyntaxKind.ExpressionWithTypeArguments) {
979- break;
980- }
971+ const parentExpression = climbToSupportedExpressionWithTypeArguments(errorLocation);
972+ if (!parentExpression) {
981973 return false;
982974 }
983- if (!parentClassExpression) {
984- return false;
985- }
986- const expression = (<ExpressionWithTypeArguments>parentClassExpression).expression;
975+ const expression = parentExpression.expression;
976+
987977 if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
988978 error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
989979 return true;
990980 }
991981 return false;
992982 }
983+ /**
984+ * Climbs up parents to a SupportedExpressionWIthTypeArguments.
985+ * Does *not* just climb to an ExpressionWithTypeArguments; instead, ensures that this really is supported.
986+ */
987+ function climbToSupportedExpressionWithTypeArguments(node: Node): SupportedExpressionWithTypeArguments | undefined {
988+ while (node) {
989+ switch (node.kind) {
990+ case SyntaxKind.Identifier:
991+ case SyntaxKind.PropertyAccessExpression:
992+ node = node.parent;
993+ break;
994+ case SyntaxKind.ExpressionWithTypeArguments:
995+ Debug.assert(isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node));
996+ return <SupportedExpressionWithTypeArguments>node;
997+ default:
998+ return undefined;
999+ }
1000+ }
1001+ return undefined;
1002+ }
1003+
9931004
9941005 function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
9951006 Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
@@ -1274,7 +1285,7 @@ namespace ts {
12741285 }
12751286
12761287 // Resolves a qualified name and any involved aliases
1277- function resolveEntityName(name: EntityName | Expression , meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol {
1288+ function resolveEntityName(name: EntityNameOrEntityNameExpression , meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol | undefined {
12781289 if (nodeIsMissing(name)) {
12791290 return undefined;
12801291 }
@@ -1289,7 +1300,7 @@ namespace ts {
12891300 }
12901301 }
12911302 else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
1292- const left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression >name).expression;
1303+ const left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessEntityNameExpression >name).expression;
12931304 const right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
12941305
12951306 const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
@@ -1845,7 +1856,7 @@ namespace ts {
18451856 }
18461857 }
18471858
1848- function isEntityNameVisible(entityName: EntityName | Expression , enclosingDeclaration: Node): SymbolVisibilityResult {
1859+ function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression , enclosingDeclaration: Node): SymbolVisibilityResult {
18491860 // get symbol of the first identifier of the entityName
18501861 let meaning: SymbolFlags;
18511862 if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) {
@@ -5022,7 +5033,7 @@ namespace ts {
50225033 return getDeclaredTypeOfSymbol(symbol);
50235034 }
50245035
5025- function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName {
5036+ function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined {
50265037 switch (node.kind) {
50275038 case SyntaxKind.TypeReference:
50285039 return (<TypeReferenceNode>node).typeName;
@@ -5031,8 +5042,9 @@ namespace ts {
50315042 case SyntaxKind.ExpressionWithTypeArguments:
50325043 // We only support expressions that are simple qualified names. For other
50335044 // expressions this produces undefined.
5034- if (isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node)) {
5035- return (<ExpressionWithTypeArguments>node).expression;
5045+ const expr = <ExpressionWithTypeArguments>node;
5046+ if (isSupportedExpressionWithTypeArguments(expr)) {
5047+ return expr.expression;
50365048 }
50375049
50385050 // fall through;
@@ -5043,7 +5055,7 @@ namespace ts {
50435055
50445056 function resolveTypeReferenceName(
50455057 node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
5046- typeReferenceName: LeftHandSideExpression | EntityName) {
5058+ typeReferenceName: EntityNameExpression | EntityName) {
50475059
50485060 if (!typeReferenceName) {
50495061 return unknownSymbol;
@@ -5084,15 +5096,14 @@ namespace ts {
50845096 const typeReferenceName = getTypeReferenceName(node);
50855097 symbol = resolveTypeReferenceName(node, typeReferenceName);
50865098 type = getTypeReferenceType(node, symbol);
5087-
5088- links.resolvedSymbol = symbol;
5089- links.resolvedType = type;
50905099 }
50915100 else {
50925101 // We only support expressions that are simple qualified names. For other expressions this produces undefined.
5093- const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
5094- isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
5095- undefined;
5102+ const typeNameOrExpression: EntityNameOrEntityNameExpression = node.kind === SyntaxKind.TypeReference
5103+ ? (<TypeReferenceNode>node).typeName
5104+ : isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node)
5105+ ? (<SupportedExpressionWithTypeArguments>node).expression
5106+ : undefined;
50965107 symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
50975108 type = symbol === unknownSymbol ? unknownType :
50985109 symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
@@ -16951,20 +16962,21 @@ namespace ts {
1695116962 }
1695216963 }
1695316964
16954- function getFirstIdentifier(node: EntityName | Expression): Identifier {
16955- while (true) {
16956- if (node.kind === SyntaxKind.QualifiedName) {
16957- node = (<QualifiedName>node).left;
16958- }
16959- else if (node.kind === SyntaxKind.PropertyAccessExpression) {
16960- node = (<PropertyAccessExpression>node).expression;
16961- }
16962- else {
16963- break;
16964- }
16965+ function getFirstIdentifier(node: EntityNameOrEntityNameExpression): Identifier {
16966+ switch (node.kind) {
16967+ case SyntaxKind.Identifier:
16968+ return <Identifier>node;
16969+ case SyntaxKind.QualifiedName:
16970+ do {
16971+ node = (<QualifiedName>node).left;
16972+ } while (node.kind !== SyntaxKind.Identifier);
16973+ return <Identifier>node;
16974+ case SyntaxKind.PropertyAccessExpression:
16975+ do {
16976+ node = (<PropertyAccessEntityNameExpression>node).expression;
16977+ } while (node.kind !== SyntaxKind.Identifier);
16978+ return <Identifier>node;
1696516979 }
16966- Debug.assert(node.kind === SyntaxKind.Identifier);
16967- return <Identifier>node;
1696816980 }
1696916981
1697016982 function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
@@ -17663,7 +17675,7 @@ namespace ts {
1766317675 return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
1766417676 }
1766517677
17666- function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
17678+ function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol | undefined {
1766717679 if (isDeclarationName(entityName)) {
1766817680 return getSymbolOfNode(entityName.parent);
1766917681 }
@@ -17682,8 +17694,8 @@ namespace ts {
1768217694 }
1768317695 }
1768417696
17685- if (entityName.parent.kind === SyntaxKind.ExportAssignment) {
17686- return resolveEntityName(<Identifier >entityName,
17697+ if (entityName.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(<Identifier | PropertyAccessExpression>entityName) ) {
17698+ return resolveEntityName(<EntityNameExpression >entityName,
1768717699 /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
1768817700 }
1768917701
@@ -17697,7 +17709,7 @@ namespace ts {
1769717709 }
1769817710
1769917711 if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
17700- entityName = <QualifiedName | PropertyAccessExpression >entityName.parent;
17712+ entityName = <QualifiedName | PropertyAccessEntityNameExpression >entityName.parent;
1770117713 }
1770217714
1770317715 if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
@@ -18410,7 +18422,7 @@ namespace ts {
1841018422 };
1841118423
1841218424 // defined here to avoid outer scope pollution
18413- function getTypeReferenceDirectivesForEntityName(node: EntityName | PropertyAccessExpression ): string[] {
18425+ function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression ): string[] {
1841418426 // program does not have any files with type reference directives - bail out
1841518427 if (!fileToDirective) {
1841618428 return undefined;
0 commit comments