blob: 7ecbc643a278b95a2be91760c5558cdbc5e81e2e [file] [log] [blame]
// 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.
library services.completion.contributor.dart.library_member;
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/src/generated/ast.dart';
import 'package:analyzer/src/generated/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 {
// Determine if the target looks like a library prefix
if (request.dotTarget is! SimpleIdentifier) {
return EMPTY_LIST;
}
// Resolve the expression and the containing library
await request.resolveExpression(request.dotTarget);
// Recompute the target since resolution may have changed it
Expression targetId = request.dotTarget;
if (targetId is SimpleIdentifier && !request.target.isCascade) {
Element elem = targetId.bestElement;
if (elem is PrefixElement) {
List<Directive> directives = await request.resolveDirectives();
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 && directives != null) {
return _buildSuggestions(
request, elem, containingLibrary, directives);
}
}
}
return EMPTY_LIST;
}
List<CompletionSuggestion> _buildSuggestions(
DartCompletionRequest request,
PrefixElement elem,
LibraryElement containingLibrary,
List<Directive> directives) {
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
for (Directive directive in directives) {
if (directive is ImportDirective) {
if (directive.prefix != null) {
if (directive.prefix.name == elem.name) {
LibraryElement library = directive.uriElement;
// Suggest elements from the imported library
if (library != null) {
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);
library.visitChildren(builder);
suggestions.addAll(builder.suggestions);
// If the import is 'deferred' then suggest 'loadLibrary'
if (directive.deferredKeyword != null) {
FunctionElement loadLibFunct = library.loadLibraryFunction;
suggestions.add(createSuggestion(loadLibFunct));
}
}
}
}
}
}
return suggestions;
}
}