Use instantiated signatures in super calls
This commit is contained in:
parent
dfa149457c
commit
80ea68701b
1 changed files with 22 additions and 37 deletions
|
@ -2608,22 +2608,31 @@ module ts {
|
||||||
return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
|
return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConstructorsForTypeArguments(type: ObjectType, typeArguments: TypeNode[]): Signature[] {
|
function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] {
|
||||||
let typeArgCount = typeArguments ? typeArguments.length : 0;
|
let typeArgCount = typeArgumentNodes ? typeArgumentNodes.length : 0;
|
||||||
return filter(getSignaturesOfType(type, SignatureKind.Construct),
|
return filter(getSignaturesOfType(type, SignatureKind.Construct),
|
||||||
sig => (sig.typeParameters ? sig.typeParameters.length : 0) === typeArgCount);
|
sig => (sig.typeParameters ? sig.typeParameters.length : 0) === typeArgCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getInstantiatedConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] {
|
||||||
|
let signatures = getConstructorsForTypeArguments(type, typeArgumentNodes);
|
||||||
|
if (typeArgumentNodes) {
|
||||||
|
let typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
|
||||||
|
signatures = map(signatures, sig => getSignatureInstantiation(sig, typeArguments));
|
||||||
|
}
|
||||||
|
return signatures;
|
||||||
|
}
|
||||||
|
|
||||||
function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType {
|
function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType {
|
||||||
if (!type.baseConstructorType) {
|
if (!type.baseConstructorType) {
|
||||||
let baseTypeNode = getBaseTypeNodeOfClass(type);
|
let baseTypeNode = getBaseTypeNodeOfClass(type);
|
||||||
if (!baseTypeNode) {
|
if (!baseTypeNode) {
|
||||||
return type.baseConstructorType = unknownType;
|
return type.baseConstructorType = undefinedType;
|
||||||
}
|
}
|
||||||
if (!pushTypeResolution(type)) {
|
if (!pushTypeResolution(type)) {
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
let baseConstructorType = checkExpressionCached(baseTypeNode.expression);
|
let baseConstructorType = checkExpression(baseTypeNode.expression);
|
||||||
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
||||||
// Force resolution of members such that we catch circularities
|
// Force resolution of members such that we catch circularities
|
||||||
resolveObjectOrUnionTypeMembers(baseConstructorType);
|
resolveObjectOrUnionTypeMembers(baseConstructorType);
|
||||||
|
@ -2632,7 +2641,7 @@ module ts {
|
||||||
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
||||||
return type.baseConstructorType = unknownType;
|
return type.baseConstructorType = unknownType;
|
||||||
}
|
}
|
||||||
if (baseConstructorType !== unknownType && !isConstructorType(baseConstructorType)) {
|
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
|
||||||
error(baseTypeNode, Diagnostics.Base_expression_is_not_of_a_constructor_function_type);
|
error(baseTypeNode, Diagnostics.Base_expression_is_not_of_a_constructor_function_type);
|
||||||
return type.baseConstructorType = unknownType;
|
return type.baseConstructorType = unknownType;
|
||||||
}
|
}
|
||||||
|
@ -2660,7 +2669,7 @@ module ts {
|
||||||
function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes): void {
|
function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes): void {
|
||||||
type.baseTypes = emptyArray;
|
type.baseTypes = emptyArray;
|
||||||
let baseContructorType = getBaseConstructorTypeOfClass(type);
|
let baseContructorType = getBaseConstructorTypeOfClass(type);
|
||||||
if (baseContructorType === unknownType) {
|
if (!(baseContructorType.flags & TypeFlags.ObjectType)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let baseTypeNode = getBaseTypeNodeOfClass(type);
|
let baseTypeNode = getBaseTypeNodeOfClass(type);
|
||||||
|
@ -2669,16 +2678,12 @@ module ts {
|
||||||
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol);
|
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let constructors = getConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments);
|
let constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments);
|
||||||
if (!constructors.length) {
|
if (!constructors.length) {
|
||||||
error(baseTypeNode, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
|
error(baseTypeNode, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let constructor = constructors[0];
|
baseType = getReturnTypeOfSignature(constructors[0]);
|
||||||
if (baseTypeNode.typeArguments) {
|
|
||||||
constructor = getSignatureInstantiation(constructor, map(baseTypeNode.typeArguments, getTypeFromTypeNode));
|
|
||||||
}
|
|
||||||
baseType = getReturnTypeOfSignature(constructor);
|
|
||||||
}
|
}
|
||||||
if (baseType === unknownType) {
|
if (baseType === unknownType) {
|
||||||
return;
|
return;
|
||||||
|
@ -3054,7 +3059,7 @@ module ts {
|
||||||
constructSignatures = getDefaultConstructSignatures(classType);
|
constructSignatures = getDefaultConstructSignatures(classType);
|
||||||
}
|
}
|
||||||
let baseConstructorType = getBaseConstructorTypeOfClass(classType);
|
let baseConstructorType = getBaseConstructorTypeOfClass(classType);
|
||||||
if (baseConstructorType !== unknownType) {
|
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
||||||
members = createSymbolTable(getNamedMembers(members));
|
members = createSymbolTable(getNamedMembers(members));
|
||||||
addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType));
|
addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType));
|
||||||
}
|
}
|
||||||
|
@ -7202,35 +7207,13 @@ module ts {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* In a 'super' call, type arguments are not provided within the CallExpression node itself.
|
|
||||||
* Instead, they must be fetched from the class declaration's base type node.
|
|
||||||
*
|
|
||||||
* If 'node' is a 'super' call (e.g. super(...), new super(...)), then we attempt to fetch
|
|
||||||
* the type arguments off the containing class's first heritage clause (if one exists). Note that if
|
|
||||||
* type arguments are supplied on the 'super' call, they are ignored (though this is syntactically incorrect).
|
|
||||||
*
|
|
||||||
* In all other cases, the call's explicit type arguments are returned.
|
|
||||||
*/
|
|
||||||
function getEffectiveTypeArguments(callExpression: CallExpression): TypeNode[] {
|
|
||||||
if (callExpression.expression.kind === SyntaxKind.SuperKeyword) {
|
|
||||||
let containingClass = <ClassDeclaration>getAncestor(callExpression, SyntaxKind.ClassDeclaration);
|
|
||||||
let baseClassTypeNode = containingClass && getClassExtendsHeritageClauseElement(containingClass);
|
|
||||||
return baseClassTypeNode && baseClassTypeNode.typeArguments;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Ordinary case - simple function invocation.
|
|
||||||
return callExpression.typeArguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
|
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
|
||||||
let isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
|
let isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
|
||||||
|
|
||||||
let typeArguments: TypeNode[];
|
let typeArguments: TypeNode[];
|
||||||
|
|
||||||
if (!isTaggedTemplate) {
|
if (!isTaggedTemplate) {
|
||||||
typeArguments = getEffectiveTypeArguments(<CallExpression>node);
|
typeArguments = (<CallExpression>node).typeArguments;
|
||||||
|
|
||||||
// We already perform checking on the type arguments on the class declaration itself.
|
// We already perform checking on the type arguments on the class declaration itself.
|
||||||
if ((<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
|
if ((<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
|
||||||
|
@ -7438,7 +7421,9 @@ module ts {
|
||||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||||
let superType = checkSuperExpression(node.expression);
|
let superType = checkSuperExpression(node.expression);
|
||||||
if (superType !== unknownType) {
|
if (superType !== unknownType) {
|
||||||
return resolveCall(node, getConstructorsForTypeArguments(superType, getEffectiveTypeArguments(node)), candidatesOutArray);
|
let baseTypeNode = getClassExtendsHeritageClauseElement(<ClassDeclaration>getAncestor(node, SyntaxKind.ClassDeclaration));
|
||||||
|
let baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments);
|
||||||
|
return resolveCall(node, baseConstructors, candidatesOutArray);
|
||||||
}
|
}
|
||||||
return resolveUntypedCall(node);
|
return resolveUntypedCall(node);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue