@@ -152,8 +152,6 @@ import {
152
152
forEachChild ,
153
153
forEachChildRecursively ,
154
154
ForInOrOfStatement ,
155
- ForInStatement ,
156
- ForOfStatement ,
157
155
ForStatement ,
158
156
FunctionBody ,
159
157
FunctionDeclaration ,
@@ -3417,9 +3415,9 @@ export function isInExpressionContext(node: Node): boolean {
3417
3415
forStatement . incrementor === node ;
3418
3416
case SyntaxKind . ForInStatement :
3419
3417
case SyntaxKind . ForOfStatement :
3420
- const forInStatement = parent as ForInStatement | ForOfStatement ;
3421
- return ( forInStatement . initializer === node && forInStatement . initializer . kind !== SyntaxKind . VariableDeclarationList ) ||
3422
- forInStatement . expression === node ;
3418
+ const forInOrOfStatement = parent as ForInOrOfStatement ;
3419
+ return ( forInOrOfStatement . initializer === node && forInOrOfStatement . initializer . kind !== SyntaxKind . VariableDeclarationList ) ||
3420
+ forInOrOfStatement . expression === node ;
3423
3421
case SyntaxKind . TypeAssertionExpression :
3424
3422
case SyntaxKind . AsExpression :
3425
3423
return node === ( parent as AssertionExpression ) . expression ;
@@ -4464,27 +4462,31 @@ export function hasTypeArguments(node: Node): node is HasTypeArguments {
4464
4462
4465
4463
/** @internal */
4466
4464
export const enum AssignmentKind {
4467
- None , Definite , Compound , CompoundLike
4465
+ None , Definite , Compound
4468
4466
}
4469
4467
4470
- /** @internal */
4471
- export function getAssignmentTargetKind ( node : Node ) : AssignmentKind {
4468
+ type AssignmentTarget =
4469
+ | BinaryExpression
4470
+ | PrefixUnaryExpression
4471
+ | PostfixUnaryExpression
4472
+ | ForInOrOfStatement ;
4473
+
4474
+ function getAssignmentTarget ( node : Node ) : AssignmentTarget | undefined {
4472
4475
let parent = node . parent ;
4473
4476
while ( true ) {
4474
4477
switch ( parent . kind ) {
4475
4478
case SyntaxKind . BinaryExpression :
4476
- const binaryOperator = ( parent as BinaryExpression ) . operatorToken . kind ;
4477
- return isAssignmentOperator ( binaryOperator ) && ( parent as BinaryExpression ) . left === node ?
4478
- binaryOperator === SyntaxKind . EqualsToken ? ( isCompoundLikeAssignment ( parent as BinaryExpression ) ? AssignmentKind . CompoundLike : AssignmentKind . Definite ) :
4479
- isLogicalOrCoalescingAssignmentOperator ( binaryOperator ) ? AssignmentKind . Definite : AssignmentKind . Compound :
4480
- AssignmentKind . None ;
4479
+ const binaryExpression = parent as BinaryExpression ;
4480
+ const binaryOperator = binaryExpression . operatorToken . kind ;
4481
+ return isAssignmentOperator ( binaryOperator ) && binaryExpression . left === node ? binaryExpression : undefined ;
4481
4482
case SyntaxKind . PrefixUnaryExpression :
4482
4483
case SyntaxKind . PostfixUnaryExpression :
4483
- const unaryOperator = ( parent as PrefixUnaryExpression | PostfixUnaryExpression ) . operator ;
4484
- return unaryOperator === SyntaxKind . PlusPlusToken || unaryOperator === SyntaxKind . MinusMinusToken ? AssignmentKind . Compound : AssignmentKind . None ;
4484
+ const unaryExpression = ( parent as PrefixUnaryExpression | PostfixUnaryExpression ) ;
4485
+ const unaryOperator = unaryExpression . operator ;
4486
+ return unaryOperator === SyntaxKind . PlusPlusToken || unaryOperator === SyntaxKind . MinusMinusToken ? unaryExpression : undefined ;
4485
4487
case SyntaxKind . ForInStatement :
4486
4488
case SyntaxKind . ForOfStatement :
4487
- return ( parent as ForInOrOfStatement ) . initializer === node ? AssignmentKind . Definite : AssignmentKind . None ;
4489
+ return parent as ForInOrOfStatement ;
4488
4490
case SyntaxKind . ParenthesizedExpression :
4489
4491
case SyntaxKind . ArrayLiteralExpression :
4490
4492
case SyntaxKind . SpreadElement :
@@ -4496,37 +4498,64 @@ export function getAssignmentTargetKind(node: Node): AssignmentKind {
4496
4498
break ;
4497
4499
case SyntaxKind . ShorthandPropertyAssignment :
4498
4500
if ( ( parent as ShorthandPropertyAssignment ) . name !== node ) {
4499
- return AssignmentKind . None ;
4501
+ return undefined ;
4500
4502
}
4501
4503
node = parent . parent ;
4502
4504
break ;
4503
4505
case SyntaxKind . PropertyAssignment :
4504
- if ( ( parent as ShorthandPropertyAssignment ) . name === node ) {
4505
- return AssignmentKind . None ;
4506
+ if ( ( parent as PropertyAssignment ) . name === node ) {
4507
+ return undefined ;
4506
4508
}
4507
4509
node = parent . parent ;
4508
4510
break ;
4509
4511
default :
4510
- return AssignmentKind . None ;
4512
+ return undefined ;
4511
4513
}
4512
4514
parent = node . parent ;
4513
4515
}
4514
4516
}
4515
4517
4518
+ /** @internal */
4519
+ export function getAssignmentTargetKind ( node : Node ) : AssignmentKind {
4520
+ const target = getAssignmentTarget ( node ) ;
4521
+ if ( ! target ) {
4522
+ return AssignmentKind . None ;
4523
+ }
4524
+ switch ( target . kind ) {
4525
+ case SyntaxKind . BinaryExpression :
4526
+ const binaryOperator = target . operatorToken . kind ;
4527
+ return binaryOperator === SyntaxKind . EqualsToken || isLogicalOrCoalescingAssignmentOperator ( binaryOperator ) ?
4528
+ AssignmentKind . Definite :
4529
+ AssignmentKind . Compound ;
4530
+ case SyntaxKind . PrefixUnaryExpression :
4531
+ case SyntaxKind . PostfixUnaryExpression :
4532
+ return AssignmentKind . Compound ;
4533
+ case SyntaxKind . ForInStatement :
4534
+ case SyntaxKind . ForOfStatement :
4535
+ return AssignmentKind . Definite ;
4536
+ }
4537
+ }
4538
+
4516
4539
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
4517
4540
// assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
4518
4541
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'.
4519
4542
// (Note that `p` is not a target in the above examples, only `a`.)
4520
4543
/** @internal */
4521
4544
export function isAssignmentTarget ( node : Node ) : boolean {
4522
- return getAssignmentTargetKind ( node ) !== AssignmentKind . None ;
4545
+ return ! ! getAssignmentTarget ( node ) ;
4523
4546
}
4524
4547
4525
- function isCompoundLikeAssignment ( assignment : BinaryExpression ) : boolean {
4548
+ function isCompoundLikeAssignment ( assignment : AssignmentExpression < EqualsToken > ) : boolean {
4526
4549
const right = skipParentheses ( assignment . right ) ;
4527
4550
return right . kind === SyntaxKind . BinaryExpression && isAdditiveOperatorOrHigher ( ( right as BinaryExpression ) . operatorToken . kind ) ;
4528
4551
}
4529
4552
4553
+ /** @internal */
4554
+ export function isInCompoundLikeAssignment ( node : Node ) : boolean {
4555
+ const target = getAssignmentTarget ( node ) ;
4556
+ return ! ! target && isAssignmentExpression ( target , /*excludeCompoundAssignment*/ true ) && isCompoundLikeAssignment ( target ) ;
4557
+ }
4558
+
4530
4559
/** @internal */
4531
4560
export type NodeWithPossibleHoistedDeclaration =
4532
4561
| Block
@@ -4539,8 +4568,7 @@ export type NodeWithPossibleHoistedDeclaration =
4539
4568
| DefaultClause
4540
4569
| LabeledStatement
4541
4570
| ForStatement
4542
- | ForInStatement
4543
- | ForOfStatement
4571
+ | ForInOrOfStatement
4544
4572
| DoStatement
4545
4573
| WhileStatement
4546
4574
| TryStatement
0 commit comments