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

Unified Diff: pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart

Issue 1504223005: extract TypeMemberContributor from prefixed element contributor (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: mege Created 5 years 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/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 {

Powered by Google App Engine
This is Rietveld 408576698