| 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 domain.completion; | 5 library domain.completion; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 10 import 'package:analysis_server/src/constants.dart'; | 10 import 'package:analysis_server/src/constants.dart'; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 /** | 82 /** |
| 83 * Return the completion manager for most recent [Source] and [AnalysisContext
], | 83 * Return the completion manager for most recent [Source] and [AnalysisContext
], |
| 84 * or `null` if none. | 84 * or `null` if none. |
| 85 */ | 85 */ |
| 86 CompletionManager get manager => _manager; | 86 CompletionManager get manager => _manager; |
| 87 | 87 |
| 88 /** | 88 /** |
| 89 * Return the [CompletionManager] for the given [context] and [source], | 89 * Return the [CompletionManager] for the given [context] and [source], |
| 90 * creating a new manager or returning an existing manager as necessary. | 90 * creating a new manager or returning an existing manager as necessary. |
| 91 */ | 91 */ |
| 92 CompletionManager completionManagerFor(AnalysisContext context, | 92 CompletionManager completionManagerFor( |
| 93 Source source) { | 93 AnalysisContext context, Source source) { |
| 94 if (_manager != null) { | 94 if (_manager != null) { |
| 95 if (_manager.context == context && _manager.source == source) { | 95 if (_manager.context == context && _manager.source == source) { |
| 96 return _manager; | 96 return _manager; |
| 97 } | 97 } |
| 98 _discardManager(); | 98 _discardManager(); |
| 99 } | 99 } |
| 100 _manager = createCompletionManager(context, source, searchEngine); | 100 _manager = createCompletionManager(context, source, searchEngine); |
| 101 if (context != null) { | 101 if (context != null) { |
| 102 _sourcesChangedSubscription = | 102 _sourcesChangedSubscription = |
| 103 context.onSourcesChanged.listen(sourcesChanged); | 103 context.onSourcesChanged.listen(sourcesChanged); |
| 104 } | 104 } |
| 105 return _manager; | 105 return _manager; |
| 106 } | 106 } |
| 107 | 107 |
| 108 /** | 108 /** |
| 109 * If the context associated with the cache has changed or been removed | 109 * If the context associated with the cache has changed or been removed |
| 110 * then discard the cache. | 110 * then discard the cache. |
| 111 */ | 111 */ |
| 112 void contextsChanged(ContextsChangedEvent event) { | 112 void contextsChanged(ContextsChangedEvent event) { |
| 113 if (_manager != null) { | 113 if (_manager != null) { |
| 114 AnalysisContext context = _manager.context; | 114 AnalysisContext context = _manager.context; |
| 115 if (event.changed.contains(context) || event.removed.contains(context)) { | 115 if (event.changed.contains(context) || event.removed.contains(context)) { |
| 116 _discardManager(); | 116 _discardManager(); |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 | 120 |
| 121 CompletionManager createCompletionManager(AnalysisContext context, | 121 CompletionManager createCompletionManager( |
| 122 Source source, SearchEngine searchEngine) { | 122 AnalysisContext context, Source source, SearchEngine searchEngine) { |
| 123 return new CompletionManager.create(context, source, searchEngine); | 123 return new CompletionManager.create(context, source, searchEngine); |
| 124 } | 124 } |
| 125 | 125 |
| 126 @override | 126 @override |
| 127 Response handleRequest(Request request) { | 127 Response handleRequest(Request request) { |
| 128 if (searchEngine == null) { | 128 if (searchEngine == null) { |
| 129 return new Response.noIndexGenerated(request); | 129 return new Response.noIndexGenerated(request); |
| 130 } | 130 } |
| 131 try { | 131 try { |
| 132 String requestName = request.method; | 132 String requestName = request.method; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 recordRequest(performance, context, source, params.offset); | 179 recordRequest(performance, context, source, params.offset); |
| 180 if (manager == null) { | 180 if (manager == null) { |
| 181 manager = completionManagerFor(context, source); | 181 manager = completionManagerFor(context, source); |
| 182 } | 182 } |
| 183 CompletionRequest completionRequest = | 183 CompletionRequest completionRequest = |
| 184 new CompletionRequest(params.offset, performance); | 184 new CompletionRequest(params.offset, performance); |
| 185 int notificationCount = 0; | 185 int notificationCount = 0; |
| 186 manager.results(completionRequest).listen((CompletionResult result) { | 186 manager.results(completionRequest).listen((CompletionResult result) { |
| 187 ++notificationCount; | 187 ++notificationCount; |
| 188 performance.logElapseTime("notification $notificationCount send", () { | 188 performance.logElapseTime("notification $notificationCount send", () { |
| 189 sendCompletionNotification( | 189 sendCompletionNotification(completionId, result.replacementOffset, |
| 190 completionId, | 190 result.replacementLength, result.suggestions, result.last); |
| 191 result.replacementOffset, | |
| 192 result.replacementLength, | |
| 193 result.suggestions, | |
| 194 result.last); | |
| 195 }); | 191 }); |
| 196 if (notificationCount == 1) { | 192 if (notificationCount == 1) { |
| 197 performance.logFirstNotificationComplete('notification 1 complete'); | 193 performance.logFirstNotificationComplete('notification 1 complete'); |
| 198 performance.suggestionCountFirst = result.suggestions.length; | 194 performance.suggestionCountFirst = result.suggestions.length; |
| 199 } | 195 } |
| 200 if (result.last) { | 196 if (result.last) { |
| 201 performance.notificationCount = notificationCount; | 197 performance.notificationCount = notificationCount; |
| 202 performance.suggestionCountLast = result.suggestions.length; | 198 performance.suggestionCountLast = result.suggestions.length; |
| 203 performance.complete(); | 199 performance.complete(); |
| 204 } | 200 } |
| 205 }); | 201 }); |
| 206 // initial response without results | 202 // initial response without results |
| 207 return new CompletionGetSuggestionsResult( | 203 return new CompletionGetSuggestionsResult(completionId) |
| 208 completionId).toResponse(request.id); | 204 .toResponse(request.id); |
| 209 } | 205 } |
| 210 | 206 |
| 211 /** | 207 /** |
| 212 * If tracking code completion performance over time, then | 208 * If tracking code completion performance over time, then |
| 213 * record addition information about the request in the performance record. | 209 * record addition information about the request in the performance record. |
| 214 */ | 210 */ |
| 215 void recordRequest(CompletionPerformance performance, AnalysisContext context, | 211 void recordRequest(CompletionPerformance performance, AnalysisContext context, |
| 216 Source source, int offset) { | 212 Source source, int offset) { |
| 217 performance.source = source; | 213 performance.source = source; |
| 218 if (performanceListMaxLength == 0 || context == null || source == null) { | 214 if (performanceListMaxLength == 0 || context == null || source == null) { |
| 219 return; | 215 return; |
| 220 } | 216 } |
| 221 TimestampedData<String> data = context.getContents(source); | 217 TimestampedData<String> data = context.getContents(source); |
| 222 if (data == null) { | 218 if (data == null) { |
| 223 return; | 219 return; |
| 224 } | 220 } |
| 225 performance.setContentsAndOffset(data.data, offset); | 221 performance.setContentsAndOffset(data.data, offset); |
| 226 while (performanceList.length >= performanceListMaxLength) { | 222 while (performanceList.length >= performanceListMaxLength) { |
| 227 performanceList.removeAt(0); | 223 performanceList.removeAt(0); |
| 228 } | 224 } |
| 229 performanceList.add(performance); | 225 performanceList.add(performance); |
| 230 } | 226 } |
| 231 | 227 |
| 232 /** | 228 /** |
| 233 * Send completion notification results. | 229 * Send completion notification results. |
| 234 */ | 230 */ |
| 235 void sendCompletionNotification(String completionId, int replacementOffset, | 231 void sendCompletionNotification(String completionId, int replacementOffset, |
| 236 int replacementLength, Iterable<CompletionSuggestion> results, bool isLast
) { | 232 int replacementLength, Iterable<CompletionSuggestion> results, |
| 237 server.sendNotification( | 233 bool isLast) { |
| 238 new CompletionResultsParams( | 234 server.sendNotification(new CompletionResultsParams( |
| 239 completionId, | 235 completionId, replacementOffset, replacementLength, results, isLast) |
| 240 replacementOffset, | 236 .toNotification()); |
| 241 replacementLength, | |
| 242 results, | |
| 243 isLast).toNotification()); | |
| 244 } | 237 } |
| 245 | 238 |
| 246 /** | 239 /** |
| 247 * Discard the cache if a source other than the source referenced by | 240 * Discard the cache if a source other than the source referenced by |
| 248 * the cache changes or if any source is added, removed, or deleted. | 241 * the cache changes or if any source is added, removed, or deleted. |
| 249 */ | 242 */ |
| 250 void sourcesChanged(SourcesChangedEvent event) { | 243 void sourcesChanged(SourcesChangedEvent event) { |
| 251 | |
| 252 bool shouldDiscardManager(SourcesChangedEvent event) { | 244 bool shouldDiscardManager(SourcesChangedEvent event) { |
| 253 if (_manager == null) { | 245 if (_manager == null) { |
| 254 return false; | 246 return false; |
| 255 } | 247 } |
| 256 if (event.wereSourcesAdded || event.wereSourcesRemovedOrDeleted) { | 248 if (event.wereSourcesAdded || event.wereSourcesRemovedOrDeleted) { |
| 257 return true; | 249 return true; |
| 258 } | 250 } |
| 259 var changedSources = event.changedSources; | 251 var changedSources = event.changedSources; |
| 260 return changedSources.length > 2 || | 252 return changedSources.length > 2 || |
| 261 (changedSources.length == 1 && !changedSources.contains(_manager.sourc
e)); | 253 (changedSources.length == 1 && |
| 254 !changedSources.contains(_manager.source)); |
| 262 } | 255 } |
| 263 | 256 |
| 264 if (shouldDiscardManager(event)) { | 257 if (shouldDiscardManager(event)) { |
| 265 _discardManager(); | 258 _discardManager(); |
| 266 } | 259 } |
| 267 } | 260 } |
| 268 | 261 |
| 269 /** | 262 /** |
| 270 * Discard the sourcesChanged subscription if any | 263 * Discard the sourcesChanged subscription if any |
| 271 */ | 264 */ |
| 272 void _discardManager() { | 265 void _discardManager() { |
| 273 if (_sourcesChangedSubscription != null) { | 266 if (_sourcesChangedSubscription != null) { |
| 274 _sourcesChangedSubscription.cancel(); | 267 _sourcesChangedSubscription.cancel(); |
| 275 _sourcesChangedSubscription = null; | 268 _sourcesChangedSubscription = null; |
| 276 } | 269 } |
| 277 if (_manager != null) { | 270 if (_manager != null) { |
| 278 _manager.dispose(); | 271 _manager.dispose(); |
| 279 _manager = null; | 272 _manager = null; |
| 280 } | 273 } |
| 281 } | 274 } |
| 282 } | 275 } |
| OLD | NEW |