mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 13:08:01 +00:00
[cfe] Pass on guard in if-case statement
Change-Id: Ic7c201bd90b2cf67a2b7526fc4ac035b21f34cc6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265720 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
7e87efd2e7
commit
142bf69440
|
@ -2317,7 +2317,7 @@ class BodyBuilder extends StackListenerImpl
|
|||
libraryFeatures.patterns, case_.charOffset, case_.charCount);
|
||||
Matcher matcher = toMatcher(pop());
|
||||
Expression expression = popForValue();
|
||||
push(new Condition(expression, matcher));
|
||||
push(new Condition(expression, matcher, guard));
|
||||
} else {
|
||||
assert(checkState(token, [
|
||||
unionOfKinds([
|
||||
|
@ -3495,11 +3495,12 @@ class BodyBuilder extends StackListenerImpl
|
|||
Statement thenPart = popStatement();
|
||||
Condition condition = pop() as Condition;
|
||||
Matcher? matcher = condition.matcher;
|
||||
Expression? guard = condition.guard;
|
||||
Expression expression = condition.expression;
|
||||
Statement node;
|
||||
if (matcher != null) {
|
||||
node = new IfCaseStatement(
|
||||
expression, matcher, thenPart, elsePart, ifToken.charOffset);
|
||||
expression, matcher, guard, thenPart, elsePart, ifToken.charOffset);
|
||||
} else {
|
||||
node = forest.createIfStatement(
|
||||
offsetForToken(ifToken), expression, thenPart, elsePart);
|
||||
|
@ -8809,10 +8810,14 @@ class _FindChildVisitor extends Visitor<void> with VisitorVoidMixin {
|
|||
class Condition {
|
||||
final Expression expression;
|
||||
final Matcher? matcher;
|
||||
final Expression? guard;
|
||||
|
||||
Condition(this.expression, [this.matcher]);
|
||||
Condition(this.expression, [this.matcher, this.guard])
|
||||
: assert(guard == null || matcher != null,
|
||||
"Unexpected guard without matcher.");
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'Condition($expression${matcher != null ? ',$matcher' : ''})';
|
||||
String toString() => 'Condition($expression'
|
||||
'${matcher != null ? ',$matcher' : ''}'
|
||||
'${guard != null ? ',$guard' : ''})';
|
||||
}
|
||||
|
|
|
@ -5461,17 +5461,26 @@ class PatternVariableDeclaration extends Statement {
|
|||
|
||||
final Matcher dummyMatcher = new ExpressionMatcher(dummyExpression);
|
||||
|
||||
/// Internal statement for a if-case statements:
|
||||
///
|
||||
/// if (expression case matcher) then
|
||||
/// if (expression case matcher) then else otherwise
|
||||
/// if (expression case matcher when guard) then
|
||||
/// if (expression case matcher when guard) then else otherwise
|
||||
///
|
||||
class IfCaseStatement extends InternalStatement {
|
||||
Expression expression;
|
||||
Matcher matcher;
|
||||
Expression? guard;
|
||||
Statement then;
|
||||
Statement? otherwise;
|
||||
|
||||
IfCaseStatement(this.expression, this.matcher, this.then, this.otherwise,
|
||||
int fileOffset) {
|
||||
IfCaseStatement(this.expression, this.matcher, this.guard, this.then,
|
||||
this.otherwise, int fileOffset) {
|
||||
this.fileOffset = fileOffset;
|
||||
expression.parent = this;
|
||||
matcher.parent = this;
|
||||
guard?.parent = this;
|
||||
then.parent = this;
|
||||
otherwise?.parent = this;
|
||||
}
|
||||
|
@ -5487,6 +5496,10 @@ class IfCaseStatement extends InternalStatement {
|
|||
printer.writeExpression(expression);
|
||||
printer.write(' case ');
|
||||
matcher.toTextInternal(printer);
|
||||
if (guard != null) {
|
||||
printer.write(' when ');
|
||||
printer.writeExpression(guard!);
|
||||
}
|
||||
printer.write(') ');
|
||||
printer.writeStatement(then);
|
||||
if (otherwise != null) {
|
||||
|
|
|
@ -1802,7 +1802,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
}
|
||||
|
||||
StatementInferenceResult visitIfCaseStatement(IfCaseStatement node) {
|
||||
// TODO(cstefantsova): Handle if-case statements.
|
||||
// TODO(cstefantsova): Handle if-case-when statements.
|
||||
return new StatementInferenceResult.single(
|
||||
new EmptyStatement()..fileOffset = node.fileOffset);
|
||||
}
|
||||
|
|
|
@ -1144,6 +1144,7 @@ void _testIfCaseStatement() {
|
|||
new IfCaseStatement(
|
||||
new IntLiteral(0),
|
||||
new ExpressionMatcher(new IntLiteral(1)),
|
||||
null,
|
||||
new ReturnStatement(),
|
||||
null,
|
||||
TreeNode.noOffset),
|
||||
|
@ -1154,9 +1155,32 @@ if (0 case 1) return;''');
|
|||
new IfCaseStatement(
|
||||
new IntLiteral(0),
|
||||
new ExpressionMatcher(new IntLiteral(1)),
|
||||
null,
|
||||
new ReturnStatement(new IntLiteral(2)),
|
||||
new ReturnStatement(new IntLiteral(3)),
|
||||
TreeNode.noOffset),
|
||||
'''
|
||||
if (0 case 1) return 2; else return 3;''');
|
||||
|
||||
testStatement(
|
||||
new IfCaseStatement(
|
||||
new IntLiteral(0),
|
||||
new ExpressionMatcher(new IntLiteral(1)),
|
||||
new IntLiteral(2),
|
||||
new ReturnStatement(),
|
||||
null,
|
||||
TreeNode.noOffset),
|
||||
'''
|
||||
if (0 case 1 when 2) return;''');
|
||||
|
||||
testStatement(
|
||||
new IfCaseStatement(
|
||||
new IntLiteral(0),
|
||||
new ExpressionMatcher(new IntLiteral(1)),
|
||||
new IntLiteral(2),
|
||||
new ReturnStatement(new IntLiteral(3)),
|
||||
new ReturnStatement(new IntLiteral(4)),
|
||||
TreeNode.noOffset),
|
||||
'''
|
||||
if (0 case 1 when 2) return 3; else return 4;''');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
void f(x) {
|
||||
if (x case 0 when true) {}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void
|
||||
;
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
void f(x) {
|
||||
switch (x) {
|
||||
case 0 when true:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 0
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 0
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 0
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 0
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void
|
||||
;
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 0
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void f(x) {
|
||||
if (x case 0 as int when true) {}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void
|
||||
;
|
|
@ -0,0 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
void f(x) {
|
||||
switch (x) {
|
||||
case 0 as int when true:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = null
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = null
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1 @@
|
|||
void f(x) {}
|
|
@ -0,0 +1,17 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = null
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = null
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void
|
||||
;
|
|
@ -0,0 +1,17 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method f(dynamic x) → void {
|
||||
#L1:
|
||||
switch(x) {
|
||||
#L2:
|
||||
case #C1:
|
||||
{
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = null
|
||||
}
|
Loading…
Reference in a new issue