Refactor logical assignment
This commit is contained in:
parent
cb2e71cdb9
commit
81ce254a73
13 changed files with 47 additions and 117 deletions
|
@ -1047,24 +1047,9 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLogicalAssignmentExpressioin(node: Node) {
|
function isLogicalAssignmentExpression(node: Node) {
|
||||||
while (true) {
|
node = skipParentheses(node);
|
||||||
if (isParenthesizedExpression(node)) {
|
return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind);
|
||||||
node = node.expression;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return isBinaryExpression(node) && isLogicalAssignmentOperator(node.operatorToken.kind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTopLevelLogicalAssignmentExpression(node: Node): boolean {
|
|
||||||
while (isParenthesizedExpression(node.parent)) {
|
|
||||||
node = node.parent;
|
|
||||||
}
|
|
||||||
return !isStatementCondition(node) &&
|
|
||||||
!isLogicalAssignmentExpressioin(node.parent) &&
|
|
||||||
!(isOptionalChain(node.parent) && node.parent.expression === node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTopLevelLogicalExpression(node: Node): boolean {
|
function isTopLevelLogicalExpression(node: Node): boolean {
|
||||||
|
@ -1073,6 +1058,7 @@ namespace ts {
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
}
|
}
|
||||||
return !isStatementCondition(node) &&
|
return !isStatementCondition(node) &&
|
||||||
|
!isLogicalAssignmentExpression(node.parent) &&
|
||||||
!isLogicalExpression(node.parent) &&
|
!isLogicalExpression(node.parent) &&
|
||||||
!(isOptionalChain(node.parent) && node.parent.expression === node);
|
!(isOptionalChain(node.parent) && node.parent.expression === node);
|
||||||
}
|
}
|
||||||
|
@ -1089,7 +1075,7 @@ namespace ts {
|
||||||
|
|
||||||
function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
||||||
doWithConditionalBranches(bind, node, trueTarget, falseTarget);
|
doWithConditionalBranches(bind, node, trueTarget, falseTarget);
|
||||||
if (!node || !isLogicalAssignmentExpressioin(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
|
if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
|
||||||
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
|
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
|
||||||
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
|
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
|
||||||
}
|
}
|
||||||
|
@ -1189,24 +1175,6 @@ namespace ts {
|
||||||
currentFlow = finishFlowLabel(postIfLabel);
|
currentFlow = finishFlowLabel(postIfLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindLogicalAssignmentExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
|
||||||
const preRightLabel = createBranchLabel();
|
|
||||||
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) {
|
|
||||||
bindCondition(node.left, preRightLabel, falseTarget);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bindCondition(node.left, trueTarget, preRightLabel);
|
|
||||||
}
|
|
||||||
currentFlow = finishFlowLabel(preRightLabel);
|
|
||||||
bind(node.operatorToken);
|
|
||||||
|
|
||||||
doWithConditionalBranches(bind, node.right, trueTarget, falseTarget);
|
|
||||||
bindAssignmentTargetFlow(node.left);
|
|
||||||
|
|
||||||
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
|
|
||||||
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void {
|
function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void {
|
||||||
bind(node.expression);
|
bind(node.expression);
|
||||||
if (node.kind === SyntaxKind.ReturnStatement) {
|
if (node.kind === SyntaxKind.ReturnStatement) {
|
||||||
|
@ -1448,9 +1416,9 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
||||||
const preRightLabel = createBranchLabel();
|
const preRightLabel = createBranchLabel();
|
||||||
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
|
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) {
|
||||||
bindCondition(node.left, preRightLabel, falseTarget);
|
bindCondition(node.left, preRightLabel, falseTarget);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1458,7 +1426,17 @@ namespace ts {
|
||||||
}
|
}
|
||||||
currentFlow = finishFlowLabel(preRightLabel);
|
currentFlow = finishFlowLabel(preRightLabel);
|
||||||
bind(node.operatorToken);
|
bind(node.operatorToken);
|
||||||
bindCondition(node.right, trueTarget, falseTarget);
|
|
||||||
|
if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) {
|
||||||
|
doWithConditionalBranches(bind, node.right, trueTarget, falseTarget);
|
||||||
|
bindAssignmentTargetFlow(node.left);
|
||||||
|
|
||||||
|
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
|
||||||
|
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bindCondition(node.right, trueTarget, falseTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) {
|
function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) {
|
||||||
|
@ -1544,25 +1522,15 @@ namespace ts {
|
||||||
// TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
|
// TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
|
||||||
// we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
|
// we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
|
||||||
// For now, though, since the common cases are chained `+`, leaving it recursive is fine
|
// For now, though, since the common cases are chained `+`, leaving it recursive is fine
|
||||||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
|
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken ||
|
||||||
|
isLogicalOrCoalescingAssignmentOperator(operator)) {
|
||||||
if (isTopLevelLogicalExpression(node)) {
|
if (isTopLevelLogicalExpression(node)) {
|
||||||
const postExpressionLabel = createBranchLabel();
|
const postExpressionLabel = createBranchLabel();
|
||||||
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
|
bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);
|
||||||
currentFlow = finishFlowLabel(postExpressionLabel);
|
currentFlow = finishFlowLabel(postExpressionLabel);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!);
|
bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!);
|
||||||
}
|
|
||||||
completeNode();
|
|
||||||
}
|
|
||||||
else if(isLogicalAssignmentOperator(operator)) {
|
|
||||||
if (isTopLevelLogicalAssignmentExpression(node)) {
|
|
||||||
const postExpressionLabel = createBranchLabel();
|
|
||||||
bindLogicalAssignmentExpression(node, postExpressionLabel, postExpressionLabel);
|
|
||||||
currentFlow = finishFlowLabel(postExpressionLabel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bindLogicalAssignmentExpression(node, currentTrueTarget!, currentFalseTarget!);
|
|
||||||
}
|
}
|
||||||
completeNode();
|
completeNode();
|
||||||
}
|
}
|
||||||
|
@ -3656,7 +3624,7 @@ namespace ts {
|
||||||
if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) {
|
if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) {
|
||||||
transformFlags |= TransformFlags.AssertES2020;
|
transformFlags |= TransformFlags.AssertES2020;
|
||||||
}
|
}
|
||||||
else if (isLogicalAssignmentOperator(operatorTokenKind)) {
|
else if (isLogicalOrCoalescingAssignmentOperator(operatorTokenKind)) {
|
||||||
transformFlags |= TransformFlags.AssertESNext;
|
transformFlags |= TransformFlags.AssertESNext;
|
||||||
}
|
}
|
||||||
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
|
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
|
||||||
|
|
|
@ -28596,7 +28596,7 @@ namespace ts {
|
||||||
getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) :
|
getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) :
|
||||||
leftType;
|
leftType;
|
||||||
if (operator === SyntaxKind.BarBarEqualsToken) {
|
if (operator === SyntaxKind.BarBarEqualsToken) {
|
||||||
checkAssignmentOperator(resultType);
|
checkAssignmentOperator(rightType);
|
||||||
}
|
}
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
@ -28606,7 +28606,7 @@ namespace ts {
|
||||||
getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) :
|
getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) :
|
||||||
leftType;
|
leftType;
|
||||||
if (operator === SyntaxKind.QuestionQuestionEqualsToken) {
|
if (operator === SyntaxKind.QuestionQuestionEqualsToken) {
|
||||||
checkAssignmentOperator(resultType);
|
checkAssignmentOperator(rightType);
|
||||||
}
|
}
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace ts {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case SyntaxKind.BinaryExpression:
|
case SyntaxKind.BinaryExpression:
|
||||||
const binaryExpression = <BinaryExpression>node;
|
const binaryExpression = <BinaryExpression>node;
|
||||||
if (isLogicalAssignmentOperator(binaryExpression.operatorToken.kind)) {
|
if (isLogicalOrCoalescingAssignmentOperator(binaryExpression.operatorToken.kind)) {
|
||||||
return transformLogicalAssignmentOperators(binaryExpression);
|
return transformLogicalAssignmentOperators(binaryExpression);
|
||||||
}
|
}
|
||||||
// falls through
|
// falls through
|
||||||
|
@ -29,7 +29,7 @@ namespace ts {
|
||||||
|
|
||||||
function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult<Node> {
|
function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult<Node> {
|
||||||
const operator = binaryExpression.operatorToken;
|
const operator = binaryExpression.operatorToken;
|
||||||
if (isCompoundAssignment(operator.kind) && isLogicalAssignmentOperator(operator.kind)) {
|
if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) {
|
||||||
const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind);
|
const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind);
|
||||||
const left = visitNode(binaryExpression.left, visitor, isExpression);
|
const left = visitNode(binaryExpression.left, visitor, isExpression);
|
||||||
const right = visitNode(binaryExpression.right, visitor, isExpression);
|
const right = visitNode(binaryExpression.right, visitor, isExpression);
|
||||||
|
|
|
@ -2594,7 +2594,7 @@ namespace ts {
|
||||||
switch (parent.kind) {
|
switch (parent.kind) {
|
||||||
case SyntaxKind.BinaryExpression:
|
case SyntaxKind.BinaryExpression:
|
||||||
const binaryOperator = (<BinaryExpression>parent).operatorToken.kind;
|
const binaryOperator = (<BinaryExpression>parent).operatorToken.kind;
|
||||||
return isAssignmentOperator(binaryOperator) && !isLogicalAssignmentOperator(binaryOperator) && (<BinaryExpression>parent).left === node ?
|
return isAssignmentOperator(binaryOperator) && !isLogicalOrCoalescingAssignmentOperator(binaryOperator) && (<BinaryExpression>parent).left === node ?
|
||||||
binaryOperator === SyntaxKind.EqualsToken ? AssignmentKind.Definite : AssignmentKind.Compound :
|
binaryOperator === SyntaxKind.EqualsToken ? AssignmentKind.Definite : AssignmentKind.Compound :
|
||||||
AssignmentKind.None;
|
AssignmentKind.None;
|
||||||
case SyntaxKind.PrefixUnaryExpression:
|
case SyntaxKind.PrefixUnaryExpression:
|
||||||
|
@ -3378,10 +3378,6 @@ namespace ts {
|
||||||
return 14;
|
return 14;
|
||||||
case SyntaxKind.AsteriskAsteriskToken:
|
case SyntaxKind.AsteriskAsteriskToken:
|
||||||
return 15;
|
return 15;
|
||||||
case SyntaxKind.BarBarEqualsToken:
|
|
||||||
case SyntaxKind.AmpersandAmpersandEqualsToken:
|
|
||||||
case SyntaxKind.QuestionQuestionEqualsToken:
|
|
||||||
return 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||||
|
@ -4454,7 +4450,7 @@ namespace ts {
|
||||||
|| token === SyntaxKind.ExclamationToken;
|
|| token === SyntaxKind.ExclamationToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLogicalAssignmentOperator(token: SyntaxKind): boolean {
|
export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): boolean {
|
||||||
return token === SyntaxKind.BarBarEqualsToken
|
return token === SyntaxKind.BarBarEqualsToken
|
||||||
|| token === SyntaxKind.AmpersandAmpersandEqualsToken
|
|| token === SyntaxKind.AmpersandAmpersandEqualsToken
|
||||||
|| token === SyntaxKind.QuestionQuestionEqualsToken;
|
|| token === SyntaxKind.QuestionQuestionEqualsToken;
|
||||||
|
|
|
@ -785,12 +785,6 @@ namespace ts.codefix {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SyntaxKind.BarBarEqualsToken:
|
|
||||||
case SyntaxKind.QuestionQuestionEqualsToken:
|
|
||||||
case SyntaxKind.AmpersandAmpersandEqualsToken:
|
|
||||||
// TODO: infer here
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.AmpersandAmpersandToken:
|
case SyntaxKind.AmpersandAmpersandToken:
|
||||||
case SyntaxKind.CommaToken:
|
case SyntaxKind.CommaToken:
|
||||||
case SyntaxKind.InstanceOfKeyword:
|
case SyntaxKind.InstanceOfKeyword:
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ====
|
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ====
|
||||||
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ||= results1 ||= []).push(100);
|
(results ||= results1 ||= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ??= results1 ??= []).push(100);
|
(results ??= results1 ??= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results &&= results1 &&= []).push(100);
|
(results &&= results1 &&= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
!!! error TS2532: Object is possibly 'undefined'.
|
!!! error TS2532: Object is possibly 'undefined'.
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
~~~
|
~~~
|
||||||
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
}
|
}
|
|
@ -14,12 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
//// [logicalAssignment7.js]
|
//// [logicalAssignment7.js]
|
||||||
"use strict";
|
"use strict";
|
||||||
function foo1(results, results1) {
|
function foo1(results, results1) {
|
||||||
(results || (results = results1) || (results || (results = results1) = [])).push(100);
|
(results || (results = results1 || (results1 = []))).push(100);
|
||||||
}
|
}
|
||||||
function foo2(results, results1) {
|
function foo2(results, results1) {
|
||||||
var _a;
|
(results !== null && results !== void 0 ? results : (results = results1 !== null && results1 !== void 0 ? results1 : (results1 = []))).push(100);
|
||||||
((_a = results !== null && results !== void 0 ? results : (results = results1)) !== null && _a !== void 0 ? _a : (results !== null && results !== void 0 ? results : (results = results1) = [])).push(100);
|
|
||||||
}
|
}
|
||||||
function foo3(results, results1) {
|
function foo3(results, results1) {
|
||||||
(results && (results = results1) && (results && (results = results1) = [])).push(100);
|
(results && (results = results1 && (results1 = []))).push(100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
||||||
>(results ||= results1 ||= []) : number[]
|
>(results ||= results1 ||= []) : number[]
|
||||||
>results ||= results1 ||= [] : number[]
|
>results ||= results1 ||= [] : number[]
|
||||||
>results ||= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ||= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
||||||
>(results ??= results1 ??= []) : number[]
|
>(results ??= results1 ??= []) : number[]
|
||||||
>results ??= results1 ??= [] : number[]
|
>results ??= results1 ??= [] : number[]
|
||||||
>results ??= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ??= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
||||||
>(results &&= results1 &&= []) : never[] | undefined
|
>(results &&= results1 &&= []) : never[] | undefined
|
||||||
>results &&= results1 &&= [] : never[] | undefined
|
>results &&= results1 &&= [] : never[] | undefined
|
||||||
>results &&= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 &&= [] : never[] | undefined
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: never[]) => number
|
>push : (...items: never[]) => number
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ====
|
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ====
|
||||||
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ||= results1 ||= []).push(100);
|
(results ||= results1 ||= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ??= results1 ??= []).push(100);
|
(results ??= results1 ??= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results &&= results1 &&= []).push(100);
|
(results &&= results1 &&= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
!!! error TS2532: Object is possibly 'undefined'.
|
!!! error TS2532: Object is possibly 'undefined'.
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
~~~
|
~~~
|
||||||
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
}
|
}
|
|
@ -14,11 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
//// [logicalAssignment7.js]
|
//// [logicalAssignment7.js]
|
||||||
"use strict";
|
"use strict";
|
||||||
function foo1(results, results1) {
|
function foo1(results, results1) {
|
||||||
(results || (results = results1) || (results || (results = results1) = [])).push(100);
|
(results || (results = results1 || (results1 = []))).push(100);
|
||||||
}
|
}
|
||||||
function foo2(results, results1) {
|
function foo2(results, results1) {
|
||||||
(results ?? (results = results1) ?? (results ?? (results = results1) = [])).push(100);
|
(results ?? (results = results1 ?? (results1 = []))).push(100);
|
||||||
}
|
}
|
||||||
function foo3(results, results1) {
|
function foo3(results, results1) {
|
||||||
(results && (results = results1) && (results && (results = results1) = [])).push(100);
|
(results && (results = results1 && (results1 = []))).push(100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
||||||
>(results ||= results1 ||= []) : number[]
|
>(results ||= results1 ||= []) : number[]
|
||||||
>results ||= results1 ||= [] : number[]
|
>results ||= results1 ||= [] : number[]
|
||||||
>results ||= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ||= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
||||||
>(results ??= results1 ??= []) : number[]
|
>(results ??= results1 ??= []) : number[]
|
||||||
>results ??= results1 ??= [] : number[]
|
>results ??= results1 ??= [] : number[]
|
||||||
>results ??= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ??= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
||||||
>(results &&= results1 &&= []) : never[] | undefined
|
>(results &&= results1 &&= []) : never[] | undefined
|
||||||
>results &&= results1 &&= [] : never[] | undefined
|
>results &&= results1 &&= [] : never[] | undefined
|
||||||
>results &&= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 &&= [] : never[] | undefined
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: never[]) => number
|
>push : (...items: never[]) => number
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'.
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
|
|
||||||
|
|
||||||
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ====
|
==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ====
|
||||||
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ||= results1 ||= []).push(100);
|
(results ||= results1 ||= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results ??= results1 ??= []).push(100);
|
(results ??= results1 ??= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
(results &&= results1 &&= []).push(100);
|
(results &&= results1 &&= []).push(100);
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
!!! error TS2532: Object is possibly 'undefined'.
|
!!! error TS2532: Object is possibly 'undefined'.
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
|
|
||||||
~~~
|
~~~
|
||||||
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'.
|
||||||
}
|
}
|
|
@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
>(results ||= results1 ||= []).push : (...items: number[]) => number
|
||||||
>(results ||= results1 ||= []) : number[]
|
>(results ||= results1 ||= []) : number[]
|
||||||
>results ||= results1 ||= [] : number[]
|
>results ||= results1 ||= [] : number[]
|
||||||
>results ||= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ||= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
>(results ??= results1 ??= []).push : (...items: number[]) => number
|
||||||
>(results ??= results1 ??= []) : number[]
|
>(results ??= results1 ??= []) : number[]
|
||||||
>results ??= results1 ??= [] : number[]
|
>results ??= results1 ??= [] : number[]
|
||||||
>results ??= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 ??= [] : number[]
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: number[]) => number
|
>push : (...items: number[]) => number
|
||||||
|
@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) {
|
||||||
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
>(results &&= results1 &&= []).push : (...items: never[]) => number
|
||||||
>(results &&= results1 &&= []) : never[] | undefined
|
>(results &&= results1 &&= []) : never[] | undefined
|
||||||
>results &&= results1 &&= [] : never[] | undefined
|
>results &&= results1 &&= [] : never[] | undefined
|
||||||
>results &&= results1 : number[] | undefined
|
|
||||||
>results : number[] | undefined
|
>results : number[] | undefined
|
||||||
|
>results1 &&= [] : never[] | undefined
|
||||||
>results1 : number[] | undefined
|
>results1 : number[] | undefined
|
||||||
>[] : never[]
|
>[] : never[]
|
||||||
>push : (...items: never[]) => number
|
>push : (...items: never[]) => number
|
||||||
|
|
Loading…
Reference in a new issue