| 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.contributor.dart.invocation; |  | 
| 6 |  | 
| 7 import 'dart:async'; |  | 
| 8 |  | 
| 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'; |  | 
| 11 import 'package:analysis_server/src/services/completion/local_suggestion_builder
     .dart' |  | 
| 12     hide createSuggestion; |  | 
| 13 import 'package:analysis_server/src/services/completion/optype.dart'; |  | 
| 14 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
     ; |  | 
| 15 import 'package:analysis_server/src/services/completion/suggestion_builder.dart' |  | 
| 16     show createSuggestion; |  | 
| 17 import 'package:analyzer/src/generated/ast.dart'; |  | 
| 18 import 'package:analyzer/src/generated/element.dart'; |  | 
| 19 |  | 
| 20 import '../../protocol_server.dart' |  | 
| 21     show CompletionSuggestion, CompletionSuggestionKind; |  | 
| 22 |  | 
| 23 /** |  | 
| 24  * A contributor for calculating invocation / access suggestions |  | 
| 25  * `completion.getSuggestions` request results. |  | 
| 26  */ |  | 
| 27 class PrefixedElementContributor extends DartCompletionContributor { |  | 
| 28   SuggestionBuilder builder; |  | 
| 29 |  | 
| 30   @override |  | 
| 31   bool computeFast(DartCompletionRequest request) { |  | 
| 32     OpType optype = request.optype; |  | 
| 33     if (optype.isPrefixed) { |  | 
| 34       builder = request.target.containingNode |  | 
| 35           .accept(new _InvocationAstVisitor(request)); |  | 
| 36       if (builder != null) { |  | 
| 37         return builder.computeFast(request.target.containingNode); |  | 
| 38       } |  | 
| 39     } |  | 
| 40 |  | 
| 41     return true; |  | 
| 42   } |  | 
| 43 |  | 
| 44   @override |  | 
| 45   Future<bool> computeFull(DartCompletionRequest request) { |  | 
| 46     if (builder != null) { |  | 
| 47       return builder.computeFull(request.target.containingNode); |  | 
| 48     } |  | 
| 49     return new Future.value(false); |  | 
| 50   } |  | 
| 51 } |  | 
| 52 |  | 
| 53 class _ExpressionSuggestionBuilder implements SuggestionBuilder { |  | 
| 54   final DartCompletionRequest request; |  | 
| 55 |  | 
| 56   _ExpressionSuggestionBuilder(this.request); |  | 
| 57 |  | 
| 58   @override |  | 
| 59   bool computeFast(AstNode node) { |  | 
| 60     return false; |  | 
| 61   } |  | 
| 62 |  | 
| 63   @override |  | 
| 64   Future<bool> computeFull(AstNode node) { |  | 
| 65     if (node is MethodInvocation) { |  | 
| 66       node = (node as MethodInvocation).realTarget; |  | 
| 67     } else if (node is PropertyAccess) { |  | 
| 68       node = (node as PropertyAccess).realTarget; |  | 
| 69     } |  | 
| 70     if (node is Identifier) { |  | 
| 71       Element elem = node.bestElement; |  | 
| 72       if (elem is ClassElement || elem is PrefixElement) { |  | 
| 73         elem.accept(new _PrefixedIdentifierSuggestionBuilder(request)); |  | 
| 74         return new Future.value(true); |  | 
| 75       } |  | 
| 76     } |  | 
| 77     if (node is Expression) { |  | 
| 78       String containingMethodName; |  | 
| 79       bool isSuper = node is SuperExpression; |  | 
| 80       if (isSuper) { |  | 
| 81         MethodDeclaration containingMethod = |  | 
| 82             node.getAncestor((p) => p is MethodDeclaration); |  | 
| 83         if (containingMethod != null) { |  | 
| 84           SimpleIdentifier id = containingMethod.name; |  | 
| 85           if (id != null) { |  | 
| 86             containingMethodName = id.name; |  | 
| 87           } |  | 
| 88         } |  | 
| 89       } |  | 
| 90       InterfaceTypeSuggestionBuilder.suggestionsFor(request, node.bestType, |  | 
| 91           isSuper: isSuper, containingMethodName: containingMethodName); |  | 
| 92       return new Future.value(true); |  | 
| 93     } |  | 
| 94     return new Future.value(false); |  | 
| 95   } |  | 
| 96 } |  | 
| 97 |  | 
| 98 /** |  | 
| 99  * An [AstNode] vistor for determining which suggestion builder |  | 
| 100  * should be used to build invocation/access suggestions. |  | 
| 101  */ |  | 
| 102 class _InvocationAstVisitor extends GeneralizingAstVisitor<SuggestionBuilder> { |  | 
| 103   final DartCompletionRequest request; |  | 
| 104 |  | 
| 105   _InvocationAstVisitor(this.request); |  | 
| 106 |  | 
| 107   @override |  | 
| 108   SuggestionBuilder visitConstructorName(ConstructorName node) { |  | 
| 109     // some PrefixedIdentifier nodes are transformed into |  | 
| 110     // ConstructorName nodes during the resolution process. |  | 
| 111     return new _PrefixedIdentifierSuggestionBuilder(request); |  | 
| 112   } |  | 
| 113 |  | 
| 114   @override |  | 
| 115   SuggestionBuilder visitMethodInvocation(MethodInvocation node) { |  | 
| 116     return new _ExpressionSuggestionBuilder(request); |  | 
| 117   } |  | 
| 118 |  | 
| 119   @override |  | 
| 120   SuggestionBuilder visitNode(AstNode node) { |  | 
| 121     return null; |  | 
| 122   } |  | 
| 123 |  | 
| 124   @override |  | 
| 125   SuggestionBuilder visitPrefixedIdentifier(PrefixedIdentifier node) { |  | 
| 126     // some PrefixedIdentifier nodes are transformed into |  | 
| 127     // ConstructorName nodes during the resolution process. |  | 
| 128     return new _PrefixedIdentifierSuggestionBuilder(request); |  | 
| 129   } |  | 
| 130 |  | 
| 131   @override |  | 
| 132   SuggestionBuilder visitPropertyAccess(PropertyAccess node) { |  | 
| 133     return new _ExpressionSuggestionBuilder(request); |  | 
| 134   } |  | 
| 135 } |  | 
| 136 |  | 
| 137 /** |  | 
| 138  * An [AstVisitor] which looks for a declaration with the given name |  | 
| 139  * and if found, tries to determine a type for that declaration. |  | 
| 140  */ |  | 
| 141 class _LocalBestTypeVisitor extends LocalDeclarationVisitor { |  | 
| 142   /** |  | 
| 143    * The name for the declaration to be found. |  | 
| 144    */ |  | 
| 145   final String targetName; |  | 
| 146 |  | 
| 147   /** |  | 
| 148    * The best type for the found declaration, |  | 
| 149    * or `null` if no declaration found or failed to determine a type. |  | 
| 150    */ |  | 
| 151   DartType typeFound; |  | 
| 152 |  | 
| 153   /** |  | 
| 154    * Construct a new instance to search for a declaration |  | 
| 155    */ |  | 
| 156   _LocalBestTypeVisitor(this.targetName, int offset) : super(offset); |  | 
| 157 |  | 
| 158   @override |  | 
| 159   void declaredClass(ClassDeclaration declaration) { |  | 
| 160     if (declaration.name.name == targetName) { |  | 
| 161       // no type |  | 
| 162       finished(); |  | 
| 163     } |  | 
| 164   } |  | 
| 165 |  | 
| 166   @override |  | 
| 167   void declaredClassTypeAlias(ClassTypeAlias declaration) { |  | 
| 168     if (declaration.name.name == targetName) { |  | 
| 169       // no type |  | 
| 170       finished(); |  | 
| 171     } |  | 
| 172   } |  | 
| 173 |  | 
| 174   @override |  | 
| 175   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) { |  | 
| 176     if (varDecl.name.name == targetName) { |  | 
| 177       // Type provided by the element in computeFull above |  | 
| 178       finished(); |  | 
| 179     } |  | 
| 180   } |  | 
| 181 |  | 
| 182   @override |  | 
| 183   void declaredFunction(FunctionDeclaration declaration) { |  | 
| 184     if (declaration.name.name == targetName) { |  | 
| 185       TypeName typeName = declaration.returnType; |  | 
| 186       if (typeName != null) { |  | 
| 187         typeFound = typeName.type; |  | 
| 188       } |  | 
| 189       finished(); |  | 
| 190     } |  | 
| 191   } |  | 
| 192 |  | 
| 193   @override |  | 
| 194   void declaredFunctionTypeAlias(FunctionTypeAlias declaration) { |  | 
| 195     if (declaration.name.name == targetName) { |  | 
| 196       TypeName typeName = declaration.returnType; |  | 
| 197       if (typeName != null) { |  | 
| 198         typeFound = typeName.type; |  | 
| 199       } |  | 
| 200       finished(); |  | 
| 201     } |  | 
| 202   } |  | 
| 203 |  | 
| 204   @override |  | 
| 205   void declaredLabel(Label label, bool isCaseLabel) { |  | 
| 206     if (label.label.name == targetName) { |  | 
| 207       // no type |  | 
| 208       finished(); |  | 
| 209     } |  | 
| 210   } |  | 
| 211 |  | 
| 212   @override |  | 
| 213   void declaredLocalVar(SimpleIdentifier name, TypeName type) { |  | 
| 214     if (name.name == targetName) { |  | 
| 215       typeFound = name.bestType; |  | 
| 216       finished(); |  | 
| 217     } |  | 
| 218   } |  | 
| 219 |  | 
| 220   @override |  | 
| 221   void declaredMethod(MethodDeclaration declaration) { |  | 
| 222     if (declaration.name.name == targetName) { |  | 
| 223       TypeName typeName = declaration.returnType; |  | 
| 224       if (typeName != null) { |  | 
| 225         typeFound = typeName.type; |  | 
| 226       } |  | 
| 227       finished(); |  | 
| 228     } |  | 
| 229   } |  | 
| 230 |  | 
| 231   @override |  | 
| 232   void declaredParam(SimpleIdentifier name, TypeName type) { |  | 
| 233     if (name.name == targetName) { |  | 
| 234       // Type provided by the element in computeFull above |  | 
| 235       finished(); |  | 
| 236     } |  | 
| 237   } |  | 
| 238 |  | 
| 239   @override |  | 
| 240   void declaredTopLevelVar( |  | 
| 241       VariableDeclarationList varList, VariableDeclaration varDecl) { |  | 
| 242     if (varDecl.name.name == targetName) { |  | 
| 243       // Type provided by the element in computeFull above |  | 
| 244       finished(); |  | 
| 245     } |  | 
| 246   } |  | 
| 247 } |  | 
| 248 |  | 
| 249 /** |  | 
| 250  * An [Element] visitor for determining the appropriate invocation/access |  | 
| 251  * suggestions based upon the element for which the completion is requested. |  | 
| 252  */ |  | 
| 253 class _PrefixedIdentifierSuggestionBuilder |  | 
| 254     extends GeneralizingElementVisitor<Future<bool>> |  | 
| 255     implements SuggestionBuilder { |  | 
| 256   final DartCompletionRequest request; |  | 
| 257 |  | 
| 258   _PrefixedIdentifierSuggestionBuilder(this.request); |  | 
| 259 |  | 
| 260   @override |  | 
| 261   bool computeFast(AstNode node) { |  | 
| 262     return false; |  | 
| 263   } |  | 
| 264 |  | 
| 265   @override |  | 
| 266   Future<bool> computeFull(AstNode node) { |  | 
| 267     if (node is PrefixedIdentifier) { |  | 
| 268       SimpleIdentifier prefix = node.prefix; |  | 
| 269       if (prefix != null) { |  | 
| 270         Element element = prefix.bestElement; |  | 
| 271         DartType type = prefix.bestType; |  | 
| 272         if (element is! ClassElement) { |  | 
| 273           if (type == null || type.isDynamic) { |  | 
| 274             // |  | 
| 275             // Given `g. int y = 0;`, the parser interprets `g` as a prefixed |  | 
| 276             // identifier with no type. |  | 
| 277             // If the user is requesting completions for `g`, |  | 
| 278             // then check for a function, getter, or similar with a type. |  | 
| 279             // |  | 
| 280             _LocalBestTypeVisitor visitor = |  | 
| 281                 new _LocalBestTypeVisitor(prefix.name, request.offset); |  | 
| 282             if (visitor.visit(prefix)) { |  | 
| 283               type = visitor.typeFound; |  | 
| 284             } |  | 
| 285           } |  | 
| 286           if (type != null && !type.isDynamic) { |  | 
| 287             InterfaceTypeSuggestionBuilder.suggestionsFor(request, type); |  | 
| 288             return new Future.value(true); |  | 
| 289           } |  | 
| 290         } |  | 
| 291         if (element != null) { |  | 
| 292           return element.accept(this); |  | 
| 293         } |  | 
| 294       } |  | 
| 295     } |  | 
| 296     return new Future.value(false); |  | 
| 297   } |  | 
| 298 |  | 
| 299   @override |  | 
| 300   Future<bool> visitClassElement(ClassElement element) { |  | 
| 301     if (element != null) { |  | 
| 302       InterfaceType type = element.type; |  | 
| 303       if (type != null) { |  | 
| 304         // Suggested by StaticMemberContributor |  | 
| 305         // StaticClassElementSuggestionBuilder.suggestionsFor( |  | 
| 306         //     request, type.element); |  | 
| 307       } |  | 
| 308     } |  | 
| 309     return new Future.value(false); |  | 
| 310   } |  | 
| 311 |  | 
| 312   @override |  | 
| 313   Future<bool> visitElement(Element element) { |  | 
| 314     return new Future.value(false); |  | 
| 315   } |  | 
| 316 |  | 
| 317   @override |  | 
| 318   Future<bool> visitPrefixElement(PrefixElement element) { |  | 
| 319     bool modified = false; |  | 
| 320 |  | 
| 321     // Suggested by LibraryMemberContributor |  | 
| 322 |  | 
| 323     // Find the import directive with the given prefix |  | 
| 324     // for (Directive directive in request.unit.directives) { |  | 
| 325     //   if (directive is ImportDirective) { |  | 
| 326     //     if (directive.prefix != null) { |  | 
| 327     //       if (directive.prefix.name == element.name) { |  | 
| 328     //         // Suggest elements from the imported library |  | 
| 329     //         LibraryElement library = directive.uriElement; |  | 
| 330     //         AstNode node = request.target.containingNode; |  | 
| 331     //         bool typesOnly = node.parent is TypeName; |  | 
| 332     //         bool instCreation = |  | 
| 333     //             typesOnly && node.parent.parent is ConstructorName; |  | 
| 334     //         LibraryElementSuggestionBuilder.suggestionsFor( |  | 
| 335     //             request, |  | 
| 336     //             CompletionSuggestionKind.INVOCATION, |  | 
| 337     //             library, |  | 
| 338     //             typesOnly, |  | 
| 339     //             instCreation); |  | 
| 340     //         modified = true; |  | 
| 341     //         if (directive.deferredKeyword != null) { |  | 
| 342     //           FunctionElement loadLibFunct = library.loadLibraryFunction; |  | 
| 343     //           request.addSuggestion(createSuggestion(loadLibFunct)); |  | 
| 344     //         } |  | 
| 345     //       } |  | 
| 346     //     } |  | 
| 347     //   } |  | 
| 348     // } |  | 
| 349     return new Future.value(modified); |  | 
| 350   } |  | 
| 351 |  | 
| 352   @override |  | 
| 353   Future<bool> visitPropertyAccessorElement(PropertyAccessorElement element) { |  | 
| 354     if (element != null) { |  | 
| 355       PropertyInducingElement elemVar = element.variable; |  | 
| 356       if (elemVar != null) { |  | 
| 357         InterfaceTypeSuggestionBuilder.suggestionsFor(request, elemVar.type); |  | 
| 358       } |  | 
| 359       return new Future.value(true); |  | 
| 360     } |  | 
| 361     return new Future.value(false); |  | 
| 362   } |  | 
| 363 |  | 
| 364   @override |  | 
| 365   Future<bool> visitVariableElement(VariableElement element) { |  | 
| 366     InterfaceTypeSuggestionBuilder.suggestionsFor(request, element.type); |  | 
| 367     return new Future.value(true); |  | 
| 368   } |  | 
| 369 } |  | 
| OLD | NEW | 
|---|