Skip to content

Commit 6a4927c

Browse files
Provide unique nodes for void/typeof/delete expressions.
1 parent e37f4ce commit 6a4927c

7 files changed

Lines changed: 140 additions & 41 deletions

File tree

src/compiler/checker.ts

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4333,7 +4333,10 @@ module ts {
43334333
case SyntaxKind.NewExpression:
43344334
case SyntaxKind.TypeAssertion:
43354335
case SyntaxKind.ParenExpression:
4336-
case SyntaxKind.PrefixOperator:
4336+
case SyntaxKind.PrefixUnaryExpression:
4337+
case SyntaxKind.DeleteExpression:
4338+
case SyntaxKind.TypeOfExpression:
4339+
case SyntaxKind.VoidExpression:
43374340
case SyntaxKind.PostfixOperator:
43384341
case SyntaxKind.ConditionalExpression:
43394342
case SyntaxKind.Block:
@@ -4416,12 +4419,12 @@ module ts {
44164419
return type;
44174420

44184421
function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
4419-
var left = <UnaryExpression>expr.left;
4422+
var left = <TypeOfExpression>expr.left;
44204423
var right = <LiteralExpression>expr.right;
44214424
// Check that we have 'typeof <symbol>' on the left and string literal on the right
4422-
if (left.kind !== SyntaxKind.PrefixOperator || left.operator !== SyntaxKind.TypeOfKeyword ||
4423-
left.operand.kind !== SyntaxKind.Identifier || right.kind !== SyntaxKind.StringLiteral ||
4424-
getResolvedSymbol(<Identifier>left.operand) !== symbol) {
4425+
if (left.kind !== SyntaxKind.TypeOfExpression ||
4426+
left.expression.kind !== SyntaxKind.Identifier || right.kind !== SyntaxKind.StringLiteral ||
4427+
getResolvedSymbol(<Identifier>left.expression) !== symbol) {
44254428
return type;
44264429
}
44274430
var t = right.text;
@@ -4510,7 +4513,7 @@ module ts {
45104513
return narrowTypeByInstanceof(type, <BinaryExpression>expr, assumeTrue);
45114514
}
45124515
break;
4513-
case SyntaxKind.PrefixOperator:
4516+
case SyntaxKind.PrefixUnaryExpression:
45144517
if ((<UnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
45154518
return narrowType(type, (<UnaryExpression>expr).operand, !assumeTrue);
45164519
}
@@ -6211,6 +6214,21 @@ module ts {
62116214
return true;
62126215
}
62136216

6217+
function checkDeleteExpression(node: DeleteExpression): Type {
6218+
var operandType = checkExpression(node.expression);
6219+
return booleanType;
6220+
}
6221+
6222+
function checkTypeOfExpression(node: TypeOfExpression): Type {
6223+
var operandType = checkExpression(node.expression);
6224+
return stringType;
6225+
}
6226+
6227+
function checkVoidExpression(node: VoidExpression): Type {
6228+
var operandType = checkExpression(node.expression);
6229+
return undefinedType;
6230+
}
6231+
62146232
function checkPrefixExpression(node: UnaryExpression): Type {
62156233
var operandType = checkExpression(node.operand);
62166234
switch (node.operator) {
@@ -6219,12 +6237,7 @@ module ts {
62196237
case SyntaxKind.TildeToken:
62206238
return numberType;
62216239
case SyntaxKind.ExclamationToken:
6222-
case SyntaxKind.DeleteKeyword:
62236240
return booleanType;
6224-
case SyntaxKind.TypeOfKeyword:
6225-
return stringType;
6226-
case SyntaxKind.VoidKeyword:
6227-
return undefinedType;
62286241
case SyntaxKind.PlusPlusToken:
62296242
case SyntaxKind.MinusMinusToken:
62306243
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 {
65666579
case SyntaxKind.FunctionExpression:
65676580
case SyntaxKind.ArrowFunction:
65686581
return checkFunctionExpression(<FunctionExpression>node, contextualMapper);
6569-
case SyntaxKind.PrefixOperator:
6582+
case SyntaxKind.TypeOfExpression:
6583+
return checkTypeOfExpression(<TypeOfExpression>node);
6584+
case SyntaxKind.DeleteExpression:
6585+
return checkDeleteExpression(<DeleteExpression>node);
6586+
case SyntaxKind.VoidExpression:
6587+
return checkVoidExpression(<VoidExpression>node);
6588+
case SyntaxKind.PrefixUnaryExpression:
65706589
return checkPrefixExpression(<UnaryExpression>node);
65716590
case SyntaxKind.PostfixOperator:
65726591
return checkPostfixExpression(<UnaryExpression>node);
@@ -8077,7 +8096,7 @@ module ts {
80778096

80788097
function evalConstant(e: Node): number {
80798098
switch (e.kind) {
8080-
case SyntaxKind.PrefixOperator:
8099+
case SyntaxKind.PrefixUnaryExpression:
80818100
var value = evalConstant((<UnaryExpression>e).operand);
80828101
if (value === undefined) {
80838102
return undefined;
@@ -8478,7 +8497,10 @@ module ts {
84788497
case SyntaxKind.TaggedTemplateExpression:
84798498
case SyntaxKind.TypeAssertion:
84808499
case SyntaxKind.ParenExpression:
8481-
case SyntaxKind.PrefixOperator:
8500+
case SyntaxKind.TypeOfExpression:
8501+
case SyntaxKind.VoidExpression:
8502+
case SyntaxKind.DeleteExpression:
8503+
case SyntaxKind.PrefixUnaryExpression:
84828504
case SyntaxKind.PostfixOperator:
84838505
case SyntaxKind.BinaryExpression:
84848506
case SyntaxKind.ConditionalExpression:
@@ -8705,7 +8727,7 @@ module ts {
87058727
case SyntaxKind.BooleanKeyword:
87068728
return true;
87078729
case SyntaxKind.VoidKeyword:
8708-
return node.parent.kind !== SyntaxKind.PrefixOperator;
8730+
return node.parent.kind !== SyntaxKind.VoidExpression;
87098731
case SyntaxKind.StringLiteral:
87108732
// Specialized signatures can have string literals as their parameters' type names
87118733
return node.parent.kind === SyntaxKind.Parameter;

src/compiler/emitter.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,12 @@ module ts {
23392339
// (<any>typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
23402340
// new (<any>A()) should be emitted as new (A()) and not new A()
23412341
// (<any>function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
2342-
if (operand.kind !== SyntaxKind.PrefixOperator && operand.kind !== SyntaxKind.PostfixOperator && operand.kind !== SyntaxKind.NewExpression &&
2342+
if (operand.kind !== SyntaxKind.PrefixUnaryExpression &&
2343+
operand.kind !== SyntaxKind.VoidExpression &&
2344+
operand.kind !== SyntaxKind.TypeOfExpression &&
2345+
operand.kind !== SyntaxKind.DeleteExpression &&
2346+
operand.kind !== SyntaxKind.PostfixOperator &&
2347+
operand.kind !== SyntaxKind.NewExpression &&
23432348
!(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
23442349
!(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression)) {
23452350
emit(operand);
@@ -2351,8 +2356,26 @@ module ts {
23512356
write(")");
23522357
}
23532358

2359+
function emitDeleteExpression(node: DeleteExpression) {
2360+
write(tokenToString(SyntaxKind.DeleteKeyword));
2361+
write(" ");
2362+
emit(node.expression);
2363+
}
2364+
2365+
function emitVoidExpression(node: VoidExpression) {
2366+
write(tokenToString(SyntaxKind.VoidKeyword));
2367+
write(" ");
2368+
emit(node.expression);
2369+
}
2370+
2371+
function emitTypeOfExpression(node: TypeOfExpression) {
2372+
write(tokenToString(SyntaxKind.TypeOfKeyword));
2373+
write(" ");
2374+
emit(node.expression);
2375+
}
2376+
23542377
function emitUnaryExpression(node: UnaryExpression) {
2355-
if (node.kind === SyntaxKind.PrefixOperator) {
2378+
if (node.kind === SyntaxKind.PrefixUnaryExpression) {
23562379
write(tokenToString(node.operator));
23572380
}
23582381
// In some cases, we need to emit a space between the operator and the operand. One obvious case
@@ -2370,7 +2393,7 @@ module ts {
23702393
if (node.operator >= SyntaxKind.Identifier) {
23712394
write(" ");
23722395
}
2373-
else if (node.kind === SyntaxKind.PrefixOperator && node.operand.kind === SyntaxKind.PrefixOperator) {
2396+
else if (node.kind === SyntaxKind.PrefixUnaryExpression && node.operand.kind === SyntaxKind.PrefixUnaryExpression) {
23742397
var operand = <UnaryExpression>node.operand;
23752398
if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
23762399
write(" ");
@@ -3500,7 +3523,13 @@ module ts {
35003523
case SyntaxKind.FunctionExpression:
35013524
case SyntaxKind.ArrowFunction:
35023525
return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
3503-
case SyntaxKind.PrefixOperator:
3526+
case SyntaxKind.DeleteExpression:
3527+
return emitDeleteExpression(<DeleteExpression>node);
3528+
case SyntaxKind.TypeOfExpression:
3529+
return emitTypeOfExpression(<TypeOfExpression>node);
3530+
case SyntaxKind.VoidExpression:
3531+
return emitVoidExpression(<VoidExpression>node);
3532+
case SyntaxKind.PrefixUnaryExpression:
35043533
case SyntaxKind.PostfixOperator:
35053534
return emitUnaryExpression(<UnaryExpression>node);
35063535
case SyntaxKind.BinaryExpression:

src/compiler/parser.ts

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,13 @@ module ts {
278278
child((<TypeAssertion>node).operand);
279279
case SyntaxKind.ParenExpression:
280280
return child((<ParenExpression>node).expression);
281-
case SyntaxKind.PrefixOperator:
281+
case SyntaxKind.DeleteExpression:
282+
return child((<DeleteExpression>node).expression);
283+
case SyntaxKind.TypeOfExpression:
284+
return child((<TypeOfExpression>node).expression);
285+
case SyntaxKind.VoidExpression:
286+
return child((<VoidExpression>node).expression);
287+
case SyntaxKind.PrefixUnaryExpression:
282288
case SyntaxKind.PostfixOperator:
283289
return child((<UnaryExpression>node).operand);
284290
case SyntaxKind.BinaryExpression:
@@ -518,7 +524,10 @@ module ts {
518524
case SyntaxKind.ParenExpression:
519525
case SyntaxKind.FunctionExpression:
520526
case SyntaxKind.ArrowFunction:
521-
case SyntaxKind.PrefixOperator:
527+
case SyntaxKind.VoidExpression:
528+
case SyntaxKind.DeleteExpression:
529+
case SyntaxKind.TypeOfExpression:
530+
case SyntaxKind.PrefixUnaryExpression:
522531
case SyntaxKind.PostfixOperator:
523532
case SyntaxKind.BinaryExpression:
524533
case SyntaxKind.ConditionalExpression:
@@ -1659,7 +1668,7 @@ module ts {
16591668
// <T extends "">
16601669
//
16611670
// We do *not* want to consume the > as we're consuming the expression for "".
1662-
node.expression = parseUnaryExpression();
1671+
node.expression = parseUnaryExpressionOrHigher();
16631672
}
16641673
}
16651674

@@ -2532,7 +2541,7 @@ module ts {
25322541
}
25332542

25342543
function parseBinaryExpressionOrHigher(precedence: number): Expression {
2535-
var leftOperand = parseUnaryExpression();
2544+
var leftOperand = parseUnaryExpressionOrHigher();
25362545
return parseBinaryExpressionRest(precedence, leftOperand);
25372546
}
25382547

@@ -2611,21 +2620,33 @@ module ts {
26112620
return finishNode(node);
26122621
}
26132622

2614-
function parseUnaryExpression(): Expression {
2623+
function parseUnaryExpressionOrHigher(): Expression {
26152624
var pos = getNodePos();
26162625
switch (token) {
26172626
case SyntaxKind.PlusToken:
26182627
case SyntaxKind.MinusToken:
26192628
case SyntaxKind.TildeToken:
26202629
case SyntaxKind.ExclamationToken:
2621-
case SyntaxKind.DeleteKeyword:
2622-
case SyntaxKind.TypeOfKeyword:
2623-
case SyntaxKind.VoidKeyword:
26242630
case SyntaxKind.PlusPlusToken:
26252631
case SyntaxKind.MinusMinusToken:
26262632
var operator = token;
26272633
nextToken();
2628-
return makeUnaryExpression(SyntaxKind.PrefixOperator, pos, operator, parseUnaryExpression());
2634+
return makeUnaryExpression(SyntaxKind.PrefixUnaryExpression, pos, operator, parseUnaryExpressionOrHigher());
2635+
case SyntaxKind.DeleteKeyword:
2636+
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
2637+
nextToken();
2638+
node.expression = parseUnaryExpressionOrHigher();
2639+
return finishNode(node);
2640+
case SyntaxKind.TypeOfKeyword:
2641+
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
2642+
nextToken();
2643+
node.expression = parseUnaryExpressionOrHigher();
2644+
return finishNode(node);
2645+
case SyntaxKind.VoidKeyword:
2646+
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
2647+
nextToken();
2648+
node.expression = parseUnaryExpressionOrHigher();
2649+
return finishNode(node);
26292650
case SyntaxKind.LessThanToken:
26302651
return parseTypeAssertion();
26312652
}
@@ -2659,7 +2680,7 @@ module ts {
26592680
parseExpected(SyntaxKind.LessThanToken);
26602681
node.type = parseType();
26612682
parseExpected(SyntaxKind.GreaterThanToken);
2662-
node.operand = parseUnaryExpression();
2683+
node.operand = parseUnaryExpressionOrHigher();
26632684
return finishNode(node);
26642685
}
26652686

@@ -4073,6 +4094,7 @@ module ts {
40734094
case SyntaxKind.ClassDeclaration: return checkClassDeclaration(<ClassDeclaration>node);
40744095
case SyntaxKind.ComputedPropertyName: return checkComputedPropertyName(<ComputedPropertyName>node);
40754096
case SyntaxKind.Constructor: return checkConstructor(<ConstructorDeclaration>node);
4097+
case SyntaxKind.DeleteExpression: return checkDeleteExpression(<DeleteExpression> node);
40764098
case SyntaxKind.ExportAssignment: return checkExportAssignment(<ExportAssignment>node);
40774099
case SyntaxKind.ForInStatement: return checkForInStatement(<ForInStatement>node);
40784100
case SyntaxKind.ForStatement: return checkForStatement(<ForStatement>node);
@@ -4089,7 +4111,7 @@ module ts {
40894111
case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
40904112
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
40914113
case SyntaxKind.PostfixOperator: return checkPostfixOperator(<UnaryExpression>node);
4092-
case SyntaxKind.PrefixOperator: return checkPrefixOperator(<UnaryExpression>node);
4114+
case SyntaxKind.PrefixUnaryExpression: return checkPrefixOperator(<UnaryExpression>node);
40934115
case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
40944116
case SyntaxKind.PropertyAssignment: return checkPropertyAssignment(<PropertyDeclaration>node);
40954117
case SyntaxKind.ReturnStatement: return checkReturnStatement(<ReturnStatement>node);
@@ -4355,6 +4377,19 @@ module ts {
43554377
}
43564378
}
43574379

4380+
function checkDeleteExpression(node: DeleteExpression) {
4381+
if (node.parserContextFlags & ParserContextFlags.StrictMode) {
4382+
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
4383+
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
4384+
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
4385+
if (node.expression.kind === SyntaxKind.Identifier) {
4386+
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
4387+
// UnaryExpression is a direct reference to a variable, function argument, or function name
4388+
return grammarErrorOnNode(node.expression, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
4389+
}
4390+
}
4391+
}
4392+
43584393
function checkEnumDeclaration(enumDecl: EnumDeclaration): boolean {
43594394
var enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0;
43604395

@@ -4396,7 +4431,7 @@ module ts {
43964431
return /^[0-9]+([eE]\+?[0-9]+)?$/.test(literalExpression.text);
43974432
}
43984433

4399-
if (expression.kind === SyntaxKind.PrefixOperator) {
4434+
if (expression.kind === SyntaxKind.PrefixUnaryExpression) {
44004435
var unaryExpression = <UnaryExpression>expression;
44014436
if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) {
44024437
expression = unaryExpression.operand;
@@ -4872,11 +4907,6 @@ module ts {
48724907
if ((node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) && isEvalOrArgumentsIdentifier(node.operand)) {
48734908
return reportInvalidUseInStrictMode(<Identifier>node.operand);
48744909
}
4875-
else if (node.operator === SyntaxKind.DeleteKeyword && node.operand.kind === SyntaxKind.Identifier) {
4876-
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
4877-
// UnaryExpression is a direct reference to a variable, function argument, or function name
4878-
return grammarErrorOnNode(node.operand, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
4879-
}
48804910
}
48814911
}
48824912

src/compiler/types.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ module ts {
178178
ParenExpression,
179179
FunctionExpression,
180180
ArrowFunction,
181-
PrefixOperator,
181+
DeleteExpression,
182+
TypeOfExpression,
183+
VoidExpression,
184+
PrefixUnaryExpression,
182185
PostfixOperator,
183186
BinaryExpression,
184187
ConditionalExpression,
@@ -438,6 +441,18 @@ module ts {
438441
operator: SyntaxKind;
439442
operand: Expression;
440443
}
444+
445+
export interface DeleteExpression extends Expression {
446+
expression: Expression;
447+
}
448+
449+
export interface TypeOfExpression extends Expression {
450+
expression: Expression;
451+
}
452+
453+
export interface VoidExpression extends Expression {
454+
expression: Expression;
455+
}
441456

442457
export interface YieldExpression extends Expression {
443458
asteriskToken?: Node;

0 commit comments

Comments
 (0)