| // Copyright (c) 2020, 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/range_factory.dart'; |
| |
| class FlutterConvertToChildren extends CorrectionProducer { |
| @override |
| AssistKind get assistKind => DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN; |
| |
| @override |
| Future<void> compute(ChangeBuilder builder) async { |
| // Find "child: widget" under selection. |
| NamedExpression namedExp; |
| { |
| var node = this.node; |
| var parent = node?.parent; |
| var parent2 = parent?.parent; |
| if (node is SimpleIdentifier && |
| parent is Label && |
| parent2 is NamedExpression && |
| node.name == 'child' && |
| node.staticElement != null && |
| flutter.isWidgetExpression(parent2.expression)) { |
| namedExp = parent2; |
| } else { |
| return; |
| } |
| } |
| |
| await builder.addDartFileEdit(file, (builder) { |
| _convertFlutterChildToChildren(namedExp, eol, utils.getNodeText, |
| utils.getLinePrefix, utils.getIndent, utils.getText, builder); |
| }); |
| } |
| |
| void _convertFlutterChildToChildren( |
| NamedExpression namedExp, |
| String eol, |
| Function getNodeText, |
| Function getLinePrefix, |
| Function getIndent, |
| Function getText, |
| FileEditBuilder builder) { |
| var childArg = namedExp.expression; |
| var childLoc = namedExp.offset + 'child'.length; |
| builder.addSimpleInsertion(childLoc, 'ren'); |
| var listLoc = childArg.offset; |
| String childArgSrc = getNodeText(childArg); |
| if (!childArgSrc.contains(eol)) { |
| builder.addSimpleInsertion(listLoc, '['); |
| builder.addSimpleInsertion(listLoc + childArg.length, ']'); |
| } else { |
| var newlineLoc = childArgSrc.lastIndexOf(eol); |
| if (newlineLoc == childArgSrc.length) { |
| newlineLoc -= 1; |
| } |
| String indentOld = |
| getLinePrefix(childArg.offset + eol.length + newlineLoc); |
| var indentNew = '$indentOld${getIndent(1)}'; |
| // The separator includes 'child:' but that has no newlines. |
| String separator = |
| getText(namedExp.offset, childArg.offset - namedExp.offset); |
| var prefix = separator.contains(eol) ? '' : '$eol$indentNew'; |
| if (prefix.isEmpty) { |
| builder.addSimpleInsertion(namedExp.offset + 'child:'.length, ' ['); |
| var argOffset = childArg.offset; |
| builder |
| .addDeletion(range.startOffsetEndOffset(argOffset - 2, argOffset)); |
| } else { |
| builder.addSimpleInsertion(listLoc, '['); |
| } |
| var newChildArgSrc = |
| replaceSourceIndent(childArgSrc, indentOld, indentNew); |
| newChildArgSrc = '$prefix$newChildArgSrc,$eol$indentOld]'; |
| builder.addSimpleReplacement(range.node(childArg), newChildArgSrc); |
| } |
| } |
| |
| /// Return an instance of this class. Used as a tear-off in `AssistProcessor`. |
| static FlutterConvertToChildren newInstance() => FlutterConvertToChildren(); |
| } |