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 * Return 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 Map<String, List<String>> get selectorRelevance => { | |
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 'dart.math.Random': ['nextInt', 'nextDouble'], | |
26 'dart.async.Future': ['value', 'wait'], | |
lukechurch
2015/02/13 11:23:01
Lets not land a change that affects something as i
danrubel
2015/02/15 04:53:41
Good point. To better address this I've added a co
| |
27 }; | |
28 | |
29 /** | |
30 * A computer for adjusting the relevance of completions computed by others | |
31 * based upon common Dart usage patterns. | |
32 */ | |
33 class CommonUsageComputer { | |
34 | |
35 /** | |
36 * Adjusts the relevance based on the given completion context. | |
37 * The compilation unit and completion node | |
38 * in the given completion context may not be resolved. | |
39 * This method should execute quickly and not block waiting for any analysis. | |
40 */ | |
41 void computeFast(DartCompletionRequest request) { | |
42 _update(request); | |
43 } | |
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 are resolved. | |
49 */ | |
50 void computeFull(DartCompletionRequest request) { | |
51 _update(request); | |
52 } | |
53 | |
54 /** | |
55 * Adjusts the relevance based on the given completion context. | |
56 * The compilation unit and completion node | |
57 * in the given completion context may not be resolved. | |
58 */ | |
59 void _update(DartCompletionRequest request) { | |
60 var visitor = new _BestTypeVisitor(request.target.entity); | |
61 DartType type = request.target.containingNode.accept(visitor); | |
62 if (type != null) { | |
63 Element typeElem = type.element; | |
64 if (typeElem != null) { | |
65 LibraryElement libElem = | |
66 typeElem.getAncestor((p) => p is LibraryElement); | |
67 if (libElem != null) { | |
68 _updateMethodRelevance(request, type, libElem); | |
69 } | |
70 } | |
71 } | |
72 } | |
73 | |
74 /** | |
75 * Adjusts the relevance of all method suggestions based upon the given | |
76 * target type and library. | |
77 */ | |
78 void _updateMethodRelevance(DartCompletionRequest request, DartType type, | |
79 LibraryElement libElem) { | |
80 String typeName = type.name; | |
81 List<String> selectors = selectorRelevance['${libElem.name}.${typeName}']; | |
82 if (selectors != null) { | |
83 for (CompletionSuggestion suggestion in request.suggestions) { | |
84 protocol.Element element = suggestion.element; | |
85 if (element != null && | |
86 (element.kind == protocol.ElementKind.CONSTRUCTOR || | |
87 element.kind == protocol.ElementKind.METHOD) && | |
88 suggestion.kind == CompletionSuggestionKind.INVOCATION && | |
89 suggestion.declaringType == typeName) { | |
90 int index = selectors.indexOf(suggestion.completion); | |
91 if (index != -1) { | |
92 suggestion.relevance = DART_RELEVANCE_COMMON_USAGE - index; | |
93 } | |
94 } | |
95 } | |
96 } | |
97 } | |
98 } | |
99 | |
100 /** | |
101 * An [AstVisitor] used to determine the best [DartType] of a node. | |
102 */ | |
103 class _BestTypeVisitor extends GeneralizingAstVisitor { | |
lukechurch
2015/02/13 11:23:01
This seems more generally useful than only for doi
danrubel
2015/02/15 04:53:41
Agreed, but I'm not planning major refactoring unt
| |
104 final entity; | |
105 | |
106 _BestTypeVisitor(this.entity); | |
107 | |
108 DartType visitConstructorName(ConstructorName node) { | |
109 if (node.period != null && node.name == entity) { | |
110 TypeName typeName = node.type; | |
111 if (typeName != null) { | |
112 return typeName.type; | |
113 } | |
114 } | |
115 return null; | |
116 } | |
117 | |
118 DartType visitNode(AstNode node) { | |
119 return null; | |
120 } | |
121 | |
122 DartType visitPrefixedIdentifier(PrefixedIdentifier node) { | |
123 if (node.identifier == entity) { | |
124 SimpleIdentifier prefix = node.prefix; | |
125 if (prefix != null) { | |
126 return prefix.bestType; | |
127 } | |
128 } | |
129 return null; | |
130 } | |
131 | |
132 DartType visitPropertyAccess(PropertyAccess node) { | |
133 if (node.propertyName == entity) { | |
134 Expression target = node.realTarget; | |
135 if (target != null) { | |
136 return target.bestType; | |
137 } | |
138 } | |
139 return null; | |
140 } | |
141 } | |
OLD | NEW |