| Index: pkg/analysis_server/lib/src/services/completion/imported_computer.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart b/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
|
| index 24ae17476f5fb32734d9286387b207a609281e14..e5a50724700ec870def4ef3e1924963df5bd37cd 100644
|
| --- a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
|
| +++ b/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
|
| @@ -49,7 +49,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
|
|
| @override
|
| Future<bool> visitBlock(Block node) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
|
|
| @override
|
| @@ -58,7 +58,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| // InvocationComputer makes selector suggestions
|
| Expression target = node.target;
|
| if (target != null && request.offset <= target.end) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -68,7 +68,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| // Make suggestions in the body of the class declaration
|
| Token leftBracket = node.leftBracket;
|
| if (leftBracket != null && request.offset >= leftBracket.end) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -80,7 +80,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
|
|
| @override
|
| Future<bool> visitExpression(Expression node) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
|
|
| @override
|
| @@ -89,7 +89,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| // A pre-variable declaration (e.g. C ^) is parsed as an expression
|
| // statement. Do not make suggestions for the variable name.
|
| if (expression is SimpleIdentifier && request.offset <= expression.end) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -98,7 +98,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| Future<bool> visitForStatement(ForStatement node) {
|
| Token leftParenthesis = node.leftParenthesis;
|
| if (leftParenthesis != null && request.offset >= leftParenthesis.end) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -109,7 +109,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| if (leftParen != null && request.offset >= leftParen.end) {
|
| Token rightParen = node.rightParenthesis;
|
| if (rightParen == null || request.offset <= rightParen.offset) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| }
|
| return new Future.value(false);
|
| @@ -119,7 +119,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| Future<bool> visitInterpolationExpression(InterpolationExpression node) {
|
| Expression expression = node.expression;
|
| if (expression is SimpleIdentifier) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -128,7 +128,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| Future<bool> visitMethodInvocation(MethodInvocation node) {
|
| Token period = node.period;
|
| if (period == null || request.offset <= period.offset) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -144,7 +144,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| // InvocationComputer makes selector suggestions
|
| Token period = node.period;
|
| if (period != null && request.offset <= period.offset) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -155,7 +155,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| // InvocationComputer makes property name suggestions
|
| var operator = node.operator;
|
| if (operator != null && request.offset < operator.offset) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -172,7 +172,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
|
|
| @override
|
| Future<bool> visitTypeName(TypeName node) {
|
| - return _addImportedElementSuggestions(typesOnly: true);
|
| + return _addImportedElementSuggestions(node, typesOnly: true);
|
| }
|
|
|
| @override
|
| @@ -180,7 +180,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| Token equals = node.equals;
|
| // Make suggestions for the RHS of a variable declaration
|
| if (equals != null && request.offset >= equals.end) {
|
| - return _addImportedElementSuggestions();
|
| + return _addImportedElementSuggestions(node);
|
| }
|
| return new Future.value(false);
|
| }
|
| @@ -197,6 +197,13 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| }
|
|
|
| void _addElementSuggestion(Element element, CompletionRelevance relevance) {
|
| +
|
| + if (element is ExecutableElement) {
|
| + if (element.isOperator) {
|
| + return;
|
| + }
|
| + }
|
| +
|
| CompletionSuggestionKind kind =
|
| newCompletionSuggestionKind_fromElementKind(element.kind);
|
|
|
| @@ -230,7 +237,14 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| request.suggestions.add(suggestion);
|
| }
|
|
|
| - Future<bool> _addImportedElementSuggestions({bool typesOnly: false}) {
|
| + void _addElementSuggestions(List<Element> elements) {
|
| + elements.forEach((Element elem) {
|
| + _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
|
| + });
|
| + }
|
| +
|
| + Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly:
|
| + false}) {
|
|
|
| // Exclude elements from local library
|
| // because they are provided by LocalComputer
|
| @@ -238,6 +252,7 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| excludedLibs.add(request.unit.element.enclosingElement);
|
|
|
| // Include explicitly imported elements
|
| + Map<String, ClassElement> classMap = new Map<String, ClassElement>();
|
| request.unit.directives.forEach((Directive directive) {
|
| if (directive is ImportDirective) {
|
| ImportElement importElem = directive.element;
|
| @@ -245,9 +260,13 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| if (directive.prefix == null) {
|
| Namespace importNamespace =
|
| new NamespaceBuilder().createImportNamespaceForDirective(importElem);
|
| - importNamespace.definedNames.forEach((_, Element element) {
|
| - if (!typesOnly || element is ClassElement) {
|
| - _addElementSuggestion(element, CompletionRelevance.DEFAULT);
|
| + // Include top level elements
|
| + importNamespace.definedNames.forEach((String name, Element elem) {
|
| + if (elem is ClassElement) {
|
| + classMap[name] = elem;
|
| + _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
|
| + } else if (!typesOnly) {
|
| + _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
|
| }
|
| });
|
| } else {
|
| @@ -265,12 +284,42 @@ class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| LibraryElement coreLib = request.context.getLibraryElement(coreUri);
|
| Namespace coreNamespace =
|
| new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
|
| - coreNamespace.definedNames.forEach((_, Element element) {
|
| - if (!typesOnly || element is ClassElement) {
|
| - _addElementSuggestion(element, CompletionRelevance.DEFAULT);
|
| + coreNamespace.definedNames.forEach((String name, Element elem) {
|
| + if (elem is ClassElement) {
|
| + classMap[name] = elem;
|
| + _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
|
| + } else if (!typesOnly) {
|
| + _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
|
| }
|
| });
|
|
|
| + // Build a list of inherited types that are imported
|
| + // and include any inherited imported members
|
| + var classDecl = node.getAncestor((p) => p is ClassDeclaration);
|
| + if (classDecl is ClassDeclaration) {
|
| + List<String> inheritedTypes = new List<String>();
|
| + visitInheritedTypes(classDecl, (ClassDeclaration classDecl) {
|
| + // ignored
|
| + }, (String typeName) {
|
| + inheritedTypes.add(typeName);
|
| + });
|
| + Set<String> visited = new Set<String>();
|
| + while (inheritedTypes.length > 0) {
|
| + String name = inheritedTypes.removeLast();
|
| + ClassElement elem = classMap[name];
|
| + if (visited.add(name) && elem != null) {
|
| + _addElementSuggestions(elem.accessors);
|
| + _addElementSuggestions(elem.methods);
|
| + elem.allSupertypes.forEach((InterfaceType type) {
|
| + if (visited.add(type.name)) {
|
| + _addElementSuggestions(type.accessors);
|
| + _addElementSuggestions(type.methods);
|
| + }
|
| + });
|
| + }
|
| + }
|
| + }
|
| +
|
| // Add non-imported elements as low relevance
|
| var future = request.searchEngine.searchTopLevelDeclarations('');
|
| return future.then((List<SearchMatch> matches) {
|
|
|