Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart

Issue 815683002: support part file completions (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merge and address comments Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library services.completion.dart.cache; 5 library services.completion.dart.cache;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'package:analysis_server/src/protocol_server.dart' hide Element, 10 import 'package:analysis_server/src/protocol_server.dart' hide Element,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 DartCompletionCache(AnalysisContext context, Source source) 74 DartCompletionCache(AnalysisContext context, Source source)
75 : super(context, source); 75 : super(context, source);
76 76
77 /** 77 /**
78 * Return a hash of the import directives for the cached import info 78 * Return a hash of the import directives for the cached import info
79 * or `null` if nothing has been cached. 79 * or `null` if nothing has been cached.
80 */ 80 */
81 String get importKey => _importKey; 81 String get importKey => _importKey;
82 82
83 /** 83 /**
84 * Compute suggestions based upon the imports in the given compilation unit. 84 * Given a resolved compilation unit, compute suggestions based upon the
85 * On return, the cache will be populated except for lower priority 85 * imports and other dart files (e.g. "part" files) in the library containing
86 * suggestions added as a result of a global search. Callers may wait 86 * the given compilation unit. The returned future completes when the cache
87 * on the returned future if they want to ensure those lower priority 87 * is populated.
88 * suggestions are part of the cached suggestions. 88 *
89 * If [shouldWaitForLowPrioritySuggestions] is `true` then the returned
90 * future will complete when the cache is fully populated. If `false`,
91 * the returned future will complete sooner, but the cache will not include
92 * the lower priority suggestions added as a result of a global search.
93 * In this case, those lower priority suggestions will be added later
94 * when the index has been updated and the global search completes.
89 */ 95 */
90 Future<bool> computeImportInfo(CompilationUnit unit, 96 Future<bool> computeImportInfo(CompilationUnit unit,
91 SearchEngine searchEngine) { 97 SearchEngine searchEngine, bool shouldWaitForLowPrioritySuggestions) {
92 importedTypeSuggestions = <CompletionSuggestion>[]; 98 importedTypeSuggestions = <CompletionSuggestion>[];
93 libraryPrefixSuggestions = <CompletionSuggestion>[]; 99 libraryPrefixSuggestions = <CompletionSuggestion>[];
94 otherImportedSuggestions = <CompletionSuggestion>[]; 100 otherImportedSuggestions = <CompletionSuggestion>[];
95 importedVoidReturnSuggestions = <CompletionSuggestion>[]; 101 importedVoidReturnSuggestions = <CompletionSuggestion>[];
96 importedClassMap = new Map<String, ClassElement>(); 102 importedClassMap = new Map<String, ClassElement>();
97 _importedCompletions = new HashSet<String>(); 103 _importedCompletions = new HashSet<String>();
98 104
105 // Assert that the compilation unit is resolved
106 // and represents the expected source
107 assert(unit.element.source == source);
108
99 // Exclude elements from local library 109 // Exclude elements from local library
100 // because they are provided by LocalComputer 110 // because they are provided by LocalComputer
101 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); 111 Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
102 excludedLibs.add(unit.element.enclosingElement); 112 excludedLibs.add(unit.element.enclosingElement);
103 113
114 // Determine the compilation unit defining the library containing
115 // this compilation unit
116 List<Source> libraries = context.getLibrariesContaining(source);
117 Source libSource = null;
118 Future<CompilationUnit> futureLibUnit;
119 if (libraries != null && libraries.length > 0) {
120 libSource = libraries[0];
121 if (libSource == source) {
122 // If the sources are the same then we already have the library unit
123 futureLibUnit = new Future.value(unit);
124 } else {
125 futureLibUnit =
126 context.computeResolvedCompilationUnitAsync(libSource, libSource);
127 }
128 } else {
129 futureLibUnit = new Future.value(null);
130 }
131
104 // Include explicitly imported elements 132 // Include explicitly imported elements
105 unit.directives.forEach((Directive directive) { 133 Future futureImportsCached = futureLibUnit.then((CompilationUnit libUnit) {
106 if (directive is ImportDirective) { 134 if (libUnit != null) {
107 ImportElement importElem = directive.element; 135 libUnit.directives.forEach((Directive directive) {
108 if (importElem != null && importElem.importedLibrary != null) { 136 if (directive is ImportDirective) {
109 if (directive.prefix == null) { 137 ImportElement importElem = directive.element;
110 Namespace importNamespace = 138 if (importElem != null && importElem.importedLibrary != null) {
111 new NamespaceBuilder().createImportNamespaceForDirective(importE lem); 139 if (directive.prefix == null) {
112 // Include top level elements 140 Namespace importNamespace =
113 importNamespace.definedNames.forEach((String name, Element elem) { 141 new NamespaceBuilder().createImportNamespaceForDirective(imp ortElem);
114 if (elem is ClassElement) { 142 // Include top level elements
115 importedClassMap[name] = elem; 143 importNamespace.definedNames.forEach(
144 (String name, Element elem) {
145 if (elem is ClassElement) {
146 importedClassMap[name] = elem;
147 }
148 addSuggestion(elem, CompletionRelevance.DEFAULT);
149 });
150 } else {
151 // Exclude elements from prefixed imports
152 // because they are provided by InvocationComputer
153 excludedLibs.add(importElem.importedLibrary);
154 _addLibraryPrefixSuggestion(importElem);
116 } 155 }
117 addSuggestion(elem, CompletionRelevance.DEFAULT); 156 }
118 }); 157 } else if (directive is PartDirective) {
119 } else { 158 CompilationUnitElement partElem = directive.element;
120 // Exclude elements from prefixed imports 159 if (partElem != null && partElem.source != source) {
121 // because they are provided by InvocationComputer 160 partElem.accept(new _NonLocalElementCacheVisitor(this));
122 excludedLibs.add(importElem.importedLibrary); 161 }
123 _addLibraryPrefixSuggestion(importElem);
124 } 162 }
163 });
164 if (libSource != source) {
165 libUnit.element.accept(new _NonLocalElementCacheVisitor(this));
125 } 166 }
126 } 167 }
168 // Don't wait for search of lower relevance results to complete.
169 // Set key indicating results are ready, and lower relevance results
170 // will be added to the cache when the search completes.
171 _importKey = _computeImportKey(unit);
172 return true;
127 }); 173 });
128 174
129 // Include implicitly imported dart:core elements 175 // Include implicitly imported dart:core elements
130 Source coreUri = context.sourceFactory.forUri('dart:core'); 176 Source coreUri = context.sourceFactory.forUri('dart:core');
131 LibraryElement coreLib = context.getLibraryElement(coreUri); 177 LibraryElement coreLib = context.getLibraryElement(coreUri);
132 Namespace coreNamespace = 178 Namespace coreNamespace =
133 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); 179 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
134 coreNamespace.definedNames.forEach((String name, Element elem) { 180 coreNamespace.definedNames.forEach((String name, Element elem) {
135 if (elem is ClassElement) { 181 if (elem is ClassElement) {
136 importedClassMap[name] = elem; 182 importedClassMap[name] = elem;
137 } 183 }
138 addSuggestion(elem, CompletionRelevance.DEFAULT); 184 addSuggestion(elem, CompletionRelevance.DEFAULT);
139 }); 185 });
140 _objectClassElement = importedClassMap['Object']; 186 _objectClassElement = importedClassMap['Object'];
141 187
142 /* 188 // Add non-imported elements as low relevance
143 * Don't wait for search of lower relevance results to complete. 189 // after the imported element suggestions have been added
144 * Set key indicating results are ready, and lower relevance results 190 Future<bool> futureAllCached = futureImportsCached.then((_) {
145 * will be added to the cache when the search completes. 191 return searchEngine.searchTopLevelDeclarations(
146 */ 192 '').then((List<SearchMatch> matches) {
147 _importKey = _computeImportKey(unit); 193 matches.forEach((SearchMatch match) {
194 if (match.kind == MatchKind.DECLARATION) {
195 Element element = match.element;
196 if (element.isPublic &&
197 !excludedLibs.contains(element.library) &&
198 !_importedCompletions.contains(element.displayName)) {
199 addSuggestion(element, CompletionRelevance.LOW);
200 }
201 }
202 });
203 return true;
204 });
205 });
148 206
149 // Add non-imported elements as low relevance 207 return shouldWaitForLowPrioritySuggestions ?
150 Future<List<SearchMatch>> future = 208 futureAllCached :
151 searchEngine.searchTopLevelDeclarations(''); 209 futureImportsCached;
152 return future.then((List<SearchMatch> matches) {
153 matches.forEach((SearchMatch match) {
154 if (match.kind == MatchKind.DECLARATION) {
155 Element element = match.element;
156 if (element.isPublic &&
157 !excludedLibs.contains(element.library) &&
158 !_importedCompletions.contains(element.displayName)) {
159 addSuggestion(element, CompletionRelevance.LOW);
160 }
161 }
162 });
163 return true;
164 });
165 } 210 }
166 211
167 /** 212 /**
168 * Return the [ClassElement] for Object. 213 * Return the [ClassElement] for Object.
169 */ 214 */
170 ClassElement get objectClassElement { 215 ClassElement get objectClassElement {
171 if (_objectClassElement == null) { 216 if (_objectClassElement == null) {
172 Source coreUri = context.sourceFactory.forUri('dart:core'); 217 Source coreUri = context.sourceFactory.forUri('dart:core');
173 LibraryElement coreLib = context.getLibraryElement(coreUri); 218 LibraryElement coreLib = context.getLibraryElement(coreUri);
174 Namespace coreNamespace = 219 Namespace coreNamespace =
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 String _computeImportKey(CompilationUnit unit) { 283 String _computeImportKey(CompilationUnit unit) {
239 StringBuffer sb = new StringBuffer(); 284 StringBuffer sb = new StringBuffer();
240 unit.directives.forEach((Directive directive) { 285 unit.directives.forEach((Directive directive) {
241 if (directive is ImportDirective) { 286 if (directive is ImportDirective) {
242 sb.write(directive.toSource()); 287 sb.write(directive.toSource());
243 } 288 }
244 }); 289 });
245 return sb.toString(); 290 return sb.toString();
246 } 291 }
247 } 292 }
293
294 /**
295 * A visitor for building suggestions based upon the elements defined by
296 * a source file contained in the same library but not the same as
297 * the source in which the completions are being requested.
298 */
299 class _NonLocalElementCacheVisitor extends GeneralizingElementVisitor {
300 final DartCompletionCache cache;
301
302 _NonLocalElementCacheVisitor(this.cache);
303
304 @override
305 void visitClassElement(ClassElement element) {
306 cache.addSuggestion(element, CompletionRelevance.DEFAULT);
307 }
308
309 @override
310 void visitCompilationUnitElement(CompilationUnitElement element) {
311 element.visitChildren(this);
312 }
313
314 @override
315 void visitElement(Element element) {
316 // ignored
317 }
318
319 @override
320 void visitFunctionElement(FunctionElement element) {
321 cache.addSuggestion(element, CompletionRelevance.DEFAULT);
322 }
323
324 @override
325 void visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
326 cache.addSuggestion(element, CompletionRelevance.DEFAULT);
327 }
328
329 @override
330 void visitTopLevelVariableElement(TopLevelVariableElement element) {
331 cache.addSuggestion(element, CompletionRelevance.DEFAULT);
332 }
333 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698