OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library services.completion.computer.dart.relevance; |
| 6 |
| 7 import 'package:analysis_server/src/protocol_server.dart' as protocol; |
| 8 import 'package:analysis_server/src/protocol_server.dart' show |
| 9 CompletionSuggestion, CompletionSuggestionKind; |
| 10 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| 11 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 |
| 14 /** |
| 15 * A map of <library>.<classname> to an ordered list of method names, |
| 16 * field names, getter names, and named constructors. |
| 17 * The names are ordered from most relevant to least relevant. |
| 18 * Names not listed are considered equally less relevant than those listed. |
| 19 */ |
| 20 const Map<String, List<String>> defaultSelectorRelevance = const {// |
| 21 // Sample implementation which updates the relevance of the following |
| 22 // new Random().nextInt(...) |
| 23 // new Random().nextDouble(...) |
| 24 // new Random().nextBool() - not commonly used thus omitted from list |
| 25 // Entries should look something like this |
| 26 // 'dart.math.Random': const ['nextInt', 'nextDouble'], |
| 27 // 'dart.async.Future': const ['value', 'wait'], |
| 28 }; |
| 29 |
| 30 /** |
| 31 * A computer for adjusting the relevance of completions computed by others |
| 32 * based upon common Dart usage patterns. |
| 33 */ |
| 34 class CommonUsageComputer { |
| 35 /** |
| 36 * A map of <library>.<classname> to an ordered list of method names, |
| 37 * field names, getter names, and named constructors. |
| 38 * The names are ordered from most relevant to least relevant. |
| 39 * Names not listed are considered equally less relevant than those listed. |
| 40 */ |
| 41 Map<String, List<String>> selectorRelevance; |
| 42 |
| 43 CommonUsageComputer([this.selectorRelevance = defaultSelectorRelevance]); |
| 44 |
| 45 /** |
| 46 * Adjusts the relevance based on the given completion context. |
| 47 * The compilation unit and completion node |
| 48 * in the given completion context may not be resolved. |
| 49 * This method should execute quickly and not block waiting for any analysis. |
| 50 */ |
| 51 void computeFast(DartCompletionRequest request) { |
| 52 _update(request); |
| 53 } |
| 54 |
| 55 /** |
| 56 * Adjusts the relevance based on the given completion context. |
| 57 * The compilation unit and completion node |
| 58 * in the given completion context are resolved. |
| 59 */ |
| 60 void computeFull(DartCompletionRequest request) { |
| 61 _update(request); |
| 62 } |
| 63 |
| 64 /** |
| 65 * Adjusts the relevance based on the given completion context. |
| 66 * The compilation unit and completion node |
| 67 * in the given completion context may not be resolved. |
| 68 */ |
| 69 void _update(DartCompletionRequest request) { |
| 70 var visitor = new _BestTypeVisitor(request.target.entity); |
| 71 DartType type = request.target.containingNode.accept(visitor); |
| 72 if (type != null) { |
| 73 Element typeElem = type.element; |
| 74 if (typeElem != null) { |
| 75 LibraryElement libElem = typeElem.library; |
| 76 if (libElem != null) { |
| 77 _updateInvocationRelevance(request, type, libElem); |
| 78 } |
| 79 } |
| 80 } |
| 81 } |
| 82 |
| 83 /** |
| 84 * Adjusts the relevance of all method suggestions based upon the given |
| 85 * target type and library. |
| 86 */ |
| 87 void _updateInvocationRelevance(DartCompletionRequest request, DartType type, |
| 88 LibraryElement libElem) { |
| 89 String typeName = type.name; |
| 90 List<String> selectors = selectorRelevance['${libElem.name}.${typeName}']; |
| 91 if (selectors != null) { |
| 92 for (CompletionSuggestion suggestion in request.suggestions) { |
| 93 protocol.Element element = suggestion.element; |
| 94 if (element != null && |
| 95 (element.kind == protocol.ElementKind.CONSTRUCTOR || |
| 96 element.kind == protocol.ElementKind.FIELD || |
| 97 element.kind == protocol.ElementKind.GETTER || |
| 98 element.kind == protocol.ElementKind.METHOD || |
| 99 element.kind == protocol.ElementKind.SETTER) && |
| 100 suggestion.kind == CompletionSuggestionKind.INVOCATION && |
| 101 suggestion.declaringType == typeName) { |
| 102 int index = selectors.indexOf(suggestion.completion); |
| 103 if (index != -1) { |
| 104 suggestion.relevance = DART_RELEVANCE_COMMON_USAGE - index; |
| 105 } |
| 106 } |
| 107 } |
| 108 } |
| 109 } |
| 110 } |
| 111 |
| 112 /** |
| 113 * An [AstVisitor] used to determine the best defining type of a node. |
| 114 */ |
| 115 class _BestTypeVisitor extends GeneralizingAstVisitor { |
| 116 |
| 117 /** |
| 118 * The entity which the completed text will replace (or which will be |
| 119 * displaced once the completed text is inserted). This may be an AstNode or |
| 120 * a Token, or it may be null if the cursor is after all tokens in the file. |
| 121 * See field of the same name in [CompletionTarget]. |
| 122 */ |
| 123 final Object entity; |
| 124 |
| 125 _BestTypeVisitor(this.entity); |
| 126 |
| 127 DartType visitConstructorName(ConstructorName node) { |
| 128 if (node.period != null && node.name == entity) { |
| 129 TypeName typeName = node.type; |
| 130 if (typeName != null) { |
| 131 return typeName.type; |
| 132 } |
| 133 } |
| 134 return null; |
| 135 } |
| 136 |
| 137 DartType visitNode(AstNode node) { |
| 138 return null; |
| 139 } |
| 140 |
| 141 DartType visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 142 if (node.identifier == entity) { |
| 143 SimpleIdentifier prefix = node.prefix; |
| 144 if (prefix != null) { |
| 145 return prefix.bestType; |
| 146 } |
| 147 } |
| 148 return null; |
| 149 } |
| 150 |
| 151 DartType visitPropertyAccess(PropertyAccess node) { |
| 152 if (node.propertyName == entity) { |
| 153 Expression target = node.realTarget; |
| 154 if (target != null) { |
| 155 return target.bestType; |
| 156 } |
| 157 } |
| 158 return null; |
| 159 } |
| 160 } |
OLD | NEW |