OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.dart.suggestion.builder; | 5 library services.completion.dart.suggestion.builder; |
6 | 6 |
7 import 'package:analysis_server/src/protocol_server.dart' as protocol; | 7 import 'package:analysis_server/src/protocol_server.dart' as protocol; |
8 import 'package:analysis_server/src/protocol_server.dart' | 8 import 'package:analysis_server/src/protocol_server.dart' |
9 hide Element, ElementKind; | 9 hide Element, ElementKind; |
10 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; | 10 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 /** | 102 /** |
103 * Common mixin for sharing behavior | 103 * Common mixin for sharing behavior |
104 */ | 104 */ |
105 abstract class ElementSuggestionBuilder { | 105 abstract class ElementSuggestionBuilder { |
106 /** | 106 /** |
107 * A collection of completion suggestions. | 107 * A collection of completion suggestions. |
108 */ | 108 */ |
109 final List<CompletionSuggestion> suggestions = <CompletionSuggestion>[]; | 109 final List<CompletionSuggestion> suggestions = <CompletionSuggestion>[]; |
110 | 110 |
111 /** | 111 /** |
| 112 * A set of existing completions used to prevent duplicate suggestions. |
| 113 */ |
| 114 final Set<String> _completions = new Set<String>(); |
| 115 |
| 116 /** |
| 117 * A map of element names to suggestions for synthetic getters and setters. |
| 118 */ |
| 119 final Map<String, CompletionSuggestion> _syntheticMap = |
| 120 <String, CompletionSuggestion>{}; |
| 121 |
| 122 /** |
112 * Return the library in which the completion is requested. | 123 * Return the library in which the completion is requested. |
113 */ | 124 */ |
114 LibraryElement get containingLibrary; | 125 LibraryElement get containingLibrary; |
115 | 126 |
116 /** | 127 /** |
117 * Return the kind of suggestions that should be built. | 128 * Return the kind of suggestions that should be built. |
118 */ | 129 */ |
119 CompletionSuggestionKind get kind; | 130 CompletionSuggestionKind get kind; |
120 | 131 |
121 /** | 132 /** |
122 * Add a suggestion based upon the given element. | 133 * Add a suggestion based upon the given element. |
123 */ | 134 */ |
124 void addSuggestion(Element element, | 135 void addSuggestion(Element element, |
125 {String prefix, int relevance: DART_RELEVANCE_DEFAULT}) { | 136 {String prefix, int relevance: DART_RELEVANCE_DEFAULT}) { |
126 if (element.isPrivate) { | 137 if (element.isPrivate) { |
127 if (element.library != containingLibrary) { | 138 if (element.library != containingLibrary) { |
128 return; | 139 return; |
129 } | 140 } |
130 } | 141 } |
131 if (prefix == null && element.isSynthetic) { | |
132 if ((element is PropertyAccessorElement) || | |
133 element is FieldElement && !_isSpecialEnumField(element)) { | |
134 return; | |
135 } | |
136 } | |
137 String completion = element.displayName; | 142 String completion = element.displayName; |
138 if (prefix != null && prefix.length > 0) { | 143 if (prefix != null && prefix.length > 0) { |
139 if (completion == null || completion.length <= 0) { | 144 if (completion == null || completion.length <= 0) { |
140 completion = prefix; | 145 completion = prefix; |
141 } else { | 146 } else { |
142 completion = '$prefix.$completion'; | 147 completion = '$prefix.$completion'; |
143 } | 148 } |
144 } | 149 } |
145 if (completion == null || completion.length <= 0) { | 150 if (completion == null || completion.length <= 0) { |
146 return; | 151 return; |
147 } | 152 } |
148 CompletionSuggestion suggestion = createSuggestion(element, | 153 CompletionSuggestion suggestion = createSuggestion(element, |
149 completion: completion, kind: kind, relevance: relevance); | 154 completion: completion, kind: kind, relevance: relevance); |
150 if (suggestion != null) { | 155 if (suggestion != null) { |
151 suggestions.add(suggestion); | 156 if (element.isSynthetic && element is PropertyAccessorElement) { |
152 } | 157 String cacheKey; |
153 } | 158 if (element.isGetter) { |
| 159 cacheKey = element.name; |
| 160 } |
| 161 if (element.isSetter) { |
| 162 cacheKey = element.name; |
| 163 cacheKey = cacheKey.substring(0, cacheKey.length - 1); |
| 164 } |
| 165 if (cacheKey != null) { |
| 166 CompletionSuggestion existingSuggestion = _syntheticMap[cacheKey]; |
154 | 167 |
155 /** | 168 // Pair getter/setter by updating the existing suggestion |
156 * Determine if the given element is one of the synthetic enum accessors | 169 if (existingSuggestion != null) { |
157 * for which we should generate a suggestion. | 170 CompletionSuggestion getter = |
158 */ | 171 element.isGetter ? suggestion : existingSuggestion; |
159 bool _isSpecialEnumField(FieldElement element) { | 172 protocol.ElementKind elemKind = |
160 Element parent = element.enclosingElement; | 173 element.enclosingElement is ClassElement |
161 if (parent is ClassElement && parent.isEnum) { | 174 ? protocol.ElementKind.FIELD |
162 if (element.name == 'values') { | 175 : protocol.ElementKind.TOP_LEVEL_VARIABLE; |
163 return true; | 176 existingSuggestion.element = new protocol.Element( |
| 177 elemKind, |
| 178 existingSuggestion.element.name, |
| 179 existingSuggestion.element.flags, |
| 180 location: getter.element.location, |
| 181 typeParameters: getter.element.typeParameters, |
| 182 parameters: null, |
| 183 returnType: getter.returnType); |
| 184 return; |
| 185 } |
| 186 |
| 187 // Cache lone getter/setter so that it can be paired |
| 188 _syntheticMap[cacheKey] = suggestion; |
| 189 } |
| 190 } |
| 191 if (_completions.add(suggestion.completion)) { |
| 192 suggestions.add(suggestion); |
164 } | 193 } |
165 } | 194 } |
166 return false; | |
167 } | 195 } |
168 } | 196 } |
169 | 197 |
170 /** | 198 /** |
171 * This class visits elements in a library and provides suggestions based upon | 199 * This class visits elements in a library and provides suggestions based upon |
172 * the visible members in that library. | 200 * the visible members in that library. |
173 */ | 201 */ |
174 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor | 202 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor |
175 with ElementSuggestionBuilder { | 203 with ElementSuggestionBuilder { |
176 final LibraryElement containingLibrary; | 204 final LibraryElement containingLibrary; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 } | 243 } |
216 | 244 |
217 @override | 245 @override |
218 visitElement(Element element) { | 246 visitElement(Element element) { |
219 // ignored | 247 // ignored |
220 } | 248 } |
221 | 249 |
222 @override | 250 @override |
223 visitFunctionElement(FunctionElement element) { | 251 visitFunctionElement(FunctionElement element) { |
224 if (!typesOnly) { | 252 if (!typesOnly) { |
225 addSuggestion(element); | 253 int relevance = element.library == containingLibrary |
| 254 ? DART_RELEVANCE_LOCAL_FUNCTION |
| 255 : DART_RELEVANCE_DEFAULT; |
| 256 addSuggestion(element, relevance: relevance); |
226 } | 257 } |
227 } | 258 } |
228 | 259 |
229 @override | 260 @override |
230 visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { | 261 visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
231 if (!instCreation) { | 262 if (!instCreation) { |
232 addSuggestion(element); | 263 addSuggestion(element); |
233 } | 264 } |
234 } | 265 } |
235 | 266 |
236 @override | 267 @override |
237 visitTopLevelVariableElement(TopLevelVariableElement element) { | 268 visitTopLevelVariableElement(TopLevelVariableElement element) { |
238 if (!typesOnly) { | 269 if (!typesOnly) { |
239 addSuggestion(element); | 270 int relevance = element.library == containingLibrary |
| 271 ? DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE |
| 272 : DART_RELEVANCE_DEFAULT; |
| 273 addSuggestion(element, relevance: relevance); |
240 } | 274 } |
241 } | 275 } |
242 } | 276 } |
OLD | NEW |