@@ -944,28 +944,39 @@ namespace ts {
944
944
945
945
946
946
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) {
957
949
return false;
958
950
}
959
- if (!parentClassExpression) {
960
- return false;
961
- }
962
- const expression = (<ExpressionWithTypeArguments>parentClassExpression).expression;
951
+ const expression = parentExpression.expression;
952
+
963
953
if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
964
954
error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
965
955
return true;
966
956
}
967
957
return false;
968
958
}
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
+
969
980
970
981
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
971
982
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
@@ -1250,7 +1261,7 @@ namespace ts {
1250
1261
}
1251
1262
1252
1263
// 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 {
1254
1265
if (nodeIsMissing(name)) {
1255
1266
return undefined;
1256
1267
}
@@ -1265,7 +1276,7 @@ namespace ts {
1265
1276
}
1266
1277
}
1267
1278
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;
1269
1280
const right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
1270
1281
1271
1282
const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
@@ -1814,7 +1825,7 @@ namespace ts {
1814
1825
}
1815
1826
}
1816
1827
1817
- function isEntityNameVisible(entityName: EntityName | Expression , enclosingDeclaration: Node): SymbolVisibilityResult {
1828
+ function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression , enclosingDeclaration: Node): SymbolVisibilityResult {
1818
1829
// get symbol of the first identifier of the entityName
1819
1830
let meaning: SymbolFlags;
1820
1831
if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) {
@@ -4885,7 +4896,7 @@ namespace ts {
4885
4896
return getDeclaredTypeOfSymbol(symbol);
4886
4897
}
4887
4898
4888
- function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName {
4899
+ function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined {
4889
4900
switch (node.kind) {
4890
4901
case SyntaxKind.TypeReference:
4891
4902
return (<TypeReferenceNode>node).typeName;
@@ -4894,8 +4905,9 @@ namespace ts {
4894
4905
case SyntaxKind.ExpressionWithTypeArguments:
4895
4906
// We only support expressions that are simple qualified names. For other
4896
4907
// 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;
4899
4911
}
4900
4912
4901
4913
// fall through;
@@ -4906,7 +4918,7 @@ namespace ts {
4906
4918
4907
4919
function resolveTypeReferenceName(
4908
4920
node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
4909
- typeReferenceName: LeftHandSideExpression | EntityName) {
4921
+ typeReferenceName: EntityNameExpression | EntityName) {
4910
4922
4911
4923
if (!typeReferenceName) {
4912
4924
return unknownSymbol;
@@ -4947,15 +4959,14 @@ namespace ts {
4947
4959
const typeReferenceName = getTypeReferenceName(node);
4948
4960
symbol = resolveTypeReferenceName(node, typeReferenceName);
4949
4961
type = getTypeReferenceType(node, symbol);
4950
-
4951
- links.resolvedSymbol = symbol;
4952
- links.resolvedType = type;
4953
4962
}
4954
4963
else {
4955
4964
// 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;
4959
4970
symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
4960
4971
type = symbol === unknownSymbol ? unknownType :
4961
4972
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
@@ -16594,20 +16605,21 @@ namespace ts {
16594
16605
}
16595
16606
}
16596
16607
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;
16608
16622
}
16609
- Debug.assert(node.kind === SyntaxKind.Identifier);
16610
- return <Identifier>node;
16611
16623
}
16612
16624
16613
16625
function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
@@ -17306,7 +17318,7 @@ namespace ts {
17306
17318
return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
17307
17319
}
17308
17320
17309
- function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
17321
+ function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol | undefined {
17310
17322
if (isDeclarationName(entityName)) {
17311
17323
return getSymbolOfNode(entityName.parent);
17312
17324
}
@@ -17325,8 +17337,8 @@ namespace ts {
17325
17337
}
17326
17338
}
17327
17339
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,
17330
17342
/*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
17331
17343
}
17332
17344
@@ -17340,7 +17352,7 @@ namespace ts {
17340
17352
}
17341
17353
17342
17354
if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
17343
- entityName = <QualifiedName | PropertyAccessExpression >entityName.parent;
17355
+ entityName = <QualifiedName | PropertyAccessEntityNameExpression >entityName.parent;
17344
17356
}
17345
17357
17346
17358
if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
@@ -18053,7 +18065,7 @@ namespace ts {
18053
18065
};
18054
18066
18055
18067
// defined here to avoid outer scope pollution
18056
- function getTypeReferenceDirectivesForEntityName(node: EntityName | PropertyAccessExpression ): string[] {
18068
+ function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression ): string[] {
18057
18069
// program does not have any files with type reference directives - bail out
18058
18070
if (!fileToDirective) {
18059
18071
return undefined;
0 commit comments