mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 18:46:06 +00:00
Support for converting 'if' statements with bool conditions into patterns.
Bug: https://github.com/dart-lang/sdk/issues/52068 Change-Id: I187b3e3cad66eff7a266478df0c09ffb3d642e34 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/296067 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
dc34fe9f86
commit
ac1bdebff7
|
@ -40,7 +40,7 @@ class ConvertIfStatementToSwitchStatement extends CorrectionProducer {
|
|||
|
||||
await builder.addDartFileEdit(file, (builder) {
|
||||
builder.addReplacement(range.node(ifStatement), (builder) {
|
||||
final expressionCode = firstThen.identifier;
|
||||
final expressionCode = firstThen.expressionCode;
|
||||
builder.writeln('switch ($expressionCode) {');
|
||||
|
||||
for (final case_ in cases) {
|
||||
|
@ -69,26 +69,11 @@ class ConvertIfStatementToSwitchStatement extends CorrectionProducer {
|
|||
}
|
||||
|
||||
List<_IfCase>? _buildCases(IfStatement ifStatement) {
|
||||
final expression = ifStatement.expression;
|
||||
if (expression is! SimpleIdentifier) {
|
||||
final thenCase = _buildThenCase(ifStatement);
|
||||
if (thenCase == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String patternCode;
|
||||
final caseClause = ifStatement.caseClause;
|
||||
if (caseClause != null) {
|
||||
patternCode = utils.getNodeText(caseClause.guardedPattern);
|
||||
} else {
|
||||
// TODO(scheglov) support converting conditions to patterns
|
||||
return null;
|
||||
}
|
||||
|
||||
final thenCase = _IfCaseThen(
|
||||
identifier: expression.token,
|
||||
patternCode: patternCode,
|
||||
statement: ifStatement.thenStatement,
|
||||
);
|
||||
|
||||
final cases = <_IfCase>[];
|
||||
cases.add(thenCase);
|
||||
|
||||
|
@ -100,7 +85,7 @@ class ConvertIfStatementToSwitchStatement extends CorrectionProducer {
|
|||
}
|
||||
for (final elseCase in elseCases) {
|
||||
if (elseCase is _IfCaseThen) {
|
||||
if (elseCase.identifier.lexeme != thenCase.identifier.lexeme) {
|
||||
if (elseCase.expressionCode != thenCase.expressionCode) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +102,36 @@ class ConvertIfStatementToSwitchStatement extends CorrectionProducer {
|
|||
return cases;
|
||||
}
|
||||
|
||||
_IfCaseThen? _buildThenCase(IfStatement ifStatement) {
|
||||
final expression = ifStatement.expression;
|
||||
final caseClause = ifStatement.caseClause;
|
||||
|
||||
if (caseClause != null) {
|
||||
if (expression is! SimpleIdentifier) {
|
||||
return null;
|
||||
}
|
||||
final guardedPattern = caseClause.guardedPattern;
|
||||
final patternCode = utils.getNodeText(guardedPattern);
|
||||
return _IfCaseThen(
|
||||
expressionCode: expression.token.lexeme,
|
||||
patternCode: patternCode,
|
||||
statement: ifStatement.thenStatement,
|
||||
);
|
||||
}
|
||||
|
||||
// The expression is the bool condition.
|
||||
final result = utils.patternOfBoolCondition(expression);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _IfCaseThen(
|
||||
expressionCode: result.expressionCode,
|
||||
patternCode: result.patternCode,
|
||||
statement: ifStatement.thenStatement,
|
||||
);
|
||||
}
|
||||
|
||||
/// Writes [statement], if it is a [Block], inlines it.
|
||||
void _writeStatement({
|
||||
required DartEditBuilder builder,
|
||||
|
@ -356,11 +371,11 @@ class _IfCaseElse extends _IfCase {
|
|||
}
|
||||
|
||||
class _IfCaseThen extends _IfCase {
|
||||
final Token identifier;
|
||||
final String expressionCode;
|
||||
final String patternCode;
|
||||
|
||||
_IfCaseThen({
|
||||
required this.identifier,
|
||||
required this.expressionCode,
|
||||
required this.patternCode,
|
||||
required super.statement,
|
||||
});
|
||||
|
|
|
@ -1038,6 +1038,26 @@ class CorrectionUtils {
|
|||
return InsertionLocation(prefix, offset, suffix);
|
||||
}
|
||||
|
||||
ExpressionCasePattern? patternOfBoolCondition(Expression node) {
|
||||
if (node is BinaryExpression) {
|
||||
if (node.isNotEqNull) {
|
||||
final expressionCode = getNodeText(node.leftOperand);
|
||||
return ExpressionCasePattern(
|
||||
expressionCode: expressionCode,
|
||||
patternCode: '_?',
|
||||
);
|
||||
}
|
||||
} else if (node is IsExpression) {
|
||||
final expressionCode = getNodeText(node.expression);
|
||||
final typeCode = getNodeText(node.type);
|
||||
return ExpressionCasePattern(
|
||||
expressionCode: expressionCode,
|
||||
patternCode: '$typeCode()',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
InsertionLocation? prepareEnumNewConstructorLocation(
|
||||
EnumDeclaration enumDeclaration,
|
||||
) {
|
||||
|
@ -1502,6 +1522,16 @@ class CorrectionUtils_InsertDesc {
|
|||
String suffix = '';
|
||||
}
|
||||
|
||||
class ExpressionCasePattern {
|
||||
final String expressionCode;
|
||||
final String patternCode;
|
||||
|
||||
ExpressionCasePattern({
|
||||
required this.expressionCode,
|
||||
required this.patternCode,
|
||||
});
|
||||
}
|
||||
|
||||
class InsertionLocation {
|
||||
final String prefix;
|
||||
final int offset;
|
||||
|
|
|
@ -122,6 +122,12 @@ extension AstNodeExtensions on AstNode {
|
|||
}
|
||||
}
|
||||
|
||||
extension BinaryExpressionExtensions on BinaryExpression {
|
||||
bool get isNotEqNull {
|
||||
return operator.type == TokenType.BANG_EQ && rightOperand is NullLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
extension CompilationUnitExtension on CompilationUnit {
|
||||
/// Return the list of tokens that comprise the file header comment for this
|
||||
/// compilation unit.
|
||||
|
|
|
@ -20,7 +20,7 @@ class ConvertIfStatementToSwitchStatementTest extends AssistProcessorTest {
|
|||
@override
|
||||
AssistKind get kind => DartAssistKind.CONVERT_TO_SWITCH_STATEMENT;
|
||||
|
||||
Future<void> test_chain2_case_case_differentIdentifier() async {
|
||||
Future<void> test_chain_case2_differentIdentifier() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x, Object? y) {
|
||||
if (x case int()) {
|
||||
|
@ -33,7 +33,7 @@ void f(Object? x, Object? y) {
|
|||
await assertNoAssistAt('if');
|
||||
}
|
||||
|
||||
Future<void> test_chain2_case_case_elseBlock() async {
|
||||
Future<void> test_chain_case2_elseBlock() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x case int()) {
|
||||
|
@ -59,7 +59,7 @@ void f(Object? x) {
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_chain2_case_case_noElse() async {
|
||||
Future<void> test_chain_case2_noElse() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x case int()) {
|
||||
|
@ -81,7 +81,7 @@ void f(Object? x) {
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_chain2_case_case_notIdentifier() async {
|
||||
Future<void> test_chain_case2_notIdentifier() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x case int()) {
|
||||
|
@ -94,6 +94,50 @@ void f(Object? x) {
|
|||
await assertNoAssistAt('if');
|
||||
}
|
||||
|
||||
Future<void> test_chain_case_expression() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x case int()) {
|
||||
0;
|
||||
} else if (x is double) {
|
||||
1;
|
||||
}
|
||||
}
|
||||
''');
|
||||
await assertHasAssistAt('if', '''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case int():
|
||||
0;
|
||||
case double():
|
||||
1;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_chain_expression2() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x is int) {
|
||||
0;
|
||||
} else if (x is double) {
|
||||
1;
|
||||
}
|
||||
}
|
||||
''');
|
||||
await assertHasAssistAt('if', '''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case int():
|
||||
0;
|
||||
case double():
|
||||
1;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_single_case_thenBlock() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
|
@ -191,6 +235,42 @@ void f(Object? x) {
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_single_expression_isType() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x is List<int>) {
|
||||
0;
|
||||
}
|
||||
}
|
||||
''');
|
||||
await assertHasAssistAt('if', '''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case List<int>():
|
||||
0;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_single_expression_notEqNull() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
if (x != null) {
|
||||
0;
|
||||
}
|
||||
}
|
||||
''');
|
||||
await assertHasAssistAt('if', '''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case _?:
|
||||
0;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_single_expression_notSupported() async {
|
||||
await resolveTestCode('''
|
||||
void f(Object? x) {
|
||||
|
|
Loading…
Reference in a new issue