Version 2.11.0-255.0.dev
Merge commit '4be43f44306290241c1af19296a2651c92404d97' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
new file mode 100644
index 0000000..0d17244
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
@@ -0,0 +1,136 @@
+// 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/parameter_reference.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+
+/// A class that can be used to access a value from a target.
+abstract class Accessor {
+ /// Return the result of using this accessor to access a value from the
+ /// [target].
+ AccessorResult getValue(Object target);
+}
+
+/// The result of using an accessor to get a result.
+abstract class AccessorResult {
+ /// Initialize a newly created result.
+ const AccessorResult();
+
+ /// Return `true` if the accessor returned a valid result.
+ bool get isValid;
+
+ /// Return the result of the accessor if it was valid.
+ ///
+ /// Throws a `StateError` if the accessor did not return a valid result.
+ Object get result;
+}
+
+/// An accessor that returns a specific argument from an argument list.
+class ArgumentAccessor extends Accessor {
+ /// The parameter corresponding to the argument from the original invocation.
+ final ParameterReference parameter;
+
+ /// Initialize a newly created accessor to access the argument that
+ /// corresponds to the given [parameter].
+ ArgumentAccessor(this.parameter) : assert(parameter != null);
+
+ @override
+ AccessorResult getValue(Object target) {
+ if (target is AstNode) {
+ var argumentList = _getArgumentList(target);
+ if (argumentList != null) {
+ var argument = parameter.argumentFrom(argumentList);
+ if (argument != null) {
+ return ValidResult(argument);
+ }
+ }
+ }
+ return const InvalidResult();
+ }
+
+ /// Return the argument list associated with the [node].
+ ArgumentList _getArgumentList(AstNode node) {
+ if (node is Annotation) {
+ return node.arguments;
+ } else if (node is ExtensionOverride) {
+ return node.argumentList;
+ } else if (node is InstanceCreationExpression) {
+ return node.argumentList;
+ } else if (node is InvocationExpression) {
+ return node.argumentList;
+ } else if (node is RedirectingConstructorInvocation) {
+ return node.argumentList;
+ } else if (node is SuperConstructorInvocation) {
+ return node.argumentList;
+ }
+ return null;
+ }
+}
+
+/// A representation of an invalid result.
+class InvalidResult implements AccessorResult {
+ /// Initialize a newly created invalid result.
+ const InvalidResult();
+
+ @override
+ bool get isValid => false;
+
+ @override
+ Object get result => throw StateError('Cannot access an invalid result');
+}
+
+/// An accessor that returns a specific type argument from a type argument list.
+class TypeArgumentAccessor extends Accessor {
+ /// The index of the type argument.
+ final int index;
+
+ /// Initialize a newly created accessor to access the type argument at the
+ /// given [index].
+ TypeArgumentAccessor(this.index) : assert(index != null);
+
+ @override
+ AccessorResult getValue(Object target) {
+ if (target is AstNode) {
+ var typeArgumentList = _getTypeArgumentList(target);
+ if (typeArgumentList != null) {
+ var arguments = typeArgumentList.arguments;
+ if (arguments.length > index) {
+ var argument = arguments[index];
+ if (argument != null) {
+ return ValidResult(argument);
+ }
+ }
+ }
+ }
+ return const InvalidResult();
+ }
+
+ /// Return the type argument list associated with the [node].
+ TypeArgumentList _getTypeArgumentList(AstNode node) {
+ if (node is ExtensionOverride) {
+ return node.typeArguments;
+ } else if (node is InstanceCreationExpression) {
+ return node.constructorName.type.typeArguments;
+ } else if (node is InvocationExpression) {
+ return node.typeArguments;
+ } else if (node is NamedType) {
+ return node.typeArguments;
+ } else if (node is TypedLiteral) {
+ return node.typeArguments;
+ }
+ return null;
+ }
+}
+
+/// A representation of a valid result.
+class ValidResult implements AccessorResult {
+ @override
+ final Object result;
+
+ /// Initialize a newly created valid result.
+ ValidResult(this.result);
+
+ @override
+ bool get isValid => true;
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
index 936237a..6fbcad4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
@@ -50,7 +50,7 @@
@override
_Data validate(DataDrivenFix fix) {
var node = fix.node;
- var context = TemplateContext(node, fix.utils);
+ var context = TemplateContext(getInvocation(node), fix.utils);
if (node is NamedType) {
// wrong_number_of_type_arguments
// wrong_number_of_type_arguments_constructor
@@ -101,7 +101,7 @@
void _applyToTypeArguments(
DartFileEditBuilder builder, DataDrivenFix fix, _TypeArgumentData data) {
- var context = TemplateContext(fix.node, fix.utils);
+ var context = TemplateContext(getInvocation(fix.node), fix.utils);
var typeArguments = data.typeArguments;
if (typeArguments == null) {
// Adding the first type argument.
@@ -130,7 +130,7 @@
void _applyToTypeParameters(
DartFileEditBuilder builder, DataDrivenFix fix, _TypeParameterData data) {
- var context = TemplateContext(fix.node, fix.utils);
+ var context = TemplateContext(getInvocation(fix.node), fix.utils);
void writeParameter(DartEditBuilder builder) {
builder.write(name);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/change.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/change.dart
index f73f6ae..39b5db6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/change.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/change.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
+import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
/// The behavior common to all of the changes used to construct a transform.
@@ -12,6 +13,36 @@
/// [validate] method.
void apply(DartFileEditBuilder builder, DataDrivenFix fix, D data);
+ /// Return the invocation containing the given [node]. The invocation will be
+ /// either an instance creation expression, function invocation, method
+ /// invocation, or an extension override.
+ AstNode getInvocation(AstNode node) {
+ if (node is ArgumentList) {
+ return node.parent;
+ } else if (node is InstanceCreationExpression ||
+ node is InvocationExpression) {
+ return node;
+ } else if (node is SimpleIdentifier) {
+ var parent = node.parent;
+ if (parent is ConstructorName) {
+ var grandparent = parent.parent;
+ if (grandparent is InstanceCreationExpression) {
+ return grandparent;
+ }
+ } else if (parent is MethodInvocation && parent.methodName == node) {
+ return parent;
+ }
+ } else if (node is TypeArgumentList) {
+ var parent = node.parent;
+ if (parent is InvocationExpression) {
+ return parent;
+ } else if (parent is ExtensionOverride) {
+ return parent;
+ }
+ }
+ return null;
+ }
+
/// Validate that this change can be applied. Return the data to be passed to
/// [apply] if the change can be applied, or `null` if it can't be applied.
D validate(DataDrivenFix fix);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
index a2c627e..452db16 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
@@ -96,7 +96,7 @@
builder.write(': ');
}
parameter.argumentValue
- .writeOn(builder, TemplateContext(argumentList, fix.utils));
+ .writeOn(builder, TemplateContext(argumentList.parent, fix.utils));
}
var insertionRanges = argumentsToInsert.contiguousSubRanges.toList();
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index 9632f4c..86ea95b 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -2,6 +2,7 @@
// 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/accessor.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
@@ -361,7 +362,8 @@
// The error has already been reported.
return null;
}
- return ArgumentExpression(PositionalParameterReference(index));
+ return CodeFragment(
+ [ArgumentAccessor(PositionalParameterReference(index))]);
}
var nameNode = node.valueAt(_nameKey);
if (nameNode != null) {
@@ -372,7 +374,7 @@
// The error has already been reported.
return null;
}
- return ArgumentExpression(NamedParameterReference(name));
+ return CodeFragment([ArgumentAccessor(NamedParameterReference(name))]);
}
// TODO(brianwilkerson) Report the missing YAML.
return null;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
index 3bfb639..659bb47 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
@@ -2,74 +2,48 @@
// 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/accessor.dart';
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/dart/element/type.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.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;
+class CodeFragment extends ValueGenerator {
+ /// The accessor used to access the code fragment.
+ final List<Accessor> accessors;
- /// Initialize a newly created extractor to extract the argument that
- /// corresponds to the given [parameter].
- ArgumentExpression(this.parameter) : assert(parameter != null);
+ /// Initialize a newly created extractor to extract a code fragment.
+ CodeFragment(this.accessors);
@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;
+ Object target = context.node;
+ for (var accessor in accessors) {
+ var result = accessor.getValue(target);
+ if (!result.isValid) {
+ return false;
+ }
+ target = result.result;
}
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));
- }
+ Object target = context.node;
+ for (var accessor in accessors) {
+ target = accessor.getValue(target).result;
}
- }
-
- /// 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;
- }
+ if (target is AstNode) {
+ builder.write(context.utils.getRangeText(range.node(target)));
+ } else if (target is DartType) {
+ builder.writeType(target);
+ } else {
+ throw UnsupportedError('Unexpected result of ${target.runtimeType}');
}
- return null;
}
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
index 4802e4a..22a45ab 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
@@ -2,6 +2,7 @@
// 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/accessor.dart';
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:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
@@ -90,6 +91,6 @@
TemplateText _text(String text) => TemplateText(text);
- TemplateVariable _variable(int index) =>
- TemplateVariable(ArgumentExpression(PositionalParameterReference(index)));
+ TemplateVariable _variable(int index) => TemplateVariable(
+ CodeFragment([ArgumentAccessor(PositionalParameterReference(index))]));
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index 84bd57b..0e526cb 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -2,6 +2,7 @@
// 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/accessor.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
@@ -63,8 +64,7 @@
expect(modification.isPositional, false);
var components = modification.argumentValue.components;
expect(components, hasLength(1));
- var value =
- (components[0] as TemplateVariable).generator as ArgumentExpression;
+ var value = _accessor(components[0]) as ArgumentAccessor;
var parameter = value.parameter as PositionalParameterReference;
expect(parameter.index, 1);
}
@@ -135,8 +135,7 @@
expect(modification.isPositional, false);
var components = modification.argumentValue.components;
expect(components, hasLength(1));
- var value =
- (components[0] as TemplateVariable).generator as ArgumentExpression;
+ var value = _accessor(components[0]) as ArgumentAccessor;
var parameter = value.parameter as PositionalParameterReference;
expect(parameter.index, 1);
}
@@ -177,8 +176,7 @@
expect(modification.isPositional, true);
var components = modification.argumentValue.components;
expect(components, hasLength(1));
- var value =
- (components[0] as TemplateVariable).generator as ArgumentExpression;
+ var value = _accessor(components[0]) as ArgumentAccessor;
var parameter = value.parameter as PositionalParameterReference;
expect(parameter.index, 1);
}
@@ -222,13 +220,11 @@
expect(modification.isPositional, true);
var components = modification.argumentValue.components;
expect(components, hasLength(4));
- var extractorA =
- (components[0] as TemplateVariable).generator as ArgumentExpression;
+ var extractorA = _accessor(components[0]) as ArgumentAccessor;
var parameterA = extractorA.parameter as PositionalParameterReference;
expect(parameterA.index, 1);
expect((components[1] as TemplateText).text, '(');
- var extractorB =
- (components[2] as TemplateVariable).generator as ArgumentExpression;
+ var extractorB = _accessor(components[2]) as ArgumentAccessor;
var parameterB = extractorB.parameter as PositionalParameterReference;
expect(parameterB.index, 2);
expect((components[3] as TemplateText).text, ')');
@@ -304,8 +300,7 @@
var components = change.argumentValue.components;
expect(components, hasLength(1));
- var value =
- (components[0] as TemplateVariable).generator as ArgumentExpression;
+ var value = _accessor(components[0]) as ArgumentAccessor;
var parameter = value.parameter as NamedParameterReference;
expect(parameter.name, 'p');
}
@@ -348,8 +343,7 @@
var argumentComponents = change.argumentValue.components;
expect(argumentComponents, hasLength(1));
- var value = (argumentComponents[0] as TemplateVariable).generator
- as ArgumentExpression;
+ var value = _accessor(argumentComponents[0]) as ArgumentAccessor;
var parameter = value.parameter as PositionalParameterReference;
expect(parameter.index, 2);
}
@@ -562,6 +556,10 @@
expect(rename.newName, 'B');
}
+ /// Return the first accessor from the given [component].
+ Accessor _accessor(TemplateComponent component) =>
+ ((component as TemplateVariable).generator as CodeFragment).accessors[0];
+
ElementMatcher _matcher(String name) =>
ElementMatcher(importedUris: uris, name: name);
diff --git a/tools/VERSION b/tools/VERSION
index b4ad066..5ab24c7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 254
+PRERELEASE 255
PRERELEASE_PATCH 0
\ No newline at end of file