Add greater typesafety in the expression portion of the syntax system.

Note: this change reveals that there is definitely some wonkyness going on
with nodes like FunctionLikeDeclaration.
This commit is contained in:
Cyrus Najmabadi
2014-11-29 16:48:28 -08:00
parent e4b543981c
commit 8989f1a782
4 changed files with 183 additions and 121 deletions
+43 -32
View File
@@ -4514,8 +4514,8 @@ module ts {
}
break;
case SyntaxKind.PrefixUnaryExpression:
if ((<UnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
return narrowType(type, (<UnaryExpression>expr).operand, !assumeTrue);
if ((<PrefixUnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
return narrowType(type,(<PrefixUnaryExpression>expr).operand, !assumeTrue);
}
break;
}
@@ -4722,8 +4722,9 @@ module ts {
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
var func = <FunctionLikeDeclaration>parameter.parent;
if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
if (isContextSensitiveExpression(func)) {
var contextualSignature = getContextualSignature(func);
var funcExpr = <Expression>parameter.parent;
if (isContextSensitiveExpression(funcExpr)) {
var contextualSignature = getContextualSignature(funcExpr);
if (contextualSignature) {
var funcHasRestParameters = hasRestParameters(func);
@@ -4771,7 +4772,7 @@ module ts {
}
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
var signature = getContextualSignature(func);
var signature = getContextualSignature(<Expression><Node>func);
if (signature) {
return getReturnTypeOfSignature(signature);
}
@@ -5053,7 +5054,9 @@ module ts {
}
else {
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
type = checkExpression(memberDecl.name, contextualMapper);
type = memberDecl.name.kind === SyntaxKind.ComputedPropertyName
? unknownType
: checkExpression(<Expression><Node>memberDecl.name, contextualMapper);
}
var prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
prop.declarations = member.declarations;
@@ -5115,7 +5118,7 @@ module ts {
return s.valueDeclaration ? s.valueDeclaration.flags : s.flags & SymbolFlags.Prototype ? NodeFlags.Public | NodeFlags.Static : 0;
}
function checkClassPropertyAccess(node: PropertyAccessExpression, type: Type, prop: Symbol) {
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, type: Type, prop: Symbol) {
var flags = getDeclarationFlagsFromSymbol(prop);
// Public properties are always accessible
if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
@@ -5154,7 +5157,15 @@ module ts {
}
function checkPropertyAccess(node: PropertyAccessExpression) {
var type = checkExpression(node.left);
return checkPropertyAccessCore(node, node.left, node.right);
}
function checkQualifiedName(node: QualifiedName) {
return checkPropertyAccessCore(node, node.left, node.right);
}
function checkPropertyAccessCore(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
var type = checkExpression(left);
if (type === unknownType) return type;
if (type !== anyType) {
var apparentType = getApparentType(getWidenedType(type));
@@ -5162,10 +5173,10 @@ module ts {
// handle cases when type is Type parameter with invalid constraint
return unknownType;
}
var prop = getPropertyOfType(apparentType, node.right.text);
var prop = getPropertyOfType(apparentType, right.text);
if (!prop) {
if (node.right.text) {
error(node.right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(node.right), typeToString(type));
if (right.text) {
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
}
return unknownType;
}
@@ -5178,8 +5189,8 @@ module ts {
// - In a static member function or static member accessor
// where this references the constructor function object of a derived class,
// a super property access is permitted and must specify a public static member function of the base class.
if (node.left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.Method) {
error(node.right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.Method) {
error(right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
}
else {
checkClassPropertyAccess(node, type, prop);
@@ -5477,7 +5488,7 @@ module ts {
// String literals get string literal types unless we're reporting errors
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
? getStringLiteralType(<LiteralExpression>arg)
: checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
: checkExpressionWithContextualType(<LiteralExpression>arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
}
// Use argument expression as error location when reporting errors
@@ -5968,9 +5979,9 @@ module ts {
}
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
var contextualSignature = getContextualSignature(func);
var contextualSignature = getContextualSignature(<Expression><Node>func);
if (func.body.kind !== SyntaxKind.FunctionBlock) {
var unwidenedType = checkAndMarkExpression(func.body, contextualMapper);
var unwidenedType = checkAndMarkExpression(<Expression>func.body, contextualMapper);
var widenedType = getWidenedType(unwidenedType);
if (fullTypeCheck && compilerOptions.noImplicitAny && !contextualSignature && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
@@ -6126,7 +6137,7 @@ module ts {
checkSourceElement(node.body);
}
else {
var exprType = checkExpression(node.body);
var exprType = checkExpression(<Expression>node.body);
if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
}
@@ -6229,7 +6240,7 @@ module ts {
return undefinedType;
}
function checkPrefixExpression(node: UnaryExpression): Type {
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
var operandType = checkExpression(node.operand);
switch (node.operator) {
case SyntaxKind.PlusToken:
@@ -6252,7 +6263,7 @@ module ts {
return unknownType;
}
function checkPostfixExpression(node: UnaryExpression): Type {
function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type {
var operandType = checkExpression(node.operand);
var ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
if (ok) {
@@ -6503,12 +6514,12 @@ module ts {
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
// have the wildcard function type; this form of type check is used during overload resolution to exclude
// contextually typed function and arrow expressions in the initial phase.
function checkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
function checkExpression(node: Expression | QualifiedName, contextualMapper?: TypeMapper): Type {
var type = checkExpressionNode(node, contextualMapper);
if (contextualMapper && contextualMapper !== identityMapper) {
if (contextualMapper && contextualMapper !== identityMapper && node.kind !== SyntaxKind.QualifiedName) {
var signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
var contextualType = getContextualType(node);
var contextualType = getContextualType(<Expression>node);
if (contextualType) {
var contextualSignature = getSingleCallSignature(contextualType);
if (contextualSignature && !contextualSignature.typeParameters) {
@@ -6526,7 +6537,7 @@ module ts {
var ok =
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).left === node) ||
(node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).expression === node) ||
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<EntityName>node));
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<Identifier>node));
if (!ok) {
error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
@@ -6535,7 +6546,7 @@ module ts {
return type;
}
function checkExpressionNode(node: Expression, contextualMapper: TypeMapper): Type {
function checkExpressionNode(node: Expression | QualifiedName, contextualMapper: TypeMapper): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
return checkIdentifier(<Identifier>node);
@@ -6558,7 +6569,7 @@ module ts {
case SyntaxKind.RegularExpressionLiteral:
return globalRegExpType;
case SyntaxKind.QualifiedName:
return checkPropertyAccess(<QualifiedName>node);
return checkQualifiedName(<QualifiedName>node);
case SyntaxKind.ArrayLiteralExpression:
return checkArrayLiteral(<ArrayLiteralExpression>node, contextualMapper);
case SyntaxKind.ObjectLiteralExpression:
@@ -6586,9 +6597,9 @@ module ts {
case SyntaxKind.VoidExpression:
return checkVoidExpression(<VoidExpression>node);
case SyntaxKind.PrefixUnaryExpression:
return checkPrefixExpression(<UnaryExpression>node);
return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.PostfixUnaryExpression:
return checkPostfixExpression(<UnaryExpression>node);
return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.BinaryExpression:
return checkBinaryExpression(<BinaryExpression>node, contextualMapper);
case SyntaxKind.ConditionalExpression:
@@ -8097,11 +8108,11 @@ module ts {
function evalConstant(e: Node): number {
switch (e.kind) {
case SyntaxKind.PrefixUnaryExpression:
var value = evalConstant((<UnaryExpression>e).operand);
var value = evalConstant((<PrefixUnaryExpression>e).operand);
if (value === undefined) {
return undefined;
}
switch ((<UnaryExpression>e).operator) {
switch ((<PrefixUnaryExpression>e).operator) {
case SyntaxKind.PlusToken: return value;
case SyntaxKind.MinusToken: return -value;
case SyntaxKind.TildeToken: return enumIsConst ? ~value : undefined;
@@ -8839,7 +8850,7 @@ module ts {
else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression) {
var symbol = getNodeLinks(entityName).resolvedSymbol;
if (!symbol) {
checkPropertyAccess(<QualifiedName>entityName);
checkQualifiedName(<QualifiedName>entityName);
}
return getNodeLinks(entityName).resolvedSymbol;
}
@@ -8885,7 +8896,7 @@ module ts {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
var type = checkExpression(node);
var type = checkExpression(<Expression>node);
return type.symbol;
case SyntaxKind.ConstructorKeyword:
@@ -8976,7 +8987,7 @@ module ts {
function getTypeOfExpression(expr: Expression): Type {
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
expr = expr.parent;
expr = <Expression>expr.parent;
}
return checkExpression(expr);
}
+21 -10
View File
@@ -2268,6 +2268,12 @@ module ts {
emit(node.right);
}
function emitQualifiedName(node: QualifiedName) {
emit(node.left);
write(".");
emit(node.right);
}
function emitIndexedAccess(node: ElementAccessExpression) {
if (tryEmitConstantValue(node)) {
return;
@@ -2374,10 +2380,8 @@ module ts {
emit(node.expression);
}
function emitUnaryExpression(node: UnaryExpression) {
if (node.kind === SyntaxKind.PrefixUnaryExpression) {
write(tokenToString(node.operator));
}
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
write(tokenToString(node.operator));
// In some cases, we need to emit a space between the operator and the operand. One obvious case
// is when the operator is an identifier, like delete or typeof. We also need to do this for plus
// and minus expressions in certain cases. Specifically, consider the following two cases (parens
@@ -2394,7 +2398,7 @@ module ts {
write(" ");
}
else if (node.kind === SyntaxKind.PrefixUnaryExpression && node.operand.kind === SyntaxKind.PrefixUnaryExpression) {
var operand = <UnaryExpression>node.operand;
var operand = <PrefixUnaryExpression>node.operand;
if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
write(" ");
}
@@ -2403,11 +2407,17 @@ module ts {
}
}
emit(node.operand);
if (node.kind === SyntaxKind.PostfixUnaryExpression) {
write(tokenToString(node.operator));
}
}
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
if (node.operator >= SyntaxKind.Identifier) {
write(" ");
}
emit(node.operand);
write(tokenToString(node.operator));
}
function emitBinaryExpression(node: BinaryExpression) {
emit(node.left);
if (node.operator !== SyntaxKind.CommaToken) write(" ");
@@ -3494,7 +3504,7 @@ module ts {
case SyntaxKind.TemplateSpan:
return emitTemplateSpan(<TemplateSpan>node);
case SyntaxKind.QualifiedName:
return emitPropertyAccess(<QualifiedName>node);
return emitQualifiedName(<QualifiedName>node);
case SyntaxKind.ArrayLiteralExpression:
return emitArrayLiteral(<ArrayLiteralExpression>node);
case SyntaxKind.ObjectLiteralExpression:
@@ -3530,8 +3540,9 @@ module ts {
case SyntaxKind.VoidExpression:
return emitVoidExpression(<VoidExpression>node);
case SyntaxKind.PrefixUnaryExpression:
return emitPrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.PostfixUnaryExpression:
return emitUnaryExpression(<UnaryExpression>node);
return emitPostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.BinaryExpression:
return emitBinaryExpression(<BinaryExpression>node);
case SyntaxKind.ConditionalExpression:
+74 -60
View File
@@ -285,8 +285,9 @@ module ts {
case SyntaxKind.VoidExpression:
return child((<VoidExpression>node).expression);
case SyntaxKind.PrefixUnaryExpression:
return child((<PrefixUnaryExpression>node).operand);
case SyntaxKind.PostfixUnaryExpression:
return child((<UnaryExpression>node).operand);
return child((<PostfixUnaryExpression>node).operand);
case SyntaxKind.BinaryExpression:
return child((<BinaryExpression>node).left) ||
child((<BinaryExpression>node).right);
@@ -1557,8 +1558,8 @@ module ts {
return entity;
}
function parseAnyTokenNode(): Node {
var node = createNode(token);
function parseAnyTokenNode(): PrimaryExpression {
var node = <PrimaryExpression>createNode(token);
nextToken();
return finishNode(node);
}
@@ -1572,7 +1573,7 @@ module ts {
return createMissingNode();
}
function parseTemplateExpression() {
function parseTemplateExpression(): TemplateExpression {
var template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
template.head = parseLiteralNode();
@@ -2396,7 +2397,7 @@ module ts {
}
else {
// If not, we're probably better off bailing out and returning a bogus function expression.
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, createMissingNode());
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, <Expression>createMissingNode());
}
}
@@ -2510,7 +2511,7 @@ module ts {
}
function parseArrowExpressionTail(pos: number, sig: ParsedSignature): FunctionExpression {
var body: Node;
var body: Block | Expression;
if (token === SyntaxKind.OpenBraceToken) {
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
@@ -2635,8 +2636,37 @@ module ts {
return finishNode(node);
}
function parseUnaryExpressionOrHigher(): Expression {
var pos = getNodePos();
function parsePrefixUnaryExpression() {
var node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
var operator = token;
nextToken();
node.operator = operator;
node.operand = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function parseDeleteExpression() {
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function parseTypeOfExpression() {
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function parseVoidExpression() {
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function parseUnaryExpressionOrHigher(): UnaryExpression {
switch (token) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
@@ -2644,24 +2674,13 @@ module ts {
case SyntaxKind.ExclamationToken:
case SyntaxKind.PlusPlusToken:
case SyntaxKind.MinusMinusToken:
var operator = token;
nextToken();
return makeUnaryExpression(SyntaxKind.PrefixUnaryExpression, pos, operator, parseUnaryExpressionOrHigher());
return parsePrefixUnaryExpression();
case SyntaxKind.DeleteKeyword:
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
return parseDeleteExpression();
case SyntaxKind.TypeOfKeyword:
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
return parseTypeOfExpression();
case SyntaxKind.VoidKeyword:
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
return parseVoidExpression();
case SyntaxKind.LessThanToken:
return parseTypeAssertion();
default:
@@ -2669,20 +2688,22 @@ module ts {
}
}
function parsePostfixExpressionOrHigher(): Expression {
function parsePostfixExpressionOrHigher(): PostfixExpression {
var expression = parseLeftHandSideExpressionOrHigher();
Debug.assert(isLeftHandSideExpression(expression));
if ((token === SyntaxKind.PlusPlusToken || token === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
var operator = token;
var node = <PostfixUnaryExpression>createNode(SyntaxKind.PostfixUnaryExpression, expression.pos);
node.operand = expression;
node.operator = token;
nextToken();
return makeUnaryExpression(SyntaxKind.PostfixUnaryExpression, expression.pos, operator, expression);
return finishNode(node);
}
return expression;
}
function parseLeftHandSideExpressionOrHigher(): Expression {
function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
// Original Ecma:
// LeftHandSideExpression: See 11.2
// NewExpression
@@ -2713,7 +2734,7 @@ module ts {
// the last two CallExpression productions. Or we have a MemberExpression which either
// completes the LeftHandSideExpression, or starts the beginning of the first four
// CallExpression productions.
var expression: Expression;
var expression: MemberExpression;
if (token === SyntaxKind.SuperKeyword) {
expression = parseSuperExpression();
}
@@ -2726,7 +2747,7 @@ module ts {
return parseCallExpressionRest(expression);
}
function parseMemberExpressionOrHigher(): Expression {
function parseMemberExpressionOrHigher(): MemberExpression {
// Note: to make our lives simpler, we decompose the the NewExpression productions and
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
// like so:
@@ -2778,7 +2799,7 @@ module ts {
return parseMemberExpressionRest(expression);
}
function parseSuperExpression(): Expression {
function parseSuperExpression(): MemberExpression {
var expression = parseAnyTokenNode();
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) {
return expression;
@@ -2802,14 +2823,7 @@ module ts {
return finishNode(node);
}
function makeUnaryExpression(kind: SyntaxKind, pos: number, operator: SyntaxKind, operand: Expression): UnaryExpression {
var node = <UnaryExpression>createNode(kind, pos);
node.operator = operator;
node.operand = operand;
return finishNode(node);
}
function parseMemberExpressionRest(expression: Expression): Expression {
function parseMemberExpressionRest(expression: LeftHandSideExpression): MemberExpression {
while (true) {
var dotOrBracketStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.DotToken)) {
@@ -2867,7 +2881,7 @@ module ts {
}
}
else {
indexedAccess.argumentExpression = createMissingNode();
indexedAccess.argumentExpression = <Expression>createMissingNode();
}
indexedAccess.closeBracketToken = parseTokenNode(SyntaxKind.CloseBracketToken);
@@ -2885,11 +2899,11 @@ module ts {
continue;
}
return expression;
return <MemberExpression>expression;
}
}
function parseCallExpressionRest(expression: Expression): Expression {
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
while (true) {
expression = parseMemberExpressionRest(expression);
@@ -2950,7 +2964,7 @@ module ts {
return parseType();
}
function parsePrimaryExpression(): Expression {
function parsePrimaryExpression(): PrimaryExpression {
switch (token) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
@@ -2963,11 +2977,11 @@ module ts {
case SyntaxKind.NoSubstitutionTemplateLiteral:
return parseLiteralNode();
case SyntaxKind.OpenParenToken:
return parseParenExpression();
return parseParenthesizedExpression();
case SyntaxKind.OpenBracketToken:
return parseArrayLiteral();
return parseArrayLiteralExpression();
case SyntaxKind.OpenBraceToken:
return parseObjectLiteral();
return parseObjectLiteralExpression();
case SyntaxKind.FunctionKeyword:
return parseFunctionExpression();
case SyntaxKind.NewKeyword:
@@ -2987,10 +3001,10 @@ module ts {
}
}
error(Diagnostics.Expression_expected);
return <Expression>createMissingNode();
return <PrimaryExpression>createMissingNode();
}
function parseParenExpression(): ParenthesizedExpression {
function parseParenthesizedExpression(): ParenthesizedExpression {
var node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression);
parseExpected(SyntaxKind.OpenParenToken);
node.expression = allowInAnd(parseExpression);
@@ -3000,7 +3014,7 @@ module ts {
function parseAssignmentExpressionOrOmittedExpression(): Expression {
return token === SyntaxKind.CommaToken
? createNode(SyntaxKind.OmittedExpression)
? <Expression>createNode(SyntaxKind.OmittedExpression)
: parseAssignmentExpressionOrHigher();
}
@@ -3012,7 +3026,7 @@ module ts {
return allowInAnd(parseAssignmentExpressionOrOmittedExpression);
}
function parseArrayLiteral(): ArrayLiteralExpression {
function parseArrayLiteralExpression(): ArrayLiteralExpression {
var node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
parseExpected(SyntaxKind.OpenBracketToken);
if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
@@ -3077,7 +3091,7 @@ module ts {
return parsePropertyAssignment();
}
function parseObjectLiteral(): ObjectLiteralExpression {
function parseObjectLiteralExpression(): ObjectLiteralExpression {
var node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
parseExpected(SyntaxKind.OpenBraceToken);
if (scanner.hasPrecedingLineBreak()) {
@@ -3109,7 +3123,7 @@ module ts {
return isIdentifier() ? parseIdentifier() : undefined;
}
function makeFunctionExpression(kind: SyntaxKind, pos: number, asteriskToken: Node, name: Identifier, sig: ParsedSignature, body: Node): FunctionExpression {
function makeFunctionExpression(kind: SyntaxKind, pos: number, asteriskToken: Node, name: Identifier, sig: ParsedSignature, body: Block | Expression): FunctionExpression {
var node = <FunctionExpression>createNode(kind, pos);
node.asteriskToken = asteriskToken;
node.name = name;
@@ -4236,17 +4250,17 @@ module ts {
case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.FunctionExpression: return checkFunctionExpression(<FunctionExpression>node);
case SyntaxKind.GetAccessor: return checkGetAccessor(<MethodDeclaration>node);
case SyntaxKind.ElementAccessExpression: return checkIndexedAccess(<ElementAccessExpression>node);
case SyntaxKind.ElementAccessExpression: return checkElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.IndexSignature: return checkIndexSignature(<SignatureDeclaration>node);
case SyntaxKind.InterfaceDeclaration: return checkInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.LabeledStatement: return checkLabeledStatement(<LabeledStatement>node);
case SyntaxKind.Method: return checkMethod(<MethodDeclaration>node);
case SyntaxKind.ModuleDeclaration: return checkModuleDeclaration(<ModuleDeclaration>node);
case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteral(<ObjectLiteralExpression>node);
case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteralExpression(<ObjectLiteralExpression>node);
case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
case SyntaxKind.PostfixUnaryExpression: return checkPostfixOperator(<UnaryExpression>node);
case SyntaxKind.PrefixUnaryExpression: return checkPrefixOperator(<UnaryExpression>node);
case SyntaxKind.PostfixUnaryExpression: return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.PrefixUnaryExpression: return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
case SyntaxKind.PropertyAssignment: return checkPropertyAssignment(<PropertyDeclaration>node);
case SyntaxKind.ReturnStatement: return checkReturnStatement(<ReturnStatement>node);
@@ -4567,7 +4581,7 @@ module ts {
}
if (expression.kind === SyntaxKind.PrefixUnaryExpression) {
var unaryExpression = <UnaryExpression>expression;
var unaryExpression = <PrefixUnaryExpression>expression;
if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) {
expression = unaryExpression.operand;
}
@@ -4632,7 +4646,7 @@ module ts {
checkAccessor(node);
}
function checkIndexedAccess(node: ElementAccessExpression) {
function checkElementAccessExpression(node: ElementAccessExpression) {
if (node.argumentExpression.kind === SyntaxKind.Missing) {
if (node.parent.kind === SyntaxKind.NewExpression &&
(<NewExpression>node.parent).expression === node) {
@@ -4763,7 +4777,7 @@ module ts {
}
}
function checkObjectLiteral(node: ObjectLiteralExpression): boolean {
function checkObjectLiteralExpression(node: ObjectLiteralExpression): boolean {
var seen: Map<SymbolFlags> = {};
var Property = 1;
var GetAccessor = 2;
@@ -5029,7 +5043,7 @@ module ts {
}
}
function checkPostfixOperator(node: UnaryExpression) {
function checkPostfixUnaryExpression(node: PostfixUnaryExpression) {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
@@ -5038,7 +5052,7 @@ module ts {
}
}
function checkPrefixOperator(node: UnaryExpression) {
function checkPrefixUnaryExpression(node: PrefixUnaryExpression) {
if (node.parserContextFlags & ParserContextFlags.StrictMode) {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
+45 -19
View File
@@ -315,7 +315,7 @@ module ts {
flags: number;
}
export interface Identifier extends Node {
export interface Identifier extends PrimaryExpression {
text: string; // Text of identifier (with escapes converted to characters)
}
@@ -436,23 +436,49 @@ module ts {
}
export interface Expression extends Node {
_expressionBrand: any;
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
}
export interface UnaryExpression extends Expression {
_unaryExpressionBrand: any;
}
export interface PrefixUnaryExpression extends UnaryExpression {
operator: SyntaxKind;
operand: Expression;
}
export interface DeleteExpression extends Expression {
export interface PostfixUnaryExpression extends PostfixExpression {
operand: LeftHandSideExpression;
operator: SyntaxKind;
}
export interface PostfixExpression extends UnaryExpression {
_postfixExpressionBrand: any;
}
export interface LeftHandSideExpression extends PostfixExpression {
_leftHandSideExpressionBrand: any;
}
export interface MemberExpression extends LeftHandSideExpression {
_memberExpressionBrand: any;
}
export interface PrimaryExpression extends MemberExpression {
_primaryExpressionBrand: any;
}
export interface DeleteExpression extends UnaryExpression {
expression: Expression;
}
export interface TypeOfExpression extends Expression {
export interface TypeOfExpression extends UnaryExpression {
expression: Expression;
}
export interface VoidExpression extends Expression {
export interface VoidExpression extends UnaryExpression {
expression: Expression;
}
@@ -473,7 +499,7 @@ module ts {
whenFalse: Expression;
}
export interface FunctionExpression extends Expression, FunctionLikeDeclaration {
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
name?: Identifier;
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
}
@@ -481,11 +507,11 @@ module ts {
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
export interface LiteralExpression extends Expression {
export interface LiteralExpression extends PrimaryExpression {
text: string;
}
export interface TemplateExpression extends Expression {
export interface TemplateExpression extends PrimaryExpression {
head: LiteralExpression;
templateSpans: NodeArray<TemplateSpan>;
}
@@ -497,46 +523,46 @@ module ts {
literal: LiteralExpression;
}
export interface ParenthesizedExpression extends Expression {
export interface ParenthesizedExpression extends PrimaryExpression {
expression: Expression;
}
export interface ArrayLiteralExpression extends Expression {
export interface ArrayLiteralExpression extends PrimaryExpression {
elements: NodeArray<Expression>;
}
export interface ObjectLiteralExpression extends Expression {
export interface ObjectLiteralExpression extends PrimaryExpression {
properties: NodeArray<Node>;
}
export interface PropertyAccessExpression extends Expression {
left: Expression;
export interface PropertyAccessExpression extends MemberExpression {
left: LeftHandSideExpression;
right: Identifier;
}
export interface ElementAccessExpression extends Expression {
expression: Expression;
export interface ElementAccessExpression extends MemberExpression {
expression: LeftHandSideExpression;
openBracketToken: Node;
argumentExpression: Expression;
closeBracketToken: Node;
}
export interface CallExpression extends Expression {
export interface CallExpression extends LeftHandSideExpression {
expression: Expression;
typeArguments?: NodeArray<TypeNode>;
arguments: NodeArray<Expression>;
}
export interface NewExpression extends CallExpression { }
export interface NewExpression extends CallExpression, PrimaryExpression { }
export interface TaggedTemplateExpression extends Expression {
tag: Expression;
export interface TaggedTemplateExpression extends MemberExpression {
tag: LeftHandSideExpression;
template: LiteralExpression | TemplateExpression;
}
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
export interface TypeAssertion extends Expression {
export interface TypeAssertion extends UnaryExpression {
type: TypeNode;
expression: Expression;
}