Fix for curly_braces_in_flow_control_structures lint.

Quick assist for converting single line statements to blocks and
vice-versa is also sometimes useful, but separate.

R=brianwilkerson@google.com, pquitslund@google.com

Bug: https://github.com/dart-lang/sdk/issues/37084
Change-Id: I9c6b2f7c063bc339a57d991e4d675b87e1910413
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103721
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2019-07-01 18:50:49 +00:00 committed by commit-bot@chromium.org
parent b6c3b2c98c
commit 39b71253ce
4 changed files with 574 additions and 0 deletions

View file

@ -232,4 +232,6 @@ class DartAssistKind {
'dart.assist.surround.tryFinally', 29, "Surround with 'try-finally'");
static const SURROUND_WITH_WHILE = const AssistKind(
'dart.assist.surround.while', 24, "Surround with 'while'");
static const USE_CURLY_BRACES =
const AssistKind('USE_CURLY_BRACES', 30, "Use curly braces");
}

View file

@ -149,6 +149,7 @@ class AssistProcessor {
await _addProposal_splitAndCondition();
await _addProposal_splitVariableDeclaration();
await _addProposal_surroundWith();
await _addProposal_useCurlyBraces();
if (experimentStatus.control_flow_collections) {
await _addProposal_convertConditionalExpressionToIfElement();
@ -3947,6 +3948,132 @@ class AssistProcessor {
}
}
Future<void> _addProposal_useCurlyBraces() async {
Future<void> doStatement(DoStatement node) async {
var body = node.body;
if (body is Block) return;
var prefix = utils.getLinePrefix(node.offset);
var indent = prefix + utils.getIndent(1);
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (builder) {
builder.addSimpleReplacement(
range.endStart(node.doKeyword, body),
' {$eol$indent',
);
builder.addSimpleReplacement(
range.endStart(body, node.whileKeyword),
'$eol$prefix} ',
);
});
_addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
}
Future<void> forStatement(ForStatement node) async {
var body = node.body;
if (body is Block) return;
var prefix = utils.getLinePrefix(node.offset);
var indent = prefix + utils.getIndent(1);
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (builder) {
builder.addSimpleReplacement(
range.endStart(node.rightParenthesis, body),
' {$eol$indent',
);
builder.addSimpleInsertion(body.end, '$eol$prefix}');
});
_addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
}
Future<void> ifStatement(IfStatement node, Statement thenOrElse) async {
var prefix = utils.getLinePrefix(node.offset);
var indent = prefix + utils.getIndent(1);
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (builder) {
var thenStatement = node.thenStatement;
if (thenStatement is! Block &&
(thenOrElse == null || thenOrElse == thenStatement)) {
builder.addSimpleReplacement(
range.endStart(node.rightParenthesis, thenStatement),
' {$eol$indent',
);
if (node.elseKeyword != null) {
builder.addSimpleReplacement(
range.endStart(thenStatement, node.elseKeyword),
'$eol$prefix} ',
);
} else {
builder.addSimpleInsertion(thenStatement.end, '$eol$prefix}');
}
}
var elseStatement = node.elseStatement;
if (elseStatement != null &&
elseStatement is! Block &&
(thenOrElse == null || thenOrElse == elseStatement)) {
builder.addSimpleReplacement(
range.endStart(node.elseKeyword, elseStatement),
' {$eol$indent',
);
builder.addSimpleInsertion(elseStatement.end, '$eol$prefix}');
}
});
_addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
}
Future<void> whileStatement(WhileStatement node) async {
var body = node.body;
if (body is Block) return;
var prefix = utils.getLinePrefix(node.offset);
var indent = prefix + utils.getIndent(1);
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (builder) {
builder.addSimpleReplacement(
range.endStart(node.rightParenthesis, body),
' {$eol$indent',
);
builder.addSimpleInsertion(body.end, '$eol$prefix}');
});
_addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
}
var statement = this.node.thisOrAncestorOfType<Statement>();
var parent = statement?.parent;
if (statement is DoStatement) {
return doStatement(statement);
} else if (parent is DoStatement) {
return doStatement(parent);
} else if (statement is ForStatement) {
return forStatement(statement);
} else if (parent is ForStatement) {
return forStatement(parent);
} else if (statement is IfStatement) {
if (statement.elseKeyword != null &&
range.token(statement.elseKeyword).contains(selectionOffset)) {
return ifStatement(statement, statement.elseStatement);
} else {
return ifStatement(statement, null);
}
} else if (parent is IfStatement) {
return ifStatement(parent, statement);
} else if (statement is WhileStatement) {
return whileStatement(statement);
} else if (parent is WhileStatement) {
return whileStatement(parent);
}
}
/**
* Return `true` if all of the parameters in the given list of [parameters]
* have an explicit type annotation.

View file

@ -78,6 +78,7 @@ import 'surround_with_if_test.dart' as surround_with_if;
import 'surround_with_try_catch_test.dart' as surround_with_try_catch;
import 'surround_with_try_finally_test.dart' as surround_with_try_finally;
import 'surround_with_while_test.dart' as surround_with_while;
import 'use_curly_braces_test.dart' as use_curly_braces;
main() {
defineReflectiveSuite(() {
@ -147,5 +148,6 @@ main() {
surround_with_try_catch.main();
surround_with_try_finally.main();
surround_with_while.main();
use_curly_braces.main();
}, name: 'assist');
}

View file

@ -0,0 +1,443 @@
// Copyright (c) 2019, 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';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(UseCurlyBracesTest);
});
}
@reflectiveTest
class UseCurlyBracesTest extends AssistProcessorTest {
@override
AssistKind get kind => DartAssistKind.USE_CURLY_BRACES;
test_do_block() async {
await resolveTestUnit('''
main() {
/*caret*/do {
print(0);
} while (true);
}
''');
await assertNoAssist();
}
test_do_body_middle() async {
await resolveTestUnit('''
main() {
do print/*caret*/(0); while (true);
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_do_body_start() async {
await resolveTestUnit('''
main() {
do /*caret*/print(0); while (true);
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_do_condition() async {
await resolveTestUnit('''
main() {
do print(0); while (/*caret*/true);
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_do_end() async {
await resolveTestUnit('''
main() {
do print(0); while (true);/*caret*/
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_do_keyword_do() async {
await resolveTestUnit('''
main() {
/*caret*/do print(0); while (true);
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_do_keyword_while() async {
await resolveTestUnit('''
main() {
do print(0); /*caret*/while (true);
}
''');
await assertHasAssist('''
main() {
do {
print(0);
} while (true);
}
''');
}
test_for_body_end() async {
await resolveTestUnit('''
main() {
for (;;) print(0);/*caret*/
}
''');
await assertHasAssist('''
main() {
for (;;) {
print(0);
}
}
''');
}
test_for_body_middle() async {
await resolveTestUnit('''
main() {
for (;;) print/*caret*/(0);
}
''');
await assertHasAssist('''
main() {
for (;;) {
print(0);
}
}
''');
}
test_for_body_start() async {
await resolveTestUnit('''
main() {
for (;;) /*caret*/print(0);
}
''');
await assertHasAssist('''
main() {
for (;;) {
print(0);
}
}
''');
}
test_for_condition() async {
await resolveTestUnit('''
main() {
for (/*caret*/;;) print(0);
}
''');
await assertHasAssist('''
main() {
for (;;) {
print(0);
}
}
''');
}
test_for_keyword() async {
await resolveTestUnit('''
main() {
/*caret*/for (;;) print(0);
}
''');
await assertHasAssist('''
main() {
for (;;) {
print(0);
}
}
''');
}
test_for_keyword_block() async {
await resolveTestUnit('''
main() {
/*caret*/for (;;) {
print(0);
}
}
''');
await assertNoAssist();
}
test_if_else_keyword() async {
await resolveTestUnit('''
main(int a) {
if (a == 0)
print(0);
/*caret*/else print(1);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0)
print(0);
else {
print(1);
}
}
''');
}
test_if_else_statement() async {
await resolveTestUnit('''
main(int a) {
if (a == 0)
print(0);
else /*caret*/print(1);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0)
print(0);
else {
print(1);
}
}
''');
}
test_if_keyword_blockBoth() async {
await resolveTestUnit('''
main(int a) {
/*caret*/if (a == 0) {
print(0);
} else {
print(1);
}
}
''');
await assertNoAssist();
}
test_if_keyword_blockElse() async {
await resolveTestUnit('''
main(int a) {
/*caret*/if (a == 0) print(0);
else {
print(1);
}
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0) {
print(0);
} else {
print(1);
}
}
''');
}
test_if_keyword_blockThen() async {
await resolveTestUnit('''
main(int a) {
/*caret*/if (a == 0) {
print(0);
}
}
''');
await assertNoAssist();
}
test_if_keyword_withElse() async {
await resolveTestUnit('''
main(int a) {
/*caret*/if (a == 0)
print(0);
else print(1);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0) {
print(0);
} else {
print(1);
}
}
''');
}
test_if_keyword_withoutElse() async {
await resolveTestUnit('''
main(int a) {
/*caret*/if (a == 0)
print(0);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0) {
print(0);
}
}
''');
}
test_if_then_withElse() async {
await resolveTestUnit('''
main(int a) {
if (a == 0)
/*caret*/print(0);
else print(1);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0) {
print(0);
} else print(1);
}
''');
}
test_if_then_withoutElse() async {
await resolveTestUnit('''
main(int a) {
if (a == 0) /*caret*/print(0);
}
''');
await assertHasAssist('''
main(int a) {
if (a == 0) {
print(0);
}
}
''');
}
test_while_body_end() async {
await resolveTestUnit('''
main() {
while (true) print(0);/*caret*/
}
''');
await assertHasAssist('''
main() {
while (true) {
print(0);
}
}
''');
}
test_while_body_middle() async {
await resolveTestUnit('''
main() {
while (true) print/*caret*/(0);
}
''');
await assertHasAssist('''
main() {
while (true) {
print(0);
}
}
''');
}
test_while_body_start() async {
await resolveTestUnit('''
main() {
while (true) /*caret*/print(0);
}
''');
await assertHasAssist('''
main() {
while (true) {
print(0);
}
}
''');
}
test_while_condition() async {
await resolveTestUnit('''
main() {
while (/*caret*/true) print(0);
}
''');
await assertHasAssist('''
main() {
while (true) {
print(0);
}
}
''');
}
test_while_keyword() async {
await resolveTestUnit('''
main() {
/*caret*/while (true) print(0);
}
''');
await assertHasAssist('''
main() {
while (true) {
print(0);
}
}
''');
}
test_while_keyword_block() async {
await resolveTestUnit('''
main() {
/*caret*/while (true) {
print(0);
}
}
''');
await assertNoAssist();
}
}