| 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 {
|
|
|