OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library services.completion.computer.dart.invocation; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_services/completion/completion_suggestion.dart'; | |
10 import 'package:analysis_services/src/completion/dart_completion_manager.dart'; | |
11 import 'package:analyzer/src/generated/ast.dart'; | |
12 import 'package:analyzer/src/generated/element.dart'; | |
13 | |
14 /** | |
15 * A computer for calculating invocation / access suggestions | |
16 * `completion.getSuggestions` request results. | |
17 */ | |
18 class InvocationComputer extends DartCompletionComputer { | |
19 | |
20 @override | |
21 bool computeFast(DartCompletionRequest request) { | |
22 // TODO: implement computeFast | |
23 return false; | |
24 } | |
25 | |
26 @override | |
27 Future<bool> computeFull(DartCompletionRequest request) { | |
28 return request.node.accept(new _InvocationAstVisitor(request)); | |
29 } | |
30 } | |
31 | |
32 /** | |
33 * An [AstNode] vistor for determining the appropriate invocation/access | |
34 * suggestions based upon the node in which the completion is requested. | |
35 */ | |
36 class _InvocationAstVisitor extends GeneralizingAstVisitor<Future<bool>> { | |
37 final DartCompletionRequest request; | |
38 AstNode completionNode; | |
39 | |
40 _InvocationAstVisitor(this.request); | |
41 | |
42 @override | |
43 Future<bool> visitNode(AstNode node) { | |
44 return new Future.value(false); | |
45 } | |
46 | |
47 @override | |
48 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) { | |
49 if (node.identifier == completionNode) { | |
50 return _addSuggestions(node.prefix.bestElement); | |
51 } | |
52 return super.visitPrefixedIdentifier(node); | |
53 } | |
54 | |
55 @override | |
56 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) { | |
57 completionNode = node; | |
58 return node.parent.accept(this); | |
59 } | |
60 | |
61 /** | |
62 * Add invocation / access suggestions for the given element. | |
63 */ | |
64 Future<bool> _addSuggestions(Element element) { | |
65 if (element != null) { | |
66 return element.accept(new _InvocationElementVisitor(request)); | |
67 } | |
68 return new Future.value(false); | |
69 } | |
70 } | |
71 | |
72 /** | |
73 * An [Element] visitor for determining the appropriate invocation/access | |
74 * suggestions based upon the element for which the completion is requested. | |
75 */ | |
76 class _InvocationElementVisitor extends GeneralizingElementVisitor<Future<bool>> | |
77 { | |
78 final DartCompletionRequest request; | |
79 | |
80 _InvocationElementVisitor(this.request); | |
81 | |
82 @override | |
83 Future<bool> visitElement(Element element) { | |
84 return new Future.value(false); | |
85 } | |
86 | |
87 @override | |
88 Future<bool> visitVariableElement(VariableElement element) { | |
89 return _addSuggestions(element.type); | |
90 } | |
91 | |
92 Future<bool> _addSuggestions(DartType type) { | |
93 if (type != null && type.element != null) { | |
94 type.element.accept(new _SuggestionBuilderVisitor(request)); | |
95 return new Future.value(true); | |
96 } | |
97 return new Future.value(false); | |
98 } | |
99 } | |
100 | |
101 /** | |
102 * An [Element] visitor that builds suggestions by recursively visiting | |
103 * elements in a type hierarchy. | |
104 */ | |
105 class _SuggestionBuilderVisitor extends GeneralizingElementVisitor { | |
106 final DartCompletionRequest request; | |
107 | |
108 _SuggestionBuilderVisitor(this.request); | |
109 | |
110 @override | |
111 visitClassElement(ClassElement element) { | |
112 //TODO (danrubel): filter private members if not in the same library | |
113 element.visitChildren(this); | |
114 } | |
115 | |
116 @override | |
117 visitElement(Element element) { | |
118 // ignored | |
119 } | |
120 | |
121 @override | |
122 visitFieldElement(FieldElement element) { | |
123 if (!element.isSynthetic) { | |
124 _addSuggestion(element, CompletionSuggestionKind.FIELD); | |
125 } | |
126 } | |
127 | |
128 @override | |
129 visitMethodElement(MethodElement element) { | |
130 if (!element.isSynthetic) { | |
131 _addSuggestion(element, CompletionSuggestionKind.METHOD); | |
132 } | |
133 } | |
134 | |
135 @override | |
136 visitPropertyAccessorElement(PropertyAccessorElement element) { | |
137 if (!element.isSynthetic) { | |
138 if (element.isGetter) { | |
139 _addSuggestion(element, CompletionSuggestionKind.GETTER); | |
140 } else if (element.isSetter) { | |
141 _addSuggestion( | |
142 element, | |
143 CompletionSuggestionKind.SETTER, | |
144 element.displayName); | |
145 } | |
146 } | |
147 } | |
148 | |
149 void _addSuggestion(Element element, CompletionSuggestionKind kind, | |
150 [String completion = null]) { | |
151 if (completion == null) { | |
152 completion = element.name; | |
153 } | |
154 if (completion != null && completion.length > 0) { | |
155 request.suggestions.add( | |
156 new CompletionSuggestion( | |
157 kind, | |
158 CompletionRelevance.DEFAULT, | |
159 completion, | |
160 completion.length, | |
161 0, | |
162 element.isDeprecated, | |
163 false)); | |
164 } | |
165 } | |
166 } | |
OLD | NEW |