| // 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/fix/data_driven/code_template.dart'; |
| import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart'; |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart'; |
| |
| /// Use a specified argument from an invocation as the value of a template |
| /// variable. |
| class ArgumentExpression extends ValueGenerator { |
| /// The parameter corresponding to the argument from the original invocation, |
| /// or `null` if the value of the argument can't be taken from the original |
| /// invocation. |
| final ParameterReference parameter; |
| |
| /// Initialize a newly created extractor to extract the argument that |
| /// corresponds to the given [parameter]. |
| ArgumentExpression(this.parameter) : assert(parameter != null); |
| |
| @override |
| bool validate(TemplateContext context) { |
| var argumentList = _getArgumentList(context.node); |
| if (argumentList == null) { |
| return false; |
| } |
| var expression = parameter.argumentFrom(argumentList); |
| if (expression != null) { |
| return false; |
| } |
| return true; |
| } |
| |
| @override |
| void writeOn(DartEditBuilder builder, TemplateContext context) { |
| var argumentList = _getArgumentList(context.node); |
| if (argumentList != null) { |
| var expression = parameter.argumentFrom(argumentList); |
| if (expression != null) { |
| builder.write(context.utils.getNodeText(expression)); |
| } |
| } |
| } |
| |
| /// Return the argument list associated with the given [node]. |
| ArgumentList _getArgumentList(AstNode node) { |
| if (node is ArgumentList) { |
| return node; |
| } else if (node is InvocationExpression) { |
| return node.argumentList; |
| } else if (node is InstanceCreationExpression) { |
| return node.argumentList; |
| } else if (node is SimpleIdentifier) { |
| var parent = node.parent; |
| if (parent is ConstructorName) { |
| var grandparent = parent.parent; |
| if (grandparent is InstanceCreationExpression) { |
| return grandparent.argumentList; |
| } |
| } else if (parent is MethodInvocation && parent.methodName == node) { |
| return parent.argumentList; |
| } |
| } else if (node is TypeArgumentList) { |
| var parent = node.parent; |
| if (parent is InvocationExpression) { |
| return parent.argumentList; |
| } else if (parent is ExtensionOverride) { |
| return parent.argumentList; |
| } |
| } |
| return null; |
| } |
| } |
| |
| /// Use a name that might need to be imported from a different library as the |
| /// value of a template variable. |
| class ImportedName extends ValueGenerator { |
| /// The URIs of the libraries from which the name can be imported. |
| final List<Uri> uris; |
| |
| /// The name to be used. |
| final String name; |
| |
| ImportedName(this.uris, this.name); |
| |
| @override |
| bool validate(TemplateContext context) { |
| // TODO(brianwilkerson) Validate that the import can be added. |
| return true; |
| } |
| |
| @override |
| void writeOn(DartEditBuilder builder, TemplateContext context) { |
| builder.writeImportedName(uris, name); |
| } |
| } |
| |
| /// An object used to generate the value of a template variable. |
| abstract class ValueGenerator { |
| /// Use the [context] to validate that this generator will be able to generate |
| /// a value. |
| bool validate(TemplateContext context); |
| |
| /// Write the value generated by this generator to the given [builder], using |
| /// the [context] to access needed information that isn't already known to |
| /// this generator. |
| void writeOn(DartEditBuilder builder, TemplateContext context); |
| } |