OLD | NEW |
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.contributor.dart.type_member; | 5 library services.completion.contributor.dart.type_member; |
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/provisional/completion/dart/completion_dart.
dart'; | 10 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; |
11 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.
dart'; | 11 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.
dart'; |
12 import 'package:analysis_server/src/services/completion/local_declaration_visito
r.dart'; | 12 import 'package:analysis_server/src/services/completion/local_declaration_visito
r.dart'; |
| 13 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'package:analyzer/dart/element/type.dart'; |
13 import 'package:analyzer/src/generated/ast.dart'; | 15 import 'package:analyzer/src/generated/ast.dart'; |
14 import 'package:analyzer/src/generated/element.dart'; | |
15 | 16 |
16 import '../../../protocol_server.dart' | 17 import '../../../protocol_server.dart' |
17 show CompletionSuggestion, CompletionSuggestionKind; | 18 show CompletionSuggestion, CompletionSuggestionKind; |
18 | 19 |
19 /** | 20 /** |
20 * A contributor for calculating instance invocation / access suggestions | 21 * A contributor for calculating instance invocation / access suggestions |
21 * `completion.getSuggestions` request results. | 22 * `completion.getSuggestions` request results. |
22 */ | 23 */ |
23 class TypeMemberContributor extends DartCompletionContributor { | 24 class TypeMemberContributor extends DartCompletionContributor { |
24 @override | 25 @override |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 * Map from completion identifier to completion suggestion | 274 * Map from completion identifier to completion suggestion |
274 */ | 275 */ |
275 Map<String, CompletionSuggestion> _suggestionMap = | 276 Map<String, CompletionSuggestion> _suggestionMap = |
276 <String, CompletionSuggestion>{}; | 277 <String, CompletionSuggestion>{}; |
277 | 278 |
278 _SuggestionBuilder(this.containingLibrary); | 279 _SuggestionBuilder(this.containingLibrary); |
279 | 280 |
280 Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values; | 281 Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values; |
281 | 282 |
282 /** | 283 /** |
| 284 * Return completion suggestions for 'dot' completions on the given [type]. |
| 285 * If the 'dot' completion is a super expression, then [containingMethodName] |
| 286 * is the name of the method in which the completion is requested. |
| 287 */ |
| 288 void buildSuggestions(InterfaceType type, String containingMethodName) { |
| 289 // Visit all of the types in the class hierarchy, collecting possible |
| 290 // completions. If multiple elements are found that complete to the same |
| 291 // identifier, addSuggestion will discard all but the first (with a few |
| 292 // exceptions to handle getter/setter pairs). |
| 293 List<InterfaceType> types = _getTypeOrdering(type); |
| 294 for (InterfaceType targetType in types) { |
| 295 for (MethodElement method in targetType.methods) { |
| 296 // Exclude static methods when completion on an instance |
| 297 if (!method.isStatic) { |
| 298 // Boost the relevance of a super expression |
| 299 // calling a method of the same name as the containing method |
| 300 _addSuggestion(method, |
| 301 relevance: method.name == containingMethodName |
| 302 ? DART_RELEVANCE_HIGH |
| 303 : DART_RELEVANCE_DEFAULT); |
| 304 } |
| 305 } |
| 306 for (PropertyAccessorElement propertyAccessor in targetType.accessors) { |
| 307 if (!propertyAccessor.isStatic) { |
| 308 if (propertyAccessor.isSynthetic) { |
| 309 // Avoid visiting a field twice |
| 310 if (propertyAccessor.isGetter) { |
| 311 _addSuggestion(propertyAccessor.variable); |
| 312 } |
| 313 } else { |
| 314 _addSuggestion(propertyAccessor); |
| 315 } |
| 316 } |
| 317 } |
| 318 } |
| 319 } |
| 320 |
| 321 /** |
283 * Add a suggestion based upon the given element, provided that it is not | 322 * Add a suggestion based upon the given element, provided that it is not |
284 * shadowed by a previously added suggestion. | 323 * shadowed by a previously added suggestion. |
285 */ | 324 */ |
286 void _addSuggestion(Element element, | 325 void _addSuggestion(Element element, |
287 {int relevance: DART_RELEVANCE_DEFAULT}) { | 326 {int relevance: DART_RELEVANCE_DEFAULT}) { |
288 if (element.isPrivate) { | 327 if (element.isPrivate) { |
289 if (element.library != containingLibrary) { | 328 if (element.library != containingLibrary) { |
290 // Do not suggest private members for imported libraries | 329 // Do not suggest private members for imported libraries |
291 return; | 330 return; |
292 } | 331 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 return; | 368 return; |
330 } | 369 } |
331 CompletionSuggestion suggestion = | 370 CompletionSuggestion suggestion = |
332 createSuggestion(element, relevance: relevance); | 371 createSuggestion(element, relevance: relevance); |
333 if (suggestion != null) { | 372 if (suggestion != null) { |
334 _suggestionMap[suggestion.completion] = suggestion; | 373 _suggestionMap[suggestion.completion] = suggestion; |
335 } | 374 } |
336 } | 375 } |
337 | 376 |
338 /** | 377 /** |
339 * Return completion suggestions for 'dot' completions on the given [type]. | |
340 * If the 'dot' completion is a super expression, then [containingMethodName] | |
341 * is the name of the method in which the completion is requested. | |
342 */ | |
343 void buildSuggestions(InterfaceType type, String containingMethodName) { | |
344 // Visit all of the types in the class hierarchy, collecting possible | |
345 // completions. If multiple elements are found that complete to the same | |
346 // identifier, addSuggestion will discard all but the first (with a few | |
347 // exceptions to handle getter/setter pairs). | |
348 List<InterfaceType> types = _getTypeOrdering(type); | |
349 for (InterfaceType targetType in types) { | |
350 for (MethodElement method in targetType.methods) { | |
351 // Exclude static methods when completion on an instance | |
352 if (!method.isStatic) { | |
353 // Boost the relevance of a super expression | |
354 // calling a method of the same name as the containing method | |
355 _addSuggestion(method, | |
356 relevance: method.name == containingMethodName | |
357 ? DART_RELEVANCE_HIGH | |
358 : DART_RELEVANCE_DEFAULT); | |
359 } | |
360 } | |
361 for (PropertyAccessorElement propertyAccessor in targetType.accessors) { | |
362 if (!propertyAccessor.isStatic) { | |
363 if (propertyAccessor.isSynthetic) { | |
364 // Avoid visiting a field twice | |
365 if (propertyAccessor.isGetter) { | |
366 _addSuggestion(propertyAccessor.variable); | |
367 } | |
368 } else { | |
369 _addSuggestion(propertyAccessor); | |
370 } | |
371 } | |
372 } | |
373 } | |
374 } | |
375 | |
376 /** | |
377 * Get a list of [InterfaceType]s that should be searched to find the | 378 * Get a list of [InterfaceType]s that should be searched to find the |
378 * possible completions for an object having type [type]. | 379 * possible completions for an object having type [type]. |
379 */ | 380 */ |
380 List<InterfaceType> _getTypeOrdering(InterfaceType type) { | 381 List<InterfaceType> _getTypeOrdering(InterfaceType type) { |
381 // Candidate completions can come from [type] as well as any types above it | 382 // Candidate completions can come from [type] as well as any types above it |
382 // in the class hierarchy (including mixins, superclasses, and interfaces). | 383 // in the class hierarchy (including mixins, superclasses, and interfaces). |
383 // If a given completion identifier shows up in multiple types, we should | 384 // If a given completion identifier shows up in multiple types, we should |
384 // use the element that is nearest in the superclass chain, so we will | 385 // use the element that is nearest in the superclass chain, so we will |
385 // visit [type] first, then its mixins, then its superclass, then its | 386 // visit [type] first, then its mixins, then its superclass, then its |
386 // superclass's mixins, etc., and only afterwards visit interfaces. | 387 // superclass's mixins, etc., and only afterwards visit interfaces. |
(...skipping 16 matching lines...) Expand all Loading... |
403 // in the reverse order. | 404 // in the reverse order. |
404 typesToVisit.addAll(nextType.interfaces); | 405 typesToVisit.addAll(nextType.interfaces); |
405 if (nextType.superclass != null) { | 406 if (nextType.superclass != null) { |
406 typesToVisit.add(nextType.superclass); | 407 typesToVisit.add(nextType.superclass); |
407 } | 408 } |
408 typesToVisit.addAll(nextType.mixins); | 409 typesToVisit.addAll(nextType.mixins); |
409 } | 410 } |
410 return result; | 411 return result; |
411 } | 412 } |
412 } | 413 } |
OLD | NEW |