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