@@ -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 {
4472
- let parent = node . parent ;
4473
- while ( true ) {
4468
+ type AssignmentTarget =
4469
+ | BinaryExpression
4470
+ | PrefixUnaryExpression
4471
+ | PostfixUnaryExpression
4472
+ | ForInOrOfStatement ;
4473
+
4474
+ function getAssignmentTarget ( node : Node ) : AssignmentTarget | undefined {
4475
+ let parent : Node ;
4476
+ while ( parent = node . parent ) {
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,20 +4498,39 @@ 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
- default :
4510
- return AssignmentKind . None ;
4511
4511
}
4512
- parent = node . parent ;
4512
+ }
4513
+ return undefined ;
4514
+ }
4515
+
4516
+ /** @internal */
4517
+ export function getAssignmentTargetKind ( node : Node ) : AssignmentKind {
4518
+ const target = getAssignmentTarget ( node ) ;
4519
+ if ( ! target ) {
4520
+ return AssignmentKind . None ;
4521
+ }
4522
+ switch ( target . kind ) {
4523
+ case SyntaxKind . BinaryExpression :
4524
+ const binaryOperator = target . operatorToken . kind ;
4525
+ return binaryOperator === SyntaxKind . EqualsToken || isLogicalOrCoalescingAssignmentOperator ( binaryOperator ) ?
4526
+ AssignmentKind . Definite :
4527
+ AssignmentKind . Compound ;
4528
+ case SyntaxKind . PrefixUnaryExpression :
4529
+ case SyntaxKind . PostfixUnaryExpression :
4530
+ return AssignmentKind . Compound ;
4531
+ case SyntaxKind . ForInStatement :
4532
+ case SyntaxKind . ForOfStatement :
4533
+ return AssignmentKind . Definite ;
4513
4534
}
4514
4535
}
4515
4536
@@ -4519,14 +4540,20 @@ export function getAssignmentTargetKind(node: Node): AssignmentKind {
4519
4540
// (Note that `p` is not a target in the above examples, only `a`.)
4520
4541
/** @internal */
4521
4542
export function isAssignmentTarget ( node : Node ) : boolean {
4522
- return getAssignmentTargetKind ( node ) !== AssignmentKind . None ;
4543
+ return ! ! getAssignmentTarget ( node ) ;
4523
4544
}
4524
4545
4525
- function isCompoundLikeAssignment ( assignment : BinaryExpression ) : boolean {
4546
+ function isCompoundLikeAssignment ( assignment : AssignmentExpression < EqualsToken > ) : boolean {
4526
4547
const right = skipParentheses ( assignment . right ) ;
4527
4548
return right . kind === SyntaxKind . BinaryExpression && isAdditiveOperatorOrHigher ( ( right as BinaryExpression ) . operatorToken . kind ) ;
4528
4549
}
4529
4550
4551
+ /** @internal */
4552
+ export function isInCompoundLikeAssignment ( node : Node ) : boolean {
4553
+ const target = getAssignmentTarget ( node ) ;
4554
+ return ! ! target && isAssignmentExpression ( target , /*excludeCompoundAssignment*/ true ) && isCompoundLikeAssignment ( target ) ;
4555
+ }
4556
+
4530
4557
/** @internal */
4531
4558
export type NodeWithPossibleHoistedDeclaration =
4532
4559
| Block
@@ -4539,8 +4566,7 @@ export type NodeWithPossibleHoistedDeclaration =
4539
4566
| DefaultClause
4540
4567
| LabeledStatement
4541
4568
| ForStatement
4542
- | ForInStatement
4543
- | ForOfStatement
4569
+ | ForInOrOfStatement
4544
4570
| DoStatement
4545
4571
| WhileStatement
4546
4572
| TryStatement
0 commit comments