diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cefbc3105ec..58841f96349 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1666,7 +1666,7 @@ module ts { return classType.typeParameters ? createTypeReference(classType, map(classType.typeParameters, _ => anyType)) : classType; } - function getTypeOfVariableOrPropertyDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type { + function getTypeOfVariableOrParameterOrPropertyDeclaration(declaration: VariableOrParameterOrPropertyDeclaration): Type { // A variable declared in a for..in statement is always of type any if (declaration.parent.kind === SyntaxKind.ForInStatement) { return anyType; @@ -1758,7 +1758,7 @@ module ts { } // Handle variable, parameter or property links.type = resolvingType; - var type = getTypeOfVariableOrPropertyDeclaration(declaration); + var type = getTypeOfVariableOrParameterOrPropertyDeclaration(declaration); if (links.type === resolvingType) { links.type = type; } @@ -1775,7 +1775,7 @@ module ts { return links.type; } - function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode { + function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode | LiteralExpression { return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type; } @@ -3018,14 +3018,17 @@ module ts { return links.resolvedType; } - function getStringLiteralType(node: StringLiteralTypeNode): StringLiteralType { - if (hasProperty(stringLiteralTypes, node.text)) return stringLiteralTypes[node.text]; + function getStringLiteralType(node: LiteralExpression): StringLiteralType { + if (hasProperty(stringLiteralTypes, node.text)) { + return stringLiteralTypes[node.text]; + } + var type = stringLiteralTypes[node.text] = createType(TypeFlags.StringLiteral); type.text = getTextOfNode(node); return type; } - function getTypeFromStringLiteral(node: StringLiteralTypeNode): Type { + function getTypeFromStringLiteral(node: LiteralExpression): Type { var links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getStringLiteralType(node); @@ -3033,7 +3036,7 @@ module ts { return links.resolvedType; } - function getTypeFromTypeNode(node: TypeNode): Type { + function getTypeFromTypeNode(node: TypeNode | LiteralExpression): Type { switch (node.kind) { case SyntaxKind.AnyKeyword: return anyType; @@ -3046,7 +3049,7 @@ module ts { case SyntaxKind.VoidKeyword: return voidType; case SyntaxKind.StringLiteral: - return getTypeFromStringLiteral(node); + return getTypeFromStringLiteral(node); case SyntaxKind.TypeReference: return getTypeFromTypeReferenceNode(node); case SyntaxKind.TypeQuery: @@ -4771,13 +4774,13 @@ module ts { // typed function expression, the contextual type of an initializer expression is the contextual type of the // parameter. function getContextualTypeForInitializerExpression(node: Expression): Type { - var declaration = node.parent; + var declaration = node.parent; if (node === declaration.initializer) { if (declaration.type) { return getTypeFromTypeNode(declaration.type); } if (declaration.kind === SyntaxKind.Parameter) { - return getContextuallyTypedParameterType(declaration); + return getContextuallyTypedParameterType(declaration); } } return undefined; @@ -6661,7 +6664,7 @@ module ts { } function checkParameter(parameterDeclaration: ParameterDeclaration) { - checkVariableDeclaration(parameterDeclaration); + checkVariableOrParameterDeclaration(parameterDeclaration); if (fullTypeCheck) { checkCollisionWithIndexVariableInGeneratedCode(parameterDeclaration, parameterDeclaration.name); @@ -6784,7 +6787,7 @@ module ts { function checkPropertyDeclaration(node: PropertyDeclaration) { if (fullTypeCheck) { - checkVariableOrPropertyInFullTypeCheck(node); + checkVariableOrParameterOrPropertyInFullTypeCheck(node); } } @@ -7521,7 +7524,7 @@ module ts { } } - function checkCollisionWithConstDeclarations(node: VariableDeclaration) { + function checkCollisionWithConstDeclarations(node: VariableOrParameterDeclaration) { // Variable declarations are hoisted to the top of their function scope. They can shadow // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition // by the binder as the declaration scope is different. @@ -7553,7 +7556,7 @@ module ts { } } - function checkVariableOrPropertyInFullTypeCheck(node: VariableDeclaration | PropertyDeclaration) { + function checkVariableOrParameterOrPropertyInFullTypeCheck(node: VariableOrParameterOrPropertyDeclaration) { Debug.assert(fullTypeCheck); checkSourceElement(node.type); @@ -7565,7 +7568,7 @@ module ts { var symbol = getSymbolOfNode(node); var type: Type; if (symbol.valueDeclaration !== node) { - type = getTypeOfVariableOrPropertyDeclaration(node); + type = getTypeOfVariableOrParameterOrPropertyDeclaration(node); } else { type = getTypeOfVariableOrParameterOrProperty(symbol); @@ -7579,9 +7582,9 @@ module ts { return type; } - function checkVariableDeclaration(node: VariableDeclaration) { + function checkVariableOrParameterDeclaration(node: VariableOrParameterDeclaration) { if (fullTypeCheck) { - var type = checkVariableOrPropertyInFullTypeCheck(node); + var type = checkVariableOrParameterOrPropertyInFullTypeCheck(node); checkExportsOnMergedDeclarations(node); if (node.initializer) { checkCollisionWithConstDeclarations(node); @@ -7604,7 +7607,7 @@ module ts { } function checkVariableStatement(node: VariableStatement) { - forEach(node.declarations, checkVariableDeclaration); + forEach(node.declarations, checkVariableOrParameterDeclaration); } function checkExpressionStatement(node: ExpressionStatement) { @@ -7628,7 +7631,7 @@ module ts { } function checkForStatement(node: ForStatement) { - if (node.declarations) forEach(node.declarations, checkVariableDeclaration); + if (node.declarations) forEach(node.declarations, checkVariableOrParameterDeclaration); if (node.initializer) checkExpression(node.initializer); if (node.condition) checkExpression(node.condition); if (node.iterator) checkExpression(node.iterator); @@ -7645,7 +7648,7 @@ module ts { if (node.declarations) { if (node.declarations.length >= 1) { var decl = node.declarations[0]; - checkVariableDeclaration(decl); + checkVariableOrParameterDeclaration(decl); if (decl.type) { error(decl, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation); } @@ -8847,7 +8850,7 @@ module ts { return node === (parent).type; case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: - return (parent).typeArguments && (parent).typeArguments.indexOf(node) >= 0; + return (parent).typeArguments && indexOf((parent).typeArguments, node) >= 0; case SyntaxKind.TaggedTemplateExpression: // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments. return false; @@ -9251,12 +9254,12 @@ module ts { return undefined; } - function writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) { + function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, 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 symbol = getSymbolOfNode(declaration); var type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.CallSignature | SymbolFlags.ConstructSignature)) ? getTypeOfSymbol(symbol) - : getTypeFromTypeNode(location); + : unknownType; getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); } @@ -9280,7 +9283,7 @@ module ts { isEmitBlocked, isDeclarationVisible, isImplementationOfOverload, - writeTypeAtLocation, + writeTypeOfDeclaration, writeReturnTypeOfSignatureDeclaration, isSymbolAccessible, isEntityNameVisible, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 95508687cd4..fab0433890a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -440,7 +440,7 @@ module ts { handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning)); } - function writeTypeAtLocation(location: Node, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { + function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, type: TypeNode | StringLiteralExpression, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; write(": "); if (type) { @@ -448,7 +448,7 @@ module ts { emitType(type); } else { - resolver.writeTypeAtLocation(location, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); + resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); } } @@ -494,12 +494,12 @@ module ts { } } - function emitTypeWithNewGetSymbolAccessibilityDiangostic(type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { + function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type: TypeNode | EntityName, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; emitType(type); } - function emitType(type: TypeNode) { + function emitType(type: TypeNode | StringLiteralExpression | Identifier | QualifiedName) { switch (type.kind) { case SyntaxKind.AnyKeyword: case SyntaxKind.StringKeyword: @@ -522,7 +522,7 @@ module ts { return emitParenType(type); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: - return emitSignatureDeclarationWithJsDocComments(type); + return emitSignatureDeclarationWithJsDocComments(type); case SyntaxKind.TypeLiteral: return emitTypeLiteral(type); case SyntaxKind.Identifier: @@ -666,7 +666,7 @@ module ts { writeTextOfNode(currentSourceFile, node.name); write(" = "); if (isInternalModuleImportDeclaration(node)) { - emitTypeWithNewGetSymbolAccessibilityDiangostic(node.moduleReference, getImportEntityNameVisibilityError); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); write(";"); } else { @@ -716,7 +716,7 @@ module ts { write("type "); writeTextOfNode(currentSourceFile, node.name); write(" = "); - emitTypeWithNewGetSymbolAccessibilityDiangostic(node.type, getTypeAliasDeclarationVisibilityError); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); write(";"); writeLine(); } @@ -780,7 +780,7 @@ module ts { emitType(node.constraint); } else { - emitTypeWithNewGetSymbolAccessibilityDiangostic(node.constraint, getTypeParameterConstraintVisibilityError); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError); } } @@ -845,8 +845,8 @@ module ts { emitCommaList(typeReferences, emitTypeOfTypeReference); } - function emitTypeOfTypeReference(node: Node) { - emitTypeWithNewGetSymbolAccessibilityDiangostic(node, getHeritageClauseVisibilityError); + function emitTypeOfTypeReference(node: TypeReferenceNode) { + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { var diagnosticMessage: DiagnosticMessage; @@ -950,7 +950,7 @@ module ts { emitTypeOfVariableDeclarationFromTypeLiteral(node); } else if (!(node.flags & NodeFlags.Private)) { - writeTypeAtLocation(node, node.type, getVariableDeclarationTypeVisibilityError); + writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); } } @@ -996,7 +996,7 @@ module ts { } } - function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableDeclaration) { + function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableOrParameterDeclaration) { // if this is property of type literal, // or is parameter of method/call/construct/index signature of type literal // emit only if type is specified @@ -1044,17 +1044,17 @@ module ts { accessorWithTypeAnnotation = anotherAccessor; } } - writeTypeAtLocation(node, type, getAccessorDeclarationTypeVisibilityError); + writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError); } write(";"); writeLine(); } - function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode { + function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | StringLiteralExpression { if (accessor) { - return accessor.kind === SyntaxKind.GetAccessor ? - accessor.type : // Getter - return type - accessor.parameters[0].type; // Setter parameter type + return accessor.kind === SyntaxKind.GetAccessor + ? accessor.type // Getter - return type + : accessor.parameters[0].type; // Setter parameter type } } @@ -1267,7 +1267,7 @@ module ts { emitTypeOfVariableDeclarationFromTypeLiteral(node); } else if (!(node.parent.flags & NodeFlags.Private)) { - writeTypeAtLocation(node, node.type, getParameterDeclarationTypeVisibilityError); + writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); } function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 33973f4ac3d..687eab878f3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1665,8 +1665,8 @@ module ts { return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } - function parseTokenNode(): PrimaryExpression { - var node = createNode(token); + function parseTokenNode(): T { + var node = createNode(token); nextToken(); return finishNode(node); } @@ -1789,10 +1789,14 @@ module ts { } } - function parseParameterType(): TypeNode { - return parseOptional(SyntaxKind.ColonToken) - ? token === SyntaxKind.StringLiteral ? parseLiteralNode(/*internName:*/ true) : parseType() - : undefined; + function parseParameterType(): TypeNode | StringLiteralExpression { + if (parseOptional(SyntaxKind.ColonToken)) { + return token === SyntaxKind.StringLiteral + ? parseLiteralNode(/*internName:*/ true) + : parseType(); + } + + return undefined; } function isStartOfParameter(): boolean { @@ -2095,15 +2099,15 @@ module ts { return finishNode(node); } - function parseFunctionType(typeKind: SyntaxKind): SignatureDeclaration { - var node = createNode(typeKind); + function parseFunctionType(typeKind: SyntaxKind): FunctionOrConstructorTypeNode { + var node = createNode(typeKind); fillSignature(typeKind === SyntaxKind.FunctionType ? SyntaxKind.CallSignature : SyntaxKind.ConstructSignature, SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true, /*yieldAndGeneratorParameterContext:*/ false, node); return finishNode(node); } - function parseKeywordAndNoDot(): Node { - var node = parseTokenNode(); + function parseKeywordAndNoDot(): TypeNode { + var node = parseTokenNode(); return token === SyntaxKind.DotToken ? undefined : node; } @@ -2117,7 +2121,7 @@ module ts { var node = tryParse(parseKeywordAndNoDot); return node || parseTypeReference(); case SyntaxKind.VoidKeyword: - return parseTokenNode(); + return parseTokenNode(); case SyntaxKind.TypeOfKeyword: return parseTypeQuery(); case SyntaxKind.OpenBraceToken: @@ -2888,7 +2892,7 @@ module ts { } function parseSuperExpression(): MemberExpression { - var expression = parseTokenNode(); + var expression = parseTokenNode(); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) { return expression; } @@ -3025,7 +3029,7 @@ module ts { case SyntaxKind.NullKeyword: case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: - return parseTokenNode(); + return parseTokenNode(); case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ad74280dab5..277e2cce5ff 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -368,17 +368,24 @@ module ts { initializer?: Expression; } + export interface ParameterDeclaration extends Declaration { + name: Identifier; + type?: TypeNode | StringLiteralExpression; + initializer?: Expression; + } + export interface PropertyDeclaration extends Declaration, ClassElement { type?: TypeNode; initializer?: Expression; } + export type VariableOrParameterDeclaration = VariableDeclaration | ParameterDeclaration; + export type VariableOrParameterOrPropertyDeclaration = VariableOrParameterDeclaration | PropertyDeclaration; + export interface ShortHandPropertyDeclaration extends Declaration { name: Identifier; } - export interface ParameterDeclaration extends VariableDeclaration { } - /** * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. @@ -415,7 +422,13 @@ module ts { _indexSignatureDeclarationBrand: any; } - export interface TypeNode extends Node { } + export interface TypeNode extends Node { + _typeNodeBrand: any; + } + + export interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration { + _functionOrConstructorTypeNodeBrand: any; + } export interface TypeReferenceNode extends TypeNode { typeName: EntityName; @@ -447,10 +460,6 @@ module ts { type: TypeNode; } - export interface StringLiteralTypeNode extends TypeNode { - text: string; - } - // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing. // Consider 'Expression'. Without the brand, 'Expression' is actually no different // (structurally) than 'Node'. Because of this you can pass any Node to a function that @@ -535,6 +544,10 @@ module ts { isUnterminated?: boolean; } + export interface StringLiteralExpression extends LiteralExpression { + _stringLiteralExpressionBrand: any; + } + export interface TemplateExpression extends PrimaryExpression { head: LiteralExpression; templateSpans: NodeArray; @@ -963,7 +976,7 @@ module ts { hasSemanticErrors(): boolean; isDeclarationVisible(node: Declaration): boolean; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; - writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; + writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult; isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;