Address issue where we were having to double cast between FunctionLikeDeclaration and Expression types.

Provide brands in a few more places.  Anywhere where we have a type that extends another, but only adds
optional properties, we should consider brands.

Stop SignatureDeclarations from being ClassElements.  Instead, only IndexSignatureDeclaration is
considered to be a ClassElement.
This commit is contained in:
Cyrus Najmabadi 2014-11-30 21:46:39 -08:00
parent 7cc65ca73e
commit db2bf0a309
3 changed files with 31 additions and 17 deletions

View File

@ -4727,11 +4727,10 @@ module ts {
// Return contextual type of parameter or undefined if no contextual type is available
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
var func = <FunctionLikeDeclaration>parameter.parent;
if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
var funcExpr = <Expression>parameter.parent;
if (isContextSensitiveExpression(funcExpr)) {
var contextualSignature = getContextualSignature(funcExpr);
if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
var func = <FunctionExpression>parameter.parent;
if (isContextSensitiveExpression(func)) {
var contextualSignature = getContextualSignature(func);
if (contextualSignature) {
var funcHasRestParameters = hasRestParameters(func);
@ -4779,7 +4778,7 @@ module ts {
}
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
var signature = getContextualSignature(<Expression><Node>func);
var signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>func);
if (signature) {
return getReturnTypeOfSignature(signature);
}
@ -4951,12 +4950,21 @@ module ts {
}
}
function isFunctionExpressionOrArrowFunction(node: Node): boolean {
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
}
function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature {
// Only function expressions and arrow functions are contextually typed.
return isFunctionExpressionOrArrowFunction(node) ? getContextualSignature(<FunctionExpression>node) : undefined;
}
// Return the contextual signature for a given expression node. A contextual type provides a
// contextual signature if it has a single call signature and if that call signature is non-generic.
// If the contextual type is a union type, get the signature from each type possible and if they are
// all identical ignoring their return type, the result is same signature but with return type as
// union type of return types from these signatures
function getContextualSignature(node: Expression): Signature {
function getContextualSignature(node: FunctionExpression): Signature {
var type = getContextualType(node);
if (!type) {
return undefined;
@ -5990,7 +5998,7 @@ module ts {
}
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
var contextualSignature = getContextualSignature(<Expression><Node>func);
var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
if (func.body.kind !== SyntaxKind.FunctionBlock) {
var unwidenedType = checkAndMarkExpression(<Expression>func.body, contextualMapper);
var widenedType = getWidenedType(unwidenedType);

View File

@ -445,11 +445,11 @@ module ts {
return false;
}
export function getContainingFunction(node: Node): SignatureDeclaration {
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;
if (!node || isAnyFunction(node)) {
return <SignatureDeclaration>node;
return <FunctionLikeDeclaration>node;
}
}
}
@ -1936,8 +1936,8 @@ module ts {
});
}
function parseIndexSignatureMember(fullStart: number, modifiers: ModifiersArray): SignatureDeclaration {
var node = <SignatureDeclaration>createNode(SyntaxKind.IndexSignature, fullStart);
function parseIndexSignatureDeclaration(fullStart: number, modifiers: ModifiersArray): IndexSignatureDeclaration {
var node = <IndexSignatureDeclaration>createNode(SyntaxKind.IndexSignature, fullStart);
setModifiers(node, modifiers);
node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
node.type = parseTypeAnnotation();
@ -1994,7 +1994,7 @@ module ts {
return parseSignatureMember(SyntaxKind.CallSignature, SyntaxKind.ColonToken);
case SyntaxKind.OpenBracketToken:
// Indexer or computed property
return isIndexSignature() ? parseIndexSignatureMember(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod();
return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod();
case SyntaxKind.NewKeyword:
if (lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken)) {
return parseSignatureMember(SyntaxKind.ConstructSignature, SyntaxKind.ColonToken);
@ -3779,7 +3779,7 @@ module ts {
return parseConstructorDeclaration(fullStart, modifiers);
}
if (isIndexSignature()) {
return parseIndexSignatureMember(fullStart, modifiers);
return parseIndexSignatureDeclaration(fullStart, modifiers);
}
// It is very important that we check this *after* checking indexers because
// the [ token can start an index signature or a computed property name

View File

@ -354,7 +354,7 @@ module ts {
expression?: Expression;
}
export interface SignatureDeclaration extends Declaration, ParsedSignature, ClassElement {
export interface SignatureDeclaration extends Declaration, ParsedSignature {
}
export interface VariableDeclaration extends Declaration {
@ -383,6 +383,8 @@ module ts {
* AccessorDeclaration
*/
export interface FunctionLikeDeclaration extends SignatureDeclaration {
_functionLikeDeclarationBrand: any;
asteriskToken?: Node;
body?: Block | Expression;
}
@ -396,14 +398,18 @@ module ts {
body?: Block;
}
export interface ConstructorDeclaration extends Declaration, ParsedSignature, ClassElement {
export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement {
body?: Block;
}
export interface AccessorDeclaration extends FunctionLikeDeclaration {
export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement {
body?: Block;
}
export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement {
_indexSignatureDeclarationBrand: any;
}
export interface TypeNode extends Node { }
export interface TypeReferenceNode extends TypeNode {