Chromium Code Reviews| Index: pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart |
| diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart |
| index f1e7198937ac0e13e794be23acb3b9497e1f46b8..1818bf8d1ec64b7a75216607a582954fd0c1e1d4 100644 |
| --- a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart |
| +++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart |
| @@ -81,11 +81,12 @@ class DartCompletionCache extends CompletionCache { |
| String get importKey => _importKey; |
| /** |
| - * Compute suggestions based upon the imports in the given compilation unit. |
| - * On return, the cache will be populated except for lower priority |
| - * suggestions added as a result of a global search. Callers may wait |
| - * on the returned future if they want to ensure those lower priority |
| - * suggestions are part of the cached suggestions. |
| + * Given a resolved compilation unit, compute suggestions based upon the |
| + * imports and other dart files (e.g. "part" files) in the library containing |
| + * the given compilation unit. On return, the cache will be populated |
| + * except for lower priority suggestions added as a result of a global search. |
| + * Callers may wait on the returned future if they want to ensure those lower |
| + * priority suggestions are part of the cached suggestions. |
| */ |
| Future<bool> computeImportInfo(CompilationUnit unit, |
| SearchEngine searchEngine) { |
| @@ -96,35 +97,67 @@ class DartCompletionCache extends CompletionCache { |
| importedClassMap = new Map<String, ClassElement>(); |
| _importedCompletions = new HashSet<String>(); |
| + // Assert the that compilation unit is resolved |
| + // and represents the expected source |
| + assert(unit.element.source == source); |
| + |
| // Exclude elements from local library |
| // because they are provided by LocalComputer |
| Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); |
| excludedLibs.add(unit.element.enclosingElement); |
| + // Determine the compilation unit defining the library containing |
| + // this compilation unit |
| + List<Source> libraries = context.getLibrariesContaining(source); |
| + Source libSource = null; |
| + CompilationUnit libUnit = null; |
| + if (libraries != null && libraries.length > 0) { |
| + libSource = libraries[0]; |
| + if (libSource == source) { |
| + // If the sources are the same then we already have the library unit |
| + libUnit = unit; |
| + } else { |
| + // If this is a part and we have the resolved unit for the part, |
| + // then assume that the library unit is cached |
| + // or is not-costly to recompute |
| + libUnit = context.resolveCompilationUnit2(libSource, libSource); |
|
Paul Berry
2014/12/18 18:37:02
Two issues:
1. context.resolveCompilationUnit2(lib
danrubel
2014/12/19 18:46:09
I need the library unit not the part unit to trave
Paul Berry
2014/12/19 19:13:30
Ok. It would be nice to add a comment to the code
danrubel
2014/12/20 05:12:30
Good point. Done.
|
| + } |
| + } |
| + |
| // Include explicitly imported elements |
| - unit.directives.forEach((Directive directive) { |
| - if (directive is ImportDirective) { |
| - ImportElement importElem = directive.element; |
| - if (importElem != null && importElem.importedLibrary != null) { |
| - if (directive.prefix == null) { |
| - Namespace importNamespace = |
| - new NamespaceBuilder().createImportNamespaceForDirective(importElem); |
| - // Include top level elements |
| - importNamespace.definedNames.forEach((String name, Element elem) { |
| - if (elem is ClassElement) { |
| - importedClassMap[name] = elem; |
| - } |
| - addSuggestion(elem, CompletionRelevance.DEFAULT); |
| - }); |
| - } else { |
| - // Exclude elements from prefixed imports |
| - // because they are provided by InvocationComputer |
| - excludedLibs.add(importElem.importedLibrary); |
| - _addLibraryPrefixSuggestion(importElem); |
| + if (libUnit != null) { |
| + libUnit.directives.forEach((Directive directive) { |
| + if (directive is ImportDirective) { |
| + ImportElement importElem = directive.element; |
| + if (importElem != null && importElem.importedLibrary != null) { |
| + if (directive.prefix == null) { |
| + Namespace importNamespace = |
| + new NamespaceBuilder().createImportNamespaceForDirective(importElem); |
| + // Include top level elements |
| + importNamespace.definedNames.forEach((String name, Element elem) { |
| + if (elem is ClassElement) { |
| + importedClassMap[name] = elem; |
| + } |
| + addSuggestion(elem, CompletionRelevance.DEFAULT); |
| + }); |
| + } else { |
| + // Exclude elements from prefixed imports |
| + // because they are provided by InvocationComputer |
| + excludedLibs.add(importElem.importedLibrary); |
| + _addLibraryPrefixSuggestion(importElem); |
| + } |
| + } |
| + } else if (directive is PartDirective) { |
| + CompilationUnitElement partElem = directive.element; |
| + if (partElem != null && partElem.source != source) { |
| + partElem.accept(new _NonLocalElementCacheVisitor(this)); |
| } |
| } |
| + }); |
| + if (libSource != source) { |
| + libUnit.element.accept(new _NonLocalElementCacheVisitor(this)); |
| } |
| - }); |
| + } |
| // Include implicitly imported dart:core elements |
| Source coreUri = context.sourceFactory.forUri('dart:core'); |
| @@ -245,3 +278,44 @@ class DartCompletionCache extends CompletionCache { |
| return sb.toString(); |
| } |
| } |
| + |
| +/** |
| + * A visitor for building suggestions based upon the elements defined by |
| + * a source file contained in the same library but not the same as |
| + * the source in which the completions are being requested. |
| + */ |
| +class _NonLocalElementCacheVisitor extends GeneralizingElementVisitor { |
| + final DartCompletionCache cache; |
| + |
| + _NonLocalElementCacheVisitor(this.cache); |
| + |
| + @override |
| + void visitClassElement(ClassElement element) { |
| + cache.addSuggestion(element, CompletionRelevance.DEFAULT); |
| + } |
| + |
| + @override |
| + void visitCompilationUnitElement(CompilationUnitElement element) { |
| + element.visitChildren(this); |
| + } |
| + |
| + @override |
| + void visitElement(Element element) { |
| + // ignored |
| + } |
| + |
| + @override |
| + void visitFunctionElement(FunctionElement element) { |
| + cache.addSuggestion(element, CompletionRelevance.DEFAULT); |
| + } |
| + |
| + @override |
| + void visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
| + cache.addSuggestion(element, CompletionRelevance.DEFAULT); |
| + } |
| + |
| + @override |
| + void visitTopLevelVariableElement(TopLevelVariableElement element) { |
| + cache.addSuggestion(element, CompletionRelevance.DEFAULT); |
| + } |
| +} |