| 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.suggestion.builder; | 5 library services.completion.suggestion.builder; | 
| 6 | 6 | 
| 7 import 'dart:async'; | 7 import 'dart:async'; | 
| 8 import 'dart:collection'; | 8 import 'dart:collection'; | 
| 9 | 9 | 
| 10 import 'package:analysis_server/src/protocol_server.dart' as protocol; | 10 import 'package:analysis_server/src/protocol_server.dart' as protocol; | 
| 11 import 'package:analysis_server/src/protocol_server.dart' | 11 import 'package:analysis_server/src/protocol_server.dart' | 
| 12     hide Element, ElementKind; | 12     hide Element, ElementKind; | 
| 13 import 'package:analysis_server/src/services/completion/dart_completion_manager.
     dart'; | 13 import 'package:analysis_server/src/services/completion/dart_completion_manager.
     dart'; | 
| 14 import 'package:analyzer/src/generated/ast.dart'; | 14 import 'package:analyzer/src/generated/ast.dart'; | 
| 15 import 'package:analyzer/src/generated/element.dart'; | 15 import 'package:analyzer/src/generated/element.dart'; | 
| 16 import 'package:analyzer/src/generated/utilities_dart.dart'; | 16 import 'package:analyzer/src/generated/utilities_dart.dart'; | 
| 17 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; | 
| 18 import 'package:path/path.dart' as path; | 18 import 'package:path/path.dart' as path; | 
| 19 | 19 | 
| 20 const String DYNAMIC = 'dynamic'; | 20 const String DYNAMIC = 'dynamic'; | 
| 21 | 21 | 
| 22 /** | 22 /** | 
| 23  * Return a suggestion based upon the given element | 23  * Return a suggestion based upon the given element | 
| 24  * or `null` if a suggestion is not appropriate for the given element. | 24  * or `null` if a suggestion is not appropriate for the given element. | 
| 25  * If the suggestion is not currently in scope, then specify | 25  * If the suggestion is not currently in scope, then specify | 
| 26  * importForSource as the source to which an import should be added. | 26  * importForSource as the source to which an import should be added. | 
| 27  */ | 27  */ | 
| 28 CompletionSuggestion createSuggestion(Element element, | 28 CompletionSuggestion createSuggestion(Element element, {String completion, | 
| 29     {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION, | 29     CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION, | 
| 30     int relevance: DART_RELEVANCE_DEFAULT, Source importForSource}) { | 30     int relevance: DART_RELEVANCE_DEFAULT, Source importForSource}) { | 
| 31   if (element is ExecutableElement && element.isOperator) { | 31   if (element is ExecutableElement && element.isOperator) { | 
| 32     // Do not include operators in suggestions | 32     // Do not include operators in suggestions | 
| 33     return null; | 33     return null; | 
| 34   } | 34   } | 
| 35   String completion = element.displayName; | 35   if (completion == null) { | 
|  | 36     completion = element.displayName; | 
|  | 37   } | 
| 36   bool isDeprecated = element.isDeprecated; | 38   bool isDeprecated = element.isDeprecated; | 
| 37   CompletionSuggestion suggestion = new CompletionSuggestion(kind, | 39   CompletionSuggestion suggestion = new CompletionSuggestion(kind, | 
| 38       isDeprecated ? DART_RELEVANCE_LOW : relevance, completion, | 40       isDeprecated ? DART_RELEVANCE_LOW : relevance, completion, | 
| 39       completion.length, 0, isDeprecated, false); | 41       completion.length, 0, isDeprecated, false); | 
| 40   suggestion.element = protocol.newElement_fromEngine(element); | 42   suggestion.element = protocol.newElement_fromEngine(element); | 
| 41   Element enclosingElement = element.enclosingElement; | 43   Element enclosingElement = element.enclosingElement; | 
| 42   if (enclosingElement is ClassElement) { | 44   if (enclosingElement is ClassElement) { | 
| 43     suggestion.declaringType = enclosingElement.displayName; | 45     suggestion.declaringType = enclosingElement.displayName; | 
| 44   } | 46   } | 
| 45   suggestion.returnType = getReturnTypeString(element); | 47   suggestion.returnType = getReturnTypeString(element); | 
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 182   CompletionSuggestionKind get kind; | 184   CompletionSuggestionKind get kind; | 
| 183 | 185 | 
| 184   /** | 186   /** | 
| 185    * Return the request on which the builder is operating. | 187    * Return the request on which the builder is operating. | 
| 186    */ | 188    */ | 
| 187   DartCompletionRequest get request; | 189   DartCompletionRequest get request; | 
| 188 | 190 | 
| 189   /** | 191   /** | 
| 190    * Add a suggestion based upon the given element. | 192    * Add a suggestion based upon the given element. | 
| 191    */ | 193    */ | 
| 192   void addSuggestion(Element element, {int relevance: DART_RELEVANCE_DEFAULT}) { | 194   void addSuggestion(Element element, | 
|  | 195       {String prefix, int relevance: DART_RELEVANCE_DEFAULT}) { | 
| 193     if (element.isPrivate) { | 196     if (element.isPrivate) { | 
| 194       LibraryElement elementLibrary = element.library; | 197       LibraryElement elementLibrary = element.library; | 
| 195       CompilationUnitElement unitElem = request.unit.element; | 198       CompilationUnitElement unitElem = request.unit.element; | 
| 196       if (unitElem == null) { | 199       if (unitElem == null) { | 
| 197         return; | 200         return; | 
| 198       } | 201       } | 
| 199       LibraryElement unitLibrary = unitElem.library; | 202       LibraryElement unitLibrary = unitElem.library; | 
| 200       if (elementLibrary != unitLibrary) { | 203       if (elementLibrary != unitLibrary) { | 
| 201         return; | 204         return; | 
| 202       } | 205       } | 
| 203     } | 206     } | 
| 204     if (element.isSynthetic) { | 207     if (prefix == null && element.isSynthetic) { | 
| 205       if ((element is PropertyAccessorElement) || | 208       if ((element is PropertyAccessorElement) || | 
| 206           element is FieldElement && !_isSpecialEnumField(element)) { | 209           element is FieldElement && !_isSpecialEnumField(element)) { | 
| 207         return; | 210         return; | 
| 208       } | 211       } | 
| 209     } | 212     } | 
| 210     String completion = element.displayName; | 213     String completion = element.displayName; | 
|  | 214     if (prefix != null && prefix.length > 0) { | 
|  | 215       if (completion == null || completion.length <= 0) { | 
|  | 216         completion = prefix; | 
|  | 217       } else { | 
|  | 218         completion = '$prefix.$completion'; | 
|  | 219       } | 
|  | 220     } | 
| 211     if (completion == null || completion.length <= 0) { | 221     if (completion == null || completion.length <= 0) { | 
| 212       return; | 222       return; | 
| 213     } | 223     } | 
| 214     CompletionSuggestion suggestion = | 224     CompletionSuggestion suggestion = createSuggestion(element, | 
| 215         createSuggestion(element, kind: kind, relevance: relevance); | 225         completion: completion, kind: kind, relevance: relevance); | 
| 216     if (suggestion != null) { | 226     if (suggestion != null) { | 
| 217       request.addSuggestion(suggestion); | 227       request.addSuggestion(suggestion); | 
| 218     } | 228     } | 
| 219   } | 229   } | 
| 220 | 230 | 
| 221   /** | 231   /** | 
| 222    * Determine if the given element is one of the synthetic enum accessors | 232    * Determine if the given element is one of the synthetic enum accessors | 
| 223    * for which we should generate a suggestion. | 233    * for which we should generate a suggestion. | 
| 224    */ | 234    */ | 
| 225   bool _isSpecialEnumField(FieldElement element) { | 235   bool _isSpecialEnumField(FieldElement element) { | 
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 433 /** | 443 /** | 
| 434  * This class visits elements in a library and provides suggestions based upon | 444  * This class visits elements in a library and provides suggestions based upon | 
| 435  * the visible members in that library. Clients should call | 445  * the visible members in that library. Clients should call | 
| 436  * [LibraryElementSuggestionBuilder.suggestionsFor]. | 446  * [LibraryElementSuggestionBuilder.suggestionsFor]. | 
| 437  */ | 447  */ | 
| 438 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor | 448 class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor | 
| 439     with ElementSuggestionBuilder { | 449     with ElementSuggestionBuilder { | 
| 440   final DartCompletionRequest request; | 450   final DartCompletionRequest request; | 
| 441   final CompletionSuggestionKind kind; | 451   final CompletionSuggestionKind kind; | 
| 442   final bool typesOnly; | 452   final bool typesOnly; | 
|  | 453   final bool instCreation; | 
| 443 | 454 | 
| 444   LibraryElementSuggestionBuilder(this.request, this.kind, this.typesOnly); | 455   LibraryElementSuggestionBuilder( | 
|  | 456       this.request, this.kind, this.typesOnly, this.instCreation); | 
| 445 | 457 | 
| 446   @override | 458   @override | 
| 447   visitClassElement(ClassElement element) { | 459   visitClassElement(ClassElement element) { | 
| 448     addSuggestion(element); | 460     if (instCreation) { | 
|  | 461       element.visitChildren(this); | 
|  | 462     } else { | 
|  | 463       addSuggestion(element); | 
|  | 464     } | 
| 449   } | 465   } | 
| 450 | 466 | 
| 451   @override | 467   @override | 
| 452   visitCompilationUnitElement(CompilationUnitElement element) { | 468   visitCompilationUnitElement(CompilationUnitElement element) { | 
| 453     element.visitChildren(this); | 469     element.visitChildren(this); | 
| 454     LibraryElement containingLibrary = element.library; | 470     LibraryElement containingLibrary = element.library; | 
| 455     if (containingLibrary != null) { | 471     if (containingLibrary != null) { | 
| 456       for (var lib in containingLibrary.exportedLibraries) { | 472       for (var lib in containingLibrary.exportedLibraries) { | 
| 457         lib.visitChildren(this); | 473         lib.visitChildren(this); | 
| 458       } | 474       } | 
| 459     } | 475     } | 
| 460   } | 476   } | 
| 461 | 477 | 
| 462   @override | 478   @override | 
|  | 479   visitConstructorElement(ConstructorElement element) { | 
|  | 480     if (instCreation) { | 
|  | 481       ClassElement classElem = element.enclosingElement; | 
|  | 482       if (classElem != null) { | 
|  | 483         String prefix = classElem.name; | 
|  | 484         if (prefix != null && prefix.length > 0) { | 
|  | 485           addSuggestion(element, prefix: prefix); | 
|  | 486         } | 
|  | 487       } | 
|  | 488     } | 
|  | 489   } | 
|  | 490 | 
|  | 491   @override | 
| 463   visitElement(Element element) { | 492   visitElement(Element element) { | 
| 464     // ignored | 493     // ignored | 
| 465   } | 494   } | 
| 466 | 495 | 
| 467   @override | 496   @override | 
| 468   visitFunctionElement(FunctionElement element) { | 497   visitFunctionElement(FunctionElement element) { | 
| 469     if (!typesOnly) { | 498     if (!typesOnly) { | 
| 470       addSuggestion(element); | 499       addSuggestion(element); | 
| 471     } | 500     } | 
| 472   } | 501   } | 
| 473 | 502 | 
| 474   @override | 503   @override | 
| 475   visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { | 504   visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { | 
| 476     addSuggestion(element); | 505     if (!instCreation) { | 
|  | 506       addSuggestion(element); | 
|  | 507     } | 
| 477   } | 508   } | 
| 478 | 509 | 
| 479   @override | 510   @override | 
| 480   visitTopLevelVariableElement(TopLevelVariableElement element) { | 511   visitTopLevelVariableElement(TopLevelVariableElement element) { | 
| 481     if (!typesOnly) { | 512     if (!typesOnly) { | 
| 482       addSuggestion(element); | 513       addSuggestion(element); | 
| 483     } | 514     } | 
| 484   } | 515   } | 
| 485 | 516 | 
| 486   /** | 517   /** | 
| 487    * Add suggestions for the visible members in the given library | 518    * Add suggestions for the visible members in the given library | 
| 488    */ | 519    */ | 
| 489   static void suggestionsFor(DartCompletionRequest request, | 520   static void suggestionsFor(DartCompletionRequest request, | 
| 490       CompletionSuggestionKind kind, LibraryElement library, bool typesOnly) { | 521       CompletionSuggestionKind kind, LibraryElement library, bool typesOnly, | 
|  | 522       bool instCreation) { | 
| 491     if (library != null) { | 523     if (library != null) { | 
| 492       library.visitChildren( | 524       library.visitChildren(new LibraryElementSuggestionBuilder( | 
| 493           new LibraryElementSuggestionBuilder(request, kind, typesOnly)); | 525           request, kind, typesOnly, instCreation)); | 
| 494     } | 526     } | 
| 495   } | 527   } | 
| 496 } | 528 } | 
| 497 | 529 | 
| 498 /** | 530 /** | 
| 499  * This class visits elements in a class and provides suggestions based upon | 531  * This class visits elements in a class and provides suggestions based upon | 
| 500  * the visible named constructors in that class. | 532  * the visible named constructors in that class. | 
| 501  */ | 533  */ | 
| 502 class NamedConstructorSuggestionBuilder extends GeneralizingElementVisitor | 534 class NamedConstructorSuggestionBuilder extends GeneralizingElementVisitor | 
| 503     with ElementSuggestionBuilder implements SuggestionBuilder { | 535     with ElementSuggestionBuilder implements SuggestionBuilder { | 
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 625    * or `false` if [computeFull] should be called. | 657    * or `false` if [computeFull] should be called. | 
| 626    */ | 658    */ | 
| 627   bool computeFast(AstNode node); | 659   bool computeFast(AstNode node); | 
| 628 | 660 | 
| 629   /** | 661   /** | 
| 630    * Return a future that computes the suggestions given a fully resolved AST. | 662    * Return a future that computes the suggestions given a fully resolved AST. | 
| 631    * The future returns `true` if suggestions were added, else `false`. | 663    * The future returns `true` if suggestions were added, else `false`. | 
| 632    */ | 664    */ | 
| 633   Future<bool> computeFull(AstNode node); | 665   Future<bool> computeFull(AstNode node); | 
| 634 } | 666 } | 
| OLD | NEW | 
|---|