| 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 |