blob: b2a44531b166bb4b3e98aa6c4bb877ea684a27aa [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.suggestion.builder;
import 'package:analysis_server/src/protocol.dart' hide Element;
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analyzer/src/generated/element.dart';
/**
* This class visits elements in a class and provides suggestions based upon
* the visible members in that class. Clients should call
* [ClassElementSuggestionBuilder.suggestionsFor].
*/
class ClassElementSuggestionBuilder extends GeneralizingElementVisitor {
final DartCompletionRequest request;
final Set<String> _completions = new Set<String>();
ClassElementSuggestionBuilder(this.request);
@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) {
_addSuggestion(
element,
CompletionSuggestionKind.FIELD,
element.type,
element.enclosingElement);
}
@override
visitMethodElement(MethodElement element) {
_addSuggestion(
element,
CompletionSuggestionKind.METHOD,
element.returnType,
element.enclosingElement);
}
@override
visitPropertyAccessorElement(PropertyAccessorElement element) {
if (element.isGetter) {
_addSuggestion(
element,
CompletionSuggestionKind.GETTER,
element.returnType,
element.enclosingElement);
} else if (element.isSetter) {
_addSuggestion(
element,
CompletionSuggestionKind.SETTER,
element.returnType,
element.enclosingElement);
}
}
void _addSuggestion(Element element, CompletionSuggestionKind kind,
DartType type, ClassElement enclosingElement) {
if (element.isSynthetic) {
return;
}
if (element.isPrivate) {
LibraryElement elementLibrary =
element.getAncestor((parent) => parent is LibraryElement);
LibraryElement unitLibrary =
request.unit.element.getAncestor((parent) => parent is LibraryElement);
if (elementLibrary != unitLibrary) {
return;
}
}
String completion = element.displayName;
if (completion == null ||
completion.length <= 0 ||
!_completions.add(completion)) {
return;
}
var suggestion = new CompletionSuggestion(
kind,
CompletionRelevance.DEFAULT,
completion,
completion.length,
0,
element.isDeprecated,
false);
if (enclosingElement != null) {
suggestion.declaringType = enclosingElement.displayName;
}
if (type != null) {
String typeName = type.displayName;
if (typeName != null && typeName.length > 0 && typeName != 'dynamic') {
suggestion.returnType = typeName;
}
}
request.suggestions.add(suggestion);
}
/**
* Add suggestions for the visible members in the given class
*/
static void suggestionsFor(DartCompletionRequest request, Element element) {
if (element is ClassElement) {
element.accept(new ClassElementSuggestionBuilder(request));
}
}
}
/**
* 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 {
final DartCompletionRequest request;
LibraryElementSuggestionBuilder(this.request);
@override
visitClassElement(ClassElement element) {
_addSuggestion(element);
}
@override
visitCompilationUnitElement(CompilationUnitElement element) {
element.visitChildren(this);
}
@override
visitElement(Element element) {
// ignored
}
@override
visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
_addSuggestion(element);
}
@override
visitTopLevelVariableElement(TopLevelVariableElement element) {
_addSuggestion(element);
}
void _addSuggestion(Element element) {
if (element != null) {
String completion = element.name;
if (completion != null && completion.length > 0) {
request.suggestions.add(
new CompletionSuggestion(
new CompletionSuggestionKind.fromElementKind(element.kind),
CompletionRelevance.DEFAULT,
completion,
completion.length,
0,
element.isDeprecated,
false));
}
}
}
/**
* Add suggestions for the visible members in the given library
*/
static void suggestionsFor(DartCompletionRequest request,
LibraryElement library) {
if (library != null) {
library.visitChildren(new LibraryElementSuggestionBuilder(request));
}
}
}