Addressing CR feedback
This commit is contained in:
parent
f6bcf7074c
commit
d71af8a3fb
|
@ -2639,7 +2639,8 @@ namespace ts {
|
|||
}
|
||||
let baseConstructorType = checkExpression(baseTypeNode.expression);
|
||||
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
||||
// Force resolution of members such that we catch circularities
|
||||
// Resolving the members of a class requires us to resolve the base class of that class.
|
||||
// We force resolution here such that we catch circularities now.
|
||||
resolveObjectOrUnionTypeMembers(baseConstructorType);
|
||||
}
|
||||
if (!popTypeResolution()) {
|
||||
|
@ -2647,7 +2648,7 @@ namespace ts {
|
|||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
|
||||
error(baseTypeNode.expression, Diagnostics.Base_expression_is_not_of_a_constructor_function_type);
|
||||
error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType));
|
||||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
type.resolvedBaseConstructorType = baseConstructorType;
|
||||
|
@ -2699,7 +2700,7 @@ namespace ts {
|
|||
return;
|
||||
}
|
||||
if (!(getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface))) {
|
||||
error(baseTypeNode.expression, Diagnostics.Base_constructor_does_not_return_a_class_or_interface_type);
|
||||
error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType));
|
||||
return;
|
||||
}
|
||||
if (type === baseType || hasBaseType(<InterfaceType>baseType, type)) {
|
||||
|
@ -5962,7 +5963,9 @@ namespace ts {
|
|||
let baseClassType = classType && getBaseTypes(classType)[0];
|
||||
|
||||
if (!baseClassType) {
|
||||
error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class);
|
||||
if (!classDeclaration || !getClassExtendsHeritageClauseElement(classDeclaration)) {
|
||||
error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class);
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
|
@ -8970,13 +8973,14 @@ namespace ts {
|
|||
checkDecorators(node);
|
||||
}
|
||||
|
||||
function checkTypeArgumentsAndConstraints(typeParameters: TypeParameter[], typeArguments: TypeNode[]) {
|
||||
for (let i = 0; i < typeArguments.length; i++) {
|
||||
let typeArgument = typeArguments[i];
|
||||
checkSourceElement(typeArgument);
|
||||
let constraint = getConstraintOfTypeParameter(typeParameters[i]);
|
||||
if (produceDiagnostics && constraint) {
|
||||
checkTypeAssignableTo(getTypeFromTypeNode(typeArgument), constraint, typeArgument, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
|
||||
function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArguments: TypeNode[]) {
|
||||
if (produceDiagnostics) {
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
let constraint = getConstraintOfTypeParameter(typeParameters[i]);
|
||||
if (constraint) {
|
||||
let typeArgument = typeArguments[i];
|
||||
checkTypeAssignableTo(getTypeFromTypeNode(typeArgument), constraint, typeArgument, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8986,9 +8990,10 @@ namespace ts {
|
|||
let type = getTypeFromTypeReference(node);
|
||||
if (type !== unknownType && node.typeArguments) {
|
||||
// Do type argument local checks only if referenced type is successfully resolved
|
||||
forEach(node.typeArguments, checkSourceElement);
|
||||
let symbol = getNodeLinks(node).resolvedSymbol;
|
||||
let typeParameters = symbol.flags & SymbolFlags.TypeAlias ? getSymbolLinks(symbol).typeParameters : (<TypeReference>type).target.localTypeParameters;
|
||||
checkTypeArgumentsAndConstraints(typeParameters, node.typeArguments);
|
||||
checkTypeArgumentConstraints(typeParameters, node.typeArguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10588,15 +10593,19 @@ namespace ts {
|
|||
let baseType = baseTypes[0];
|
||||
let staticBaseType = getBaseConstructorTypeOfClass(type);
|
||||
if (baseTypeNode.typeArguments) {
|
||||
let constructors = getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments);
|
||||
checkTypeArgumentsAndConstraints(constructors[0].typeParameters, baseTypeNode.typeArguments);
|
||||
forEach(baseTypeNode.typeArguments, checkSourceElement);
|
||||
for (let constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments)) {
|
||||
checkTypeArgumentConstraints(constructor.typeParameters, baseTypeNode.typeArguments);
|
||||
}
|
||||
}
|
||||
checkTypeAssignableTo(type, baseType, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class)) {
|
||||
// When the static base type is a "class-like" constructor function (but not actually a class), we verify
|
||||
// that all instantiated base constructor signatures return the same type.
|
||||
// that all instantiated base constructor signatures return the same type. We can simply compare the type
|
||||
// references (as opposed to checking the structure of the types) because elsewhere we have already checked
|
||||
// that the base type is a class or interface type (and not, for example, an anonymous object type).
|
||||
let constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments);
|
||||
if (forEach(constructors, sig => getReturnTypeOfSignature(sig) !== baseType)) {
|
||||
error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type);
|
||||
|
@ -11997,7 +12006,7 @@ namespace ts {
|
|||
return getTypeOfExpression(<Expression>node);
|
||||
}
|
||||
|
||||
if (isClassExtendsExpressionWithTypeArguments(node)) {
|
||||
if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) {
|
||||
// A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the
|
||||
// extends clause of a class. We handle that case here.
|
||||
return getBaseTypes(<InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(node.parent.parent)))[0];
|
||||
|
|
|
@ -385,9 +385,9 @@ namespace ts {
|
|||
No_best_common_type_exists_among_yield_expressions: { code: 2504, category: DiagnosticCategory.Error, key: "No best common type exists among yield expressions." },
|
||||
A_generator_cannot_have_a_void_type_annotation: { code: 2505, category: DiagnosticCategory.Error, key: "A generator cannot have a 'void' type annotation." },
|
||||
_0_is_referenced_directly_or_indirectly_in_its_own_base_expression: { code: 2506, category: DiagnosticCategory.Error, key: "'{0}' is referenced directly or indirectly in its own base expression." },
|
||||
Base_expression_is_not_of_a_constructor_function_type: { code: 2507, category: DiagnosticCategory.Error, key: "Base expression is not of a constructor function type." },
|
||||
Type_0_is_not_a_constructor_function_type: { code: 2507, category: DiagnosticCategory.Error, key: "Type '{0}' is not a constructor function type." },
|
||||
No_base_constructor_has_the_specified_number_of_type_arguments: { code: 2508, category: DiagnosticCategory.Error, key: "No base constructor has the specified number of type arguments." },
|
||||
Base_constructor_does_not_return_a_class_or_interface_type: { code: 2509, category: DiagnosticCategory.Error, key: "Base constructor does not return a class or interface type." },
|
||||
Base_constructor_return_type_0_is_not_a_class_or_interface_type: { code: 2509, category: DiagnosticCategory.Error, key: "Base constructor return type '{0}' is not a class or interface type." },
|
||||
Base_constructors_must_all_have_the_same_return_type: { code: 2510, category: DiagnosticCategory.Error, key: "Base constructors must all have the same return type." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
|
|
|
@ -1529,7 +1529,7 @@
|
|||
"category": "Error",
|
||||
"code": 2506
|
||||
},
|
||||
"Base expression is not of a constructor function type.": {
|
||||
"Type '{0}' is not a constructor function type.": {
|
||||
"category": "Error",
|
||||
"code": 2507
|
||||
},
|
||||
|
@ -1537,7 +1537,7 @@
|
|||
"category": "Error",
|
||||
"code": 2508
|
||||
},
|
||||
"Base constructor does not return a class or interface type.": {
|
||||
"Base constructor return type '{0}' is not a class or interface type.": {
|
||||
"category": "Error",
|
||||
"code": 2509
|
||||
},
|
||||
|
|
|
@ -426,7 +426,7 @@ namespace ts {
|
|||
// Specialized signatures can have string literals as their parameters' type names
|
||||
return node.parent.kind === SyntaxKind.Parameter;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return !isClassExtendsExpressionWithTypeArguments(node);
|
||||
return !isExpressionWithTypeArgumentsInClassExtendsClause(node);
|
||||
|
||||
// Identifiers and qualified names may be type nodes, depending on their context. Climb
|
||||
// above them to find the lowest container
|
||||
|
@ -460,7 +460,7 @@ namespace ts {
|
|||
}
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return !isClassExtendsExpressionWithTypeArguments(parent);
|
||||
return !isExpressionWithTypeArgumentsInClassExtendsClause(parent);
|
||||
case SyntaxKind.TypeParameter:
|
||||
return node === (<TypeParameterDeclaration>parent).constraint;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
|
@ -920,7 +920,7 @@ namespace ts {
|
|||
case SyntaxKind.Decorator:
|
||||
return true;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return isClassExtendsExpressionWithTypeArguments(parent);
|
||||
return (<ExpressionWithTypeArguments>parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent);
|
||||
default:
|
||||
if (isExpression(parent)) {
|
||||
return true;
|
||||
|
@ -1914,7 +1914,7 @@ namespace ts {
|
|||
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
|
||||
}
|
||||
|
||||
export function isClassExtendsExpressionWithTypeArguments(node: Node): boolean {
|
||||
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments &&
|
||||
(<HeritageClause>node.parent).token === SyntaxKind.ExtendsKeyword &&
|
||||
node.parent.parent.kind === SyntaxKind.ClassDeclaration;
|
||||
|
|
|
@ -43,7 +43,7 @@ class TypeWriterWalker {
|
|||
|
||||
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
|
||||
// var type = this.checker.getTypeAtLocation(node);
|
||||
var type = node.parent && ts.isClassExtendsExpressionWithTypeArguments(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
|
||||
var type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
|
||||
|
||||
ts.Debug.assert(type !== undefined, "type doesn't exist");
|
||||
var symbol = this.checker.getSymbolAtLocation(node);
|
||||
|
|
|
@ -5812,7 +5812,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
return node.parent.kind === SyntaxKind.TypeReference ||
|
||||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isClassExtendsExpressionWithTypeArguments(<ExpressionWithTypeArguments>node.parent));
|
||||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent));
|
||||
}
|
||||
|
||||
function isNamespaceReference(node: Node): boolean {
|
||||
|
|
Loading…
Reference in a new issue