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

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

Issue 658053002: filter void methods when suggesting expression (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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 Future<bool> visitBlock(Block node) { 51 Future<bool> visitBlock(Block node) {
52 return _addImportedElementSuggestions(node); 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(node); 61 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 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(node); 83 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 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(node); 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(node); 112 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 122 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 131 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 147 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node); 158 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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(node, 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(node); 183 return _addImportedElementSuggestions(node, excludeVoidReturn: true);
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, bool typesOnly, bool excludeVoidRe turn, CompletionRelevance relevance) {
200 200
201 if (element is ExecutableElement) { 201 if (element is ExecutableElement) {
202 if (element.isOperator) { 202 if (element.isOperator) {
203 return; 203 return;
204 } 204 }
205 if (excludeVoidReturn) {
206 DartType returnType = element.returnType;
207 if (returnType != null && returnType.isVoid) {
208 return;
209 }
210 }
211 }
212 if (typesOnly && element is! ClassElement) {
213 return;
205 } 214 }
206 215
207 CompletionSuggestionKind kind = 216 CompletionSuggestionKind kind =
208 newCompletionSuggestionKind_fromElementKind(element.kind); 217 newCompletionSuggestionKind_fromElementKind(element.kind);
209 218
210 String completion = element.displayName; 219 String completion = element.displayName;
211 CompletionSuggestion suggestion = new CompletionSuggestion( 220 CompletionSuggestion suggestion = new CompletionSuggestion(
212 kind, 221 kind,
213 relevance, 222 relevance,
214 completion, 223 completion,
(...skipping 15 matching lines...) Expand all
230 if (type != null) { 239 if (type != null) {
231 String name = type.displayName; 240 String name = type.displayName;
232 if (name != null && name.length > 0 && name != 'dynamic') { 241 if (name != null && name.length > 0 && name != 'dynamic') {
233 suggestion.returnType = name; 242 suggestion.returnType = name;
234 } 243 }
235 } 244 }
236 245
237 request.suggestions.add(suggestion); 246 request.suggestions.add(suggestion);
238 } 247 }
239 248
240 void _addElementSuggestions(List<Element> elements) { 249 void _addElementSuggestions(List<Element> elements, bool typesOnly, bool exclu deVoidReturn) {
241 elements.forEach((Element elem) { 250 elements.forEach((Element elem) {
242 _addElementSuggestion(elem, CompletionRelevance.DEFAULT); 251 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, CompletionReleva nce.DEFAULT);
243 }); 252 });
244 } 253 }
245 254
246 Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly: 255 Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly:
247 false}) { 256 false, bool excludeVoidReturn: false}) {
248 257
249 // Exclude elements from local library 258 // Exclude elements from local library
250 // because they are provided by LocalComputer 259 // because they are provided by LocalComputer
251 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); 260 Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
252 excludedLibs.add(request.unit.element.enclosingElement); 261 excludedLibs.add(request.unit.element.enclosingElement);
253 262
254 // Include explicitly imported elements 263 // Include explicitly imported elements
255 Map<String, ClassElement> classMap = new Map<String, ClassElement>(); 264 Map<String, ClassElement> classMap = new Map<String, ClassElement>();
256 request.unit.directives.forEach((Directive directive) { 265 request.unit.directives.forEach((Directive directive) {
257 if (directive is ImportDirective) { 266 if (directive is ImportDirective) {
258 ImportElement importElem = directive.element; 267 ImportElement importElem = directive.element;
259 if (importElem != null && importElem.importedLibrary != null) { 268 if (importElem != null && importElem.importedLibrary != null) {
260 if (directive.prefix == null) { 269 if (directive.prefix == null) {
261 Namespace importNamespace = 270 Namespace importNamespace =
262 new NamespaceBuilder().createImportNamespaceForDirective(importE lem); 271 new NamespaceBuilder().createImportNamespaceForDirective(importE lem);
263 // Include top level elements 272 // Include top level elements
264 importNamespace.definedNames.forEach((String name, Element elem) { 273 importNamespace.definedNames.forEach((String name, Element elem) {
265 if (elem is ClassElement) { 274 if (elem is ClassElement) {
266 classMap[name] = elem; 275 classMap[name] = elem;
267 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
268 } else if (!typesOnly) {
269 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
270 } 276 }
277 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, Comple tionRelevance.DEFAULT);
271 }); 278 });
272 } else { 279 } else {
273 // Exclude elements from prefixed imports 280 // Exclude elements from prefixed imports
274 // because they are provided by InvocationComputer 281 // because they are provided by InvocationComputer
275 excludedLibs.add(importElem.importedLibrary); 282 excludedLibs.add(importElem.importedLibrary);
276 _addLibraryPrefixSuggestion(importElem); 283 _addLibraryPrefixSuggestion(importElem);
277 } 284 }
278 } 285 }
279 } 286 }
280 }); 287 });
281 288
282 // Include implicitly imported dart:core elements 289 // Include implicitly imported dart:core elements
283 Source coreUri = request.context.sourceFactory.forUri('dart:core'); 290 Source coreUri = request.context.sourceFactory.forUri('dart:core');
284 LibraryElement coreLib = request.context.getLibraryElement(coreUri); 291 LibraryElement coreLib = request.context.getLibraryElement(coreUri);
285 Namespace coreNamespace = 292 Namespace coreNamespace =
286 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); 293 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
287 coreNamespace.definedNames.forEach((String name, Element elem) { 294 coreNamespace.definedNames.forEach((String name, Element elem) {
288 if (elem is ClassElement) { 295 if (elem is ClassElement) {
289 classMap[name] = elem; 296 classMap[name] = elem;
290 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
291 } else if (!typesOnly) {
292 _addElementSuggestion(elem, CompletionRelevance.DEFAULT);
293 } 297 }
298 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, CompletionRele vance.DEFAULT);
294 }); 299 });
295 300
296 // Build a list of inherited types that are imported 301 // Build a list of inherited types that are imported
297 // and include any inherited imported members 302 // and include any inherited imported members
298 var classDecl = node.getAncestor((p) => p is ClassDeclaration); 303 var classDecl = node.getAncestor((p) => p is ClassDeclaration);
299 if (classDecl is ClassDeclaration) { 304 if (classDecl is ClassDeclaration) {
300 List<String> inheritedTypes = new List<String>(); 305 List<String> inheritedTypes = new List<String>();
301 visitInheritedTypes(classDecl, (ClassDeclaration classDecl) { 306 visitInheritedTypes(classDecl, (ClassDeclaration classDecl) {
302 // ignored 307 // ignored
303 }, (String typeName) { 308 }, (String typeName) {
304 inheritedTypes.add(typeName); 309 inheritedTypes.add(typeName);
305 }); 310 });
306 Set<String> visited = new Set<String>(); 311 Set<String> visited = new Set<String>();
307 while (inheritedTypes.length > 0) { 312 while (inheritedTypes.length > 0) {
308 String name = inheritedTypes.removeLast(); 313 String name = inheritedTypes.removeLast();
309 ClassElement elem = classMap[name]; 314 ClassElement elem = classMap[name];
310 if (visited.add(name) && elem != null) { 315 if (visited.add(name) && elem != null) {
311 _addElementSuggestions(elem.accessors); 316 _addElementSuggestions(elem.accessors, typesOnly, excludeVoidReturn);
312 _addElementSuggestions(elem.methods); 317 _addElementSuggestions(elem.methods, typesOnly, excludeVoidReturn);
313 elem.allSupertypes.forEach((InterfaceType type) { 318 elem.allSupertypes.forEach((InterfaceType type) {
314 if (visited.add(type.name)) { 319 if (visited.add(type.name)) {
315 _addElementSuggestions(type.accessors); 320 _addElementSuggestions(type.accessors, typesOnly, excludeVoidRetur n);
316 _addElementSuggestions(type.methods); 321 _addElementSuggestions(type.methods, typesOnly, excludeVoidReturn) ;
317 } 322 }
318 }); 323 });
319 } 324 }
320 } 325 }
321 } 326 }
322 327
323 // Add non-imported elements as low relevance 328 // Add non-imported elements as low relevance
324 var future = request.searchEngine.searchTopLevelDeclarations(''); 329 var future = request.searchEngine.searchTopLevelDeclarations('');
325 return future.then((List<SearchMatch> matches) { 330 return future.then((List<SearchMatch> matches) {
326 Set<String> completionSet = new Set<String>(); 331 Set<String> completionSet = new Set<String>();
327 request.suggestions.forEach((CompletionSuggestion suggestion) { 332 request.suggestions.forEach((CompletionSuggestion suggestion) {
328 completionSet.add(suggestion.completion); 333 completionSet.add(suggestion.completion);
329 }); 334 });
330 matches.forEach((SearchMatch match) { 335 matches.forEach((SearchMatch match) {
331 if (match.kind == MatchKind.DECLARATION) { 336 if (match.kind == MatchKind.DECLARATION) {
332 Element element = match.element; 337 Element element = match.element;
333 if (element.isPublic && 338 if (element.isPublic &&
334 !excludedLibs.contains(element.library) && 339 !excludedLibs.contains(element.library) &&
335 !completionSet.contains(element.displayName)) { 340 !completionSet.contains(element.displayName)) {
336 if (!typesOnly || element is ClassElement) { 341 if (!typesOnly || element is ClassElement) {
337 _addElementSuggestion(element, CompletionRelevance.LOW); 342 _addElementSuggestion(element, typesOnly, excludeVoidReturn, Compl etionRelevance.LOW);
338 } 343 }
339 } 344 }
340 } 345 }
341 }); 346 });
342 return true; 347 return true;
343 }); 348 });
344 } 349 }
345 350
346 void _addLibraryPrefixSuggestion(ImportElement importElem) { 351 void _addLibraryPrefixSuggestion(ImportElement importElem) {
347 String completion = importElem.prefix.displayName; 352 String completion = importElem.prefix.displayName;
348 if (completion != null && completion.length > 0) { 353 if (completion != null && completion.length > 0) {
349 CompletionSuggestion suggestion = new CompletionSuggestion( 354 CompletionSuggestion suggestion = new CompletionSuggestion(
350 CompletionSuggestionKind.LIBRARY_PREFIX, 355 CompletionSuggestionKind.LIBRARY_PREFIX,
351 CompletionRelevance.DEFAULT, 356 CompletionRelevance.DEFAULT,
352 completion, 357 completion,
353 completion.length, 358 completion.length,
354 0, 359 0,
355 importElem.isDeprecated, 360 importElem.isDeprecated,
356 false); 361 false);
357 LibraryElement lib = importElem.importedLibrary; 362 LibraryElement lib = importElem.importedLibrary;
358 if (lib != null) { 363 if (lib != null) {
359 suggestion.element = newElement_fromEngine(lib); 364 suggestion.element = newElement_fromEngine(lib);
360 } 365 }
361 request.suggestions.add(suggestion); 366 request.suggestions.add(suggestion);
362 } 367 }
363 } 368 }
364 } 369 }
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