fix: joining if-cases

Closes https://github.com/dart-lang/sdk/pull/56920

GitOrigin-RevId: 4e9075cacc6d4af73775aae1d42ee6fde4377b4e
Change-Id: I8873082cc993de8b65191d02537f8199dd4fc68c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/390632
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
Honza Bittner
2024-10-21 15:04:57 +00:00
committed by Commit Queue
parent 49c554144e
commit ec6dfd4019
4 changed files with 312 additions and 0 deletions
@@ -42,6 +42,12 @@ class JoinIfWithInner extends ResolvedCorrectionProducer {
if (innerIfStatement.elseStatement != null) {
return;
}
// If inner is if-case, we cannot join them.
if (innerIfStatement.caseClause != null) {
return;
}
// prepare environment
var prefix = utils.getNodePrefix(targetIfStatement);
// merge conditions
@@ -55,7 +61,30 @@ class JoinIfWithInner extends ResolvedCorrectionProducer {
if (innerCondition.shouldWrapParenthesisBeforeAnd) {
innerConditionSource = '($innerConditionSource)';
}
var condition = '$targetConditionSource && $innerConditionSource';
// If outer is if-case.
var outerCaseClause = targetIfStatement.caseClause;
if (outerCaseClause != null) {
var casePattern = outerCaseClause.guardedPattern.pattern;
var caseWhenExpression =
outerCaseClause.guardedPattern.whenClause?.expression;
if (caseWhenExpression != null) {
var caseWhenSource = '$caseWhenExpression';
if (caseWhenExpression.shouldWrapParenthesisBeforeAnd) {
caseWhenSource = '($caseWhenSource)';
}
condition =
'$targetConditionSource case $casePattern when $caseWhenSource && $innerConditionSource';
} else {
condition =
'$targetConditionSource case $casePattern when $innerConditionSource';
}
}
// replace target "if" statement
var innerThenStatement = innerIfStatement.thenStatement;
var innerThenStatements = getStatements(innerThenStatement);
@@ -48,6 +48,12 @@ class JoinIfWithOuter extends ResolvedCorrectionProducer {
if (outerIfStatement.elseStatement != null) {
return;
}
// If target (inner) is if-case, we cannot join them.
if (targetIfStatement.caseClause != null) {
return;
}
// prepare environment
var prefix = utils.getNodePrefix(outerIfStatement);
// merge conditions
@@ -61,7 +67,30 @@ class JoinIfWithOuter extends ResolvedCorrectionProducer {
if (outerCondition.shouldWrapParenthesisBeforeAnd) {
outerConditionSource = '($outerConditionSource)';
}
var condition = '$outerConditionSource && $targetConditionSource';
// If outer is if-case.
var outerCaseClause = outerIfStatement.caseClause;
if (outerCaseClause != null) {
var casePattern = outerCaseClause.guardedPattern.pattern;
var caseWhenExpression =
outerCaseClause.guardedPattern.whenClause?.expression;
if (caseWhenExpression != null) {
var caseWhenSource = '$caseWhenExpression';
if (caseWhenExpression.shouldWrapParenthesisBeforeAnd) {
caseWhenSource = '($caseWhenSource)';
}
condition =
'$outerConditionSource case $casePattern when $caseWhenSource && $targetConditionSource';
} else {
condition =
'$outerConditionSource case $casePattern when $targetConditionSource';
}
}
// replace outer "if" statement
var targetThenStatement = targetIfStatement.thenStatement;
var targetThenStatements = getStatements(targetThenStatement);
@@ -19,6 +19,19 @@ class JoinIfWithInnerTest extends AssistProcessorTest {
@override
AssistKind get kind => DartAssistKind.JOIN_IF_WITH_INNER;
Future<void> test_bothOuterAndInnerAreIfCase() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final v?) {
if (v case final int x) {
print(0);
}
}
}
''');
await assertNoAssistAt('if (p');
}
Future<void> test_conditionAndOr() async {
await resolveTestCode('''
void f() {
@@ -78,6 +91,120 @@ void f() {
''');
}
Future<void> test_ifCaseAddWhen() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p) {
if (p case final int v when v == 5) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAddWhenUnrelated() async {
await resolveTestCode('''
void f(Object? p, Object? q) {
if (p case final int v) {
if (q != null) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p, Object? q) {
if (p case final int v when q != null) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhen() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p) {
if (p case final int v when v.isOdd && v == 5) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisBoth() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd || v > 3) {
if (v == 5 || v != 6) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p) {
if (p case final int v when (v.isOdd || v > 3) && (v == 5 || v != 6)) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisInner() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd) {
if (v == 5 || v != 3) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p) {
if (p case final int v when v.isOdd && (v == 5 || v != 3)) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisOuter() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd || v != 3) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (p', '''
void f(Object? p) {
if (p case final int v when (v.isOdd || v != 3) && v == 5) {
print(0);
}
}
''');
}
Future<void> test_innerNotIf() async {
await resolveTestCode('''
void f() {
@@ -19,6 +19,19 @@ class JoinIfWithOuterTest extends AssistProcessorTest {
@override
AssistKind get kind => DartAssistKind.JOIN_IF_WITH_OUTER;
Future<void> test_bothOuterAndInnerAreIfCase() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final v?) {
if (v case final int x) {
print(x);
}
}
}
''');
await assertNoAssistAt('if (v');
}
Future<void> test_conditionAndOr() async {
await resolveTestCode('''
void f() {
@@ -78,6 +91,120 @@ void f() {
''');
}
Future<void> test_ifCaseAddWhen() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (v == 5', '''
void f(Object? p) {
if (p case final int v when v == 5) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAddWhenUnrelated() async {
await resolveTestCode('''
void f(Object? p, Object? q) {
if (p case final int v) {
if (q != null) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (q != null', '''
void f(Object? p, Object? q) {
if (p case final int v when q != null) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhen() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (v == 5', '''
void f(Object? p) {
if (p case final int v when v.isOdd && v == 5) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisBoth() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd || v > 3) {
if (v == 5 || v != 6) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (v', '''
void f(Object? p) {
if (p case final int v when (v.isOdd || v > 3) && (v == 5 || v != 6)) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisInner() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd) {
if (v == 5 || v != 3) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (v', '''
void f(Object? p) {
if (p case final int v when v.isOdd && (v == 5 || v != 3)) {
print(0);
}
}
''');
}
Future<void> test_ifCaseAppendWhenWithParenthesisOuter() async {
await resolveTestCode('''
void f(Object? p) {
if (p case final int v when v.isOdd || v != 3) {
if (v == 5) {
print(0);
}
}
}
''');
await assertHasAssistAt('if (v', '''
void f(Object? p) {
if (p case final int v when (v.isOdd || v != 3) && v == 5) {
print(0);
}
}
''');
}
Future<void> test_onCondition() async {
await resolveTestCode('''
void f() {