Add quick assist to convert SwitchStatement (with patterns) into if-case chain.

Bug: https://github.com/dart-lang/sdk/issues/52068
Change-Id: Ia20b943dfc5212764f31cd94f4f8cce8755628bc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/297140
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-04-21 22:07:02 +00:00 committed by Commit Queue
parent 529adda42e
commit b5d63cb67f
5 changed files with 168 additions and 0 deletions

View file

@ -146,6 +146,11 @@ class DartAssistKind {
DartAssistKindPriority.DEFAULT,
"Convert to 'if-case' statement",
);
static const CONVERT_TO_IF_CASE_STATEMENT_CHAIN = AssistKind(
'dart.assist.convert.ifCaseStatementChain',
DartAssistKindPriority.DEFAULT,
"Convert to 'if-case' statement chain",
);
static const CONVERT_TO_IF_ELEMENT = AssistKind(
'dart.assist.convert.toIfElement',
DartAssistKindPriority.DEFAULT,

View file

@ -31,6 +31,7 @@ import 'package:analysis_server/src/services/correction/dart/convert_to_expressi
import 'package:analysis_server/src/services/correction/dart/convert_to_field_parameter.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_if_case_statement.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_if_case_statement_chain.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_multiline_string.dart';
@ -116,6 +117,7 @@ class AssistProcessor extends BaseProcessor {
ConvertToFieldParameter.new,
ConvertToGenericFunctionSyntax.new,
ConvertToIfCaseStatement.new,
ConvertToIfCaseStatementChain.new,
ConvertToIntLiteral.new,
ConvertToMapLiteral.new,
ConvertToMultilineString.new,

View file

@ -0,0 +1,89 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
class ConvertToIfCaseStatementChain extends CorrectionProducer {
@override
AssistKind get assistKind =>
DartAssistKind.CONVERT_TO_IF_CASE_STATEMENT_CHAIN;
@override
Future<void> compute(ChangeBuilder builder) async {
final switchStatement = node;
if (switchStatement is! SwitchStatement) {
return;
}
final ifIndent = utils.getLinePrefix(switchStatement.offset);
final expressionCode = utils.getNodeText(switchStatement.expression);
final switchPatternCases = <SwitchPatternCase>[];
SwitchDefault? defaultCase;
for (final member in switchStatement.members) {
switch (member) {
case SwitchPatternCase():
switchPatternCases.add(member);
case SwitchDefault():
defaultCase = member;
default:
return;
}
}
await builder.addDartFileEdit(file, (builder) {
builder.addReplacement(range.node(switchStatement), (builder) {
var isFirst = true;
for (final case_ in switchPatternCases) {
if (isFirst) {
isFirst = false;
} else {
builder.write(' else ');
}
final patternCode = utils.getNodeText(case_.guardedPattern);
builder.writeln('if ($expressionCode case $patternCode) {');
_writeStatements(
builder: builder,
blockIndent: ifIndent,
statements: case_.statements,
);
builder.write('$ifIndent}');
}
if (defaultCase case final defaultCase?) {
builder.writeln(' else {');
_writeStatements(
builder: builder,
blockIndent: ifIndent,
statements: defaultCase.statements,
);
builder.write('$ifIndent}');
}
});
});
}
void _writeStatements({
required DartEditBuilder builder,
required List<Statement> statements,
required String blockIndent,
}) {
final range = utils.getLinesRangeStatements(statements);
final firstIndent = utils.getLinePrefix(statements.first.offset);
final singleIndent = utils.getIndent(1);
final code = utils.replaceSourceRangeIndent(
range,
firstIndent,
blockIndent + singleIndent,
);
builder.write(code);
}
}

View file

@ -0,0 +1,69 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'assist_processor.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConvertToIfCaseStatementChainTest);
});
}
@reflectiveTest
class ConvertToIfCaseStatementChainTest extends AssistProcessorTest {
@override
AssistKind get kind => DartAssistKind.CONVERT_TO_IF_CASE_STATEMENT_CHAIN;
Future<void> test_noDefault() async {
await resolveTestCode('''
void f(Object? x) {
switch (x) {
case int():
0;
case double():
1;
}
}
''');
await assertHasAssistAt('switch', '''
void f(Object? x) {
if (x case int()) {
0;
} else if (x case double()) {
1;
}
}
''');
}
Future<void> test_withDefault() async {
await resolveTestCode('''
void f(Object? x) {
switch (x) {
case int():
0;
case double():
1;
default:
2;
}
}
''');
await assertHasAssistAt('switch', '''
void f(Object? x) {
if (x case int()) {
0;
} else if (x case double()) {
1;
} else {
2;
}
}
''');
}
}

View file

@ -30,6 +30,8 @@ import 'convert_to_double_quoted_string_test.dart'
as convert_to_double_quoted_string;
import 'convert_to_field_parameter_test.dart' as convert_to_field_parameter;
import 'convert_to_for_element_test.dart' as convert_to_for_element;
import 'convert_to_if_case_statement_chain_test.dart'
as convert_to_if_case_statement_chain;
import 'convert_to_if_case_statement_test.dart' as convert_to_if_case_statement;
import 'convert_to_if_element_test.dart' as convert_to_if_element;
import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
@ -119,6 +121,7 @@ void main() {
convert_to_double_quoted_string.main();
convert_to_field_parameter.main();
convert_to_for_element.main();
convert_to_if_case_statement_chain.main();
convert_to_if_case_statement.main();
convert_to_if_element.main();
convert_to_int_literal.main();