OLD | NEW |
---|---|
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:analyzer/file_system/file_system.dart'; | 5 import 'package:analyzer/file_system/file_system.dart'; |
6 import 'package:analyzer/src/dart/analysis/byte_store.dart'; | 6 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
7 import 'package:analyzer/src/dart/analysis/driver.dart' | 7 import 'package:analyzer/src/dart/analysis/driver.dart' |
8 show AnalysisDriverGeneric, AnalysisDriverScheduler, PerformanceLog; | 8 show AnalysisDriverGeneric, AnalysisDriverScheduler, PerformanceLog; |
9 import 'package:analyzer/src/dart/analysis/file_byte_store.dart'; | 9 import 'package:analyzer/src/dart/analysis/file_byte_store.dart'; |
10 import 'package:analyzer/src/dart/analysis/file_state.dart'; | 10 import 'package:analyzer/src/dart/analysis/file_state.dart'; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 /** | 171 /** |
172 * Create an analysis driver that can analyze the files within the given | 172 * Create an analysis driver that can analyze the files within the given |
173 * [contextRoot]. | 173 * [contextRoot]. |
174 */ | 174 */ |
175 AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot); | 175 AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot); |
176 | 176 |
177 /** | 177 /** |
178 * Handle an 'analysis.handleWatchEvents' request. | 178 * Handle an 'analysis.handleWatchEvents' request. |
179 */ | 179 */ |
180 AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents( | 180 AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents( |
181 AnalysisHandleWatchEventsParams parameters) => | 181 AnalysisHandleWatchEventsParams parameters) { |
182 null; | 182 for (WatchEvent event in parameters.events) { |
183 switch (event.type) { | |
184 case WatchEventType.ADD: | |
185 // TODO(brianwilkerson) Handle the event. | |
186 break; | |
187 case WatchEventType.MODIFY: | |
188 contentChanged(event.path); | |
189 break; | |
190 case WatchEventType.REMOVE: | |
191 // TODO(brianwilkerson) Handle the event. | |
192 break; | |
193 default: | |
194 // Ignore unhandled watch event types. | |
195 break; | |
196 } | |
197 } | |
198 return new AnalysisHandleWatchEventsResult(); | |
199 } | |
183 | 200 |
184 /** | 201 /** |
185 * Handle an 'analysis.reanalyze' request. | 202 * Handle an 'analysis.reanalyze' request. |
186 */ | 203 */ |
187 AnalysisReanalyzeResult handleAnalysisReanalyze( | 204 AnalysisReanalyzeResult handleAnalysisReanalyze( |
188 AnalysisReanalyzeParams parameters) => | 205 AnalysisReanalyzeParams parameters) { |
189 null; | 206 var rootPaths = parameters.roots; |
207 if (rootPaths == null) { | |
208 // | |
209 // Reanalyze everything. | |
210 // | |
211 List<ContextRoot> roots = driverMap.keys.toList(); | |
212 for (ContextRoot contextRoot in roots) { | |
scheglov
2017/05/08 16:45:43
Do we want to handle this as "reanalyze contexts"
Brian Wilkerson
2017/05/08 17:01:10
Interesting question. My intuition is that (a) cha
| |
213 AnalysisDriverGeneric driver = driverMap[contextRoot]; | |
214 driver.dispose(); | |
215 driver = createAnalysisDriver(contextRoot); | |
216 driverMap[contextRoot] = driver; | |
217 } | |
218 return new AnalysisReanalyzeResult(); | |
219 } else { | |
220 // | |
221 // Reanalyze a specific set of files. | |
222 // | |
223 // TODO(brianwilkerson) There is no API for telling a driver that we need | |
224 // to have some files reanalyzed. | |
225 // for (String rootPath in rootPaths) { | |
226 // ContextRoot contextRoot = contextRootContaining(rootPath); | |
227 // AnalysisDriverGeneric driver = driverMap[contextRoot]; | |
228 // driver.reanalyze(rootPath); | |
229 // } | |
230 return null; | |
231 } | |
232 } | |
190 | 233 |
191 /** | 234 /** |
192 * Handle an 'analysis.setContextBuilderOptions' request. | 235 * Handle an 'analysis.setContextBuilderOptions' request. |
193 */ | 236 */ |
194 AnalysisSetContextBuilderOptionsResult handleAnalysisSetContextBuilderOptions( | 237 AnalysisSetContextBuilderOptionsResult handleAnalysisSetContextBuilderOptions( |
195 AnalysisSetContextBuilderOptionsParams parameters) => | 238 AnalysisSetContextBuilderOptionsParams parameters) => |
196 null; | 239 null; |
197 | 240 |
198 /** | 241 /** |
199 * Handle an 'analysis.setContextRoots' request. | 242 * Handle an 'analysis.setContextRoots' request. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 } | 286 } |
244 | 287 |
245 /** | 288 /** |
246 * Handle an 'analysis.setSubscriptions' request. Most subclasses should not | 289 * Handle an 'analysis.setSubscriptions' request. Most subclasses should not |
247 * override this method, but should instead use the [subscriptionManager] to | 290 * override this method, but should instead use the [subscriptionManager] to |
248 * access the list of subscriptions for any given file. | 291 * access the list of subscriptions for any given file. |
249 */ | 292 */ |
250 AnalysisSetSubscriptionsResult handleAnalysisSetSubscriptions( | 293 AnalysisSetSubscriptionsResult handleAnalysisSetSubscriptions( |
251 AnalysisSetSubscriptionsParams parameters) { | 294 AnalysisSetSubscriptionsParams parameters) { |
252 Map<AnalysisService, List<String>> subscriptions = parameters.subscriptions; | 295 Map<AnalysisService, List<String>> subscriptions = parameters.subscriptions; |
253 subscriptionManager.setSubscriptions(subscriptions); | 296 Map<String, List<AnalysisService>> newSubscriptions = |
254 // TODO(brianwilkerson) Cause any newly subscribed for notifications to be s ent. | 297 subscriptionManager.setSubscriptions(subscriptions); |
298 sendNotificationsForSubscriptions(newSubscriptions); | |
255 return new AnalysisSetSubscriptionsResult(); | 299 return new AnalysisSetSubscriptionsResult(); |
256 } | 300 } |
257 | 301 |
258 /** | 302 /** |
259 * Handle an 'analysis.updateContent' request. Most subclasses should not | 303 * Handle an 'analysis.updateContent' request. Most subclasses should not |
260 * override this method, but should instead use the [contentCache] to access | 304 * override this method, but should instead use the [contentCache] to access |
261 * the current content of overlaid files. | 305 * the current content of overlaid files. |
262 */ | 306 */ |
263 AnalysisUpdateContentResult handleAnalysisUpdateContent( | 307 AnalysisUpdateContentResult handleAnalysisUpdateContent( |
264 AnalysisUpdateContentParams parameters) { | 308 AnalysisUpdateContentParams parameters) { |
265 Map<String, Object> files = parameters.files; | 309 Map<String, Object> files = parameters.files; |
266 files.forEach((String filePath, Object overlay) { | 310 files.forEach((String filePath, Object overlay) { |
267 // We don't need to get the correct URI because only the full path is | 311 // We don't need to get the correct URI because only the full path is |
268 // used by the contentCache. | 312 // used by the contentCache. |
269 Source source = resourceProvider.getFile(filePath).createSource(); | 313 Source source = resourceProvider.getFile(filePath).createSource(); |
270 if (overlay is AddContentOverlay) { | 314 if (overlay is AddContentOverlay) { |
271 fileContentOverlay[source.fullName] = overlay.content; | 315 fileContentOverlay[source.fullName] = overlay.content; |
272 } else if (overlay is ChangeContentOverlay) { | 316 } else if (overlay is ChangeContentOverlay) { |
273 String fileName = source.fullName; | 317 String fileName = source.fullName; |
274 String oldContents = fileContentOverlay[fileName]; | 318 String oldContents = fileContentOverlay[fileName]; |
275 String newContents; | 319 String newContents; |
276 if (oldContents == null) { | 320 if (oldContents == null) { |
277 // The server should only send a ChangeContentOverlay if there is | 321 // The server should only send a ChangeContentOverlay if there is |
278 // already an existing overlay for the source. | 322 // already an existing overlay for the source. |
279 throw new RequestFailure(new RequestError( | 323 throw new RequestFailure( |
280 RequestErrorCode.INVALID_OVERLAY_CHANGE, | 324 RequestErrorFactory.invalidOverlayChangeNoContent()); |
281 'Invalid overlay change: no content to change')); | |
282 } | 325 } |
283 try { | 326 try { |
284 newContents = SourceEdit.applySequence(oldContents, overlay.edits); | 327 newContents = SourceEdit.applySequence(oldContents, overlay.edits); |
285 } on RangeError { | 328 } on RangeError { |
286 throw new RequestFailure(new RequestError( | 329 throw new RequestFailure( |
287 RequestErrorCode.INVALID_OVERLAY_CHANGE, | 330 RequestErrorFactory.invalidOverlayChangeInvalidEdit()); |
288 'Invalid overlay change: invalid edit')); | |
289 } | 331 } |
290 fileContentOverlay[fileName] = newContents; | 332 fileContentOverlay[fileName] = newContents; |
291 } else if (overlay is RemoveContentOverlay) { | 333 } else if (overlay is RemoveContentOverlay) { |
292 fileContentOverlay[source.fullName] = null; | 334 fileContentOverlay[source.fullName] = null; |
293 } | 335 } |
294 contentChanged(filePath); | 336 contentChanged(filePath); |
295 }); | 337 }); |
296 return new AnalysisUpdateContentResult(); | 338 return new AnalysisUpdateContentResult(); |
297 } | 339 } |
298 | 340 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 */ | 412 */ |
371 void onDone() {} | 413 void onDone() {} |
372 | 414 |
373 /** | 415 /** |
374 * The method that is called when an error has occurred in the analysis | 416 * The method that is called when an error has occurred in the analysis |
375 * server. This method will not be invoked under normal conditions. | 417 * server. This method will not be invoked under normal conditions. |
376 */ | 418 */ |
377 void onError(Object exception, StackTrace stackTrace) {} | 419 void onError(Object exception, StackTrace stackTrace) {} |
378 | 420 |
379 /** | 421 /** |
422 * Send notifications corresponding to the given description of subscriptions. | |
423 * The map is keyed by the path of each file for which notifications should be | |
424 * send and has values representing the list of services associated with the | |
425 * notifications to send. | |
426 */ | |
427 void sendNotificationsForSubscriptions( | |
428 Map<String, List<AnalysisService>> subscriptions); | |
429 | |
430 /** | |
380 * Start this plugin by listening to the given communication [channel]. | 431 * Start this plugin by listening to the given communication [channel]. |
381 */ | 432 */ |
382 void start(PluginCommunicationChannel channel) { | 433 void start(PluginCommunicationChannel channel) { |
383 _channel = channel; | 434 _channel = channel; |
384 _channel.listen(_onRequest, onError: onError, onDone: onDone); | 435 _channel.listen(_onRequest, onError: onError, onDone: onDone); |
385 } | 436 } |
386 | 437 |
387 /** | 438 /** |
388 * Compute the response that should be returned for the given [request], or | 439 * Compute the response that should be returned for the given [request], or |
389 * `null` if the response has already been sent. | 440 * `null` if the response has already been sent. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
474 response = new Response(id, | 525 response = new Response(id, |
475 error: new RequestError( | 526 error: new RequestError( |
476 RequestErrorCode.PLUGIN_ERROR, exception.toString(), | 527 RequestErrorCode.PLUGIN_ERROR, exception.toString(), |
477 stackTrace: stackTrace.toString())); | 528 stackTrace: stackTrace.toString())); |
478 } | 529 } |
479 if (response != null) { | 530 if (response != null) { |
480 _channel.sendResponse(response); | 531 _channel.sendResponse(response); |
481 } | 532 } |
482 } | 533 } |
483 } | 534 } |
OLD | NEW |