| Index: pkg/analysis_services/lib/src/completion/imported_type_computer.dart
|
| diff --git a/pkg/analysis_services/lib/src/completion/imported_type_computer.dart b/pkg/analysis_services/lib/src/completion/imported_type_computer.dart
|
| index 8c04570805826078bafaba08129c4050d875c875..959f4b4effab062a17732f3b56274a2be65172d9 100644
|
| --- a/pkg/analysis_services/lib/src/completion/imported_type_computer.dart
|
| +++ b/pkg/analysis_services/lib/src/completion/imported_type_computer.dart
|
| @@ -19,7 +19,7 @@ import 'package:analyzer/src/generated/element.dart';
|
| class ImportedTypeComputer extends CompletionComputer {
|
|
|
| @override
|
| - bool computeFast(CompilationUnit unit,
|
| + bool computeFast(CompilationUnit unit, AstNode node,
|
| List<CompletionSuggestion> suggestions) {
|
| // TODO: implement computeFast
|
| // - compute results based upon current search, then replace those results
|
| @@ -29,31 +29,71 @@ class ImportedTypeComputer extends CompletionComputer {
|
| }
|
|
|
| @override
|
| - Future<bool> computeFull(CompilationUnit unit,
|
| + Future<bool> computeFull(CompilationUnit unit, AstNode node,
|
| List<CompletionSuggestion> suggestions) {
|
| + return node.accept(
|
| + new _ImportedTypeVisitor(searchEngine, unit, suggestions));
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Visits the node at which the completion is requested
|
| + * and builds the list of suggestions.
|
| + */
|
| +class _ImportedTypeVisitor extends GeneralizingAstVisitor<Future<bool>> {
|
| + final SearchEngine searchEngine;
|
| + final CompilationUnit unit;
|
| + final List<CompletionSuggestion> suggestions;
|
| +
|
| + _ImportedTypeVisitor(this.searchEngine, this.unit, this.suggestions);
|
| +
|
| + Future<bool> visitCombinator(Combinator node) {
|
| + var directive = node.getAncestor((parent) => parent is NamespaceDirective);
|
| + if (directive is NamespaceDirective) {
|
| + return _addLibraryElements(directive.uriElement);
|
| + }
|
| + return new Future.value(true);
|
| + }
|
| +
|
| + Future<bool> visitNode(AstNode node) {
|
| + return _addImportedElements();
|
| + }
|
| +
|
| + Future<bool> visitSimpleIdentifier(SimpleIdentifier node) {
|
| + return node.parent.accept(this);
|
| + }
|
| +
|
| + Future<bool> _addImportedElements() {
|
| var future = searchEngine.searchTopLevelDeclarations('');
|
| return future.then((List<SearchMatch> matches) {
|
|
|
| + Set<LibraryElement> visibleLibs = new Set<LibraryElement>();
|
| + Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
|
| +
|
| + Map<LibraryElement, Set<String>> showNames =
|
| + new Map<LibraryElement, Set<String>>();
|
| + Map<LibraryElement, Set<String>> hideNames =
|
| + new Map<LibraryElement, Set<String>>();
|
| +
|
| // Exclude elements from the local library
|
| - // which will be included by the LocalComputer
|
| -
|
| - // Compute the set of visible libraries to determine relevance
|
| - var visibleLibraries = new Set<LibraryElement>();
|
| - var excludedLibraries = new Set<LibraryElement>();
|
| - var unitLibrary = unit.element.library;
|
| - excludedLibraries.add(unitLibrary);
|
| - unitLibrary.importedLibraries.forEach((LibraryElement library) {
|
| - if (library.isDartCore) {
|
| - visibleLibraries.add(library);
|
| - }
|
| - });
|
| + // as they will be included by the LocalComputer
|
| + excludedLibs.add(unit.element.library);
|
| unit.directives.forEach((Directive directive) {
|
| if (directive is ImportDirective) {
|
| - LibraryElement library = directive.element.importedLibrary;
|
| + LibraryElement lib = directive.element.importedLibrary;
|
| if (directive.prefix == null) {
|
| - visibleLibraries.add(library);
|
| + visibleLibs.add(lib);
|
| + directive.combinators.forEach((Combinator combinator) {
|
| + if (combinator is ShowCombinator) {
|
| + showNames[lib] = combinator.shownNames.map(
|
| + (SimpleIdentifier id) => id.name).toSet();
|
| + } else if (combinator is HideCombinator) {
|
| + hideNames[lib] = combinator.hiddenNames.map(
|
| + (SimpleIdentifier id) => id.name).toSet();
|
| + }
|
| + });
|
| } else {
|
| - excludedLibraries.add(library);
|
| + excludedLibs.add(lib);
|
| }
|
| }
|
| });
|
| @@ -62,26 +102,84 @@ class ImportedTypeComputer extends CompletionComputer {
|
| matches.forEach((SearchMatch match) {
|
| if (match.kind == MatchKind.DECLARATION) {
|
| Element element = match.element;
|
| - if (element.isPublic &&
|
| - !excludedLibraries.contains(element.library)) {
|
| + LibraryElement lib = element.library;
|
| + if (element.isPublic && !excludedLibs.contains(lib)) {
|
| String completion = element.displayName;
|
| - var relevance = visibleLibraries.contains(element.library) ?
|
| - CompletionRelevance.DEFAULT :
|
| - CompletionRelevance.LOW;
|
| - suggestions.add(
|
| - new CompletionSuggestion(
|
| - CompletionSuggestionKind.fromElementKind(element.kind),
|
| - relevance,
|
| - completion,
|
| - completion.length,
|
| - 0,
|
| - element.isDeprecated,
|
| - false // isPotential
|
| - ));
|
| + Set<String> show = showNames[lib];
|
| + Set<String> hide = hideNames[lib];
|
| + if ((show == null || show.contains(completion)) &&
|
| + (hide == null || !hide.contains(completion))) {
|
| + suggestions.add(
|
| + new CompletionSuggestion(
|
| + CompletionSuggestionKind.fromElementKind(element.kind),
|
| + visibleLibs.contains(lib) || lib.isDartCore ?
|
| + CompletionRelevance.DEFAULT :
|
| + CompletionRelevance.LOW,
|
| + completion,
|
| + completion.length,
|
| + 0,
|
| + element.isDeprecated,
|
| + false // isPotential
|
| + ));
|
| + }
|
| }
|
| }
|
| });
|
| return true;
|
| });
|
| }
|
| +
|
| + Future<bool> _addLibraryElements(LibraryElement library) {
|
| + library.visitChildren(new _LibraryElementVisitor(suggestions));
|
| + return new Future.value(true);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Provides suggestions from a single library for the show/hide combinators
|
| + * as in `import "foo.dart" show ` where the completion offset is after
|
| + * the `show`.
|
| + */
|
| +class _LibraryElementVisitor extends GeneralizingElementVisitor {
|
| + final List<CompletionSuggestion> suggestions;
|
| +
|
| + _LibraryElementVisitor(this.suggestions);
|
| +
|
| + visitClassElement(ClassElement element) {
|
| + _addSuggestion(element);
|
| + }
|
| +
|
| + visitCompilationUnitElement(CompilationUnitElement element) {
|
| + element.visitChildren(this);
|
| + }
|
| +
|
| + visitElement(Element element) {
|
| + // ignored
|
| + }
|
| +
|
| + visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
|
| + _addSuggestion(element);
|
| + }
|
| +
|
| + visitTopLevelVariableElement(TopLevelVariableElement element) {
|
| + _addSuggestion(element);
|
| + }
|
| +
|
| + void _addSuggestion(Element element) {
|
| + if (element != null) {
|
| + String completion = element.name;
|
| + if (completion != null && completion.length > 0) {
|
| + suggestions.add(
|
| + new CompletionSuggestion(
|
| + CompletionSuggestionKind.fromElementKind(element.kind),
|
| + CompletionRelevance.DEFAULT,
|
| + completion,
|
| + completion.length,
|
| + 0,
|
| + element.isDeprecated,
|
| + false // isPotential
|
| + ));
|
| + }
|
| + }
|
| + }
|
| }
|
|
|