Chromium Code Reviews| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 56 AnalysisContext context = analysisServer.folderMap[contextFolder]; | 56 AnalysisContext context = analysisServer.folderMap[contextFolder]; |
| 57 if (context != null) { | 57 if (context != null) { |
| 58 context.applyChanges(changeSet); | 58 context.applyChanges(changeSet); |
| 59 analysisServer.schedulePerformAnalysisOperation(context); | 59 analysisServer.schedulePerformAnalysisOperation(context); |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 | 62 |
| 63 @override | 63 @override |
| 64 void removeContext(Folder folder) { | 64 void removeContext(Folder folder) { |
| 65 AnalysisContext context = analysisServer.folderMap.remove(folder); | 65 AnalysisContext context = analysisServer.folderMap.remove(folder); |
| 66 analysisServer.sendContextAnalysisCancelledNotifications( | 66 analysisServer.sendContextAnalysisDoneNotifications( |
| 67 context, | 67 context, |
| 68 'Context was removed'); | 68 AnalysisDoneReason.CONTEXT_REMOVED); |
| 69 } | 69 } |
| 70 | 70 |
| 71 @override | 71 @override |
| 72 void updateContextPackageMap(Folder contextFolder, | 72 void updateContextPackageMap(Folder contextFolder, |
| 73 Map<String, List<Folder>> packageMap) { | 73 Map<String, List<Folder>> packageMap) { |
| 74 AnalysisContext context = analysisServer.folderMap[contextFolder]; | 74 AnalysisContext context = analysisServer.folderMap[contextFolder]; |
| 75 context.sourceFactory = _createSourceFactory(packageMap); | 75 context.sourceFactory = _createSourceFactory(packageMap); |
| 76 analysisServer.schedulePerformAnalysisOperation(context); | 76 analysisServer.schedulePerformAnalysisOperation(context); |
| 77 } | 77 } |
| 78 | 78 |
| 79 /** | 79 /** |
| 80 * Set up a [SourceFactory] that resolves packages using the given | 80 * Set up a [SourceFactory] that resolves packages using the given |
| 81 * [packageMap]. | 81 * [packageMap]. |
| 82 */ | 82 */ |
| 83 SourceFactory _createSourceFactory(Map<String, List<Folder>> packageMap) { | 83 SourceFactory _createSourceFactory(Map<String, List<Folder>> packageMap) { |
| 84 List<UriResolver> resolvers = <UriResolver>[ | 84 List<UriResolver> resolvers = <UriResolver>[ |
| 85 new DartUriResolver(analysisServer.defaultSdk), | 85 new DartUriResolver(analysisServer.defaultSdk), |
| 86 new ResourceUriResolver(resourceProvider), | 86 new ResourceUriResolver(resourceProvider), |
| 87 new PackageMapUriResolver(resourceProvider, packageMap) | 87 new PackageMapUriResolver(resourceProvider, packageMap) |
| 88 ]; | 88 ]; |
| 89 return new SourceFactory(resolvers); | 89 return new SourceFactory(resolvers); |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 | |
| 94 /** | |
| 95 * Enum representing reasons why analysis might be done for a given file. | |
| 96 */ | |
| 97 class AnalysisDoneReason { | |
| 98 /** | |
| 99 * Analysis of the file completed successfully. | |
| 100 */ | |
| 101 static const AnalysisDoneReason COMPLETE = | |
| 102 const AnalysisDoneReason._('COMPLETE'); | |
| 103 | |
| 104 /** | |
| 105 * Analysis of the file was aborted because the context was removed. | |
| 106 */ | |
| 107 static const AnalysisDoneReason CONTEXT_REMOVED = | |
| 108 const AnalysisDoneReason._('CONTEXT_REMOVED'); | |
| 109 | |
| 110 /** | |
| 111 * Textual description of this [AnalysisDoneReason]. | |
| 112 */ | |
| 113 final String text; | |
| 114 | |
| 115 const AnalysisDoneReason._(this.text); | |
| 116 } | |
| 117 | |
| 118 | |
| 93 /** | 119 /** |
| 94 * Instances of the class [AnalysisServer] implement a server that listens on a | 120 * Instances of the class [AnalysisServer] implement a server that listens on a |
| 95 * [CommunicationChannel] for analysis requests and process them. | 121 * [CommunicationChannel] for analysis requests and process them. |
| 96 */ | 122 */ |
| 97 class AnalysisServer { | 123 class AnalysisServer { |
| 98 /** | 124 /** |
| 99 * The channel from which requests are received and to which responses should | 125 * The channel from which requests are received and to which responses should |
| 100 * be sent. | 126 * be sent. |
| 101 */ | 127 */ |
| 102 final ServerCommunicationChannel channel; | 128 final ServerCommunicationChannel channel; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 * A table mapping [AnalysisService]s to the file paths for which these | 196 * A table mapping [AnalysisService]s to the file paths for which these |
| 171 * notifications should be sent. | 197 * notifications should be sent. |
| 172 */ | 198 */ |
| 173 Map<AnalysisService, Set<String>> analysisServices = | 199 Map<AnalysisService, Set<String>> analysisServices = |
| 174 new HashMap<AnalysisService, Set<String>>(); | 200 new HashMap<AnalysisService, Set<String>>(); |
| 175 | 201 |
| 176 /** | 202 /** |
| 177 * A table mapping [AnalysisContext]s to the completers that should be | 203 * A table mapping [AnalysisContext]s to the completers that should be |
| 178 * completed when analysis of this context is finished. | 204 * completed when analysis of this context is finished. |
| 179 */ | 205 */ |
| 180 Map<AnalysisContext, Completer> contextAnalysisDoneCompleters = | 206 Map<AnalysisContext, Completer<AnalysisDoneReason>> contextAnalysisDoneComplet ers = |
| 181 new HashMap<AnalysisContext, Completer>(); | 207 new HashMap<AnalysisContext, Completer<AnalysisDoneReason>>(); |
| 182 | 208 |
| 183 /** | 209 /** |
| 184 * True if any exceptions thrown by analysis should be propagated up the call | 210 * True if any exceptions thrown by analysis should be propagated up the call |
| 185 * stack. | 211 * stack. |
| 186 */ | 212 */ |
| 187 bool rethrowExceptions; | 213 bool rethrowExceptions; |
| 188 | 214 |
| 189 /** | 215 /** |
| 190 * Initialize a newly created server to receive requests from and send | 216 * Initialize a newly created server to receive requests from and send |
| 191 * responses to the given [channel]. | 217 * responses to the given [channel]. |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 612 return null; | 638 return null; |
| 613 } | 639 } |
| 614 // if library has been already resolved, resolve unit | 640 // if library has been already resolved, resolve unit |
| 615 return context.resolveCompilationUnit2(unitSource, librarySource); | 641 return context.resolveCompilationUnit2(unitSource, librarySource); |
| 616 } | 642 } |
| 617 | 643 |
| 618 /** | 644 /** |
| 619 * Return an analysis error info containing the array of all of the errors and | 645 * Return an analysis error info containing the array of all of the errors and |
| 620 * the line info associated with [file]. | 646 * the line info associated with [file]. |
| 621 * | 647 * |
| 622 * Returns `null` if [file] does not belong to any [AnalysisContext]. | 648 * Returns `null` if [file] does not belong to any [AnalysisContext], or the |
| 649 * file does not exist. | |
| 623 * | 650 * |
| 624 * The array of errors will be empty if [file] does not exist or if there are | 651 * The array of errors will be empty if there are no errors in [file]. The |
| 625 * no errors in [file]. The errors contained in the array can be incomplete. | 652 * errors contained in the array can be incomplete. |
| 626 * | 653 * |
| 627 * This method does not wait for all errors to be computed, and returns just | 654 * This method does not wait for all errors to be computed, and returns just |
| 628 * the current state. | 655 * the current state. |
| 629 */ | 656 */ |
| 630 AnalysisErrorInfo getErrors(String file) { | 657 AnalysisErrorInfo getErrors(String file) { |
| 631 // prepare AnalysisContext | 658 // prepare AnalysisContext |
| 632 AnalysisContext context = getAnalysisContext(file); | 659 AnalysisContext context = getAnalysisContext(file); |
| 633 if (context == null) { | 660 if (context == null) { |
| 634 return null; | 661 return null; |
| 635 } | 662 } |
| 663 Source source = getSource(file); | |
|
scheglov
2014/09/03 21:24:29
// prepare Source
...just for consistency.
Paul Berry
2014/09/04 14:34:07
Done.
| |
| 664 if (context.getKindOf(source) == SourceKind.UNKNOWN) { | |
| 665 return null; | |
| 666 } | |
| 636 // get errors for the file | 667 // get errors for the file |
| 637 Source source = getSource(file); | |
| 638 return context.getErrors(source); | 668 return context.getErrors(source); |
| 639 } | 669 } |
| 640 | 670 |
| 641 /** | 671 /** |
| 642 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. | 672 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. |
| 643 * | 673 * |
| 644 * May be empty, but not `null`. | 674 * May be empty, but not `null`. |
| 645 */ | 675 */ |
| 646 List<CompilationUnit> getResolvedCompilationUnits(String path) { | 676 List<CompilationUnit> getResolvedCompilationUnits(String path) { |
| 647 List<CompilationUnit> units = <CompilationUnit>[]; | 677 List<CompilationUnit> units = <CompilationUnit>[]; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 704 } | 734 } |
| 705 if (element != null) { | 735 if (element != null) { |
| 706 elements.add(element); | 736 elements.add(element); |
| 707 } | 737 } |
| 708 } | 738 } |
| 709 return elements; | 739 return elements; |
| 710 } | 740 } |
| 711 | 741 |
| 712 /** | 742 /** |
| 713 * Returns a [Future] completing when [file] has been completely analyzed, in | 743 * Returns a [Future] completing when [file] has been completely analyzed, in |
| 714 * particular, all its errors have been computed. | 744 * particular, all its errors have been computed. The future is completed |
| 745 * with an [AnalysisDoneReason] indicating what caused the file's analysis to | |
| 746 * be considered complete. | |
| 747 * | |
| 748 * If the given file doesn't belong to any context, null is returned. | |
| 715 * | 749 * |
| 716 * TODO(scheglov) this method should be improved. | 750 * TODO(scheglov) this method should be improved. |
| 717 * | 751 * |
| 718 * 1. The analysis context should be told to analyze this particular file ASAP . | 752 * 1. The analysis context should be told to analyze this particular file ASAP . |
| 719 * | 753 * |
| 720 * 2. We should complete the future as soon as the file is analyzed (not wait | 754 * 2. We should complete the future as soon as the file is analyzed (not wait |
| 721 * until the context is completely finished) | 755 * until the context is completely finished) |
| 722 */ | 756 */ |
| 723 Future onFileAnalysisComplete(String file) { | 757 Future<AnalysisDoneReason> onFileAnalysisComplete(String file) { |
| 724 // prepare AnalysisContext | 758 // prepare AnalysisContext |
| 725 AnalysisContext context = getAnalysisContext(file); | 759 AnalysisContext context = getAnalysisContext(file); |
| 726 if (context == null) { | 760 if (context == null) { |
| 727 return new Future.value(); | 761 return null; |
| 728 } | 762 } |
| 729 // schedule context analysis | 763 // schedule context analysis |
| 730 schedulePerformAnalysisOperation(context); | 764 schedulePerformAnalysisOperation(context); |
| 731 // associate with the context completer | 765 // associate with the context completer |
| 732 Completer completer = contextAnalysisDoneCompleters[context]; | 766 Completer<AnalysisDoneReason> completer = |
| 767 contextAnalysisDoneCompleters[context]; | |
| 733 if (completer == null) { | 768 if (completer == null) { |
| 734 completer = new Completer(); | 769 completer = new Completer<AnalysisDoneReason>(); |
| 735 contextAnalysisDoneCompleters[context] = completer; | 770 contextAnalysisDoneCompleters[context] = completer; |
| 736 } | 771 } |
| 737 return completer.future; | 772 return completer.future; |
| 738 } | 773 } |
| 739 | 774 |
| 740 /** | 775 /** |
| 741 * This method is called when analysis of the given [AnalysisContext] is | 776 * This method is called when analysis of the given [AnalysisContext] is |
| 742 * done. | 777 * done. |
| 743 */ | 778 */ |
| 744 void sendContextAnalysisDoneNotifications(AnalysisContext context) { | 779 void sendContextAnalysisDoneNotifications(AnalysisContext context, |
| 745 Completer completer = contextAnalysisDoneCompleters.remove(context); | 780 AnalysisDoneReason reason) { |
| 781 Completer<AnalysisDoneReason> completer = | |
| 782 contextAnalysisDoneCompleters.remove(context); | |
| 746 if (completer != null) { | 783 if (completer != null) { |
| 747 completer.complete(); | 784 completer.complete(reason); |
| 748 } | 785 } |
| 749 } | 786 } |
| 750 | 787 |
| 751 /** | |
| 752 * This method is called when analysis of the given [AnalysisContext] is | |
| 753 * cancelled. | |
| 754 */ | |
| 755 void sendContextAnalysisCancelledNotifications(AnalysisContext context, String message) { | |
| 756 Completer completer = contextAnalysisDoneCompleters.remove(context); | |
| 757 if (completer != null) { | |
| 758 completer.completeError(message); | |
| 759 } | |
| 760 } | |
| 761 | |
| 762 void shutdown() { | 788 void shutdown() { |
| 763 running = false; | 789 running = false; |
| 764 if (index != null) { | 790 if (index != null) { |
| 765 index.clear(); | 791 index.clear(); |
| 766 index.stop(); | 792 index.stop(); |
| 767 } | 793 } |
| 768 // Defer closing the channel so that the shutdown response can be sent. | 794 // Defer closing the channel so that the shutdown response can be sent. |
| 769 new Future(channel.close); | 795 new Future(channel.close); |
| 770 } | 796 } |
| 771 | 797 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 822 stackTraceString = 'null stackTrace'; | 848 stackTraceString = 'null stackTrace'; |
| 823 } | 849 } |
| 824 // send the notification | 850 // send the notification |
| 825 channel.sendNotification(new ServerErrorParams(true, exceptionString, | 851 channel.sendNotification(new ServerErrorParams(true, exceptionString, |
| 826 stackTraceString).toNotification()); | 852 stackTraceString).toNotification()); |
| 827 } | 853 } |
| 828 } | 854 } |
| 829 | 855 |
| 830 | 856 |
| 831 typedef void OptionUpdater(AnalysisOptionsImpl options); | 857 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| OLD | NEW |