| 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 analysis.server; | 5 library analysis.server; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 new HashMap<AnalysisService, Set<String>>(); | 200 new HashMap<AnalysisService, Set<String>>(); |
| 201 | 201 |
| 202 /** | 202 /** |
| 203 * A table mapping [AnalysisContext]s to the completers that should be | 203 * A table mapping [AnalysisContext]s to the completers that should be |
| 204 * completed when analysis of this context is finished. | 204 * completed when analysis of this context is finished. |
| 205 */ | 205 */ |
| 206 Map<AnalysisContext, Completer<AnalysisDoneReason>> contextAnalysisDoneComplet
ers = | 206 Map<AnalysisContext, Completer<AnalysisDoneReason>> contextAnalysisDoneComplet
ers = |
| 207 new HashMap<AnalysisContext, Completer<AnalysisDoneReason>>(); | 207 new HashMap<AnalysisContext, Completer<AnalysisDoneReason>>(); |
| 208 | 208 |
| 209 /** | 209 /** |
| 210 * The listeners that are listening for lifecycle events from this server. |
| 211 */ |
| 212 List<AnalysisServerListener> listeners = <AnalysisServerListener>[]; |
| 213 |
| 214 /** |
| 210 * True if any exceptions thrown by analysis should be propagated up the call | 215 * True if any exceptions thrown by analysis should be propagated up the call |
| 211 * stack. | 216 * stack. |
| 212 */ | 217 */ |
| 213 bool rethrowExceptions; | 218 bool rethrowExceptions; |
| 214 | 219 |
| 215 /** | 220 /** |
| 216 * Initialize a newly created server to receive requests from and send | 221 * Initialize a newly created server to receive requests from and send |
| 217 * responses to the given [channel]. | 222 * responses to the given [channel]. |
| 218 * | 223 * |
| 219 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are | 224 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 // | 325 // |
| 321 // Update the defaults used to create new contexts. | 326 // Update the defaults used to create new contexts. |
| 322 // | 327 // |
| 323 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions; | 328 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions; |
| 324 optionUpdaters.forEach((OptionUpdater optionUpdater) { | 329 optionUpdaters.forEach((OptionUpdater optionUpdater) { |
| 325 optionUpdater(options); | 330 optionUpdater(options); |
| 326 }); | 331 }); |
| 327 } | 332 } |
| 328 | 333 |
| 329 /** | 334 /** |
| 335 * Add the given [listener] to the list of listeners that are listening for |
| 336 * lifecycle events from this server. |
| 337 */ |
| 338 void addAnalysisServerListener(AnalysisServerListener listener) { |
| 339 if (!listeners.contains(listener)) { |
| 340 listeners.add(listener); |
| 341 } |
| 342 } |
| 343 |
| 344 /** |
| 330 * Adds the given [ServerOperation] to the queue, but does not schedule | 345 * Adds the given [ServerOperation] to the queue, but does not schedule |
| 331 * operations execution. | 346 * operations execution. |
| 332 */ | 347 */ |
| 333 void addOperation(ServerOperation operation) { | 348 void addOperation(ServerOperation operation) { |
| 334 operationQueue.add(operation); | 349 operationQueue.add(operation); |
| 335 } | 350 } |
| 336 | 351 |
| 337 /** | 352 /** |
| 338 * The socket from which requests are being read has been closed. | 353 * The socket from which requests are being read has been closed. |
| 339 */ | 354 */ |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 /** | 416 /** |
| 402 * Returns `true` if errors should be reported for [file] with the given | 417 * Returns `true` if errors should be reported for [file] with the given |
| 403 * absolute path. | 418 * absolute path. |
| 404 */ | 419 */ |
| 405 bool shouldSendErrorsNotificationFor(String file) { | 420 bool shouldSendErrorsNotificationFor(String file) { |
| 406 // TODO(scheglov) add support for the "--no-error-notification" flag. | 421 // TODO(scheglov) add support for the "--no-error-notification" flag. |
| 407 return contextDirectoryManager.isInAnalysisRoot(file); | 422 return contextDirectoryManager.isInAnalysisRoot(file); |
| 408 } | 423 } |
| 409 | 424 |
| 410 /** | 425 /** |
| 426 * Return `true` if analysis is complete. |
| 427 */ |
| 428 bool isAnalysisComplete() { |
| 429 return operationQueue.isEmpty; |
| 430 } |
| 431 |
| 432 /** |
| 411 * Returns `true` if the given [AnalysisContext] is a priority one. | 433 * Returns `true` if the given [AnalysisContext] is a priority one. |
| 412 */ | 434 */ |
| 413 bool isPriorityContext(AnalysisContext context) { | 435 bool isPriorityContext(AnalysisContext context) { |
| 414 // TODO(scheglov) implement support for priority sources/contexts | 436 // TODO(scheglov) implement support for priority sources/contexts |
| 415 return false; | 437 return false; |
| 416 } | 438 } |
| 417 | 439 |
| 418 /** | 440 /** |
| 419 * Perform the next available [ServerOperation]. | 441 * Perform the next available [ServerOperation]. |
| 420 */ | 442 */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 439 'Unexpected exception during analysis', | 461 'Unexpected exception during analysis', |
| 440 new CaughtException(exception, stackTrace)); | 462 new CaughtException(exception, stackTrace)); |
| 441 } | 463 } |
| 442 _sendServerErrorNotification(exception, stackTrace); | 464 _sendServerErrorNotification(exception, stackTrace); |
| 443 shutdown(); | 465 shutdown(); |
| 444 } finally { | 466 } finally { |
| 445 if (!operationQueue.isEmpty) { | 467 if (!operationQueue.isEmpty) { |
| 446 _schedulePerformOperation(); | 468 _schedulePerformOperation(); |
| 447 } else { | 469 } else { |
| 448 sendStatusNotification(null); | 470 sendStatusNotification(null); |
| 471 _notifyAnalysisComplete(); |
| 449 } | 472 } |
| 450 } | 473 } |
| 451 } | 474 } |
| 452 | 475 |
| 453 /** | 476 /** |
| 477 * Remove the given [listener] from the list of listeners that are listening |
| 478 * for lifecycle events from this server. |
| 479 */ |
| 480 void removeAnalysisServerListener(AnalysisServerListener listener) { |
| 481 listeners.remove(listener); |
| 482 } |
| 483 |
| 484 /** |
| 454 * Send status notification to the client. The `operation` is the operation | 485 * Send status notification to the client. The `operation` is the operation |
| 455 * being performed or `null` if analysis is complete. | 486 * being performed or `null` if analysis is complete. |
| 456 */ | 487 */ |
| 457 void sendStatusNotification(ServerOperation operation) { | 488 void sendStatusNotification(ServerOperation operation) { |
| 458 // Only send status when subscribed. | 489 // Only send status when subscribed. |
| 459 if (!serverServices.contains(ServerService.STATUS)) { | 490 if (!serverServices.contains(ServerService.STATUS)) { |
| 460 return; | 491 return; |
| 461 } | 492 } |
| 462 // Only send status when it changes | 493 // Only send status when it changes |
| 463 bool isAnalyzing = operation != null; | 494 bool isAnalyzing = operation != null; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 } | 606 } |
| 576 } | 607 } |
| 577 } | 608 } |
| 578 } | 609 } |
| 579 }); | 610 }); |
| 580 // remember new subscriptions | 611 // remember new subscriptions |
| 581 this.analysisServices = subscriptions; | 612 this.analysisServices = subscriptions; |
| 582 } | 613 } |
| 583 | 614 |
| 584 /** | 615 /** |
| 616 * Return the [AnalysisContext]s that are being used to analyze the analysis |
| 617 * roots. |
| 618 */ |
| 619 Iterable<AnalysisContext> getAnalysisContexts() { |
| 620 return folderMap.values; |
| 621 } |
| 622 |
| 623 /** |
| 585 * Return the [AnalysisContext] that is used to analyze the given [path]. | 624 * Return the [AnalysisContext] that is used to analyze the given [path]. |
| 586 * Return `null` if there is no such context. | 625 * Return `null` if there is no such context. |
| 587 */ | 626 */ |
| 588 AnalysisContext getAnalysisContext(String path) { | 627 AnalysisContext getAnalysisContext(String path) { |
| 589 // try to find a containing context | 628 // try to find a containing context |
| 590 for (Folder folder in folderMap.keys) { | 629 for (Folder folder in folderMap.keys) { |
| 591 if (path.startsWith(folder.path)) { | 630 if (path.startsWith(folder.path)) { |
| 592 return folderMap[folder]; | 631 return folderMap[folder]; |
| 593 } | 632 } |
| 594 } | 633 } |
| 595 // check if there is a context that analyzed this source | 634 // check if there is a context that analyzed this source |
| 596 { | 635 Source source = getSource(path); |
| 597 Source source = getSource(path); | 636 for (AnalysisContext context in folderMap.values) { |
| 598 for (AnalysisContext context in folderMap.values) { | 637 SourceKind kind = context.getKindOf(source); |
| 599 SourceKind kind = context.getKindOf(source); | 638 if (kind != null) { |
| 600 if (kind != null) { | 639 return context; |
| 601 return context; | |
| 602 } | |
| 603 } | 640 } |
| 604 } | 641 } |
| 605 return null; | 642 return null; |
| 606 } | 643 } |
| 607 | 644 |
| 608 /** | 645 /** |
| 609 * Return the [Source] of the Dart file with the given [path]. | 646 * Return the [Source] of the Dart file with the given [path]. |
| 610 */ | 647 */ |
| 611 Source getSource(String path) { | 648 Source getSource(String path) { |
| 612 // try SDK | 649 // try SDK |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 } | 862 } |
| 826 | 863 |
| 827 /** | 864 /** |
| 828 * Return `true` if all operations have been performed in this [AnalysisServer
]. | 865 * Return `true` if all operations have been performed in this [AnalysisServer
]. |
| 829 */ | 866 */ |
| 830 bool test_areOperationsFinished() { | 867 bool test_areOperationsFinished() { |
| 831 return operationQueue.isEmpty; | 868 return operationQueue.isEmpty; |
| 832 } | 869 } |
| 833 | 870 |
| 834 /** | 871 /** |
| 872 * Notify all listeners that analysis is complete. |
| 873 */ |
| 874 void _notifyAnalysisComplete() { |
| 875 listeners.forEach((AnalysisServerListener listener) { |
| 876 listener.analysisComplete(); |
| 877 }); |
| 878 } |
| 879 |
| 880 /** |
| 835 * Schedules [performOperation] exection. | 881 * Schedules [performOperation] exection. |
| 836 */ | 882 */ |
| 837 void _schedulePerformOperation() { | 883 void _schedulePerformOperation() { |
| 838 new Future(performOperation); | 884 new Future(performOperation); |
| 839 } | 885 } |
| 840 | 886 |
| 841 /** | 887 /** |
| 842 * Sends a fatal `server.error` notification. | 888 * Sends a fatal `server.error` notification. |
| 843 */ | 889 */ |
| 844 void _sendServerErrorNotification(exception, stackTrace) { | 890 void _sendServerErrorNotification(exception, stackTrace) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 855 stackTraceString = stackTrace.toString(); | 901 stackTraceString = stackTrace.toString(); |
| 856 } else { | 902 } else { |
| 857 stackTraceString = 'null stackTrace'; | 903 stackTraceString = 'null stackTrace'; |
| 858 } | 904 } |
| 859 // send the notification | 905 // send the notification |
| 860 channel.sendNotification(new ServerErrorParams(true, exceptionString, | 906 channel.sendNotification(new ServerErrorParams(true, exceptionString, |
| 861 stackTraceString).toNotification()); | 907 stackTraceString).toNotification()); |
| 862 } | 908 } |
| 863 } | 909 } |
| 864 | 910 |
| 911 /** |
| 912 * An object that is listening for lifecycle events from an analysis server. |
| 913 */ |
| 914 abstract class AnalysisServerListener { |
| 915 /** |
| 916 * Analysis is complete. |
| 917 */ |
| 918 void analysisComplete(); |
| 919 } |
| 865 | 920 |
| 866 typedef void OptionUpdater(AnalysisOptionsImpl options); | 921 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| OLD | NEW |