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

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

Issue 2866603002: Remove the use of CorrectionUtilities (Closed)
Patch Set: Created 3 years, 7 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
« no previous file with comments | « pkg/analysis_server/lib/src/provisional/edit/utilities/change_builder_dart.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 87d450051eca253d1e44e62f618deee24f193540..cfe406706935b67eb92c717770895bd5e8e7db1f 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -17,6 +17,8 @@ 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/dart/ast/utilities.dart';
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -49,26 +51,15 @@ class DartChangeBuilderImpl extends ChangeBuilderImpl
*/
class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
/**
- * A utility class used to help build the source code.
- */
- final CorrectionUtils utils;
-
- /**
* Initialize a newly created builder to build a source edit.
*/
DartEditBuilderImpl(
DartFileEditBuilderImpl sourceFileEditBuilder, int offset, int length)
- : utils = sourceFileEditBuilder.utils,
- super(sourceFileEditBuilder, offset, length);
+ : super(sourceFileEditBuilder, offset, length);
DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder;
@override
- void set targetClassElement(ClassElement element) {
- utils.targetClassElement = element;
- }
-
- @override
LinkedEditBuilderImpl createLinkedEditBuilder() {
return new DartLinkedEditBuilderImpl(this);
}
@@ -78,13 +69,6 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
*/
String getIndent(int level) => ' ' * level;
-// /**
-// * Arrange to have imports added for each of the given [libraries].
-// */
-// void importLibraries(Iterable<Source> libraries) {
-// dartFileEditBuilder.importLibraries(libraries);
-// }
-
/**
* Arrange to have an import added for the given [library].
*/
@@ -474,8 +458,10 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
@override
void writeParameterSource(DartType type, String name) {
- String parameterSource = utils.getParameterSource(
- type, name, dartFileEditBuilder.librariesToImport);
+ _EnclosingElementFinder finder = new _EnclosingElementFinder();
+ finder.find(dartFileEditBuilder.unit, offset);
+ String parameterSource = _getParameterSource(
+ type, name, finder.enclosingClass, finder.enclosingExecutable);
write(parameterSource);
}
@@ -485,8 +471,10 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
String groupName,
bool required: false}) {
if (type != null && !type.isDynamic) {
- String typeSource =
- utils.getTypeSource(type, dartFileEditBuilder.librariesToImport);
+ _EnclosingElementFinder finder = new _EnclosingElementFinder();
+ finder.find(dartFileEditBuilder.unit, offset);
+ String typeSource = _getTypeSource(
+ type, finder.enclosingClass, finder.enclosingExecutable);
if (typeSource != 'dynamic') {
if (groupName != null) {
addLinkedEdit(groupName, (LinkedEditBuilder builder) {
@@ -571,6 +559,21 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
/**
+ * Return the import element used to import the given [element] into the given
+ * [library], or `null` if the element was not imported, such as when the
+ * element is declared in the same library.
+ */
+ ImportElement _getImportElement(Element element, LibraryElement library) {
+ for (ImportElement imp in library.imports) {
+ Map<String, Element> definedNames = getImportNamespace(imp);
+ if (definedNames.containsValue(element)) {
+ return imp;
+ }
+ }
+ return null;
+ }
+
+ /**
* 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
@@ -587,6 +590,171 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
// TODO(brianwilkerson) Verify that the name below is not in the set of used names.
return <String>['param$index'];
}
+
+ /**
+ * Return the source for the parameter with the given [type] and [name].
+ */
+ String _getParameterSource(DartType type, String name,
+ ClassElement enclosingClass, ExecutableElement enclosingExecutable) {
+ // no type
+ if (type == null || type.isDynamic) {
+ return name;
+ }
+ // function type
+ if (type is FunctionType && type.element.isSynthetic) {
+ FunctionType functionType = type;
+ StringBuffer sb = new StringBuffer();
+ // return type
+ DartType returnType = functionType.returnType;
+ if (returnType != null && !returnType.isDynamic) {
+ String returnTypeSource =
+ _getTypeSource(returnType, enclosingClass, enclosingExecutable);
+ sb.write(returnTypeSource);
+ sb.write(' ');
+ }
+ // parameter name
+ sb.write(name);
+ // parameters
+ sb.write('(');
+ List<ParameterElement> fParameters = functionType.parameters;
+ for (int i = 0; i < fParameters.length; i++) {
+ ParameterElement fParameter = fParameters[i];
+ if (i != 0) {
+ sb.write(", ");
+ }
+ sb.write(_getParameterSource(fParameter.type, fParameter.name,
+ enclosingClass, enclosingExecutable));
+ }
+ sb.write(')');
+ // done
+ return sb.toString();
+ }
+ // simple type
+ String typeSource =
+ _getTypeSource(type, enclosingClass, enclosingExecutable);
+ return '$typeSource $name';
+ }
+
+ /**
+ * Returns the source to reference [type] in this [CompilationUnit].
+ *
+ * Fills [librariesToImport] with [LibraryElement]s whose elements are
+ * used by the generated source, but not imported.
+ */
+ String _getTypeSource(DartType type, ClassElement enclosingClass,
+ ExecutableElement enclosingExecutable,
+ {StringBuffer parametersBuffer}) {
+ StringBuffer sb = new StringBuffer();
+ // type parameter
+ if (!_isTypeVisible(type, enclosingClass, enclosingExecutable)) {
+ return 'dynamic';
+ }
+ // just a Function, not FunctionTypeAliasElement
+ if (type is FunctionType && type.element is! FunctionTypeAliasElement) {
+ if (parametersBuffer == null) {
+ return "Function";
+ }
+ parametersBuffer.write('(');
+ for (ParameterElement parameter in type.parameters) {
+ String parameterType =
+ _getTypeSource(parameter.type, enclosingClass, enclosingExecutable);
+ if (parametersBuffer.length != 1) {
+ parametersBuffer.write(', ');
+ }
+ parametersBuffer.write(parameterType);
+ parametersBuffer.write(' ');
+ parametersBuffer.write(parameter.name);
+ }
+ parametersBuffer.write(')');
+ return _getTypeSource(
+ type.returnType, enclosingClass, enclosingExecutable);
+ }
+ // <Bottom>, Null
+ if (type.isBottom || type.isDartCoreNull) {
+ return 'dynamic';
+ }
+ // prepare element
+ Element element = type.element;
+ if (element == null) {
+ String source = type.toString();
+ source = source.replaceAll('<dynamic>', '');
+ source = source.replaceAll('<dynamic, dynamic>', '');
+ return source;
+ }
+ // check if imported
+ LibraryElement definingLibrary = element.library;
+ LibraryElement importingLibrary = dartFileEditBuilder.unit.element.library;
+ if (definingLibrary != null && definingLibrary != importingLibrary) {
+ // no source, if private
+ if (element.isPrivate) {
+ return null;
+ }
+ // ensure import
+ ImportElement importElement =
+ _getImportElement(element, importingLibrary);
+ if (importElement != null) {
+ if (importElement.prefix != null) {
+ sb.write(importElement.prefix.displayName);
+ sb.write(".");
+ }
+ } else {
+ importLibrary(definingLibrary.source);
+ }
+ }
+ // append simple name
+ String name = element.displayName;
+ sb.write(name);
+ // may be type arguments
+ if (type is ParameterizedType) {
+ List<DartType> arguments = type.typeArguments;
+ // check if has arguments
+ bool hasArguments = false;
+ bool allArgumentsVisible = true;
+ for (DartType argument in arguments) {
+ hasArguments = hasArguments || !argument.isDynamic;
+ allArgumentsVisible = allArgumentsVisible &&
+ _isTypeVisible(argument, enclosingClass, enclosingExecutable);
+ }
+ // append type arguments
+ if (hasArguments && allArgumentsVisible) {
+ sb.write("<");
+ for (int i = 0; i < arguments.length; i++) {
+ DartType argument = arguments[i];
+ if (i != 0) {
+ sb.write(", ");
+ }
+ String argumentSrc =
+ _getTypeSource(argument, enclosingClass, enclosingExecutable);
+ if (argumentSrc != null) {
+ sb.write(argumentSrc);
+ } else {
+ return null;
+ }
+ }
+ sb.write(">");
+ }
+ }
+ // done
+ return sb.toString();
+ }
+
+ /**
+ * Checks if [type] is visible in either the [enclosingExecutable] or
+ * [enclosingClass].
+ */
+ bool _isTypeVisible(DartType type, ClassElement enclosingClass,
+ ExecutableElement enclosingExecutable) {
+ if (type is TypeParameterType) {
+ TypeParameterElement parameterElement = type.element;
+ Element parameterParent = parameterElement.enclosingElement;
+ // TODO(brianwilkerson) This needs to compare the parameterParent with
+ // each of the parents of the enclosingElement. (That means that we only
+ // need the most closely enclosing element.)
+ return identical(parameterParent, enclosingExecutable) ||
+ identical(parameterParent, enclosingClass);
+ }
+ return true;
+ }
}
/**
@@ -600,26 +768,24 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
CompilationUnit unit;
/**
- * A utility class used to help build the source code.
- */
- CorrectionUtils utils;
-
- /**
* A set containing the sources of the libraries that need to be imported in
* order to make visible the names used in generated code.
*/
Set<Source> librariesToImport = new Set<Source>();
/**
+ * The content of the file being edited.
+ */
+ String _content;
+
+ /**
* Initialize a newly created builder to build a source file edit within the
* change being built by the given [changeBuilder]. The file being edited has
* the given [source] and [timeStamp], and the given fully resolved [unit].
*/
DartFileEditBuilderImpl(DartChangeBuilderImpl changeBuilder, String path,
int timeStamp, this.unit)
- : super(changeBuilder, path, timeStamp) {
- utils = new CorrectionUtils(unit);
- }
+ : super(changeBuilder, path, timeStamp);
@override
void convertFunctionFromSyncToAsync(
@@ -645,6 +811,21 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
changeBuilder.sourceChange, unit.element.library, librariesToImport);
}
+ /**
+ * Return the content of the file being edited.
+ */
+ String getContent() {
+ if (_content == null) {
+ CompilationUnitElement unitElement = unit.element;
+ AnalysisContext context = unitElement.context;
+ if (context == null) {
+ throw new CancelCorrectionException();
+ }
+ _content = context.getContents(unitElement.source).data;
+ }
+ return _content;
+ }
+
@override
void importLibraries(Iterable<Source> libraries) {
librariesToImport.addAll(libraries);
@@ -663,18 +844,30 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
type is InterfaceType && type.element == futureType.element) {
return;
}
+ futureType = futureType.instantiate(<DartType>[type]);
// 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(rangeNode(typeAnnotation), (EditBuilder builder) {
- builder.write(returnTypeCode);
+ if (!(builder as DartEditBuilder).writeType(futureType)) {
+ builder.write('void');
+ }
});
}
/**
+ * Returns the text of the given [AstNode] in the unit.
+ */
+ String _getNodeText(AstNode node) {
+ return _getText(node.offset, node.length);
+ }
+
+ /**
+ * Returns the text of the given range in the unit.
+ */
+ String _getText(int offset, int length) {
+ return getContent().substring(offset, offset + length);
+ }
+
+ /**
* 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
@@ -725,3 +918,26 @@ class DartLinkedEditBuilderImpl extends LinkedEditBuilderImpl
}
}
}
+
+class _EnclosingElementFinder {
+ ClassElement enclosingClass;
+ ExecutableElement enclosingExecutable;
+
+ _EnclosingElementFinder();
+
+ void find(AstNode target, int offset) {
+ AstNode node = new NodeLocator2(offset).searchWithin(target);
+ while (node != null) {
+ if (node is ClassDeclaration) {
+ enclosingClass = node.element;
+ } else if (node is ConstructorDeclaration) {
+ enclosingExecutable = node.element;
+ } else if (node is MethodDeclaration) {
+ enclosingExecutable = node.element;
+ } else if (node is FunctionDeclaration) {
+ enclosingExecutable = node.element;
+ }
+ node = node.parent;
+ }
+ }
+}
« no previous file with comments | « pkg/analysis_server/lib/src/provisional/edit/utilities/change_builder_dart.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698