fix for sort_child_properties_last

Change-Id: Ife3f05077fcd48e8f821314b55ba481918ba05c6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/116822
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
pq 2019-09-12 00:07:40 +00:00 committed by commit-bot@chromium.org
parent 586869c3f6
commit 1d01d91c33
9 changed files with 141 additions and 43 deletions

View file

@ -189,11 +189,7 @@ class DartAssistKind {
static const SORT_CHILD_PROPERTY_LAST = const AssistKind(
'dart.assist.sort.child.properties.last',
30,
"Move child property to end of arguments",
// todo (pq): migrate to (conditional) fix
associatedErrorCodes: <String>[
'sort_child_properties_last',
]);
"Move child property to end of arguments");
static const SPLIT_AND_CONDITION = const AssistKind(
'dart.assist.splitIfConjunction', 30, "Split && condition");
static const SPLIT_VARIABLE_DECLARATION = const AssistKind(

View file

@ -140,7 +140,11 @@ class AssistProcessor extends BaseProcessor {
await _addProposal_reparentFlutterList();
await _addProposal_replaceConditionalWithIfElse();
await _addProposal_replaceIfElseWithConditional();
await _addProposal_sortChildPropertyLast();
if (!_containsErrorCode(
{LintNames.sort_child_properties_last},
)) {
await _addProposal_sortChildPropertyLast();
}
await _addProposal_splitAndCondition();
await _addProposal_splitVariableDeclaration();
await _addProposal_surroundWith();
@ -2732,42 +2736,7 @@ class AssistProcessor extends BaseProcessor {
}
Future<void> _addProposal_sortChildPropertyLast() async {
NamedExpression childProp = flutter.findNamedExpression(node, 'child');
if (childProp == null) {
childProp = flutter.findNamedExpression(node, 'children');
}
if (childProp == null) {
return;
}
var parent = childProp.parent?.parent;
if (parent is! InstanceCreationExpression ||
!flutter.isWidgetCreation(parent)) {
return;
}
InstanceCreationExpression creationExpression = parent;
var args = creationExpression.argumentList;
var last = args.arguments.last;
if (last == childProp) {
// Already sorted.
return;
}
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
var start = childProp.beginToken.previous.end;
var end = childProp.endToken.next.end;
var childRange = range.startOffsetEndOffset(start, end);
var childText = utils.getRangeText(childRange);
builder.addSimpleReplacement(childRange, '');
builder.addSimpleInsertion(last.end + 1, childText);
changeBuilder.setSelection(new Position(file, last.end + 1));
});
final changeBuilder = await createBuilder_sortChildPropertyLast();
_addAssistFromBuilder(
changeBuilder, DartAssistKind.SORT_CHILD_PROPERTY_LAST);
}

View file

