Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12399,17 +12399,32 @@ func (c *Checker) checkNullishCoalesceOperands(left *ast.Node, right *ast.Node)
if ast.IsBinaryExpression(right) && ast.IsLogicalBinaryOperator(right.AsBinaryExpression().OperatorToken.Kind) {
c.grammarErrorOnNode(right, diagnostics.X_0_and_1_operations_cannot_be_mixed_without_parentheses, scanner.TokenToString(right.AsBinaryExpression().OperatorToken.Kind), scanner.TokenToString(ast.KindQuestionQuestionToken))
}
c.checkNullishCoalesceOperandLeft(left)
c.checkNullishCoalesceOperandRight(right)
}

func (c *Checker) checkNullishCoalesceOperandLeft(left *ast.Node) {
leftTarget := ast.SkipOuterExpressions(left, ast.OEKAll)
nullishSemantics := c.getSyntacticNullishnessSemantics(leftTarget)
if nullishSemantics != PredicateSemanticsSometimes {
if left.Parent.Parent.Kind == ast.KindBinaryExpression {
c.error(leftTarget, diagnostics.This_binary_expression_is_never_nullish_Are_you_missing_parentheses)
if nullishSemantics == PredicateSemanticsAlways {
c.error(leftTarget, diagnostics.This_expression_is_always_nullish)
} else {
if nullishSemantics == PredicateSemanticsAlways {
c.error(leftTarget, diagnostics.This_expression_is_always_nullish)
} else {
c.error(leftTarget, diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish)
}
c.error(leftTarget, diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish)
}
}
}

func (c *Checker) checkNullishCoalesceOperandRight(right *ast.Node) {
binaryExpression := right.Parent
if binaryExpression.Parent != nil && ast.IsBinaryExpression(binaryExpression.Parent) && binaryExpression.Parent.AsBinaryExpression().OperatorToken.Kind == ast.KindQuestionQuestionToken {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is retaining isNotWithinNullishCoalesceExpression too annoying?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not like super annoying, but it's a rather straightforward check and it was only used in this single place so I decided to inline it

rightTarget := ast.SkipOuterExpressions(right, ast.OEKAll)
nullishSemantics := c.getSyntacticNullishnessSemantics(rightTarget)
switch nullishSemantics {
case PredicateSemanticsAlways:
c.error(rightTarget, diagnostics.This_expression_is_always_nullish)
case PredicateSemanticsNever:
c.error(rightTarget, diagnostics.This_expression_is_never_nullish)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@ predicateSemantics.ts(28,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(29,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(30,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(31,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(32,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(33,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(34,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(32,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(33,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,22): error TS2871: This expression is always nullish.
predicateSemantics.ts(36,20): error TS2871: This expression is always nullish.
predicateSemantics.ts(37,20): error TS2871: This expression is always nullish.
predicateSemantics.ts(38,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(39,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(40,21): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(45,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(46,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(47,13): error TS2870: This binary expression is never nullish. Are you missing parentheses?
predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(40,29): error TS2871: This expression is always nullish.
predicateSemantics.ts(41,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(42,20): error TS2881: This expression is never nullish.
predicateSemantics.ts(43,21): error TS2881: This expression is never nullish.
predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,29): error TS2871: This expression is always nullish.
predicateSemantics.ts(46,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(46,21): error TS2881: This expression is never nullish.
predicateSemantics.ts(47,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(47,22): error TS2881: This expression is never nullish.
predicateSemantics.ts(50,8): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(51,11): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(52,8): error TS2872: This kind of expression is always truthy.
Expand All @@ -26,7 +38,7 @@ predicateSemantics.ts(89,1): error TS2869: Right operand of ?? is unreachable be
predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.


==== predicateSemantics.ts (26 errors) ====
==== predicateSemantics.ts (38 errors) ====
declare let opt: number | undefined;

// OK: One or other operand is possibly nullish
Expand Down Expand Up @@ -76,16 +88,24 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be
!!! error TS2872: This kind of expression is always truthy.
const p07 = null ?? null ?? null;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~~~~
!!! error TS2871: This expression is always nullish.
const p08 = null ?? opt ?? null;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
const p09 = null ?? (opt ? null : undefined) ?? null;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.

const p10 = opt ?? null ?? 1;
~~~~
!!! error TS2871: This expression is always nullish.
const p11 = opt ?? null ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
const p12 = opt ?? (null ?? 1);
~~~~
!!! error TS2871: This expression is always nullish.
Expand All @@ -94,20 +114,36 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be
!!! error TS2871: This expression is always nullish.
const p14 = opt ?? (null ?? null ?? null);
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~~~~
!!! error TS2871: This expression is always nullish.
const p15 = opt ?? (opt ? null : undefined) ?? null;
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p16 = opt ?? 1 ?? 2;
~
!!! error TS2881: This expression is never nullish.
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
~~~~~~~~~~~
!!! error TS2881: This expression is never nullish.

const p21 = null ?? null ?? null ?? null;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~~~~
!!! error TS2871: This expression is always nullish.
~~~~
!!! error TS2871: This expression is always nullish.
const p22 = null ?? 1 ?? 1;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~
!!! error TS2881: This expression is never nullish.
const p23 = null ?? (opt ? 1 : 2) ?? 1;
~~~~
!!! error TS2870: This binary expression is never nullish. Are you missing parentheses?
!!! error TS2871: This expression is always nullish.
~~~~~~~~~~~
!!! error TS2881: This expression is never nullish.

// Outer expression tests
while ({} as any) { }
Expand Down

This file was deleted.