Index: pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart |
diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart |
index 2acb7e600f660c5cdff3ded829f598ed0af0e82b..4379e7fadc7f9beecfe12d09a6745d56ece8956b 100644 |
--- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart |
+++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart |
@@ -5,7 +5,6 @@ |
library services.completion.suggestion.builder; |
import 'dart:async'; |
-import 'dart:collection'; |
import 'package:analysis_server/src/protocol_server.dart' |
hide Element, ElementKind; |
@@ -14,7 +13,6 @@ import 'package:analysis_server/src/services/completion/dart/suggestion_builder. |
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart'; |
import 'package:analyzer/src/generated/ast.dart'; |
import 'package:analyzer/src/generated/element.dart'; |
-import 'package:analyzer/src/generated/engine.dart' as engine; |
export 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart' |
show createSuggestion; |
@@ -174,366 +172,6 @@ abstract class ElementSuggestionBuilder { |
} |
/** |
- * This class provides suggestions based upon the visible instance members in |
- * an interface type. Clients should call |
- * [InterfaceTypeSuggestionBuilder.suggestionsFor]. |
- */ |
-class InterfaceTypeSuggestionBuilder { |
- /** |
- * Enumerated value indicating that we have not generated any completions for |
- * a given identifier yet. |
- */ |
- static const int _COMPLETION_TYPE_NONE = 0; |
- |
- /** |
- * Enumerated value indicating that we have generated a completion for a |
- * getter. |
- */ |
- static const int _COMPLETION_TYPE_GETTER = 1; |
- |
- /** |
- * Enumerated value indicating that we have generated a completion for a |
- * setter. |
- */ |
- static const int _COMPLETION_TYPE_SETTER = 2; |
- |
- /** |
- * Enumerated value indicating that we have generated a completion for a |
- * field, a method, or a getter/setter pair. |
- */ |
- static const int _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET = 3; |
- |
- final DartCompletionRequest request; |
- |
- /** |
- * Map indicating, for each possible completion identifier, whether we have |
- * already generated completions for a getter, setter, or both. The "both" |
- * case also handles the case where have generated a completion for a method |
- * or a field. |
- * |
- * Note: the enumerated values stored in this map are intended to be bitwise |
- * compared. |
- */ |
- Map<String, int> _completionTypesGenerated = new HashMap<String, int>(); |
- |
- InterfaceTypeSuggestionBuilder(this.request); |
- |
- CompletionSuggestionKind get kind => CompletionSuggestionKind.INVOCATION; |
- |
- /** |
- * Add a suggestion based upon the given element, provided that it is not |
- * shadowed by a previously added suggestion. |
- */ |
- void addSuggestion(Element element, {int relevance: DART_RELEVANCE_DEFAULT}) { |
- if (element.isPrivate) { |
- LibraryElement elementLibrary = element.library; |
- LibraryElement unitLibrary = request.unit.element.library; |
- if (elementLibrary != unitLibrary) { |
- return; |
- } |
- } |
- String identifier = element.displayName; |
- int alreadyGenerated = _completionTypesGenerated.putIfAbsent( |
- identifier, () => _COMPLETION_TYPE_NONE); |
- if (element is MethodElement) { |
- // Anything shadows a method. |
- if (alreadyGenerated != _COMPLETION_TYPE_NONE) { |
- return; |
- } |
- _completionTypesGenerated[identifier] = |
- _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET; |
- } else if (element is PropertyAccessorElement) { |
- if (element.isGetter) { |
- // Getters, fields, and methods shadow a getter. |
- if ((alreadyGenerated & _COMPLETION_TYPE_GETTER) != 0) { |
- return; |
- } |
- _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_GETTER; |
- } else { |
- // Setters, fields, and methods shadow a setter. |
- if ((alreadyGenerated & _COMPLETION_TYPE_SETTER) != 0) { |
- return; |
- } |
- _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_SETTER; |
- } |
- } else if (element is FieldElement) { |
- // Fields and methods shadow a field. A getter/setter pair shadows a |
- // field, but a getter or setter by itself doesn't. |
- if (alreadyGenerated == _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET) { |
- return; |
- } |
- _completionTypesGenerated[identifier] = |
- _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET; |
- } else { |
- // Unexpected element type; skip it. |
- assert(false); |
- return; |
- } |
- CompletionSuggestion suggestion = |
- createSuggestion(element, kind: kind, relevance: relevance); |
- if (suggestion != null) { |
- request.addSuggestion(suggestion); |
- } |
- } |
- |
- void _buildSuggestions(InterfaceType type, LibraryElement library, |
- bool isSuper, String containingMethodName) { |
- if (isSuper) { |
- // Suggest members from superclass if the target is "super" |
- type = type.superclass; |
- if (type == null) { |
- return; |
- } |
- } |
- // Visit all of the types in the class hierarchy, collecting possible |
- // completions. If multiple elements are found that complete to the same |
- // identifier, addSuggestion will discard all but the first (with a few |
- // exceptions to handle getter/setter pairs). |
- List<InterfaceType> types = _getTypeOrdering(type); |
- for (InterfaceType targetType in types) { |
- for (MethodElement method in targetType.methods) { |
- // Exclude static methods when completion on an instance |
- if (!method.isStatic) { |
- addSuggestion(method, |
- relevance: method.name == containingMethodName |
- ? DART_RELEVANCE_HIGH |
- : DART_RELEVANCE_DEFAULT); |
- } |
- } |
- for (PropertyAccessorElement propertyAccessor in targetType.accessors) { |
- if (!propertyAccessor.isStatic) { |
- if (propertyAccessor.isSynthetic) { |
- // Avoid visiting a field twice |
- if (propertyAccessor.isGetter) { |
- addSuggestion(propertyAccessor.variable); |
- } |
- } else { |
- addSuggestion(propertyAccessor); |
- } |
- } |
- } |
- } |
- } |
- |
- /** |
- * Get a list of [InterfaceType]s that should be searched to find the |
- * possible completions for an object having type [type]. |
- */ |
- List<InterfaceType> _getTypeOrdering(InterfaceType type) { |
- // Candidate completions can come from [type] as well as any types above it |
- // in the class hierarchy (including mixins, superclasses, and interfaces). |
- // If a given completion identifier shows up in multiple types, we should |
- // use the element that is nearest in the superclass chain, so we will |
- // visit [type] first, then its mixins, then its superclass, then its |
- // superclass's mixins, etc., and only afterwards visit interfaces. |
- // |
- // We short-circuit loops in the class hierarchy by keeping track of the |
- // classes seen (not the interfaces) so that we won't be fooled by nonsense |
- // like "class C<T> extends C<List<T>> {}" |
- List<InterfaceType> result = <InterfaceType>[]; |
- Set<ClassElement> classesSeen = new HashSet<ClassElement>(); |
- List<InterfaceType> typesToVisit = <InterfaceType>[type]; |
- while (typesToVisit.isNotEmpty) { |
- InterfaceType nextType = typesToVisit.removeLast(); |
- if (!classesSeen.add(nextType.element)) { |
- // Class had already been seen, so ignore this type. |
- continue; |
- } |
- result.add(nextType); |
- // typesToVisit is a stack, so push on the interfaces first, then the |
- // superclass, then the mixins. This will ensure that they are visited |
- // in the reverse order. |
- typesToVisit.addAll(nextType.interfaces); |
- if (nextType.superclass != null) { |
- typesToVisit.add(nextType.superclass); |
- } |
- typesToVisit.addAll(nextType.mixins); |
- } |
- return result; |
- } |
- |
- /** |
- * Add suggestions for the visible members in the given interface |
- */ |
- static void suggestionsFor(DartCompletionRequest request, DartType type, |
- {bool isSuper: false, String containingMethodName: null}) { |
- CompilationUnit compilationUnit = |
- request.target.containingNode.getAncestor((n) => n is CompilationUnit); |
- CompilationUnitElement unitElem = compilationUnit.element; |
- if (unitElem == null) { |
- engine.AnalysisEngine.instance.logger |
- .logInformation('Completion expected resolved AST'); |
- return; |
- } |
- LibraryElement library = unitElem.library; |
- if (type is DynamicTypeImpl) { |
- type = request.cache.objectClassElement.type; |
- } |
- if (type is InterfaceType) { |
- new InterfaceTypeSuggestionBuilder(request) |
- ._buildSuggestions(type, library, isSuper, containingMethodName); |
- } |
- } |
-} |
- |
-/** |
- * This class visits elements in a library and provides suggestions based upon |
- * the visible members in that library. Clients should call |
- * [LibraryElementSuggestionBuilder.suggestionsFor]. |
- */ |
-class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor |
- with ElementSuggestionBuilder { |
- final DartCompletionRequest request; |
- final CompletionSuggestionKind kind; |
- final bool typesOnly; |
- final bool instCreation; |
- |
- LibraryElementSuggestionBuilder( |
- this.request, this.kind, this.typesOnly, this.instCreation); |
- |
- @override |
- visitClassElement(ClassElement element) { |
- if (instCreation) { |
- element.visitChildren(this); |
- } else { |
- addSuggestion(element); |
- } |
- } |
- |
- @override |
- visitCompilationUnitElement(CompilationUnitElement element) { |
- element.visitChildren(this); |
- LibraryElement containingLibrary = element.library; |
- if (containingLibrary != null) { |
- for (var lib in containingLibrary.exportedLibraries) { |
- lib.visitChildren(this); |
- } |
- } |
- } |
- |
- @override |
- visitConstructorElement(ConstructorElement element) { |
- if (instCreation) { |
- ClassElement classElem = element.enclosingElement; |
- if (classElem != null) { |
- String prefix = classElem.name; |
- if (prefix != null && prefix.length > 0) { |
- addSuggestion(element, prefix: prefix); |
- } |
- } |
- } |
- } |
- |
- @override |
- visitElement(Element element) { |
- // ignored |
- } |
- |
- @override |
- visitFunctionElement(FunctionElement element) { |
- if (!typesOnly) { |
- addSuggestion(element); |
- } |
- } |
- |
- @override |
- visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
- if (!instCreation) { |
- addSuggestion(element); |
- } |
- } |
- |
- @override |
- visitTopLevelVariableElement(TopLevelVariableElement element) { |
- if (!typesOnly) { |
- addSuggestion(element); |
- } |
- } |
- |
- /** |
- * Add suggestions for the visible members in the given library |
- */ |
- static void suggestionsFor( |
- DartCompletionRequest request, |
- CompletionSuggestionKind kind, |
- LibraryElement library, |
- bool typesOnly, |
- bool instCreation) { |
- if (library != null) { |
- library.visitChildren(new LibraryElementSuggestionBuilder( |
- request, kind, typesOnly, instCreation)); |
- } |
- } |
-} |
- |
-/** |
- * This class visits elements in a class and provides suggestions based upon |
- * the visible static members in that class. Clients should call |
- * [StaticClassElementSuggestionBuilder.suggestionsFor]. |
- */ |
-class StaticClassElementSuggestionBuilder extends GeneralizingElementVisitor |
- with ElementSuggestionBuilder { |
- final DartCompletionRequest request; |
- |
- StaticClassElementSuggestionBuilder(this.request); |
- |
- @override |
- CompletionSuggestionKind get kind => CompletionSuggestionKind.INVOCATION; |
- |
- @override |
- visitClassElement(ClassElement element) { |
- element.visitChildren(this); |
- element.allSupertypes.forEach((InterfaceType type) { |
- type.element.visitChildren(this); |
- }); |
- } |
- |
- @override |
- visitElement(Element element) { |
- // ignored |
- } |
- |
- @override |
- visitFieldElement(FieldElement element) { |
- if (!element.isStatic) { |
- return; |
- } |
- addSuggestion(element); |
- } |
- |
- @override |
- visitMethodElement(MethodElement element) { |
- if (!element.isStatic) { |
- return; |
- } |
- if (element.isOperator) { |
- return; |
- } |
- addSuggestion(element); |
- } |
- |
- @override |
- visitPropertyAccessorElement(PropertyAccessorElement element) { |
- if (!element.isStatic) { |
- return; |
- } |
- addSuggestion(element); |
- } |
- |
- /** |
- * Add suggestions for the visible members in the given class |
- */ |
- static void suggestionsFor(DartCompletionRequest request, Element element) { |
- if (element == DynamicElementImpl.instance) { |
- element = request.cache.objectClassElement; |
- } |
- if (element is ClassElement) { |
- return element.accept(new StaticClassElementSuggestionBuilder(request)); |
- } |
- } |
-} |
- |
-/** |
* Common interface implemented by suggestion builders. |
*/ |
abstract class SuggestionBuilder { |