@ -17,6 +17,7 @@ import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
@ -859,6 +860,46 @@ abstract class BaseProcessor {
return changeBuilder;
}
Future<ChangeBuilder> createBuilder_sortChildPropertyLast() async {
NamedExpression childProp = flutter.findNamedExpression(node, 'child');
if (childProp == null) {
childProp = flutter.findNamedExpression(node, 'children');
}
if (childProp == null) {
return null;
}
var parent = childProp.parent?.parent;
if (parent is! InstanceCreationExpression ||
!flutter.isWidgetCreation(parent)) {
return null;
}
InstanceCreationExpression creationExpression = parent;
var args = creationExpression.argumentList;
var last = args.arguments.last;
if (last == childProp) {
// Already sorted.
return null;
}
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
var start = childProp.beginToken.previous.end;
var end = childProp.endToken.next.end;
var childRange = range.startOffsetEndOffset(start, end);
var childText = utils.getRangeText(childRange);
builder.addSimpleReplacement(childRange, '');
builder.addSimpleInsertion(last.end + 1, childText);
changeBuilder.setSelection(new Position(file, last.end + 1));
});
return changeBuilder;
}
/// todo (pq): unify with similar behavior in fix.
Future<ChangeBuilder> createBuilder_removeTypeAnnotation() async {
VariableDeclarationList declarationList =

View file

@ -354,6 +354,10 @@ class DartFixKind {
"Replace the '.' with a '?.' in the invocation");
static const REPLACE_WITH_TEAR_OFF = const FixKind(
'REPLACE_WITH_TEAR_OFF', 50, "Replace function literal with tear-off");
static const SORT_CHILD_PROPERTY_LAST = const FixKind(
'SORT_CHILD_PROPERTY_LAST',
50,
"Move child property to end of arguments");
static const UPDATE_SDK_CONSTRAINTS =
const FixKind('UPDATE_SDK_CONSTRAINTS', 50, "Update the SDK constraints");
static const USE_CONST = const FixKind('USE_CONST', 50, "Change to constant");

View file

@ -671,6 +671,9 @@ class FixProcessor extends BaseProcessor {
if (name == LintNames.prefer_spread_collections) {
await _addFix_convertAddAllToSpread();
}
if (name == LintNames.sort_child_properties_last) {
await _addFix_sortChildPropertiesLast();
}
if (name == LintNames.type_init_formals) {
await _addFix_removeTypeAnnotation();
}
@ -3798,6 +3801,11 @@ class FixProcessor extends BaseProcessor {
}
}
Future<void> _addFix_sortChildPropertiesLast() async {
final changeBuilder = await createBuilder_sortChildPropertyLast();
_addFixFromBuilder(changeBuilder, DartFixKind.SORT_CHILD_PROPERTY_LAST);
}
Future<void> _addFix_undefinedClass_useSimilar() async {
AstNode node = this.node;
// Prepare the optional import prefix name.

View file

@ -49,8 +49,9 @@ class LintNames {
static const String prefer_null_aware_operators =
'prefer_null_aware_operators';
static const String prefer_single_quotes = 'prefer_single_quotes';
static const String slash_for_doc_comments = 'slash_for_doc_comments';
static const String prefer_spread_collections = 'prefer_spread_collections';
static const String slash_for_doc_comments = 'slash_for_doc_comments';
static const String sort_child_properties_last = 'sort_child_properties_last';
static const String type_annotate_public_apis = 'type_annotate_public_apis';
static const String type_init_formals = 'type_init_formals';
static const String unawaited_futures = 'unawaited_futures';

View file

@ -3,6 +3,7 @@
// 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/linter/lint_names.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@ -97,4 +98,24 @@ main() {
''');
assertExitPosition(after: "],");
}
test_sort_noAssistWithLint() async {
addFlutterPackage();
createAnalysisOptionsFile(lints: [LintNames.sort_child_properties_last]);
verifyNoTestUnitErrors = false;
await resolveTestUnit('''
import 'package:flutter/material.dart';
main() {
Column(
/*caret*/children: <Widget>[
Text('aaa'),
Text('bbbbbb'),
Text('ccccccccc'),
],
crossAxisAlignment: CrossAxisAlignment.center,
);
}
''');
await assertNoAssist();
}
}

View file

@ -0,0 +1,56 @@
// 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/fix.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'fix_processor.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SortChildPropertiesLastTest);
});
}
@reflectiveTest
class SortChildPropertiesLastTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.SORT_CHILD_PROPERTY_LAST;
@override
String get lintCode => LintNames.sort_child_properties_last;
/// More coverage in the `sort_child_properties_last_test.dart` assist test.
test_sort() async {
addFlutterPackage();
await resolveTestUnit('''
import 'package:flutter/material.dart';
main() {
Column(
/*LINT*/children: <Widget>[
Text('aaa'),
Text('bbbbbb'),
Text('ccccccccc'),
],
crossAxisAlignment: CrossAxisAlignment.center,
);
}
''');
await assertHasFix('''
import 'package:flutter/material.dart';
main() {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
/*LINT*/children: <Widget>[
Text('aaa'),
Text('bbbbbb'),
Text('ccccccccc'),
],
);
}
''');
}
}

View file

@ -118,6 +118,7 @@ import 'replace_with_is_empty_test.dart' as replace_with_is_empty;
import 'replace_with_is_not_empty_test.dart' as replace_with_is_not_empty;
import 'replace_with_null_aware_test.dart' as replace_with_null_aware;
import 'replace_with_tear_off_test.dart' as replace_with_tear_off;
import 'sort_child_property_last_test.dart' as sort_properties_last;
import 'update_sdk_constraints_test.dart' as update_sdk_constraints;
import 'use_const_test.dart' as use_const;
import 'use_effective_integer_division_test.dart'
@ -230,6 +231,7 @@ main() {
replace_with_is_not_empty.main();
replace_with_null_aware.main();
replace_with_tear_off.main();
sort_properties_last.main();
update_sdk_constraints.main();
use_const.main();
use_effective_integer_division.main();