| 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.computer.dart.invocation; | 5 library services.completion.computer.dart.invocation; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 9 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| 10 import 'package:analysis_server/src/services/completion/local_declaration_visito
r.dart'; |
| 10 import 'package:analysis_server/src/services/completion/optype.dart'; | 11 import 'package:analysis_server/src/services/completion/optype.dart'; |
| 11 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; | 12 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; |
| 12 import 'package:analyzer/src/generated/ast.dart'; | 13 import 'package:analyzer/src/generated/ast.dart'; |
| 13 import 'package:analyzer/src/generated/element.dart'; | 14 import 'package:analyzer/src/generated/element.dart'; |
| 14 | 15 |
| 15 import '../../protocol_server.dart' show CompletionSuggestionKind; | 16 import '../../protocol_server.dart' show CompletionSuggestionKind; |
| 16 | 17 |
| 17 /** | 18 /** |
| 18 * A computer for calculating invocation / access suggestions | 19 * A computer for calculating invocation / access suggestions |
| 19 * `completion.getSuggestions` request results. | 20 * `completion.getSuggestions` request results. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 return new _ExpressionSuggestionBuilder(request); | 115 return new _ExpressionSuggestionBuilder(request); |
| 115 } | 116 } |
| 116 | 117 |
| 117 @override | 118 @override |
| 118 SuggestionBuilder visitSimpleIdentifier(SimpleIdentifier node) { | 119 SuggestionBuilder visitSimpleIdentifier(SimpleIdentifier node) { |
| 119 return node.parent.accept(this); | 120 return node.parent.accept(this); |
| 120 } | 121 } |
| 121 } | 122 } |
| 122 | 123 |
| 123 /** | 124 /** |
| 125 * An [AstVisitor] which looks for a declaration with the given name |
| 126 * and if found, tries to determine a type for that declaration. |
| 127 */ |
| 128 class _LocalBestTypeVisitor extends LocalDeclarationVisitor { |
| 129 |
| 130 /** |
| 131 * The name for the declaration to be found. |
| 132 */ |
| 133 final String targetName; |
| 134 |
| 135 /** |
| 136 * The best type for the found declaration, |
| 137 * or `null` if no declaration found or failed to determine a type. |
| 138 */ |
| 139 DartType typeFound; |
| 140 |
| 141 /** |
| 142 * Construct a new instance to search for a declaration |
| 143 */ |
| 144 _LocalBestTypeVisitor(this.targetName, int offset) : super(offset); |
| 145 |
| 146 @override |
| 147 void declaredClass(ClassDeclaration declaration) { |
| 148 if (declaration.name.name == targetName) { |
| 149 finished = true; |
| 150 // no type |
| 151 } |
| 152 } |
| 153 |
| 154 @override |
| 155 void declaredClassTypeAlias(ClassTypeAlias declaration) { |
| 156 if (declaration.name.name == targetName) { |
| 157 finished = true; |
| 158 // no type |
| 159 } |
| 160 } |
| 161 |
| 162 @override |
| 163 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) { |
| 164 if (varDecl.name.name == targetName) { |
| 165 finished = true; |
| 166 // Type provided by the element in computeFull above |
| 167 } |
| 168 } |
| 169 |
| 170 @override |
| 171 void declaredFunction(FunctionDeclaration declaration) { |
| 172 if (declaration.name.name == targetName) { |
| 173 finished = true; |
| 174 TypeName typeName = declaration.returnType; |
| 175 if (typeName != null) { |
| 176 typeFound = typeName.type; |
| 177 } |
| 178 } |
| 179 } |
| 180 |
| 181 @override |
| 182 void declaredFunctionTypeAlias(FunctionTypeAlias declaration) { |
| 183 if (declaration.name.name == targetName) { |
| 184 finished = true; |
| 185 TypeName typeName = declaration.returnType; |
| 186 if (typeName != null) { |
| 187 typeFound = typeName.type; |
| 188 } |
| 189 } |
| 190 } |
| 191 |
| 192 @override |
| 193 void declaredLabel(Label label, bool isCaseLabel) { |
| 194 if (label.label.name == targetName) { |
| 195 finished = true; |
| 196 // no type |
| 197 } |
| 198 } |
| 199 |
| 200 @override |
| 201 void declaredLocalVar(SimpleIdentifier name, TypeName type) { |
| 202 if (name.name == targetName) { |
| 203 finished = true; |
| 204 typeFound = name.bestType; |
| 205 } |
| 206 } |
| 207 |
| 208 @override |
| 209 void declaredMethod(MethodDeclaration declaration) { |
| 210 if (declaration.name.name == targetName) { |
| 211 finished = true; |
| 212 TypeName typeName = declaration.returnType; |
| 213 if (typeName != null) { |
| 214 typeFound = typeName.type; |
| 215 } |
| 216 } |
| 217 } |
| 218 |
| 219 @override |
| 220 void declaredParam(SimpleIdentifier name, TypeName type) { |
| 221 if (name.name == targetName) { |
| 222 finished = true; |
| 223 // Type provided by the element in computeFull above |
| 224 } |
| 225 } |
| 226 |
| 227 @override |
| 228 void declaredTopLevelVar(VariableDeclarationList varList, |
| 229 VariableDeclaration varDecl) { |
| 230 if (varDecl.name.name == targetName) { |
| 231 finished = true; |
| 232 // Type provided by the element in computeFull above |
| 233 } |
| 234 } |
| 235 } |
| 236 |
| 237 /** |
| 124 * An [Element] visitor for determining the appropriate invocation/access | 238 * An [Element] visitor for determining the appropriate invocation/access |
| 125 * suggestions based upon the element for which the completion is requested. | 239 * suggestions based upon the element for which the completion is requested. |
| 126 */ | 240 */ |
| 127 class _PrefixedIdentifierSuggestionBuilder extends | 241 class _PrefixedIdentifierSuggestionBuilder extends |
| 128 GeneralizingElementVisitor<Future<bool>> implements SuggestionBuilder { | 242 GeneralizingElementVisitor<Future<bool>> implements SuggestionBuilder { |
| 129 | 243 |
| 130 final DartCompletionRequest request; | 244 final DartCompletionRequest request; |
| 131 | 245 |
| 132 _PrefixedIdentifierSuggestionBuilder(this.request); | 246 _PrefixedIdentifierSuggestionBuilder(this.request); |
| 133 | 247 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 144 if (node is ConstructorName) { | 258 if (node is ConstructorName) { |
| 145 // some PrefixedIdentifier nodes are transformed into | 259 // some PrefixedIdentifier nodes are transformed into |
| 146 // ConstructorName nodes during the resolution process. | 260 // ConstructorName nodes during the resolution process. |
| 147 return new NamedConstructorSuggestionBuilder(request).computeFull(node); | 261 return new NamedConstructorSuggestionBuilder(request).computeFull(node); |
| 148 } | 262 } |
| 149 if (node is PrefixedIdentifier) { | 263 if (node is PrefixedIdentifier) { |
| 150 SimpleIdentifier prefix = node.prefix; | 264 SimpleIdentifier prefix = node.prefix; |
| 151 if (prefix != null) { | 265 if (prefix != null) { |
| 152 Element element = prefix.bestElement; | 266 Element element = prefix.bestElement; |
| 153 DartType type = prefix.bestType; | 267 DartType type = prefix.bestType; |
| 154 if (element is! ClassElement && type != null && !type.isDynamic) { | 268 if (element is! ClassElement) { |
| 155 InterfaceTypeSuggestionBuilder.suggestionsFor( | 269 if (type == null || type.isDynamic) { |
| 156 request, | 270 // |
| 157 type); | 271 // Given `g. int y = 0;`, the parser interprets `g` as a prefixed |
| 158 return new Future.value(true); | 272 // identifier with no type. |
| 159 } else if (element != null) { | 273 // If the user is requesting completions for `g`, |
| 274 // then check for a function, getter, or similar with a type. |
| 275 // |
| 276 _LocalBestTypeVisitor visitor = |
| 277 new _LocalBestTypeVisitor(prefix.name, request.offset); |
| 278 prefix.accept(visitor); |
| 279 type = visitor.typeFound; |
| 280 } |
| 281 if (type != null && !type.isDynamic) { |
| 282 InterfaceTypeSuggestionBuilder.suggestionsFor(request, type); |
| 283 return new Future.value(true); |
| 284 } |
| 285 } |
| 286 if (element != null) { |
| 160 return element.accept(this); | 287 return element.accept(this); |
| 161 } | 288 } |
| 162 } | 289 } |
| 163 } | 290 } |
| 164 return new Future.value(false); | 291 return new Future.value(false); |
| 165 } | 292 } |
| 166 | 293 |
| 167 @override | 294 @override |
| 168 Future<bool> visitClassElement(ClassElement element) { | 295 Future<bool> visitClassElement(ClassElement element) { |
| 169 if (element != null) { | 296 if (element != null) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 181 Future<bool> visitElement(Element element) { | 308 Future<bool> visitElement(Element element) { |
| 182 return new Future.value(false); | 309 return new Future.value(false); |
| 183 } | 310 } |
| 184 | 311 |
| 185 @override | 312 @override |
| 186 Future<bool> visitPrefixElement(PrefixElement element) { | 313 Future<bool> visitPrefixElement(PrefixElement element) { |
| 187 //TODO (danrubel) reimplement to use prefixElement.importedLibraries | 314 //TODO (danrubel) reimplement to use prefixElement.importedLibraries |
| 188 // once that accessor is implemented and available in Dart | 315 // once that accessor is implemented and available in Dart |
| 189 bool modified = false; | 316 bool modified = false; |
| 190 // Find the import directive with the given prefix | 317 // Find the import directive with the given prefix |
| 191 request.unit.directives.forEach((Directive directive) { | 318 for (Directive directive in request.unit.directives) { |
| 192 if (directive is ImportDirective) { | 319 if (directive is ImportDirective) { |
| 193 if (directive.prefix != null) { | 320 if (directive.prefix != null) { |
| 194 if (directive.prefix.name == element.name) { | 321 if (directive.prefix.name == element.name) { |
| 195 // Suggest elements from the imported library | 322 // Suggest elements from the imported library |
| 196 LibraryElement library = directive.uriElement; | 323 LibraryElement library = directive.uriElement; |
| 197 LibraryElementSuggestionBuilder.suggestionsFor( | 324 LibraryElementSuggestionBuilder.suggestionsFor( |
| 198 request, | 325 request, |
| 199 CompletionSuggestionKind.INVOCATION, | 326 CompletionSuggestionKind.INVOCATION, |
| 200 library); | 327 library); |
| 201 modified = true; | 328 modified = true; |
| 202 } | 329 } |
| 203 } | 330 } |
| 204 } | 331 } |
| 205 }); | 332 }; |
| 206 return new Future.value(modified); | 333 return new Future.value(modified); |
| 207 } | 334 } |
| 208 | 335 |
| 209 @override | 336 @override |
| 210 Future<bool> visitPropertyAccessorElement(PropertyAccessorElement element) { | 337 Future<bool> visitPropertyAccessorElement(PropertyAccessorElement element) { |
| 211 if (element != null) { | 338 if (element != null) { |
| 212 PropertyInducingElement elemVar = element.variable; | 339 PropertyInducingElement elemVar = element.variable; |
| 213 if (elemVar != null) { | 340 if (elemVar != null) { |
| 214 InterfaceTypeSuggestionBuilder.suggestionsFor(request, elemVar.type); | 341 InterfaceTypeSuggestionBuilder.suggestionsFor(request, elemVar.type); |
| 215 } | 342 } |
| 216 return new Future.value(true); | 343 return new Future.value(true); |
| 217 } | 344 } |
| 218 return new Future.value(false); | 345 return new Future.value(false); |
| 219 } | 346 } |
| 220 | 347 |
| 221 @override | 348 @override |
| 222 Future<bool> visitVariableElement(VariableElement element) { | 349 Future<bool> visitVariableElement(VariableElement element) { |
| 223 InterfaceTypeSuggestionBuilder.suggestionsFor(request, element.type); | 350 InterfaceTypeSuggestionBuilder.suggestionsFor(request, element.type); |
| 224 return new Future.value(true); | 351 return new Future.value(true); |
| 225 } | 352 } |
| 226 } | 353 } |
| OLD | NEW |