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

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

Issue 643153003: add imported inherited member suggestions (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merge Created 6 years, 2 months 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
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/services/completion/local_computer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.computer.dart.toplevel; 5 library services.completion.computer.dart.toplevel;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analysis_server/src/protocol_server.dart' hide Element, 9 import 'package:analysis_server/src/protocol_server.dart' hide Element,
10 ElementKind; 10 ElementKind;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 * A visitor for determining which imported class and top level variable 42 * A visitor for determining which imported class and top level variable
43 * should be suggested and building those suggestions. 43 * should be suggested and building those suggestions.
44 */ 44 */
45 class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> { 45 class _ImportedVisitor extends GeneralizingAstVisitor<Future<bool>> {
46 final DartCompletionRequest request; 46 final DartCompletionRequest request;
47 47
48 _ImportedVisitor(this.request); 48 _ImportedVisitor(this.request);
49 49
50 @override 50 @override
51 Future<bool> visitBlock(Block node) { 51 Future<bool> visitBlock(Block node) {
52 return _addImportedElementSuggestions(); 52 return _addImportedElementSuggestions(node);
53 } 53 }
54 54
55 @override 55 @override
56 Future<bool> visitCascadeExpression(CascadeExpression node) { 56 Future<bool> visitCascadeExpression(CascadeExpression node) {
57 // Make suggestions for the target, but not for the selector 57 // Make suggestions for the target, but not for the selector
58 // InvocationComputer makes selector suggestions 58 // InvocationComputer makes selector suggestions
59 Expression target = node.target; 59 Expression target = node.target;
60 if (target != null && request.offset <= target.end) { 60 if (target != null && request.offset <= target.end) {
61 return _addImportedElementSuggestions(); 61 return _addImportedElementSuggestions(node);
62 } 62 }
63 return new Future.value(false); 63 return new Future.value(false);
64 } 64 }
65 65
66 @override 66 @override
67 Future<bool> visitClassDeclaration(ClassDeclaration node) { 67 Future<bool> visitClassDeclaration(ClassDeclaration node) {
68 // Make suggestions in the body of the class declaration 68 // Make suggestions in the body of the class declaration
69 Token leftBracket = node.leftBracket; 69 Token leftBracket = node.leftBracket;
70 if (leftBracket != null && request.offset >= leftBracket.end) { 70 if (leftBracket != null && request.offset >= leftBracket.end) {
71 return _addImportedElementSuggestions(); 71 return _addImportedElementSuggestions(node);
72 } 72 }
73 return new Future.value(false); 73 return new Future.value(false);
74 } 74 }
75 75
76 @override 76 @override
77 Future<bool> visitCombinator(Combinator node) { 77 Future<bool> visitCombinator(Combinator node) {
78 return _addCombinatorSuggestions(node); 78 return _addCombinatorSuggestions(node);
79 } 79 }
80 80
81 @override 81 @override
82 Future<bool> visitExpression(Expression node) { 82 Future<bool> visitExpression(Expression node) {
83 return _addImportedElementSuggestions(); 83 return _addImportedElementSuggestions(node);
84 } 84 }
85 85
86 @override 86 @override
87 Future<bool> visitExpressionStatement(ExpressionStatement node) { 87 Future<bool> visitExpressionStatement(ExpressionStatement node) {
88 Expression expression = node.expression; 88 Expression expression = node.expression;
89 // A pre-variable declaration (e.g. C ^) is parsed as an expression 89 // A pre-variable declaration (e.g. C ^) is parsed as an expression
90 // statement. Do not make suggestions for the variable name. 90 // statement. Do not make suggestions for the variable name.
91 if (expression is SimpleIdentifier && request.offset <= expression.end) { 91 if (expression is SimpleIdentifier && request.offset <= expression.end) {
92 return _addImportedElementSuggestions(); 92 return _addImportedElementSuggestions(node);
93 } 93 }
94 return new Future.value(false); 94 return new Future.value(false);
95 } 95 }
96 96
97 @override 97 @override
98 Future<bool> visitForStatement(ForStatement node) { 98 Future<bool> visitForStatement(ForStatement node) {
99 Token leftParenthesis = node.leftParenthesis; 99 Token leftParenthesis = node.leftParenthesis;
100 if (leftParenthesis != null && request.offset >= leftParenthesis.end) { 100 if (leftParenthesis != null && request.offset >= leftParenthesis.end) {
101 return _addImportedElementSuggestions(); 101 return _addImportedElementSuggestions(node);
102 } 102 }
103 return new Future.value(false); 103 return new Future.value(false);
104 } 104 }
105 105
106 @override 106 @override
107 Future<bool> visitIfStatement(IfStatement node) { 107 Future<bool> visitIfStatement(IfStatement node) {
108 Token leftParen = node.leftParenthesis; 108 Token leftParen = node.leftParenthesis;
109 if (leftParen != null && request.offset >= leftParen.end) { 109 if (leftParen != null && request.offset >= leftParen.end) {
110 Token rightParen = node.rightParenthesis; 110 Token rightParen = node.rightParenthesis;
111 if (rightParen == null || request.offset <= rightParen.offset) { 111 if (rightParen == null || request.offset <= rightParen.offset) {
112 return _addImportedElementSuggestions(); 112 return _addImportedElementSuggestions(node);
113 } 113 }
114 } 114 }
115 return new Future.value(false); 115 return new Future.value(false);
116 } 116 }
117 117
118 @override 118 @override
119 Future<bool> visitInterpolationExpression(InterpolationExpression node) { 119 Future<bool> visitInterpolationExpression(InterpolationExpression node) {
120 Expression expression = node.expression; 120 Expression expression = node.expression;
121 if (expression is SimpleIdentifier) { 121 if (expression is SimpleIdentifier) {
122 return _addImportedElementSuggestions(); 122 return _addImportedElementSuggestions(node);
123 } 123 }
124 return new Future.value(false); 124 return new Future.value(false);
125 } 125 }
126 126
127 @override 127 @override
128 Future<bool> visitMethodInvocation(MethodInvocation node) { 128 Future<bool> visitMethodInvocation(MethodInvocation node) {
129 Token period = node.period; 129 Token period = node.period;
130 if (period == null || request.offset <= period.offset) { 130 if (period == null || request.offset <= period.offset) {
131 return _addImportedElementSuggestions(); 131 return _addImportedElementSuggestions(node);
132 } 132 }
133 return new Future.value(false); 133 return new Future.value(false);
134 } 134 }
135 135
136 @override 136 @override
137 Future<bool> visitNode(AstNode node) { 137 Future<bool> visitNode(AstNode node) {
138 return new Future.value(false); 138 return new Future.value(false);
139 } 139 }
140 140
141 @override 141 @override
142 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) { 142 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) {
143 // Make suggestions for the prefix, but not for the selector 143 // Make suggestions for the prefix, but not for the selector
144 // InvocationComputer makes selector suggestions 144 // InvocationComputer makes selector suggestions
145 Token period = node.period; 145 Token period = node.period;
146 if (period != null && request.offset <= period.offset) { 146 if (period != null && request.offset <= period.offset) {
147 return _addImportedElementSuggestions(); 147 return _addImportedElementSuggestions(node);
148 } 148 }
149 return new Future.value(false); 149 return new Future.value(false);
150 } 150 }
151 151
152 @override 152 @override
153 Future<bool> visitPropertyAccess(PropertyAccess node) { 153 Future<bool> visitPropertyAccess(PropertyAccess node) {
154 // Make suggestions for the target, but not for the property name 154 // Make suggestions for the target, but not for the property name
155 // InvocationComputer makes property name suggestions 155 // InvocationComputer makes property name suggestions
156 var operator = node.operator; 156 var operator = node.operator;
157 if (operator != null && request.offset < operator.offset) { 157 if (operator != null && request.offset < operator.offset) {
158 return _addImportedElementSuggestions(); 158 return _addImportedElementSuggestions(node);
159 } 159 }
160 return new Future.value(false); 160 return new Future.value(false);
161 } 161 }
162 162
163 @override 163 @override
164 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) { 164 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) {
165 return node.parent.accept(this); 165 return node.parent.accept(this);
166 } 166 }
167 167
168 @override 168 @override
169 Future<bool> visitStringLiteral(StringLiteral node) { 169 Future<bool> visitStringLiteral(StringLiteral node) {
170 return new Future.value(false); 170 return new Future.value(false);
171 } 171 }
172 172
173 @override 173 @override
174 Future<bool> visitTypeName(TypeName node) { 174 Future<bool> visitTypeName(TypeName node) {
175 return _addImportedElementSuggestions(typesOnly: true); 175 return _addImportedElementSuggestions(node, typesOnly: true);
176 } 176 }
177 177
178 @override 178 @override
179 visitVariableDeclaration(VariableDeclaration node) { 179 visitVariableDeclaration(VariableDeclaration node) {
180 Token equals = node.equals; 180 Token equals = node.equals;
181 // Make suggestions for the RHS of a variable declaration 181 // Make suggestions for the RHS of a variable declaration
182 if (equals != null && request.offset >= equals.end) { 182 if (equals != null && request.offset >= equals.end) {
183 return _addImportedElementSuggestions(); 183 return _addImportedElementSuggestions(node);
184 } 184 }
185 return new Future.value(false); 185 return new Future.value(false);
186 } 186 }
187 187
188 Future _addCombinatorSuggestions(Combinator node) { 188 Future _addCombinatorSuggestions(Combinator node) {
189 var directive = node.getAncestor((parent) => parent is NamespaceDirective); 189 var directive = node.getAncestor((parent) => parent is NamespaceDirective);
190 if (directive is NamespaceDirective) { 190 if (directive is NamespaceDirective) {
191 LibraryElement library = directive.uriElement; 191 LibraryElement library = directive.uriElement;
192 LibraryElementSuggestionBuilder.suggestionsFor(request, library); 192 LibraryElementSuggestionBuilder.suggestionsFor(request, library);
193 return new Future.value(true); 193 return new Future.value(true);
194 } 194 }
195 195
196 return new Future.value(false); 196 return new Future.value(false);
197 } 197 }
198 198
199 void _addElementSuggestion(Element element, CompletionRelevance relevance) { 199 void _addElementSuggestion(Element element, CompletionRelevance relevance) {
200
201 if (element is ExecutableElement) {
202 if (element.isOperator) {
203 return;
204 }
205 }
206
200 CompletionSuggestionKind kind = 207 CompletionSuggestionKind kind =
201 newCompletionSuggestionKind_fromElementKind(element.kind); 208 newCompletionSuggestionKind_fromElementKind(element.kind);
202 209
203 String completion = element.displayName; 210 String completion = element.displayName;
204 CompletionSuggestion suggestion = new CompletionSuggestion( 211 CompletionSuggestion suggestion = new CompletionSuggestion(
205 kind, 212 kind,
206 relevance, 213 relevance,
207 completion, 214 completion,
208 completion.length, 215 completion.length,
209 0, 216 0,
(...skipping 13 matching lines...) Expand all
223 if (type != null) { 230 if (type != null) {
224 String name = type.displayName; 231 String name = type.displayName;
225 if (name != null && name.length > 0 && name != 'dynamic') { 232 if (name != null && name.length > 0 && name != 'dynamic') {
226 suggestion.returnType = name; 233 suggestion.returnType = name;
227 } 234 }
228 } 235 }
229 236
230 request.suggestions.add(suggestion); 237 request.suggestions.add(suggestion);
231 } 238 }
232 239
233 Future<bool> _addImportedElementSuggestions({bool typesOnly: false}) { 240 void _addElementSuggestions(List<Element> elements) {
241 elements.forEach((Element elem) {
242 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
243 });
244 }
245
246 Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly:
247 false}) {
234 248
235 // Exclude elements from local library 249 // Exclude elements from local library
236 // because they are provided by LocalComputer 250 // because they are provided by LocalComputer
237 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); 251 Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
238 excludedLibs.add(request.unit.element.enclosingElement); 252 excludedLibs.add(request.unit.element.enclosingElement);
239 253
240 // Include explicitly imported elements 254 // Include explicitly imported elements
255 Map<String, ClassElement> classMap = new Map<String, ClassElement>();
241 request.unit.directives.forEach((Directive directive) { 256 request.unit.directives.forEach((Directive directive) {
242 if (directive is ImportDirective) { 257 if (directive is ImportDirective) {
243 ImportElement importElem = directive.element; 258 ImportElement importElem = directive.element;
244 if (importElem != null && importElem.importedLibrary != null) { 259 if (importElem != null && importElem.importedLibrary != null) {
245 if (directive.prefix == null) { 260 if (directive.prefix == null) {
246 Namespace importNamespace = 261 Namespace importNamespace =
247 new NamespaceBuilder().createImportNamespaceForDirective(importE lem); 262 new NamespaceBuilder().createImportNamespaceForDirective(importE lem);
248 importNamespace.definedNames.forEach((_, Element element) { 263 // Include top level elements
249 if (!typesOnly || element is ClassElement) { 264 importNamespace.definedNames.forEach((String name, Element elem) {
250 _addElementSuggestion(element, CompletionRelevance.DEFAULT); 265 if (elem is ClassElement) {
266 classMap[name] = elem;
267 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
268 } else if (!typesOnly) {
269 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
251 } 270 }
252 }); 271 });
253 } else { 272 } else {
254 // Exclude elements from prefixed imports 273 // Exclude elements from prefixed imports
255 // because they are provided by InvocationComputer 274 // because they are provided by InvocationComputer
256 excludedLibs.add(importElem.importedLibrary); 275 excludedLibs.add(importElem.importedLibrary);
257 _addLibraryPrefixSuggestion(importElem); 276 _addLibraryPrefixSuggestion(importElem);
258 } 277 }
259 } 278 }
260 } 279 }
261 }); 280 });
262 281
263 // Include implicitly imported dart:core elements 282 // Include implicitly imported dart:core elements
264 Source coreUri = request.context.sourceFactory.forUri('dart:core'); 283 Source coreUri = request.context.sourceFactory.forUri('dart:core');
265 LibraryElement coreLib = request.context.getLibraryElement(coreUri); 284 LibraryElement coreLib = request.context.getLibraryElement(coreUri);
266 Namespace coreNamespace = 285 Namespace coreNamespace =
267 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); 286 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
268 coreNamespace.definedNames.forEach((_, Element element) { 287 coreNamespace.definedNames.forEach((String name, Element elem) {
269 if (!typesOnly || element is ClassElement) { 288 if (elem is ClassElement) {
270 _addElementSuggestion(element, CompletionRelevance.DEFAULT); 289 classMap[name] = elem;
290 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
291 } else if (!typesOnly) {
292 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
271 } 293 }
272 }); 294 });
273 295
296 // Build a list of inherited types that are imported
297 // and include any inherited imported members
298 var classDecl = node.getAncestor((p) => p is ClassDeclaration);
299 if (classDecl is ClassDeclaration) {
300 List<String> inheritedTypes = new List<String>();
301 visitInheritedTypes(classDecl, (ClassDeclaration classDecl) {
302 // ignored
303 }, (String typeName) {
304 inheritedTypes.add(typeName);
305 });
306 Set<String> visited = new Set<String>();
307 while (inheritedTypes.length > 0) {
308 String name = inheritedTypes.removeLast();
309 ClassElement elem = classMap[name];
310 if (visited.add(name) && elem != null) {
311 _addElementSuggestions(elem.accessors);
312 _addElementSuggestions(elem.methods);
313 elem.allSupertypes.forEach((InterfaceType type) {
314 if (visited.add(type.name)) {
315 _addElementSuggestions(type.accessors);
316 _addElementSuggestions(type.methods);
317 }
318 });
319 }
320 }
321 }
322
274 // Add non-imported elements as low relevance 323 // Add non-imported elements as low relevance
275 var future = request.searchEngine.searchTopLevelDeclarations(''); 324 var future = request.searchEngine.searchTopLevelDeclarations('');
276 return future.then((List<SearchMatch> matches) { 325 return future.then((List<SearchMatch> matches) {
277 Set<String> completionSet = new Set<String>(); 326 Set<String> completionSet = new Set<String>();
278 request.suggestions.forEach((CompletionSuggestion suggestion) { 327 request.suggestions.forEach((CompletionSuggestion suggestion) {
279 completionSet.add(suggestion.completion); 328 completionSet.add(suggestion.completion);
280 }); 329 });
281 matches.forEach((SearchMatch match) { 330 matches.forEach((SearchMatch match) {
282 if (match.kind == MatchKind.DECLARATION) { 331 if (match.kind == MatchKind.DECLARATION) {
283 Element element = match.element; 332 Element element = match.element;
(...skipping 22 matching lines...) Expand all
306 importElem.isDeprecated, 355 importElem.isDeprecated,
307 false); 356 false);
308 LibraryElement lib = importElem.importedLibrary; 357 LibraryElement lib = importElem.importedLibrary;
309 if (lib != null) { 358 if (lib != null) {
310 suggestion.element = newElement_fromEngine(lib); 359 suggestion.element = newElement_fromEngine(lib);
311 } 360 }
312 request.suggestions.add(suggestion); 361 request.suggestions.add(suggestion);
313 } 362 }
314 } 363 }
315 } 364 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/services/completion/local_computer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698