From d94851042516f5842736601999d94bdbb7f74ed2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 14 Nov 2014 16:19:10 -0800 Subject: [PATCH] Function and constructor types in the syntax tree. --- src/compiler/binder.ts | 30 +++++++++++++++++++++++++----- src/compiler/checker.ts | 28 ++++++++++++++++++++++++++-- src/compiler/parser.ts | 18 ++++++++++-------- src/compiler/types.ts | 4 +++- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index fe3009da3aa..bfdd41f5010 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -93,7 +93,9 @@ module ts { return (node.name).text; } switch (node.kind) { + 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 +116,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 +238,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 +301,13 @@ module ts { } } + function bindFunctionOrConstructorType(node: SignatureDeclaration) { + 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); + } + function bindAnonymousDeclaration(node: Node, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) { var symbol = createSymbol(symbolKind, name); addDeclarationToSymbol(symbol, node, symbolKind); @@ -358,12 +372,12 @@ module ts { case SyntaxKind.CallSignature: bindDeclaration(node, SymbolFlags.CallSignature, 0, /*isBlockScopeContainer*/ false); break; - case SyntaxKind.Method: - bindDeclaration(node, SymbolFlags.Method, SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true); - break; case SyntaxKind.ConstructSignature: bindDeclaration(node, SymbolFlags.ConstructSignature, 0, /*isBlockScopeContainer*/ true); break; + case SyntaxKind.Method: + bindDeclaration(node, SymbolFlags.Method, SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true); + break; case SyntaxKind.IndexSignature: bindDeclaration(node, SymbolFlags.IndexSignature, 0, /*isBlockScopeContainer*/ false); break; @@ -379,6 +393,12 @@ module ts { case SyntaxKind.SetAccessor: bindDeclaration(node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes, /*isBlockScopeContainer*/ true); break; + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + bindFunctionOrConstructorType(node); + break; + case SyntaxKind.TypeLiteral: bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type", /*isBlockScopeContainer*/ false); break; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6224e37ea53..92d474a6202 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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: @@ -2961,6 +2963,21 @@ module ts { return links.resolvedType; } + function getTypefromFunctionOrConstructorTypeNode(node: SignatureDeclaration): Type { + var links = getNodeLinks(node); + if (!links.resolvedType) { + var symbol = new Symbol(SymbolFlags.TypeLiteral, "__type"); + symbol.members = {}; + symbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = node.symbol; + symbol.declarations = [node.symbol.declarations[0]]; + + node.symbol.parent = symbol; + + links.resolvedType = createObjectType(TypeFlags.Anonymous, symbol); + } + return links.resolvedType; + } + function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type { var links = getNodeLinks(node); if (!links.resolvedType) { @@ -3011,6 +3028,9 @@ module ts { return getTypeFromUnionTypeNode(node); case SyntaxKind.ParenType: return getTypeFromTypeNode((node).type); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return getTypefromFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeLiteral: return getTypeFromTypeLiteralNode(node); // This function assumes that an identifier or qualified name is a type expression @@ -5858,7 +5878,7 @@ 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); @@ -8275,6 +8295,8 @@ module ts { return checkParameter(node); case SyntaxKind.Property: return checkPropertyDeclaration(node); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: @@ -9047,7 +9069,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); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d43bff7984a..9cb61feeea6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -205,6 +205,8 @@ module ts { return child((node).name) || child((node).type) || child((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 = createNode(SyntaxKind.TypeLiteral); - var member = createNode(signatureKind); - var sig = parseSignature(signatureKind, SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true); + function parseFunctionType(typeKind: SyntaxKind): SignatureDeclaration { + var member = 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(); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e9293070766..411be56b8b2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -155,6 +155,8 @@ module ts { IndexSignature, // Type TypeReference, + FunctionType, + ConstructorType, TypeQuery, TypeLiteral, ArrayType, @@ -1357,4 +1359,4 @@ module ts { useCaseSensitiveFileNames(): boolean; getNewLine(): string; } -} +}