Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/completion_manager.dart

Issue 1536073002: remove old completion API (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merge Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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.manager;
6
7 import 'dart:async';
8
9 import 'package:analysis_server/plugin/protocol/protocol.dart';
10 import 'package:analysis_server/src/provisional/completion/completion_core.dart'
11 show
12 CompletionContributor,
13 CompletionContributorFactory,
14 CompletionRequest,
15 CompletionResult;
16 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart';
17 import 'package:analysis_server/src/services/search/search_engine.dart';
18 import 'package:analyzer/src/generated/engine.dart';
19 import 'package:analyzer/src/generated/source.dart';
20
21 /**
22 * Manages completion contributors for a given completion request.
23 */
24 abstract class CompletionManager {
25 /**
26 * The context in which the completion was computed.
27 */
28 final AnalysisContext context;
29
30 /**
31 * The source in which the completion was computed.
32 */
33 final Source source;
34
35 CompletionManager(this.context, this.source);
36
37 /**
38 * Create a manager for the given request.
39 */
40 factory CompletionManager.create(
41 AnalysisContext context,
42 Source source,
43 SearchEngine searchEngine,
44 Iterable<CompletionContributor> newContributors) {
45 if (context != null) {
46 if (AnalysisEngine.isDartFileName(source.shortName)) {
47 return new DartCompletionManager.create(
48 context, searchEngine, source, newContributors);
49 }
50 }
51 return new NoOpCompletionManager(source);
52 }
53
54 /**
55 * Compute and cache information in preparation for a possible code
56 * completion request sometime in the future. The default implementation
57 * of this method does nothing. Subclasses may override but should not
58 * count on this method being called before [computeSuggestions].
59 * Return a future that completes when the cache is computed with a bool
60 * indicating success.
61 */
62 Future<bool> computeCache() {
63 return new Future.value(true);
64 }
65
66 /**
67 * Compute completion results for the given reqeust and append them to the str eam.
68 * Clients should not call this method directly as it is automatically called
69 * when a client listens to the stream returned by [results].
70 * Subclasses should override this method, append at least one result
71 * to the [controller], and close the controller stream once complete.
72 */
73 Future<CompletionResult> computeSuggestions(CompletionRequest request);
74
75 /**
76 * Discard any pending operations.
77 * Subclasses may override but should call super.dispose
78 */
79 void dispose() {}
80 }
81
82 /**
83 * Overall performance of a code completion operation.
84 */
85 class CompletionPerformance {
86 final DateTime start = new DateTime.now();
87 final Map<String, Duration> _startTimes = new Map<String, Duration>();
88 final Stopwatch _stopwatch = new Stopwatch();
89 final List<OperationPerformance> operations = <OperationPerformance>[];
90
91 Source source;
92 String snippet = '';
93 int notificationCount = -1;
94 int suggestionCountFirst = -1;
95 int suggestionCountLast = -1;
96 Duration _firstNotification;
97
98 CompletionPerformance() {
99 _stopwatch.start();
100 }
101
102 int get elapsedInMilliseconds =>
103 operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0;
104
105 int get firstNotificationInMilliseconds =>
106 _firstNotification != null ? _firstNotification.inMilliseconds : 0;
107
108 String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start';
109
110 String get suggestionCount {
111 if (notificationCount < 1) return '';
112 if (notificationCount == 1) return '$suggestionCountFirst';
113 return '$suggestionCountFirst, $suggestionCountLast';
114 }
115
116 void complete([String tag = null]) {
117 _stopwatch.stop();
118 _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
119 }
120
121 logElapseTime(String tag, [f() = null]) {
122 Duration start;
123 Duration end = _stopwatch.elapsed;
124 var result;
125 if (f == null) {
126 start = _startTimes[tag];
127 if (start == null) {
128 _logDuration(tag, null);
129 return null;
130 }
131 } else {
132 result = f();
133 start = end;
134 end = _stopwatch.elapsed;
135 }
136 _logDuration(tag, end - start);
137 return result;
138 }
139
140 void logFirstNotificationComplete(String tag) {
141 _firstNotification = _stopwatch.elapsed;
142 _logDuration(tag, _firstNotification);
143 }
144
145 void logStartTime(String tag) {
146 _startTimes[tag] = _stopwatch.elapsed;
147 }
148
149 void setContentsAndOffset(String contents, int offset) {
150 snippet = _computeSnippet(contents, offset);
151 }
152
153 void _logDuration(String tag, Duration elapsed) {
154 operations.add(new OperationPerformance(tag, elapsed));
155 }
156
157 static String _computeSnippet(String contents, int offset) {
158 if (contents == null ||
159 offset == null ||
160 offset < 0 ||
161 contents.length < offset) {
162 return '???';
163 }
164 int start = offset;
165 while (start > 0) {
166 String ch = contents[start - 1];
167 if (ch == '\r' || ch == '\n') {
168 break;
169 }
170 --start;
171 }
172 int end = offset;
173 while (end < contents.length) {
174 String ch = contents[end];
175 if (ch == '\r' || ch == '\n') {
176 break;
177 }
178 ++end;
179 }
180 String prefix = contents.substring(start, offset);
181 String suffix = contents.substring(offset, end);
182 return '$prefix^$suffix';
183 }
184 }
185
186 /**
187 * Code completion result generated by an [CompletionManager].
188 */
189 class CompletionResultImpl implements CompletionResult {
190 /**
191 * The length of the text to be replaced if the remainder of the identifier
192 * containing the cursor is to be replaced when the suggestion is applied
193 * (that is, the number of characters in the existing identifier).
194 */
195 final int replacementLength;
196
197 /**
198 * The offset of the start of the text to be replaced. This will be different
199 * than the offset used to request the completion suggestions if there was a
200 * portion of an identifier before the original offset. In particular, the
201 * replacementOffset will be the offset of the beginning of said identifier.
202 */
203 final int replacementOffset;
204
205 /**
206 * The suggested completions.
207 */
208 final List<CompletionSuggestion> suggestions;
209
210 CompletionResultImpl(
211 this.replacementOffset, this.replacementLength, this.suggestions);
212 }
213
214 class NoOpCompletionManager extends CompletionManager {
215 NoOpCompletionManager(Source source) : super(null, source);
216
217 @override
218 Future<CompletionResult> computeSuggestions(CompletionRequest request) async {
219 return new CompletionResultImpl(request.offset, 0, []);
220 }
221 }
222
223 /**
224 * The performance of an operation when computing code completion.
225 */
226 class OperationPerformance {
227 /**
228 * The name of the operation
229 */
230 final String name;
231
232 /**
233 * The elapse time or `null` if undefined.
234 */
235 final Duration elapsed;
236
237 OperationPerformance(this.name, this.elapsed);
238 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698