Skip to content

Commit f5a1144

Browse files
committed
Switch to a separate util
1 parent 06e7a27 commit f5a1144

File tree

2 files changed

+58
-33
lines changed

2 files changed

+58
-33
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ import {
552552
isImportOrExportSpecifier,
553553
isImportSpecifier,
554554
isImportTypeNode,
555+
isInCompoundLikeAssignment,
555556
isIndexedAccessTypeNode,
556557
isInExpressionContext,
557558
isInfinityOrNaNString,
@@ -26662,8 +26663,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2666226663
if (!isReachableFlowNode(flow)) {
2666326664
return unreachableNeverType;
2666426665
}
26665-
const assignmentKind = getAssignmentTargetKind(node);
26666-
if (assignmentKind === AssignmentKind.Compound) {
26666+
if (getAssignmentTargetKind(node) === AssignmentKind.Compound) {
2666726667
const flowType = getTypeAtFlowNode(flow.antecedent);
2666826668
return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
2666926669
}
@@ -26674,7 +26674,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2667426674
const assignedType = getWidenedLiteralType(getInitialOrAssignedType(flow));
2667526675
return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType;
2667626676
}
26677-
const t = assignmentKind === AssignmentKind.CompoundLike ? getBaseTypeOfLiteralType(declaredType) : declaredType;
26677+
const t = isInCompoundLikeAssignment(node) ? getBaseTypeOfLiteralType(declaredType) : declaredType;
2667826678
if (t.flags & TypeFlags.Union) {
2667926679
return getAssignmentReducedType(t as UnionType, getInitialOrAssignedType(flow));
2668026680
}
@@ -28037,10 +28037,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2803728037
// entities we simply return the declared type.
2803828038
if (localOrExportSymbol.flags & SymbolFlags.Variable) {
2803928039
if (assignmentKind === AssignmentKind.Definite) {
28040-
return type;
28041-
}
28042-
if (assignmentKind === AssignmentKind.CompoundLike) {
28043-
return getBaseTypeOfLiteralType(type);
28040+
return isInCompoundLikeAssignment(node) ? getBaseTypeOfLiteralType(type) : type;
2804428041
}
2804528042
}
2804628043
else if (isAlias) {
@@ -31576,7 +31573,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3157631573
}
3157731574
else {
3157831575
const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
31579-
if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite && assignmentKind !== AssignmentKind.CompoundLike) {
31576+
if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) {
3158031577
error(node, Diagnostics.Private_accessor_was_defined_without_a_getter);
3158131578
}
3158231579
}
@@ -31685,7 +31682,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3168531682
// assignment target, and the referenced property was declared as a variable, property,
3168631683
// accessor, or optional method.
3168731684
const assignmentKind = getAssignmentTargetKind(node);
31688-
if (assignmentKind === AssignmentKind.Definite || assignmentKind === AssignmentKind.CompoundLike) {
31685+
if (assignmentKind === AssignmentKind.Definite) {
3168931686
return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional));
3169031687
}
3169131688
if (prop &&

src/compiler/utilities.ts

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,6 @@ import {
152152
forEachChild,
153153
forEachChildRecursively,
154154
ForInOrOfStatement,
155-
ForInStatement,
156-
ForOfStatement,
157155
ForStatement,
158156
FunctionBody,
159157
FunctionDeclaration,
@@ -3417,9 +3415,9 @@ export function isInExpressionContext(node: Node): boolean {
34173415
forStatement.incrementor === node;
34183416
case SyntaxKind.ForInStatement:
34193417
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;
34233421
case SyntaxKind.TypeAssertionExpression:
34243422
case SyntaxKind.AsExpression:
34253423
return node === (parent as AssertionExpression).expression;
@@ -4464,27 +4462,31 @@ export function hasTypeArguments(node: Node): node is HasTypeArguments {
44644462

44654463
/** @internal */
44664464
export const enum AssignmentKind {
4467-
None, Definite, Compound, CompoundLike
4465+
None, Definite, Compound
44684466
}
44694467

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 {
44724475
let parent = node.parent;
44734476
while (true) {
44744477
switch (parent.kind) {
44754478
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;
44814482
case SyntaxKind.PrefixUnaryExpression:
44824483
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;
44854487
case SyntaxKind.ForInStatement:
44864488
case SyntaxKind.ForOfStatement:
4487-
return (parent as ForInOrOfStatement).initializer === node ? AssignmentKind.Definite : AssignmentKind.None;
4489+
return parent as ForInOrOfStatement;
44884490
case SyntaxKind.ParenthesizedExpression:
44894491
case SyntaxKind.ArrayLiteralExpression:
44904492
case SyntaxKind.SpreadElement:
@@ -4496,37 +4498,64 @@ export function getAssignmentTargetKind(node: Node): AssignmentKind {
44964498
break;
44974499
case SyntaxKind.ShorthandPropertyAssignment:
44984500
if ((parent as ShorthandPropertyAssignment).name !== node) {
4499-
return AssignmentKind.None;
4501+
return undefined;
45004502
}
45014503
node = parent.parent;
45024504
break;
45034505
case SyntaxKind.PropertyAssignment:
4504-
if ((parent as ShorthandPropertyAssignment).name === node) {
4505-
return AssignmentKind.None;
4506+
if ((parent as PropertyAssignment).name === node) {
4507+
return undefined;
45064508
}
45074509
node = parent.parent;
45084510
break;
45094511
default:
4510-
return AssignmentKind.None;
4512+
return undefined;
45114513
}
45124514
parent = node.parent;
45134515
}
45144516
}
45154517

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+
45164539
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
45174540
// assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
45184541
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'.
45194542
// (Note that `p` is not a target in the above examples, only `a`.)
45204543
/** @internal */
45214544
export function isAssignmentTarget(node: Node): boolean {
4522-
return getAssignmentTargetKind(node) !== AssignmentKind.None;
4545+
return !!getAssignmentTarget(node);
45234546
}
45244547

4525-
function isCompoundLikeAssignment(assignment: BinaryExpression): boolean {
4548+
function isCompoundLikeAssignment(assignment: AssignmentExpression<EqualsToken>): boolean {
45264549
const right = skipParentheses(assignment.right);
45274550
return right.kind === SyntaxKind.BinaryExpression && isAdditiveOperatorOrHigher((right as BinaryExpression).operatorToken.kind);
45284551
}
45294552

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+
45304559
/** @internal */
45314560
export type NodeWithPossibleHoistedDeclaration =
45324561
| Block
@@ -4539,8 +4568,7 @@ export type NodeWithPossibleHoistedDeclaration =
45394568
| DefaultClause
45404569
| LabeledStatement
45414570
| ForStatement
4542-
| ForInStatement
4543-
| ForOfStatement
4571+
| ForInOrOfStatement
45444572
| DoStatement
45454573
| WhileStatement
45464574
| TryStatement

0 commit comments

Comments
 (0)