Make StringLiterals and HeritageClauses into TypeNodes. It makes the checker much simpler and nicer.

This commit is contained in:
Cyrus Najmabadi 2015-04-16 22:48:18 -07:00
parent b22e0e9dff
commit 89bfbd0cf3
3 changed files with 43 additions and 39 deletions

View file

@ -597,7 +597,7 @@ module ts {
if (moduleSymbol.flags & SymbolFlags.Variable) { if (moduleSymbol.flags & SymbolFlags.Variable) {
let typeAnnotation = (<VariableDeclaration>moduleSymbol.valueDeclaration).type; let typeAnnotation = (<VariableDeclaration>moduleSymbol.valueDeclaration).type;
if (typeAnnotation) { if (typeAnnotation) {
return getPropertyOfType(getTypeFromTypeNodeOrHeritageClauseElement(typeAnnotation), name); return getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name);
} }
} }
} }
@ -646,7 +646,7 @@ module ts {
if (symbol.flags & SymbolFlags.Variable) { if (symbol.flags & SymbolFlags.Variable) {
var typeAnnotation = (<VariableDeclaration>symbol.valueDeclaration).type; var typeAnnotation = (<VariableDeclaration>symbol.valueDeclaration).type;
if (typeAnnotation) { if (typeAnnotation) {
return resolveSymbol(getPropertyOfType(getTypeFromTypeNodeOrHeritageClauseElement(typeAnnotation), name)); return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
} }
} }
} }
@ -2127,7 +2127,7 @@ module ts {
} }
// Use type from type annotation if one is present // Use type from type annotation if one is present
if (declaration.type) { if (declaration.type) {
return getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); return getTypeFromTypeNode(declaration.type);
} }
if (declaration.kind === SyntaxKind.Parameter) { if (declaration.kind === SyntaxKind.Parameter) {
let func = <FunctionLikeDeclaration>declaration.parent; let func = <FunctionLikeDeclaration>declaration.parent;
@ -2289,18 +2289,18 @@ module ts {
return links.type; return links.type;
} }
function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode | LiteralExpression { function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode {
return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type; return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
} }
function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type { function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type {
if (accessor) { if (accessor) {
if (accessor.kind === SyntaxKind.GetAccessor) { if (accessor.kind === SyntaxKind.GetAccessor) {
return accessor.type && getTypeFromTypeNodeOrHeritageClauseElement(accessor.type); return accessor.type && getTypeFromTypeNode(accessor.type);
} }
else { else {
let setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor); let setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
return setterTypeAnnotation && getTypeFromTypeNodeOrHeritageClauseElement(setterTypeAnnotation); return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
} }
} }
return undefined; return undefined;
@ -2541,7 +2541,7 @@ module ts {
if (!links.declaredType) { if (!links.declaredType) {
links.declaredType = resolvingType; links.declaredType = resolvingType;
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
let type = getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); let type = getTypeFromTypeNode(declaration.type);
if (links.declaredType === resolvingType) { if (links.declaredType === resolvingType) {
links.declaredType = type; links.declaredType = type;
} }
@ -3083,7 +3083,7 @@ module ts {
returnType = classType; returnType = classType;
} }
else if (declaration.type) { else if (declaration.type) {
returnType = getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); returnType = getTypeFromTypeNode(declaration.type);
} }
else { else {
// TypeScript 1.0 spec (April 2014): // TypeScript 1.0 spec (April 2014):
@ -3241,7 +3241,7 @@ module ts {
function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): Type { function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): Type {
let declaration = getIndexDeclarationOfSymbol(symbol, kind); let declaration = getIndexDeclarationOfSymbol(symbol, kind);
return declaration return declaration
? declaration.type ? getTypeFromTypeNodeOrHeritageClauseElement(declaration.type) : anyType ? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType
: undefined; : undefined;
} }
@ -3252,7 +3252,7 @@ module ts {
type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType; type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
} }
else { else {
type.constraint = getTypeFromTypeNodeOrHeritageClauseElement((<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint); type.constraint = getTypeFromTypeNode((<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint);
} }
} }
return type.constraint === noConstraintType ? undefined : type.constraint; return type.constraint === noConstraintType ? undefined : type.constraint;
@ -3383,7 +3383,7 @@ module ts {
if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) { if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) {
let typeParameters = (<InterfaceType>type).typeParameters; let typeParameters = (<InterfaceType>type).typeParameters;
if (node.typeArguments && node.typeArguments.length === typeParameters.length) { if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
type = createTypeReference(<GenericType>type, map(node.typeArguments, getTypeFromTypeNodeOrHeritageClauseElement)); type = createTypeReference(<GenericType>type, map(node.typeArguments, getTypeFromTypeNode));
} }
else { else {
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length); error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
@ -3481,7 +3481,7 @@ module ts {
function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type { function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
let links = getNodeLinks(node); let links = getNodeLinks(node);
if (!links.resolvedType) { if (!links.resolvedType) {
links.resolvedType = createArrayType(getTypeFromTypeNodeOrHeritageClauseElement(node.elementType)); links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
} }
return links.resolvedType; return links.resolvedType;
} }
@ -3499,7 +3499,7 @@ module ts {
function getTypeFromTupleTypeNode(node: TupleTypeNode): Type { function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
let links = getNodeLinks(node); let links = getNodeLinks(node);
if (!links.resolvedType) { if (!links.resolvedType) {
links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNodeOrHeritageClauseElement)); links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode));
} }
return links.resolvedType; return links.resolvedType;
} }
@ -3608,7 +3608,7 @@ module ts {
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type { function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
let links = getNodeLinks(node); let links = getNodeLinks(node);
if (!links.resolvedType) { if (!links.resolvedType) {
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNodeOrHeritageClauseElement), /*noSubtypeReduction*/ true); links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
} }
return links.resolvedType; return links.resolvedType;
} }
@ -3622,7 +3622,7 @@ module ts {
return links.resolvedType; return links.resolvedType;
} }
function getStringLiteralType(node: LiteralExpression): StringLiteralType { function getStringLiteralType(node: StringLiteralExpression): StringLiteralType {
if (hasProperty(stringLiteralTypes, node.text)) { if (hasProperty(stringLiteralTypes, node.text)) {
return stringLiteralTypes[node.text]; return stringLiteralTypes[node.text];
} }
@ -3632,7 +3632,7 @@ module ts {
return type; return type;
} }
function getTypeFromStringLiteral(node: LiteralExpression): Type { function getTypeFromStringLiteral(node: StringLiteralExpression): Type {
let links = getNodeLinks(node); let links = getNodeLinks(node);
if (!links.resolvedType) { if (!links.resolvedType) {
links.resolvedType = getStringLiteralType(node); links.resolvedType = getStringLiteralType(node);
@ -3640,7 +3640,7 @@ module ts {
return links.resolvedType; return links.resolvedType;
} }
function getTypeFromTypeNodeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type { function getTypeFromTypeNode(node: TypeNode): Type {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.AnyKeyword: case SyntaxKind.AnyKeyword:
return anyType; return anyType;
@ -3655,7 +3655,7 @@ module ts {
case SyntaxKind.VoidKeyword: case SyntaxKind.VoidKeyword:
return voidType; return voidType;
case SyntaxKind.StringLiteral: case SyntaxKind.StringLiteral:
return getTypeFromStringLiteral(<LiteralExpression>node); return getTypeFromStringLiteral(<StringLiteralExpression>node);
case SyntaxKind.TypeReference: case SyntaxKind.TypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node); return getTypeFromTypeReference(<TypeReferenceNode>node);
case SyntaxKind.HeritageClauseElement: case SyntaxKind.HeritageClauseElement:
@ -3669,7 +3669,7 @@ module ts {
case SyntaxKind.UnionType: case SyntaxKind.UnionType:
return getTypeFromUnionTypeNode(<UnionTypeNode>node); return getTypeFromUnionTypeNode(<UnionTypeNode>node);
case SyntaxKind.ParenthesizedType: case SyntaxKind.ParenthesizedType:
return getTypeFromTypeNodeOrHeritageClauseElement((<ParenthesizedTypeNode>node).type); return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
case SyntaxKind.FunctionType: case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType: case SyntaxKind.ConstructorType:
case SyntaxKind.TypeLiteral: case SyntaxKind.TypeLiteral:
@ -5680,7 +5680,7 @@ module ts {
let declaration = <VariableLikeDeclaration>node.parent; let declaration = <VariableLikeDeclaration>node.parent;
if (node === declaration.initializer) { if (node === declaration.initializer) {
if (declaration.type) { if (declaration.type) {
return getTypeFromTypeNodeOrHeritageClauseElement(declaration.type); return getTypeFromTypeNode(declaration.type);
} }
if (declaration.kind === SyntaxKind.Parameter) { if (declaration.kind === SyntaxKind.Parameter) {
let type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration); let type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
@ -5883,7 +5883,7 @@ module ts {
case SyntaxKind.NewExpression: case SyntaxKind.NewExpression:
return getContextualTypeForArgument(<CallExpression>parent, node); return getContextualTypeForArgument(<CallExpression>parent, node);
case SyntaxKind.TypeAssertionExpression: case SyntaxKind.TypeAssertionExpression:
return getTypeFromTypeNodeOrHeritageClauseElement((<TypeAssertion>parent).type); return getTypeFromTypeNode((<TypeAssertion>parent).type);
case SyntaxKind.BinaryExpression: case SyntaxKind.BinaryExpression:
return getContextualTypeForBinaryOperand(node); return getContextualTypeForBinaryOperand(node);
case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAssignment:
@ -6705,7 +6705,7 @@ module ts {
let typeArgumentsAreAssignable = true; let typeArgumentsAreAssignable = true;
for (let i = 0; i < typeParameters.length; i++) { for (let i = 0; i < typeParameters.length; i++) {
let typeArgNode = typeArguments[i]; let typeArgNode = typeArguments[i];
let typeArgument = getTypeFromTypeNodeOrHeritageClauseElement(typeArgNode); let typeArgument = getTypeFromTypeNode(typeArgNode);
// Do not push on this array! It has a preallocated length // Do not push on this array! It has a preallocated length
typeArgumentResultTypes[i] = typeArgument; typeArgumentResultTypes[i] = typeArgument;
if (typeArgumentsAreAssignable /* so far */) { if (typeArgumentsAreAssignable /* so far */) {
@ -6727,9 +6727,12 @@ module ts {
let paramType = getTypeAtPosition(signature, i); let paramType = getTypeAtPosition(signature, i);
// A tagged template expression provides a special first argument, and string literals get string literal types // A tagged template expression provides a special first argument, and string literals get string literal types
// unless we're reporting errors // unless we're reporting errors
let argType = i === 0 && node.kind === SyntaxKind.TaggedTemplateExpression ? globalTemplateStringsArrayType : let argType = i === 0 && node.kind === SyntaxKind.TaggedTemplateExpression
arg.kind === SyntaxKind.StringLiteral && !reportErrors ? getStringLiteralType(<LiteralExpression>arg) : ? globalTemplateStringsArrayType
checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); : arg.kind === SyntaxKind.StringLiteral && !reportErrors
? getStringLiteralType(<StringLiteralExpression>arg)
: checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
// Use argument expression as error location when reporting errors // Use argument expression as error location when reporting errors
if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined, if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined,
Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) { Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) {
@ -7187,7 +7190,7 @@ module ts {
function checkTypeAssertion(node: TypeAssertion): Type { function checkTypeAssertion(node: TypeAssertion): Type {
let exprType = checkExpression(node.expression); let exprType = checkExpression(node.expression);
let targetType = getTypeFromTypeNodeOrHeritageClauseElement(node.type); let targetType = getTypeFromTypeNode(node.type);
if (produceDiagnostics && targetType !== unknownType) { if (produceDiagnostics && targetType !== unknownType) {
let widenedType = getWidenedType(exprType); let widenedType = getWidenedType(exprType);
if (!(isTypeAssignableTo(targetType, widenedType))) { if (!(isTypeAssignableTo(targetType, widenedType))) {
@ -7361,7 +7364,7 @@ module ts {
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) { function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
if (node.type && !node.asteriskToken) { if (node.type && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNodeOrHeritageClauseElement(node.type)); checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
} }
if (node.body) { if (node.body) {
@ -7371,7 +7374,7 @@ module ts {
else { else {
let exprType = checkExpression(<Expression>node.body); let exprType = checkExpression(<Expression>node.body);
if (node.type) { if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNodeOrHeritageClauseElement(node.type), node.body, /*headMessage*/ undefined); checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
} }
checkFunctionExpressionBodies(node.body); checkFunctionExpressionBodies(node.body);
} }
@ -8800,12 +8803,12 @@ module ts {
} }
/** Checks a type reference node as an expression. */ /** Checks a type reference node as an expression. */
function checkTypeNodeAsExpression(node: TypeNode | LiteralExpression) { function checkTypeNodeAsExpression(node: TypeNode) {
// When we are emitting type metadata for decorators, we need to try to check the type // When we are emitting type metadata for decorators, we need to try to check the type
// as if it were an expression so that we can emit the type in a value position when we // as if it were an expression so that we can emit the type in a value position when we
// serialize the type metadata. // serialize the type metadata.
if (node && node.kind === SyntaxKind.TypeReference) { if (node && node.kind === SyntaxKind.TypeReference) {
let type = getTypeFromTypeNodeOrHeritageClauseElement(node); let type = getTypeFromTypeNode(node);
let shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation; let shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
if (!type || (!shouldCheckIfUnknownType && type.flags & (TypeFlags.Intrinsic | TypeFlags.NumberLike | TypeFlags.StringLike))) { if (!type || (!shouldCheckIfUnknownType && type.flags & (TypeFlags.Intrinsic | TypeFlags.NumberLike | TypeFlags.StringLike))) {
return; return;
@ -8825,7 +8828,8 @@ module ts {
case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertyDeclaration:
checkTypeNodeAsExpression((<PropertyDeclaration>node).type); checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
break; break;
case SyntaxKind.Parameter: checkTypeNodeAsExpression((<ParameterDeclaration>node).type); case SyntaxKind.Parameter:
checkTypeNodeAsExpression((<ParameterDeclaration>node).type);
break; break;
case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodDeclaration:
checkTypeNodeAsExpression((<MethodDeclaration>node).type); checkTypeNodeAsExpression((<MethodDeclaration>node).type);
@ -8941,7 +8945,7 @@ module ts {
checkSourceElement(node.body); checkSourceElement(node.body);
if (node.type && !isAccessor(node.kind) && !node.asteriskToken) { if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNodeOrHeritageClauseElement(node.type)); checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
} }
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method // Report an implicit any error if there is no body, no explicit return type, and node is not a private method
@ -10105,7 +10109,7 @@ module ts {
if (!tp1.constraint || !tp2.constraint) { if (!tp1.constraint || !tp2.constraint) {
return false; return false;
} }
if (!isTypeIdenticalTo(getTypeFromTypeNodeOrHeritageClauseElement(tp1.constraint), getTypeFromTypeNodeOrHeritageClauseElement(tp2.constraint))) { if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
return false; return false;
} }
} }
@ -11136,7 +11140,7 @@ module ts {
return node.parent && node.parent.kind === SyntaxKind.HeritageClauseElement; return node.parent && node.parent.kind === SyntaxKind.HeritageClauseElement;
} }
function isTypeNodeOrHeritageClauseElement(node: Node): boolean { function isTypeNode(node: Node): boolean {
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) { if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
return true; return true;
} }
@ -11385,8 +11389,8 @@ module ts {
return unknownType; return unknownType;
} }
if (isTypeNodeOrHeritageClauseElement(node)) { if (isTypeNode(node)) {
return getTypeFromTypeNodeOrHeritageClauseElement(<TypeNode | HeritageClauseElement>node); return getTypeFromTypeNode(<TypeNode>node);
} }
if (isExpression(node)) { if (isExpression(node)) {

View file

@ -689,7 +689,7 @@ module ts {
hasExtendedUnicodeEscape?: boolean; hasExtendedUnicodeEscape?: boolean;
} }
export interface StringLiteralExpression extends LiteralExpression { export interface StringLiteralExpression extends LiteralExpression, TypeNode {
_stringLiteralExpressionBrand: any; _stringLiteralExpressionBrand: any;
} }
@ -739,7 +739,7 @@ module ts {
arguments: NodeArray<Expression>; arguments: NodeArray<Expression>;
} }
export interface HeritageClauseElement extends Node { export interface HeritageClauseElement extends TypeNode {
expression: LeftHandSideExpression; expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>; typeArguments?: NodeArray<TypeNode>;
} }