blob: 24e45fcf6ca2082e447ce57fc8258ced65b3436b [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.
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 that produces suggestions based on the members of a library
/// when the library was imported using a prefix. More concretely, this class
/// produces suggestions for expressions of the form `p.^`, where `p` is a
/// prefix.
class LibraryMemberContributor extends DartCompletionContributor {
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request, SuggestionBuilder builder) async {
// Determine if the target looks like a library prefix.
var targetId = request.dotTarget;
if (targetId is SimpleIdentifier && !request.target.isCascade) {
var elem = targetId.staticElement;
if (elem is PrefixElement && !elem.isSynthetic) {
var 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) {
var imports = containingLibrary.imports;
if (imports != null) {
return _buildSuggestions(request, elem, imports);
}
}
}
}
return const <CompletionSuggestion>[];
}
List<CompletionSuggestion> _buildSuggestions(DartCompletionRequest request,
PrefixElement elem, List<ImportElement> imports) {
var parent = request.target.containingNode.parent;
var isConstructor = parent.parent is ConstructorName;
var typesOnly = parent is TypeName;
var instCreation = typesOnly && isConstructor;
var builder = LibraryElementSuggestionBuilder(
request, CompletionSuggestionKind.INVOCATION, typesOnly, instCreation);
for (var importElem in imports) {
if (importElem.prefix?.name == elem.name) {
var library = importElem.importedLibrary;
if (library != null) {
// Suggest elements from the imported library.
for (var element in importElem.namespace.definedNames.values) {
element.accept(builder);
}
// If the import is 'deferred' then suggest 'loadLibrary'.
if (importElem.isDeferred) {
var function = library.loadLibraryFunction;
var useNewRelevance = request.useNewRelevance;
var relevance = useNewRelevance
? Relevance.loadLibrary
: DART_RELEVANCE_DEFAULT;
builder.suggestions.add(createSuggestion(request, function,
relevance: relevance, useNewRelevance: useNewRelevance));
}
}
}
}
return builder.suggestions;
}
}