Include the binary expression's operator in the AST.

This commit is contained in:
Cyrus Najmabadi 2015-02-20 18:56:42 -08:00
parent 5c1ef11d69
commit fc229368d1
17 changed files with 78 additions and 78 deletions

View file

@ -3409,7 +3409,7 @@ module ts {
return isContextSensitive((<ConditionalExpression>node).whenTrue) ||
isContextSensitive((<ConditionalExpression>node).whenFalse);
case SyntaxKind.BinaryExpression:
return (<BinaryExpression>node).operator === SyntaxKind.BarBarToken &&
return (<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken &&
(isContextSensitive((<BinaryExpression>node).left) || isContextSensitive((<BinaryExpression>node).right));
case SyntaxKind.PropertyAssignment:
return isContextSensitive((<PropertyAssignment>node).initializer);
@ -4591,7 +4591,7 @@ module ts {
return links.assignmentChecks[symbol.id] = isAssignedIn(node);
function isAssignedInBinaryExpression(node: BinaryExpression) {
if (node.operator >= SyntaxKind.FirstAssignment && node.operator <= SyntaxKind.LastAssignment) {
if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) {
var n = node.left;
while (n.kind === SyntaxKind.ParenthesizedExpression) {
n = (<ParenthesizedExpression>n).expression;
@ -4724,10 +4724,10 @@ module ts {
case SyntaxKind.BinaryExpression:
// In the right operand of an && or ||, narrow based on left operand
if (child === (<BinaryExpression>node).right) {
if ((<BinaryExpression>node).operator === SyntaxKind.AmpersandAmpersandToken) {
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ true);
}
else if ((<BinaryExpression>node).operator === SyntaxKind.BarBarToken) {
else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ false);
}
}
@ -4765,7 +4765,7 @@ module ts {
return type;
}
var typeInfo = primitiveTypeInfo[right.text];
if (expr.operator === SyntaxKind.ExclamationEqualsEqualsToken) {
if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (assumeTrue) {
@ -4855,7 +4855,7 @@ module ts {
case SyntaxKind.ParenthesizedExpression:
return narrowType(type, (<ParenthesizedExpression>expr).expression, assumeTrue);
case SyntaxKind.BinaryExpression:
var operator = (<BinaryExpression>expr).operator;
var operator = (<BinaryExpression>expr).operatorToken.kind;
if (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
return narrowTypeByEquality(type, <BinaryExpression>expr, assumeTrue);
}
@ -5202,7 +5202,7 @@ module ts {
function getContextualTypeForBinaryOperand(node: Expression): Type {
var binaryExpression = <BinaryExpression>node.parent;
var operator = binaryExpression.operator;
var operator = binaryExpression.operatorToken.kind;
if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
if (node === binaryExpression.right) {
@ -5452,7 +5452,7 @@ module ts {
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'.
function isAssignmentTarget(node: Node): boolean {
var parent = node.parent;
if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operator === SyntaxKind.EqualsToken && (<BinaryExpression>parent).left === node) {
if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken && (<BinaryExpression>parent).left === node) {
return true;
}
if (parent.kind === SyntaxKind.PropertyAssignment) {
@ -7108,7 +7108,7 @@ module ts {
}
function checkDestructuringAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operator === SyntaxKind.EqualsToken) {
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
checkBinaryExpression(<BinaryExpression>target, contextualMapper);
target = (<BinaryExpression>target).left;
}
@ -7131,13 +7131,13 @@ module ts {
function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) {
// Grammar checking
if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operator)) {
if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3)
checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.left);
}
var operator = node.operator;
var operator = node.operatorToken.kind;
if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper);
}
@ -7178,8 +7178,8 @@ module ts {
// try and return them a helpful suggestion
if ((leftType.flags & TypeFlags.Boolean) &&
(rightType.flags & TypeFlags.Boolean) &&
(suggestedOperator = getSuggestedBooleanOperator(node.operator)) !== undefined) {
error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operator), tokenToString(suggestedOperator));
(suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) {
error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operatorToken.kind), tokenToString(suggestedOperator));
}
else {
// otherwise just check each operand separately and report errors as normal
@ -7312,7 +7312,7 @@ module ts {
}
function reportOperatorError() {
error(node, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, tokenToString(node.operator), typeToString(leftType), typeToString(rightType));
error(node, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType));
}
}
@ -9252,7 +9252,7 @@ module ts {
if (right === undefined) {
return undefined;
}
switch ((<BinaryExpression>e).operator) {
switch ((<BinaryExpression>e).operatorToken.kind) {
case SyntaxKind.BarToken: return left | right;
case SyntaxKind.AmpersandToken: return left & right;
case SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
@ -10830,7 +10830,7 @@ module ts {
if (languageVersion < ScriptTarget.ES6) {
return grammarErrorOnNode(node, Diagnostics.Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
else if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>computedPropertyName.expression).operator === SyntaxKind.CommaToken) {
else if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>computedPropertyName.expression).operatorToken.kind === SyntaxKind.CommaToken) {
return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
}
}

View file

@ -2252,7 +2252,7 @@ module ts {
// spread ('...') unary operators that are anticipated for ES6.
switch (expression.kind) {
case SyntaxKind.BinaryExpression:
switch ((<BinaryExpression>expression).operator) {
switch ((<BinaryExpression>expression).operatorToken.kind) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
@ -2773,14 +2773,14 @@ module ts {
}
function emitBinaryExpression(node: BinaryExpression) {
if (languageVersion < ScriptTarget.ES6 && node.operator === SyntaxKind.EqualsToken &&
if (languageVersion < ScriptTarget.ES6 && node.operatorToken.kind === SyntaxKind.EqualsToken &&
(node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
emitDestructuring(node);
}
else {
emit(node.left);
if (node.operator !== SyntaxKind.CommaToken) write(" ");
write(tokenToString(node.operator));
if (node.operatorToken.kind !== SyntaxKind.CommaToken) write(" ");
write(tokenToString(node.operatorToken.kind));
write(" ");
emit(node.right);
}
@ -3122,7 +3122,7 @@ module ts {
// Return the expression 'value === void 0 ? defaultValue : value'
var equals = <BinaryExpression>createNode(SyntaxKind.BinaryExpression);
equals.left = value;
equals.operator = SyntaxKind.EqualsEqualsEqualsToken;
equals.operatorToken = createNode(SyntaxKind.EqualsEqualsEqualsToken);
equals.right = createVoidZero();
var cond = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression);
cond.condition = equals;
@ -3205,7 +3205,7 @@ module ts {
}
function emitDestructuringAssignment(target: Expression, value: Expression) {
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operator === SyntaxKind.EqualsToken) {
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
value = createDefaultValueCheck(value,(<BinaryExpression>target).right);
target = (<BinaryExpression>target).left;
}

View file

@ -152,6 +152,7 @@ module ts {
return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
case SyntaxKind.BinaryExpression:
return visitNode(cbNode, (<BinaryExpression>node).left) ||
visitNode(cbNode, (<BinaryExpression>node).operatorToken) ||
visitNode(cbNode, (<BinaryExpression>node).right);
case SyntaxKind.ConditionalExpression:
return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
@ -1311,6 +1312,12 @@ module ts {
return undefined;
}
function parseTokenNode<T extends Node>(): T {
var node = <T>createNode(token);
nextToken();
return finishNode(node);
}
function canParseSemicolon() {
// If there's a real semicolon, then we can always parse it out.
if (token === SyntaxKind.SemicolonToken) {
@ -2084,14 +2091,6 @@ module ts {
return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
}
function parseTokenNode<T extends Node>(): T {
var node = <T>createNode(token);
nextToken();
return finishNode(node);
}
function parseTemplateExpression(): TemplateExpression {
var template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
@ -2801,8 +2800,9 @@ module ts {
// Expression[in] , AssignmentExpression[in]
var expr = parseAssignmentExpressionOrHigher();
while (parseOptional(SyntaxKind.CommaToken)) {
expr = makeBinaryExpression(expr, SyntaxKind.CommaToken, parseAssignmentExpressionOrHigher());
var operatorToken: Node;
while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) {
expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
}
return expr;
}
@ -2881,9 +2881,7 @@ module ts {
// Note: we call reScanGreaterToken so that we get an appropriately merged token
// for cases like > > = becoming >>=
if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
var operator = token;
nextToken();
return makeBinaryExpression(expr, operator, parseAssignmentExpressionOrHigher());
return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
}
// It wasn't an assignment or a lambda. This is a conditional expression:
@ -3187,9 +3185,7 @@ module ts {
break;
}
var operator = token;
nextToken();
leftOperand = makeBinaryExpression(leftOperand, operator, parseBinaryExpressionOrHigher(newPrecedence));
leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
}
return leftOperand;
@ -3245,10 +3241,10 @@ module ts {
return -1;
}
function makeBinaryExpression(left: Expression, operator: SyntaxKind, right: Expression): BinaryExpression {
function makeBinaryExpression(left: Expression, operatorToken: Node, right: Expression): BinaryExpression {
var node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, left.pos);
node.left = left;
node.operator = operator;
node.operatorToken = operatorToken;
node.right = right;
return finishNode(node);
}

View file

@ -623,7 +623,7 @@ module ts {
export interface BinaryExpression extends Expression {
left: Expression;
operator: SyntaxKind;
operatorToken: Node;
right: Expression;
}

View file

@ -69,7 +69,7 @@ module ts.BreakpointResolver {
return textSpan(node);
}
if (node.parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node.parent).operator === SyntaxKind.CommaToken) {
if (node.parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node.parent).operatorToken.kind === SyntaxKind.CommaToken) {
// if this is comma expression, the breakpoint is possible in this expression
return textSpan(node);
}

View file

@ -93,17 +93,19 @@ module ts.formatting {
savedPos = scanner.getStartPos();
}
function shouldRescanGreaterThanToken(container: Node): boolean {
if (container.kind !== SyntaxKind.BinaryExpression) {
return false;
}
switch ((<BinaryExpression>container).operator) {
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
return true;
function shouldRescanGreaterThanToken(node: Node): boolean {
//if (container.kind !== SyntaxKind.BinaryExpression) {
// return false;
//}
if (node) {
switch (node.kind) {
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
return true;
}
}
return false;
@ -164,7 +166,7 @@ module ts.formatting {
if (expectedScanAction === ScanAction.RescanGreaterThanToken && currentToken === SyntaxKind.GreaterThanToken) {
currentToken = scanner.reScanGreaterToken();
Debug.assert((<BinaryExpression>n).operator === currentToken);
Debug.assert(n.kind === currentToken);
lastScanAction = ScanAction.RescanGreaterThanToken;
}
else if (expectedScanAction === ScanAction.RescanSlashToken && startsWithSlashToken(currentToken)) {

View file

@ -4648,7 +4648,7 @@ module ts {
return true;
}
else if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).left === node) {
var operator = (<BinaryExpression>parent).operator;
var operator = (<BinaryExpression>parent).operatorToken.kind;
return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment;
}
}

View file

@ -527,7 +527,7 @@ declare module "typescript" {
}
interface BinaryExpression extends Expression {
left: Expression;
operator: SyntaxKind;
operatorToken: Node;
right: Expression;
}
interface ConditionalExpression extends Expression {

View file

@ -1585,9 +1585,9 @@ declare module "typescript" {
>left : Expression
>Expression : Expression
operator: SyntaxKind;
>operator : SyntaxKind
>SyntaxKind : SyntaxKind
operatorToken: Node;
>operatorToken : Node
>Node : Node
right: Expression;
>right : Expression

View file

@ -39,7 +39,7 @@ export function delint(sourceFile: ts.SourceFile) {
break;
case ts.SyntaxKind.BinaryExpression:
var op = (<ts.BinaryExpression>node).operator;
var op = (<ts.BinaryExpression>node).operatorToken.kind;
if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken) {
report(node, "Use '===' and '!=='.")
@ -558,7 +558,7 @@ declare module "typescript" {
}
interface BinaryExpression extends Expression {
left: Expression;
operator: SyntaxKind;
operatorToken: Node;
right: Expression;
}
interface ConditionalExpression extends Expression {
@ -2003,7 +2003,7 @@ function delint(sourceFile) {
}
break;
case 165 /* BinaryExpression */:
var op = node.operator;
var op = node.operatorToken.kind;
if (op === 28 /* EqualsEqualsToken */ || op === 29 /* ExclamationEqualsToken */) {
report(node, "Use '===' and '!=='.");
}

View file

@ -173,15 +173,17 @@ export function delint(sourceFile: ts.SourceFile) {
>SyntaxKind : typeof ts.SyntaxKind
>BinaryExpression : ts.SyntaxKind
var op = (<ts.BinaryExpression>node).operator;
var op = (<ts.BinaryExpression>node).operatorToken.kind;
>op : ts.SyntaxKind
>(<ts.BinaryExpression>node).operator : ts.SyntaxKind
>(<ts.BinaryExpression>node).operatorToken.kind : ts.SyntaxKind
>(<ts.BinaryExpression>node).operatorToken : ts.Node
>(<ts.BinaryExpression>node) : ts.BinaryExpression
><ts.BinaryExpression>node : ts.BinaryExpression
>ts : unknown
>BinaryExpression : ts.BinaryExpression
>node : ts.Node
>operator : ts.SyntaxKind
>operatorToken : ts.Node
>kind : ts.SyntaxKind
if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken) {
>op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken : boolean
@ -1729,9 +1731,9 @@ declare module "typescript" {
>left : Expression
>Expression : Expression
operator: SyntaxKind;
>operator : SyntaxKind
>SyntaxKind : SyntaxKind
operatorToken: Node;
>operatorToken : Node
>Node : Node
right: Expression;
>right : Expression

View file

@ -559,7 +559,7 @@ declare module "typescript" {
}
interface BinaryExpression extends Expression {
left: Expression;
operator: SyntaxKind;
operatorToken: Node;
right: Expression;
}
interface ConditionalExpression extends Expression {

View file

@ -1681,9 +1681,9 @@ declare module "typescript" {
>left : Expression
>Expression : Expression
operator: SyntaxKind;
>operator : SyntaxKind
>SyntaxKind : SyntaxKind
operatorToken: Node;
>operatorToken : Node
>Node : Node
right: Expression;
>right : Expression

View file

@ -596,7 +596,7 @@ declare module "typescript" {
}
interface BinaryExpression extends Expression {
left: Expression;
operator: SyntaxKind;
operatorToken: Node;
right: Expression;
}
interface ConditionalExpression extends Expression {

View file

@ -1854,9 +1854,9 @@ declare module "typescript" {
>left : Expression
>Expression : Expression
operator: SyntaxKind;
>operator : SyntaxKind
>SyntaxKind : SyntaxKind
operatorToken: Node;
>operatorToken : Node
>Node : Node
right: Expression;
>right : Expression

View file

@ -39,7 +39,7 @@ export function delint(sourceFile: ts.SourceFile) {
break;
case ts.SyntaxKind.BinaryExpression:
var op = (<ts.BinaryExpression>node).operator;
var op = (<ts.BinaryExpression>node).operatorToken.kind;
if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken) {
report(node, "Use '===' and '!=='.")

View file

@ -248,7 +248,7 @@ module ts {
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, index, 2, "+");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 21);
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 24);
});
it('Strict mode 1',() => {