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 {// | |
22 // Sample implementation which updates the relevance of the following | |
23 // new Random().nextInt(...) | |
24 // new Random().nextDouble(...) | |
25 // new Random().nextBool() - not commonly used thus omitted from list | |
26 // Entries should look something like this | |
27 // 'dart.math.Random': const ['nextInt', 'nextDouble'], | |
28 // 'dart.async.Future': const ['value', 'wait'], | |
29 }; | |
30 | |
31 /** | |
32 * A computer for adjusting the relevance of completions computed by others | |
33 * based upon common Dart usage patterns. | |
34 */ | |
35 class CommonUsageComputer { | |
36 /** | |
37 * A map of <library>.<classname> to an ordered list of method names, | |
38 * field names, getter names, and named constructors. | |
39 * The names are ordered from most relevant to least relevant. | |
40 * Names not listed are considered equally less relevant than those listed. | |
41 */ | |
42 Map<String, List<String>> selectorRelevance; | |
43 | |
44 CommonUsageComputer([this.selectorRelevance = defaultSelectorRelevance]); | |
45 | |
46 /** | |
47 * Adjusts the relevance based on the given completion context. | |
48 * The compilation unit and completion node | |
49 * in the given completion context may not be resolved. | |
50 * This method should execute quickly and not block waiting for any analysis. | |
51 */ | |
52 void computeFast(DartCompletionRequest request) { | |
53 _update(request); | |
54 } | |
55 | |
56 /** | |
57 * Adjusts the relevance based on the given completion context. | |
58 * The compilation unit and completion node | |
59 * in the given completion context are resolved. | |
60 */ | |
61 void computeFull(DartCompletionRequest request) { | |
62 _update(request); | |
63 } | |
64 | |
65 /** | |
66 * Adjusts the relevance based on the given completion context. | |
67 * The compilation unit and completion node | |
68 * in the given completion context may not be resolved. | |
69 */ | |
70 void _update(DartCompletionRequest request) { | |
71 var visitor = new _BestTypeVisitor(request.target.entity); | |
72 DartType type = request.target.containingNode.accept(visitor); | |
73 if (type != null) { | |
74 Element typeElem = type.element; | |
75 if (typeElem != null) { | |
76 LibraryElement libElem = | |
77 typeElem.getAncestor((p) => p is LibraryElement); | |
scheglov
2015/02/15 19:06:29
typeElem.library
danrubel
2015/02/15 21:17:16
Done.
| |
78 if (libElem != null) { | |
79 _updateMethodRelevance(request, type, libElem); | |
80 } | |
81 } | |
82 } | |
83 } | |
84 | |
85 /** | |
86 * Adjusts the relevance of all method suggestions based upon the given | |
87 * target type and library. | |
88 */ | |
89 void _updateMethodRelevance(DartCompletionRequest request, DartType type, | |
90 LibraryElement libElem) { | |
91 String typeName = type.name; | |
92 List<String> selectors = selectorRelevance['${libElem.name}.${typeName}']; | |
93 if (selectors != null) { | |
94 for (CompletionSuggestion suggestion in request.suggestions) { | |
95 protocol.Element element = suggestion.element; | |
96 if (element != null && | |
97 (element.kind == protocol.ElementKind.CONSTRUCTOR || | |
98 element.kind == protocol.ElementKind.METHOD) && | |
99 suggestion.kind == CompletionSuggestionKind.INVOCATION && | |
scheglov
2015/02/15 19:06:28
Field accessors?
danrubel
2015/02/15 21:17:16
Great point. I have added support and tests for fi
| |
100 suggestion.declaringType == typeName) { | |
101 int index = selectors.indexOf(suggestion.completion); | |
102 if (index != -1) { | |
103 suggestion.relevance = DART_RELEVANCE_COMMON_USAGE - index; | |
104 } | |
105 } | |
106 } | |
107 } | |
108 } | |
109 } | |
110 | |
111 /** | |
112 * An [AstVisitor] used to determine the best [DartType] of a node. | |
scheglov
2015/02/15 19:06:29
From implementation it does not look that it retur
danrubel
2015/02/15 21:17:16
Correct. I updated the comment per your suggestion
| |
113 */ | |
114 class _BestTypeVisitor extends GeneralizingAstVisitor { | |
115 final entity; | |
scheglov
2015/02/15 19:06:28
type?
danrubel
2015/02/15 21:17:16
Done.
| |
116 | |
117 _BestTypeVisitor(this.entity); | |
118 | |
119 DartType visitConstructorName(ConstructorName node) { | |
120 if (node.period != null && node.name == entity) { | |
121 TypeName typeName = node.type; | |
122 if (typeName != null) { | |
123 return typeName.type; | |
124 } | |
125 } | |
126 return null; | |
127 } | |
128 | |
129 DartType visitNode(AstNode node) { | |
130 return null; | |
131 } | |
132 | |
133 DartType visitPrefixedIdentifier(PrefixedIdentifier node) { | |
134 if (node.identifier == entity) { | |
135 SimpleIdentifier prefix = node.prefix; | |
136 if (prefix != null) { | |
137 return prefix.bestType; | |
138 } | |
139 } | |
140 return null; | |
141 } | |
142 | |
143 DartType visitPropertyAccess(PropertyAccess node) { | |
144 if (node.propertyName == entity) { | |
145 Expression target = node.realTarget; | |
146 if (target != null) { | |
147 return target.bestType; | |
148 } | |
149 } | |
150 return null; | |
151 } | |
152 } | |
OLD | NEW |