@@ -968,28 +968,39 @@ namespace ts {
968
968
969
969
970
970
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) {
981
973
return false;
982
974
}
983
- if (!parentClassExpression) {
984
- return false;
985
- }
986
- const expression = (<ExpressionWithTypeArguments>parentClassExpression).expression;
975
+ const expression = parentExpression.expression;
976
+
987
977
if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
988
978
error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
989
979
return true;
990
980
}
991
981
return false;
992
982
}
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
+
993
1004
994
1005
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
995
1006
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
@@ -1274,7 +1285,7 @@ namespace ts {
1274
1285
}
1275
1286
1276
1287
// 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 {
1278
1289
if (nodeIsMissing(name)) {
1279
1290
return undefined;
1280
1291
}
@@ -1289,7 +1300,7 @@ namespace ts {
1289
1300
}
1290
1301
}
1291
1302
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;
1293
1304
const right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
1294
1305
1295
1306
const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors);
@@ -1845,7 +1856,7 @@ namespace ts {
1845
1856
}
1846
1857
}
1847
1858
1848
- function isEntityNameVisible(entityName: EntityName | Expression , enclosingDeclaration: Node): SymbolVisibilityResult {
1859
+ function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression , enclosingDeclaration: Node): SymbolVisibilityResult {
1849
1860
// get symbol of the first identifier of the entityName
1850
1861
let meaning: SymbolFlags;
1851
1862
if (entityName.parent.kind === SyntaxKind.TypeQuery || isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) {
@@ -5022,7 +5033,7 @@ namespace ts {
5022
5033
return getDeclaredTypeOfSymbol(symbol);
5023
5034
}
5024
5035
5025
- function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): LeftHandSideExpression | EntityName {
5036
+ function getTypeReferenceName(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): EntityNameOrEntityNameExpression | undefined {
5026
5037
switch (node.kind) {
5027
5038
case SyntaxKind.TypeReference:
5028
5039
return (<TypeReferenceNode>node).typeName;
@@ -5031,8 +5042,9 @@ namespace ts {
5031
5042
case SyntaxKind.ExpressionWithTypeArguments:
5032
5043
// We only support expressions that are simple qualified names. For other
5033
5044
// 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;
5036
5048
}
5037
5049
5038
5050
// fall through;
@@ -5043,7 +5055,7 @@ namespace ts {
5043
5055
5044
5056
function resolveTypeReferenceName(
5045
5057
node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
5046
- typeReferenceName: LeftHandSideExpression | EntityName) {
5058
+ typeReferenceName: EntityNameExpression | EntityName) {
5047
5059
5048
5060
if (!typeReferenceName) {
5049
5061
return unknownSymbol;
@@ -5084,15 +5096,14 @@ namespace ts {
5084
5096
const typeReferenceName = getTypeReferenceName(node);
5085
5097
symbol = resolveTypeReferenceName(node, typeReferenceName);
5086
5098
type = getTypeReferenceType(node, symbol);
5087
-
5088
- links.resolvedSymbol = symbol;
5089
- links.resolvedType = type;
5090
5099
}
5091
5100
else {
5092
5101
// 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;
5096
5107
symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
5097
5108
type = symbol === unknownSymbol ? unknownType :
5098
5109
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
@@ -16951,20 +16962,21 @@ namespace ts {
16951
16962
}
16952
16963
}
16953
16964
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;
16965
16979
}
16966
- Debug.assert(node.kind === SyntaxKind.Identifier);
16967
- return <Identifier>node;
16968
16980
}
16969
16981
16970
16982
function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
@@ -17663,7 +17675,7 @@ namespace ts {
17663
17675
return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
17664
17676
}
17665
17677
17666
- function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
17678
+ function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol | undefined {
17667
17679
if (isDeclarationName(entityName)) {
17668
17680
return getSymbolOfNode(entityName.parent);
17669
17681
}
@@ -17682,8 +17694,8 @@ namespace ts {
17682
17694
}
17683
17695
}
17684
17696
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,
17687
17699
/*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
17688
17700
}
17689
17701
@@ -17697,7 +17709,7 @@ namespace ts {
17697
17709
}
17698
17710
17699
17711
if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
17700
- entityName = <QualifiedName | PropertyAccessExpression >entityName.parent;
17712
+ entityName = <QualifiedName | PropertyAccessEntityNameExpression >entityName.parent;
17701
17713
}
17702
17714
17703
17715
if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
@@ -18410,7 +18422,7 @@ namespace ts {
18410
18422
};
18411
18423
18412
18424
// defined here to avoid outer scope pollution
18413
- function getTypeReferenceDirectivesForEntityName(node: EntityName | PropertyAccessExpression ): string[] {
18425
+ function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression ): string[] {
18414
18426
// program does not have any files with type reference directives - bail out
18415
18427
if (!fileToDirective) {
18416
18428
return undefined;
0 commit comments