Merge pull request #1169 from Microsoft/functionConstructorNodes

Function and constructor types in the syntax tree.
This commit is contained in:
CyrusNajmabadi 2014-11-14 17:28:33 -08:00
commit 20599e6fe8
4 changed files with 76 additions and 24 deletions

View file

@ -93,10 +93,16 @@ module ts {
return (<Identifier>node.name).text;
}
switch (node.kind) {
case SyntaxKind.Constructor: return "__constructor";
case SyntaxKind.CallSignature: return "__call";
case SyntaxKind.ConstructSignature: return "__new";
case SyntaxKind.IndexSignature: return "__index";
case SyntaxKind.ConstructorType:
case SyntaxKind.Constructor:
return "__constructor";
case SyntaxKind.FunctionType:
case SyntaxKind.CallSignature:
return "__call";
case SyntaxKind.ConstructSignature:
return "__new";
case SyntaxKind.IndexSignature:
return "__index";
}
}
@ -114,8 +120,11 @@ module ts {
}
// Report errors every position with duplicate declaration
// Report errors on previous encountered declarations
var message = symbol.flags & SymbolFlags.BlockScopedVariable ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0;
forEach(symbol.declarations, (declaration) => {
var message = symbol.flags & SymbolFlags.BlockScopedVariable
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
: Diagnostics.Duplicate_identifier_0;
forEach(symbol.declarations, declaration => {
file.semanticErrors.push(createDiagnosticForNode(declaration.name, message, getDisplayName(declaration)));
});
file.semanticErrors.push(createDiagnosticForNode(node.name, message, getDisplayName(node)));
@ -233,6 +242,8 @@ module ts {
declareModuleMember(node, symbolKind, symbolExcludes);
break;
}
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
@ -294,6 +305,25 @@ module ts {
}
}
function bindFunctionOrConstructorType(node: SignatureDeclaration) {
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
// to the one we would get for: { <...>(...): T }
//
// We do that by making an anonymous type literal symbol, and then setting the function
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
// from an actual type literal symbol you would have gotten had you used the long form.
var symbolKind = node.kind === SyntaxKind.FunctionType ? SymbolFlags.CallSignature : SymbolFlags.ConstructSignature;
var symbol = createSymbol(symbolKind, getDeclarationName(node));
addDeclarationToSymbol(symbol, node, symbolKind);
bindChildren(node, symbolKind, /*isBlockScopeContainer:*/ false);
var typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = {};
typeLiteralSymbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = symbol
}
function bindAnonymousDeclaration(node: Node, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) {
var symbol = createSymbol(symbolKind, name);
addDeclarationToSymbol(symbol, node, symbolKind);
@ -358,12 +388,12 @@ module ts {
case SyntaxKind.CallSignature:
bindDeclaration(<Declaration>node, SymbolFlags.CallSignature, 0, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.Method:
bindDeclaration(<Declaration>node, SymbolFlags.Method, SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.ConstructSignature:
bindDeclaration(<Declaration>node, SymbolFlags.ConstructSignature, 0, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.Method:
bindDeclaration(<Declaration>node, SymbolFlags.Method, SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.IndexSignature:
bindDeclaration(<Declaration>node, SymbolFlags.IndexSignature, 0, /*isBlockScopeContainer*/ false);
break;
@ -379,6 +409,12 @@ module ts {
case SyntaxKind.SetAccessor:
bindDeclaration(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
bindFunctionOrConstructorType(<SignatureDeclaration>node);
break;
case SyntaxKind.TypeLiteral:
bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type", /*isBlockScopeContainer*/ false);
break;

View file

@ -2523,6 +2523,8 @@ module ts {
for (var i = 0, len = symbol.declarations.length; i < len; i++) {
var node = symbol.declarations[i];
switch (node.kind) {
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
@ -2960,8 +2962,8 @@ module ts {
}
return links.resolvedType;
}
function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type {
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type {
var links = getNodeLinks(node);
if (!links.resolvedType) {
// Deferred resolution of members is handled by resolveObjectTypeMembers
@ -3011,8 +3013,10 @@ module ts {
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
case SyntaxKind.ParenType:
return getTypeFromTypeNode((<ParenTypeNode>node).type);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.TypeLiteral:
return getTypeFromTypeLiteralNode(<TypeLiteralNode>node);
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
// This function assumes that an identifier or qualified name is a type expression
// Callers should first ensure this by calling isTypeNode
case SyntaxKind.Identifier:
@ -5858,7 +5862,11 @@ module ts {
}
if (node.kind === SyntaxKind.NewExpression) {
var declaration = signature.declaration;
if (declaration && (declaration.kind !== SyntaxKind.Constructor && declaration.kind !== SyntaxKind.ConstructSignature)) {
if (declaration &&
declaration.kind !== SyntaxKind.Constructor &&
declaration.kind !== SyntaxKind.ConstructSignature &&
declaration.kind !== SyntaxKind.ConstructorType) {
// When resolved signature is a call signature (and not a construct signature) the result type is any
if (compilerOptions.noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
@ -6801,7 +6809,7 @@ module ts {
function checkTypeLiteral(node: TypeLiteralNode) {
forEach(node.members, checkSourceElement);
if (fullTypeCheck) {
var type = getTypeFromTypeLiteralNode(node);
var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
}
@ -8275,6 +8283,8 @@ module ts {
return checkParameter(<ParameterDeclaration>node);
case SyntaxKind.Property:
return checkPropertyDeclaration(<PropertyDeclaration>node);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
@ -9047,7 +9057,9 @@ module ts {
function writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
// Get type of the symbol if this is the valid symbol otherwise get type at location
var symbol = getSymbolOfNode(location);
var type = symbol && !(symbol.flags & SymbolFlags.TypeLiteral) ? getTypeOfSymbol(symbol) : getTypeFromTypeNode(location);
var type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.CallSignature | SymbolFlags.ConstructSignature))
? getTypeOfSymbol(symbol)
: getTypeFromTypeNode(location);
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
}

View file

@ -205,6 +205,8 @@ module ts {
return child((<PropertyDeclaration>node).name) ||
child((<PropertyDeclaration>node).type) ||
child((<PropertyDeclaration>node).initializer);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
@ -1882,16 +1884,16 @@ module ts {
return finishNode(node);
}
function parseFunctionType(signatureKind: SyntaxKind): TypeLiteralNode {
var node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
var member = <SignatureDeclaration>createNode(signatureKind);
var sig = parseSignature(signatureKind, SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true);
function parseFunctionType(typeKind: SyntaxKind): SignatureDeclaration {
var member = <SignatureDeclaration>createNode(typeKind);
var sig = parseSignature(typeKind === SyntaxKind.FunctionType ? SyntaxKind.CallSignature : SyntaxKind.ConstructSignature,
SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true);
member.typeParameters = sig.typeParameters;
member.parameters = sig.parameters;
member.type = sig.type;
finishNode(member);
node.members = createNodeArray(member);
return finishNode(node);
return member;
}
function parseKeywordAndNoDot(): Node {
@ -2011,10 +2013,10 @@ module ts {
function parseType(): TypeNode {
if (isStartOfFunctionType()) {
return parseFunctionType(SyntaxKind.CallSignature);
return parseFunctionType(SyntaxKind.FunctionType);
}
if (token === SyntaxKind.NewKeyword) {
return parseFunctionType(SyntaxKind.ConstructSignature);
return parseFunctionType(SyntaxKind.ConstructorType);
}
return parseUnionType();
}

View file

@ -155,6 +155,8 @@ module ts {
IndexSignature,
// Type
TypeReference,
FunctionType,
ConstructorType,
TypeQuery,
TypeLiteral,
ArrayType,
@ -1357,4 +1359,4 @@ module ts {
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
}
}
}