mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Provide unique nodes for void/typeof/delete expressions.
This commit is contained in:
+37
-15
@@ -4333,7 +4333,10 @@ module ts {
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.TypeAssertion:
|
||||
case SyntaxKind.ParenExpression:
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.PostfixOperator:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.Block:
|
||||
@@ -4416,12 +4419,12 @@ module ts {
|
||||
return type;
|
||||
|
||||
function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
var left = <UnaryExpression>expr.left;
|
||||
var left = <TypeOfExpression>expr.left;
|
||||
var right = <LiteralExpression>expr.right;
|
||||
// Check that we have 'typeof <symbol>' on the left and string literal on the right
|
||||
if (left.kind !== SyntaxKind.PrefixOperator || left.operator !== SyntaxKind.TypeOfKeyword ||
|
||||
left.operand.kind !== SyntaxKind.Identifier || right.kind !== SyntaxKind.StringLiteral ||
|
||||
getResolvedSymbol(<Identifier>left.operand) !== symbol) {
|
||||
if (left.kind !== SyntaxKind.TypeOfExpression ||
|
||||
left.expression.kind !== SyntaxKind.Identifier || right.kind !== SyntaxKind.StringLiteral ||
|
||||
getResolvedSymbol(<Identifier>left.expression) !== symbol) {
|
||||
return type;
|
||||
}
|
||||
var t = right.text;
|
||||
@@ -4510,7 +4513,7 @@ module ts {
|
||||
return narrowTypeByInstanceof(type, <BinaryExpression>expr, assumeTrue);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
if ((<UnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
|
||||
return narrowType(type, (<UnaryExpression>expr).operand, !assumeTrue);
|
||||
}
|
||||
@@ -6211,6 +6214,21 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkDeleteExpression(node: DeleteExpression): Type {
|
||||
var operandType = checkExpression(node.expression);
|
||||
return booleanType;
|
||||
}
|
||||
|
||||
function checkTypeOfExpression(node: TypeOfExpression): Type {
|
||||
var operandType = checkExpression(node.expression);
|
||||
return stringType;
|
||||
}
|
||||
|
||||
function checkVoidExpression(node: VoidExpression): Type {
|
||||
var operandType = checkExpression(node.expression);
|
||||
return undefinedType;
|
||||
}
|
||||
|
||||
function checkPrefixExpression(node: UnaryExpression): Type {
|
||||
var operandType = checkExpression(node.operand);
|
||||
switch (node.operator) {
|
||||
@@ -6219,12 +6237,7 @@ module ts {
|
||||
case SyntaxKind.TildeToken:
|
||||
return numberType;
|
||||
case SyntaxKind.ExclamationToken:
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
return booleanType;
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
return stringType;
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return undefinedType;
|
||||
case SyntaxKind.PlusPlusToken:
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
var ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
|
||||
@@ -6566,7 +6579,13 @@ module ts {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return checkFunctionExpression(<FunctionExpression>node, contextualMapper);
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
return checkTypeOfExpression(<TypeOfExpression>node);
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return checkDeleteExpression(<DeleteExpression>node);
|
||||
case SyntaxKind.VoidExpression:
|
||||
return checkVoidExpression(<VoidExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return checkPrefixExpression(<UnaryExpression>node);
|
||||
case SyntaxKind.PostfixOperator:
|
||||
return checkPostfixExpression(<UnaryExpression>node);
|
||||
@@ -8077,7 +8096,7 @@ module ts {
|
||||
|
||||
function evalConstant(e: Node): number {
|
||||
switch (e.kind) {
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
var value = evalConstant((<UnaryExpression>e).operand);
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
@@ -8478,7 +8497,10 @@ module ts {
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.TypeAssertion:
|
||||
case SyntaxKind.ParenExpression:
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixOperator:
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
@@ -8705,7 +8727,7 @@ module ts {
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
return true;
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return node.parent.kind !== SyntaxKind.PrefixOperator;
|
||||
return node.parent.kind !== SyntaxKind.VoidExpression;
|
||||
case SyntaxKind.StringLiteral:
|
||||
// Specialized signatures can have string literals as their parameters' type names
|
||||
return node.parent.kind === SyntaxKind.Parameter;
|
||||
|
||||
+33
-4
@@ -2339,7 +2339,12 @@ module ts {
|
||||
// (<any>typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
|
||||
// new (<any>A()) should be emitted as new (A()) and not new A()
|
||||
// (<any>function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
|
||||
if (operand.kind !== SyntaxKind.PrefixOperator && operand.kind !== SyntaxKind.PostfixOperator && operand.kind !== SyntaxKind.NewExpression &&
|
||||
if (operand.kind !== SyntaxKind.PrefixUnaryExpression &&
|
||||
operand.kind !== SyntaxKind.VoidExpression &&
|
||||
operand.kind !== SyntaxKind.TypeOfExpression &&
|
||||
operand.kind !== SyntaxKind.DeleteExpression &&
|
||||
operand.kind !== SyntaxKind.PostfixOperator &&
|
||||
operand.kind !== SyntaxKind.NewExpression &&
|
||||
!(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
|
||||
!(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression)) {
|
||||
emit(operand);
|
||||
@@ -2351,8 +2356,26 @@ module ts {
|
||||
write(")");
|
||||
}
|
||||
|
||||
function emitDeleteExpression(node: DeleteExpression) {
|
||||
write(tokenToString(SyntaxKind.DeleteKeyword));
|
||||
write(" ");
|
||||
emit(node.expression);
|
||||
}
|
||||
|
||||
function emitVoidExpression(node: VoidExpression) {
|
||||
write(tokenToString(SyntaxKind.VoidKeyword));
|
||||
write(" ");
|
||||
emit(node.expression);
|
||||
}
|
||||
|
||||
function emitTypeOfExpression(node: TypeOfExpression) {
|
||||
write(tokenToString(SyntaxKind.TypeOfKeyword));
|
||||
write(" ");
|
||||
emit(node.expression);
|
||||
}
|
||||
|
||||
function emitUnaryExpression(node: UnaryExpression) {
|
||||
if (node.kind === SyntaxKind.PrefixOperator) {
|
||||
if (node.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
write(tokenToString(node.operator));
|
||||
}
|
||||
// In some cases, we need to emit a space between the operator and the operand. One obvious case
|
||||
@@ -2370,7 +2393,7 @@ module ts {
|
||||
if (node.operator >= SyntaxKind.Identifier) {
|
||||
write(" ");
|
||||
}
|
||||
else if (node.kind === SyntaxKind.PrefixOperator && node.operand.kind === SyntaxKind.PrefixOperator) {
|
||||
else if (node.kind === SyntaxKind.PrefixUnaryExpression && node.operand.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
var operand = <UnaryExpression>node.operand;
|
||||
if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
|
||||
write(" ");
|
||||
@@ -3500,7 +3523,13 @@ module ts {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return emitDeleteExpression(<DeleteExpression>node);
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
return emitTypeOfExpression(<TypeOfExpression>node);
|
||||
case SyntaxKind.VoidExpression:
|
||||
return emitVoidExpression(<VoidExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixOperator:
|
||||
return emitUnaryExpression(<UnaryExpression>node);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
|
||||
+47
-17
@@ -278,7 +278,13 @@ module ts {
|
||||
child((<TypeAssertion>node).operand);
|
||||
case SyntaxKind.ParenExpression:
|
||||
return child((<ParenExpression>node).expression);
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return child((<DeleteExpression>node).expression);
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
return child((<TypeOfExpression>node).expression);
|
||||
case SyntaxKind.VoidExpression:
|
||||
return child((<VoidExpression>node).expression);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixOperator:
|
||||
return child((<UnaryExpression>node).operand);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
@@ -518,7 +524,10 @@ module ts {
|
||||
case SyntaxKind.ParenExpression:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.PrefixOperator:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixOperator:
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
@@ -1659,7 +1668,7 @@ module ts {
|
||||
// <T extends "">
|
||||
//
|
||||
// We do *not* want to consume the > as we're consuming the expression for "".
|
||||
node.expression = parseUnaryExpression();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2532,7 +2541,7 @@ module ts {
|
||||
}
|
||||
|
||||
function parseBinaryExpressionOrHigher(precedence: number): Expression {
|
||||
var leftOperand = parseUnaryExpression();
|
||||
var leftOperand = parseUnaryExpressionOrHigher();
|
||||
return parseBinaryExpressionRest(precedence, leftOperand);
|
||||
}
|
||||
|
||||
@@ -2611,21 +2620,33 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseUnaryExpression(): Expression {
|
||||
function parseUnaryExpressionOrHigher(): Expression {
|
||||
var pos = getNodePos();
|
||||
switch (token) {
|
||||
case SyntaxKind.PlusToken:
|
||||
case SyntaxKind.MinusToken:
|
||||
case SyntaxKind.TildeToken:
|
||||
case SyntaxKind.ExclamationToken:
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.PlusPlusToken:
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
var operator = token;
|
||||
nextToken();
|
||||
return makeUnaryExpression(SyntaxKind.PrefixOperator, pos, operator, parseUnaryExpression());
|
||||
return makeUnaryExpression(SyntaxKind.PrefixUnaryExpression, pos, operator, parseUnaryExpressionOrHigher());
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
case SyntaxKind.VoidKeyword:
|
||||
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
case SyntaxKind.LessThanToken:
|
||||
return parseTypeAssertion();
|
||||
}
|
||||
@@ -2659,7 +2680,7 @@ module ts {
|
||||
parseExpected(SyntaxKind.LessThanToken);
|
||||
node.type = parseType();
|
||||
parseExpected(SyntaxKind.GreaterThanToken);
|
||||
node.operand = parseUnaryExpression();
|
||||
node.operand = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -4073,6 +4094,7 @@ module ts {
|
||||
case SyntaxKind.ClassDeclaration: return checkClassDeclaration(<ClassDeclaration>node);
|
||||
case SyntaxKind.ComputedPropertyName: return checkComputedPropertyName(<ComputedPropertyName>node);
|
||||
case SyntaxKind.Constructor: return checkConstructor(<ConstructorDeclaration>node);
|
||||
case SyntaxKind.DeleteExpression: return checkDeleteExpression(<DeleteExpression> node);
|
||||
case SyntaxKind.ExportAssignment: return checkExportAssignment(<ExportAssignment>node);
|
||||
case SyntaxKind.ForInStatement: return checkForInStatement(<ForInStatement>node);
|
||||
case SyntaxKind.ForStatement: return checkForStatement(<ForStatement>node);
|
||||
@@ -4089,7 +4111,7 @@ module ts {
|
||||
case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
|
||||
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.PostfixOperator: return checkPostfixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.PrefixOperator: return checkPrefixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression: return checkPrefixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
|
||||
case SyntaxKind.PropertyAssignment: return checkPropertyAssignment(<PropertyDeclaration>node);
|
||||
case SyntaxKind.ReturnStatement: return checkReturnStatement(<ReturnStatement>node);
|
||||
@@ -4355,6 +4377,19 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkDeleteExpression(node: DeleteExpression) {
|
||||
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
|
||||
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
|
||||
if (node.expression.kind === SyntaxKind.Identifier) {
|
||||
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
|
||||
// UnaryExpression is a direct reference to a variable, function argument, or function name
|
||||
return grammarErrorOnNode(node.expression, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkEnumDeclaration(enumDecl: EnumDeclaration): boolean {
|
||||
var enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0;
|
||||
|
||||
@@ -4396,7 +4431,7 @@ module ts {
|
||||
return /^[0-9]+([eE]\+?[0-9]+)?$/.test(literalExpression.text);
|
||||
}
|
||||
|
||||
if (expression.kind === SyntaxKind.PrefixOperator) {
|
||||
if (expression.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
var unaryExpression = <UnaryExpression>expression;
|
||||
if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) {
|
||||
expression = unaryExpression.operand;
|
||||
@@ -4872,11 +4907,6 @@ module ts {
|
||||
if ((node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(node.operand)) {
|
||||
return reportInvalidUseInStrictMode(<Identifier>node.operand);
|
||||
}
|
||||
else if (node.operator === SyntaxKind.DeleteKeyword && node.operand.kind === SyntaxKind.Identifier) {
|
||||
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
|
||||
// UnaryExpression is a direct reference to a variable, function argument, or function name
|
||||
return grammarErrorOnNode(node.operand, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -178,7 +178,10 @@ module ts {
|
||||
ParenExpression,
|
||||
FunctionExpression,
|
||||
ArrowFunction,
|
||||
PrefixOperator,
|
||||
DeleteExpression,
|
||||
TypeOfExpression,
|
||||
VoidExpression,
|
||||
PrefixUnaryExpression,
|
||||
PostfixOperator,
|
||||
BinaryExpression,
|
||||
ConditionalExpression,
|
||||
@@ -438,6 +441,18 @@ module ts {
|
||||
operator: SyntaxKind;
|
||||
operand: Expression;
|
||||
}
|
||||
|
||||
export interface DeleteExpression extends Expression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface TypeOfExpression extends Expression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface VoidExpression extends Expression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface YieldExpression extends Expression {
|
||||
asteriskToken?: Node;
|
||||
|
||||
@@ -39,7 +39,10 @@ class TypeWriterWalker {
|
||||
case ts.SyntaxKind.ParenExpression:
|
||||
case ts.SyntaxKind.FunctionExpression:
|
||||
case ts.SyntaxKind.ArrowFunction:
|
||||
case ts.SyntaxKind.PrefixOperator:
|
||||
case ts.SyntaxKind.TypeOfExpression:
|
||||
case ts.SyntaxKind.VoidExpression:
|
||||
case ts.SyntaxKind.DeleteExpression:
|
||||
case ts.SyntaxKind.PrefixUnaryExpression:
|
||||
case ts.SyntaxKind.PostfixOperator:
|
||||
case ts.SyntaxKind.BinaryExpression:
|
||||
case ts.SyntaxKind.ConditionalExpression:
|
||||
|
||||
@@ -673,7 +673,7 @@ module ts.formatting {
|
||||
}
|
||||
|
||||
static IsVoidOpContext(context: FormattingContext): boolean {
|
||||
return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.PrefixOperator;
|
||||
return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4574,7 +4574,7 @@ module ts {
|
||||
|
||||
var parent = node.parent;
|
||||
if (parent) {
|
||||
if (parent.kind === SyntaxKind.PostfixOperator || parent.kind === SyntaxKind.PrefixOperator) {
|
||||
if (parent.kind === SyntaxKind.PostfixOperator || parent.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
return true;
|
||||
}
|
||||
else if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).left === node) {
|
||||
@@ -5063,7 +5063,7 @@ module ts {
|
||||
// the '=' in a variable declaration is special cased here.
|
||||
if (token.parent.kind === SyntaxKind.BinaryExpression ||
|
||||
token.parent.kind === SyntaxKind.VariableDeclaration ||
|
||||
token.parent.kind === SyntaxKind.PrefixOperator ||
|
||||
token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
|
||||
token.parent.kind === SyntaxKind.PostfixOperator ||
|
||||
token.parent.kind === SyntaxKind.ConditionalExpression) {
|
||||
return ClassificationTypeNames.operator;
|
||||
|
||||
Reference in New Issue
Block a user