Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1684)

Unified Diff: pkg/analysis_server/lib/src/utilities/change_builder_dart.dart

Issue 2776233002: Enhance the change builders (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
diff --git a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
index 422549f16c0e5295629ca05bedcb78e30a461801..f9dfbef4f734157dfb2d707650a6639cf137a1b0 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -15,6 +15,7 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -61,16 +62,21 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder;
@override
+ LinkedEditBuilderImpl createLinkedEditBuilder() {
+ return new DartLinkedEditBuilderImpl(this);
+ }
+
+ @override
void writeClassDeclaration(String name,
{Iterable<DartType> interfaces,
bool isAbstract: false,
void memberWriter(),
Iterable<DartType> mixins,
String nameGroupName,
- DartType superclass}) {
+ DartType superclass,
+ String superclassGroupName: DartEditBuilder.SUPERCLASS_GROUP_ID}) {
// TODO(brianwilkerson) Add support for type parameters, probably as a
// parameterWriter parameter.
- // TODO(brianwilkerson) Add a superclassGroupName parameter.
if (isAbstract) {
write(Keyword.ABSTRACT.syntax);
write(' ');
@@ -85,7 +91,7 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
if (superclass != null) {
write(' extends ');
- writeType(superclass, groupName: DartEditBuilder.SUPERCLASS_GROUP_ID);
+ writeType(superclass, groupName: superclassGroupName);
} else if (mixins != null && mixins.isNotEmpty) {
write(' extends Object ');
}
@@ -132,13 +138,11 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
}
}
+ write('(');
if (argumentList != null) {
writeParametersMatchingArguments(argumentList);
- } else {
- write('()');
}
- writeln(' {');
- write(' }');
+ writeln(');');
}
@override
@@ -183,6 +187,46 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
@override
+ void writeFunctionDeclaration(String name,
+ {void bodyWriter(),
+ bool isStatic: false,
+ String nameGroupName,
+ void parameterWriter(),
+ DartType returnType,
+ String returnTypeGroupName}) {
+ if (isStatic) {
+ write(Keyword.STATIC.syntax);
+ write(' ');
+ }
+ if (returnType != null) {
+ writeType(returnType, groupName: returnTypeGroupName);
+ write(' ');
+ }
+ if (nameGroupName != null) {
+ addLinkedEdit(nameGroupName, (LinkedEditBuilder builder) {
+ write(name);
+ });
+ } else {
+ write(name);
+ }
+ write('(');
+ if (parameterWriter != null) {
+ parameterWriter();
+ }
+ write(')');
+ if (bodyWriter == null) {
+ if (returnType != null) {
+ write(' => null;');
+ } else {
+ write(' {}');
+ }
+ } else {
+ write(' ');
+ bodyWriter();
+ }
+ }
+
+ @override
void writeGetterDeclaration(String name,
{void bodyWriter(),
bool isStatic: false,
@@ -215,6 +259,46 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
@override
+ void writeLocalVariableDeclaration(String name,
+ {void initializerWriter(),
+ bool isConst: false,
+ bool isFinal: false,
+ String nameGroupName,
+ DartType type,
+ String typeGroupName}) {
+ bool typeRequired = true;
+ if (isConst) {
+ write(Keyword.CONST.syntax);
+ typeRequired = false;
+ } else if (isFinal) {
+ write(Keyword.FINAL.syntax);
+ typeRequired = false;
+ }
+ if (type != null) {
+ if (!typeRequired) {
+ // The type is required unless we're written a keyword.
+ write(' ');
+ }
+ writeType(type, groupName: typeGroupName);
+ } else if (typeRequired) {
+ write(Keyword.VAR.syntax);
+ }
+ write(' ');
+ if (nameGroupName != null) {
+ addLinkedEdit(nameGroupName, (LinkedEditBuilder builder) {
+ write(name);
+ });
+ } else {
+ write(name);
+ }
+ if (initializerWriter != null) {
+ write(' = ');
+ initializerWriter();
+ }
+ write(';');
+ }
+
+ @override
void writeOverrideOfInheritedMember(ExecutableElement member) {
// prepare environment
String prefix = utils.getIndent(1);
@@ -272,6 +356,29 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
@override
+ void writeParameterMatchingArgument(
+ Expression argument, int index, Set<String> usedNames) {
+ // append type name
+ DartType type = argument.bestType;
+ if (writeType(type, addSupertypeProposals: true, groupName: 'TYPE$index')) {
+ write(' ');
+ }
+ // append parameter name
+ if (argument is NamedExpression) {
+ write(argument.name.label.name);
+ } else {
+ List<String> suggestions =
+ _getParameterNameSuggestions(usedNames, type, argument, index);
+ String favorite = suggestions[0];
+ usedNames.add(favorite);
+ addLinkedEdit('PARAM$index', (LinkedEditBuilder builder) {
+ write(favorite);
+ builder.addSuggestions(LinkedEditSuggestionKind.PARAMETER, suggestions);
+ });
+ }
+ }
+
+ @override
void writeParameters(Iterable<ParameterElement> parameters) {
write('(');
bool sawNamed = false;
@@ -319,42 +426,26 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
@override
- void writeParametersMatchingArguments(ArgumentList arguments) {
- Set<String> excluded = new Set();
- bool namedFound = false;
- write('(');
- List<Expression> argumentList = arguments.arguments;
- for (int i = 0; i < argumentList.length; i++) {
- Expression argument = argumentList[i];
- DartType type = argument.bestType;
- List<String> suggestions =
- _getParameterNameSuggestions(excluded, type, argument, i);
- String favorite = suggestions[0];
- // append separator
+ void writeParametersMatchingArguments(ArgumentList argumentList) {
+ // TODO(brianwilkerson) Handle the case when there are required parameters
+ // after named parameters.
+ Set<String> usedNames = new Set<String>();
+ List<Expression> arguments = argumentList.arguments;
+ bool hasNamedParameters = false;
+ for (int i = 0; i < arguments.length; i++) {
+ Expression argument = arguments[i];
if (i > 0) {
write(', ');
}
- if (argument is NamedExpression) {
- if (!namedFound) {
- namedFound = true;
- write('[');
- }
- favorite = argument.name.label.name;
+ if (argument is NamedExpression && !hasNamedParameters) {
+ hasNamedParameters = true;
+ write('{');
}
- // append type name
- writeType(type, addSupertypeProposals: true, groupName: 'TYPE$i');
- write(' ');
- // append parameter name
- excluded.add(favorite);
- addLinkedEdit('ARG$i', (LinkedEditBuilder builder) {
- builder.write(favorite);
- builder.addSuggestions(LinkedEditSuggestionKind.PARAMETER, suggestions);
- });
+ writeParameterMatchingArgument(argument, i, usedNames);
}
- if (namedFound) {
- write(']');
+ if (hasNamedParameters) {
+ write('}');
}
- write(')');
}
@override
@@ -372,19 +463,23 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
if (type != null && !type.isDynamic) {
String typeSource =
utils.getTypeSource(type, dartFileEditBuilder.librariesToImport);
- if (groupName != null) {
- addLinkedEdit(groupName, (LinkedEditBuilder builder) {
+ if (typeSource != 'dynamic') {
+ if (groupName != null) {
+ addLinkedEdit(groupName, (LinkedEditBuilder builder) {
+ write(typeSource);
+ if (addSupertypeProposals) {
+ _addSuperTypeProposals(builder, type, new Set<DartType>());
+ }
+ });
+ } else {
write(typeSource);
- if (addSupertypeProposals) {
- _addSuperTypeProposals(builder, type, new Set<DartType>());
- }
- });
- } else {
- write(typeSource);
+ }
+ return true;
}
- return true;
- } else if (required) {
+ }
+ if (required) {
write(Keyword.VAR.syntax);
+ return true;
}
return false;
}
@@ -427,20 +522,21 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
/**
- * Return a list containing the suggested names for a parmeter with the given
+ * Return a list containing the suggested names for a parameter with the given
* [type] whose value in one location is computed by the given [expression].
* The list will not contain any names in the set of [excluded] names. The
* [index] is the index of the argument, used to create a name if no better
* name could be created. The first name in the list will be the best name.
*/
List<String> _getParameterNameSuggestions(
- Set<String> excluded, DartType type, Expression expression, int index) {
+ Set<String> usedNames, DartType type, Expression expression, int index) {
List<String> suggestions =
- getVariableNameSuggestionsForExpression(type, expression, excluded);
+ getVariableNameSuggestionsForExpression(type, expression, usedNames);
if (suggestions.length != 0) {
return suggestions;
}
- return <String>['arg$index'];
+ // TODO(brianwilkerson) Verify that the name below is not in the set of used names.
+ return <String>['param$index'];
}
}
@@ -477,7 +573,96 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
}
@override
+ void convertFunctionFromSyncToAsync(
+ FunctionBody body, TypeProvider typeProvider) {
+ if (body == null && body.keyword != null) {
+ throw new ArgumentError(
+ 'The function must have a synchronous, non-generator body.');
+ }
+ addInsertion(body.offset, (EditBuilder builder) {
+ builder.write('async ');
+ });
+ _replaceReturnTypeWithFuture(body, typeProvider);
+ }
+
+ @override
DartEditBuilderImpl createEditBuilder(int offset, int length) {
return new DartEditBuilderImpl(this, offset, length);
}
+
+ @override
+ void replaceTypeWithFuture(
+ TypeAnnotation typeAnnotation, TypeProvider typeProvider) {
+ InterfaceType futureType = typeProvider.futureType;
+ //
+ // Check whether the type needs to be replaced.
+ //
+ DartType type = typeAnnotation?.type;
+ if (type == null ||
+ type.isDynamic ||
+ type is InterfaceType && type.element == futureType.element) {
+ return;
+ }
+ // prepare code for the types
+ String futureTypeCode = utils.getTypeSource(futureType, librariesToImport);
+ String nodeCode = utils.getNodeText(typeAnnotation);
+ // wrap the existing type with Future
+ String returnTypeCode =
+ nodeCode == 'void' ? futureTypeCode : '$futureTypeCode<$nodeCode>';
+ addReplacement(typeAnnotation.offset, typeAnnotation.length,
+ (EditBuilder builder) {
+ builder.write(returnTypeCode);
+ });
+ }
+
+ /**
+ * Create an edit to replace the return type of the innermost function
+ * containing the given [node] with the type `Future`. The [typeProvider] is
+ * used to check the current return type, because if it is already `Future` no
+ * edit will be added.
+ */
+ void _replaceReturnTypeWithFuture(AstNode node, TypeProvider typeProvider) {
+ while (node != null) {
+ node = node.parent;
+ if (node is FunctionDeclaration) {
+ replaceTypeWithFuture(node.returnType, typeProvider);
+ return;
+ } else if (node is MethodDeclaration) {
+ replaceTypeWithFuture(node.returnType, typeProvider);
+ return;
+ }
+ }
+ }
+}
+
+/**
+ * A [LinkedEditBuilder] used to build linked edits for Dart files.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DartLinkedEditBuilderImpl extends LinkedEditBuilderImpl
+ implements DartLinkedEditBuilder {
+ /**
+ * Initialize a newly created linked edit builder.
+ */
+ DartLinkedEditBuilderImpl(EditBuilderImpl editBuilder) : super(editBuilder);
+
+ @override
+ void addSuperTypesAsSuggestions(DartType type) {
+ _addSuperTypesAsSuggestions(type, new Set<DartType>());
+ }
+
+ /**
+ * Safely implement [addSuperTypesAsSuggestions] by using the set of
+ * [alreadyAdded] types to prevent infinite loops.
+ */
+ void _addSuperTypesAsSuggestions(DartType type, Set<DartType> alreadyAdded) {
+ if (type is InterfaceType && alreadyAdded.add(type)) {
+ addSuggestion(LinkedEditSuggestionKind.TYPE, type.displayName);
+ _addSuperTypesAsSuggestions(type.superclass, alreadyAdded);
+ for (InterfaceType interfaceType in type.interfaces) {
+ _addSuperTypesAsSuggestions(interfaceType, alreadyAdded);
+ }
+ }
+ }
}

Powered by Google App Engine
This is Rietveld 408576698