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

View file

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

View file

@ -1913,4 +1913,4 @@ module ts {
return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength:*/ newEndN - oldStartN);
}
}
}