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.suggestion.builder; | 5 library services.completion.suggestion.builder; |
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' as protocol; | 10 import 'package:analysis_server/src/protocol_server.dart' as protocol; |
11 import 'package:analysis_server/src/protocol_server.dart' | 11 import 'package:analysis_server/src/protocol_server.dart' |
12 hide Element, ElementKind; | 12 hide Element, ElementKind; |
13 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 13 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
14 import 'package:analyzer/src/generated/ast.dart'; | 14 import 'package:analyzer/src/generated/ast.dart'; |
15 import 'package:analyzer/src/generated/element.dart'; | 15 import 'package:analyzer/src/generated/element.dart'; |
16 import 'package:analyzer/src/generated/utilities_dart.dart'; | 16 import 'package:analyzer/src/generated/utilities_dart.dart'; |
17 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
18 import 'package:path/path.dart' as path; | 18 import 'package:path/path.dart' as path; |
19 | 19 |
20 const String DYNAMIC = 'dynamic'; | 20 const String DYNAMIC = 'dynamic'; |
21 | 21 |
22 /** | 22 /** |
23 * Return a suggestion based upon the given element | 23 * Return a suggestion based upon the given element |
24 * or `null` if a suggestion is not appropriate for the given element. | 24 * or `null` if a suggestion is not appropriate for the given element. |
25 * If the suggestion is not currently in scope, then specify | 25 * If the suggestion is not currently in scope, then specify |
26 * importForSource as the source to which an import should be added. | 26 * importForSource as the source to which an import should be added. |
27 */ | 27 */ |
28 CompletionSuggestion createSuggestion(Element element, {String completion, | 28 CompletionSuggestion createSuggestion(Element element, |
| 29 {String completion, |
29 CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION, | 30 CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION, |
30 int relevance: DART_RELEVANCE_DEFAULT, Source importForSource}) { | 31 int relevance: DART_RELEVANCE_DEFAULT, |
| 32 Source importForSource}) { |
31 if (element is ExecutableElement && element.isOperator) { | 33 if (element is ExecutableElement && element.isOperator) { |
32 // Do not include operators in suggestions | 34 // Do not include operators in suggestions |
33 return null; | 35 return null; |
34 } | 36 } |
35 if (completion == null) { | 37 if (completion == null) { |
36 completion = element.displayName; | 38 completion = element.displayName; |
37 } | 39 } |
38 bool isDeprecated = element.isDeprecated; | 40 bool isDeprecated = element.isDeprecated; |
39 CompletionSuggestion suggestion = new CompletionSuggestion(kind, | 41 CompletionSuggestion suggestion = new CompletionSuggestion( |
40 isDeprecated ? DART_RELEVANCE_LOW : relevance, completion, | 42 kind, |
41 completion.length, 0, isDeprecated, false); | 43 isDeprecated ? DART_RELEVANCE_LOW : relevance, |
| 44 completion, |
| 45 completion.length, |
| 46 0, |
| 47 isDeprecated, |
| 48 false); |
42 suggestion.element = protocol.newElement_fromEngine(element); | 49 suggestion.element = protocol.newElement_fromEngine(element); |
43 Element enclosingElement = element.enclosingElement; | 50 Element enclosingElement = element.enclosingElement; |
44 if (enclosingElement is ClassElement) { | 51 if (enclosingElement is ClassElement) { |
45 suggestion.declaringType = enclosingElement.displayName; | 52 suggestion.declaringType = enclosingElement.displayName; |
46 } | 53 } |
47 suggestion.returnType = getReturnTypeString(element); | 54 suggestion.returnType = getReturnTypeString(element); |
48 if (element is ExecutableElement && element is! PropertyAccessorElement) { | 55 if (element is ExecutableElement && element is! PropertyAccessorElement) { |
49 suggestion.parameterNames = element.parameters | 56 suggestion.parameterNames = element.parameters |
50 .map((ParameterElement parameter) => parameter.name) | 57 .map((ParameterElement parameter) => parameter.name) |
51 .toList(); | 58 .toList(); |
52 suggestion.parameterTypes = element.parameters | 59 suggestion.parameterTypes = element.parameters |
53 .map((ParameterElement parameter) => parameter.type.displayName) | 60 .map((ParameterElement parameter) => parameter.type.displayName) |
54 .toList(); | 61 .toList(); |
55 suggestion.requiredParameterCount = element.parameters.where( | 62 suggestion.requiredParameterCount = element.parameters |
56 (ParameterElement parameter) => | 63 .where((ParameterElement parameter) => |
57 parameter.parameterKind == ParameterKind.REQUIRED).length; | 64 parameter.parameterKind == ParameterKind.REQUIRED) |
| 65 .length; |
58 suggestion.hasNamedParameters = element.parameters.any( | 66 suggestion.hasNamedParameters = element.parameters.any( |
59 (ParameterElement parameter) => | 67 (ParameterElement parameter) => |
60 parameter.parameterKind == ParameterKind.NAMED); | 68 parameter.parameterKind == ParameterKind.NAMED); |
61 } | 69 } |
62 if (importForSource != null) { | 70 if (importForSource != null) { |
63 String srcPath = path.dirname(importForSource.fullName); | 71 String srcPath = path.dirname(importForSource.fullName); |
64 LibraryElement libElem = element.library; | 72 LibraryElement libElem = element.library; |
65 if (libElem != null) { | 73 if (libElem != null) { |
66 Source libSource = libElem.source; | 74 Source libSource = libElem.source; |
67 if (libSource != null) { | 75 if (libSource != null) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 178 } |
171 } | 179 } |
172 }); | 180 }); |
173 } | 181 } |
174 } | 182 } |
175 | 183 |
176 /** | 184 /** |
177 * Common mixin for sharing behavior | 185 * Common mixin for sharing behavior |
178 */ | 186 */ |
179 abstract class ElementSuggestionBuilder { | 187 abstract class ElementSuggestionBuilder { |
180 | |
181 /** | 188 /** |
182 * Return the kind of suggestions that should be built. | 189 * Return the kind of suggestions that should be built. |
183 */ | 190 */ |
184 CompletionSuggestionKind get kind; | 191 CompletionSuggestionKind get kind; |
185 | 192 |
186 /** | 193 /** |
187 * Return the request on which the builder is operating. | 194 * Return the request on which the builder is operating. |
188 */ | 195 */ |
189 DartCompletionRequest get request; | 196 DartCompletionRequest get request; |
190 | 197 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 */ | 434 */ |
428 static void suggestionsFor(DartCompletionRequest request, DartType type, | 435 static void suggestionsFor(DartCompletionRequest request, DartType type, |
429 {bool isSuper: false, String containingMethodName: null}) { | 436 {bool isSuper: false, String containingMethodName: null}) { |
430 CompilationUnit compilationUnit = | 437 CompilationUnit compilationUnit = |
431 request.target.containingNode.getAncestor((n) => n is CompilationUnit); | 438 request.target.containingNode.getAncestor((n) => n is CompilationUnit); |
432 LibraryElement library = compilationUnit.element.library; | 439 LibraryElement library = compilationUnit.element.library; |
433 if (type is DynamicTypeImpl) { | 440 if (type is DynamicTypeImpl) { |
434 type = request.cache.objectClassElement.type; | 441 type = request.cache.objectClassElement.type; |
435 } | 442 } |
436 if (type is InterfaceType) { | 443 if (type is InterfaceType) { |
437 return new InterfaceTypeSuggestionBuilder(request)._buildSuggestions( | 444 return new InterfaceTypeSuggestionBuilder(request) |
438 type, library, isSuper, containingMethodName); | 445 ._buildSuggestions(type, library, isSuper, containingMethodName); |
439 } | 446 } |
440 } | 447 } |
441 } | 448 } |
442 | 449 |
443 /** | 450 /** |
444 * This class visits elements in a library and provides suggestions based upon | 451 * This class visits elements in a library and provides suggestions based upon |
445 * the visible members in that library. Clients should call | 452 * the visible members in that library. Clients should call |
446 * [LibraryElementSuggestionBuilder.suggestionsFor]. | 453 * [LibraryElementSuggestionBuilder.suggestionsFor]. |
447 */ | 454 */ |
448 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor | 455 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 @override | 517 @override |
511 visitTopLevelVariableElement(TopLevelVariableElement element) { | 518 visitTopLevelVariableElement(TopLevelVariableElement element) { |
512 if (!typesOnly) { | 519 if (!typesOnly) { |
513 addSuggestion(element); | 520 addSuggestion(element); |
514 } | 521 } |
515 } | 522 } |
516 | 523 |
517 /** | 524 /** |
518 * Add suggestions for the visible members in the given library | 525 * Add suggestions for the visible members in the given library |
519 */ | 526 */ |
520 static void suggestionsFor(DartCompletionRequest request, | 527 static void suggestionsFor( |
521 CompletionSuggestionKind kind, LibraryElement library, bool typesOnly, | 528 DartCompletionRequest request, |
| 529 CompletionSuggestionKind kind, |
| 530 LibraryElement library, |
| 531 bool typesOnly, |
522 bool instCreation) { | 532 bool instCreation) { |
523 if (library != null) { | 533 if (library != null) { |
524 library.visitChildren(new LibraryElementSuggestionBuilder( | 534 library.visitChildren(new LibraryElementSuggestionBuilder( |
525 request, kind, typesOnly, instCreation)); | 535 request, kind, typesOnly, instCreation)); |
526 } | 536 } |
527 } | 537 } |
528 } | 538 } |
529 | 539 |
530 /** | 540 /** |
531 * This class visits elements in a class and provides suggestions based upon | 541 * This class visits elements in a class and provides suggestions based upon |
532 * the visible named constructors in that class. | 542 * the visible named constructors in that class. |
533 */ | 543 */ |
534 class NamedConstructorSuggestionBuilder extends GeneralizingElementVisitor | 544 class NamedConstructorSuggestionBuilder extends GeneralizingElementVisitor |
535 with ElementSuggestionBuilder implements SuggestionBuilder { | 545 with ElementSuggestionBuilder |
| 546 implements SuggestionBuilder { |
536 final DartCompletionRequest request; | 547 final DartCompletionRequest request; |
537 | 548 |
538 NamedConstructorSuggestionBuilder(this.request); | 549 NamedConstructorSuggestionBuilder(this.request); |
539 | 550 |
540 @override | 551 @override |
541 CompletionSuggestionKind get kind => CompletionSuggestionKind.INVOCATION; | 552 CompletionSuggestionKind get kind => CompletionSuggestionKind.INVOCATION; |
542 | 553 |
543 @override | 554 @override |
544 bool computeFast(AstNode node) { | 555 bool computeFast(AstNode node) { |
545 return false; | 556 return false; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 * or `false` if [computeFull] should be called. | 668 * or `false` if [computeFull] should be called. |
658 */ | 669 */ |
659 bool computeFast(AstNode node); | 670 bool computeFast(AstNode node); |
660 | 671 |
661 /** | 672 /** |
662 * Return a future that computes the suggestions given a fully resolved AST. | 673 * Return a future that computes the suggestions given a fully resolved AST. |
663 * The future returns `true` if suggestions were added, else `false`. | 674 * The future returns `true` if suggestions were added, else `false`. |
664 */ | 675 */ |
665 Future<bool> computeFull(AstNode node); | 676 Future<bool> computeFull(AstNode node); |
666 } | 677 } |
OLD | NEW |