| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart'; |
| import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'; |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| |
| import '../../../protocol_server.dart' |
| show CompletionSuggestion, CompletionSuggestionKind; |
| |
| /** |
| * A contributor for calculating prefixed import library member suggestions |
| * `completion.getSuggestions` request results. |
| */ |
| class LibraryMemberContributor extends DartCompletionContributor { |
| @override |
| Future<List<CompletionSuggestion>> computeSuggestions( |
| DartCompletionRequest request) async { |
| // TODO(brianwilkerson) Determine whether this await is necessary. |
| await null; |
| // Determine if the target looks like a library prefix |
| Expression targetId = request.dotTarget; |
| if (targetId is SimpleIdentifier && !request.target.isCascade) { |
| Element elem = targetId.staticElement; |
| if (elem is PrefixElement && !elem.isSynthetic) { |
| LibraryElement containingLibrary = request.libraryElement; |
| // Gracefully degrade if the library or directives |
| // could not be determined (e.g. detached part file or source change) |
| if (containingLibrary != null) { |
| List<ImportElement> imports = containingLibrary.imports; |
| if (imports != null) { |
| return _buildSuggestions(request, elem, containingLibrary, imports); |
| } |
| } |
| } |
| } |
| return const <CompletionSuggestion>[]; |
| } |
| |
| List<CompletionSuggestion> _buildSuggestions( |
| DartCompletionRequest request, |
| PrefixElement elem, |
| LibraryElement containingLibrary, |
| List<ImportElement> imports) { |
| List<CompletionSuggestion> suggestions = <CompletionSuggestion>[]; |
| for (ImportElement importElem in imports) { |
| if (importElem.prefix?.name == elem.name) { |
| LibraryElement library = importElem.importedLibrary; |
| if (library != null) { |
| // Suggest elements from the imported library |
| AstNode parent = request.target.containingNode.parent; |
| bool isConstructor = parent.parent is ConstructorName; |
| bool typesOnly = parent is TypeName; |
| bool instCreation = typesOnly && isConstructor; |
| LibraryElementSuggestionBuilder builder = |
| new LibraryElementSuggestionBuilder(containingLibrary, |
| CompletionSuggestionKind.INVOCATION, typesOnly, instCreation); |
| for (var element in importElem.namespace.definedNames.values) { |
| element.accept(builder); |
| } |
| suggestions.addAll(builder.suggestions); |
| |
| // If the import is 'deferred' then suggest 'loadLibrary' |
| if (importElem.isDeferred) { |
| FunctionElement loadLibFunct = library.loadLibraryFunction; |
| suggestions.add(createSuggestion(loadLibFunct)); |
| } |
| } |
| } |
| } |
| return suggestions; |
| } |
| } |