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:analysis_server/src/analysis_logger.dart'; | 10 import 'package:analysis_server/src/analysis_logger.dart'; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 /** | 200 /** |
| 201 * The next time (milliseconds since epoch) after which the analysis server | 201 * The next time (milliseconds since epoch) after which the analysis server |
| 202 * should pause so that pending requests can be fetched by the system. | 202 * should pause so that pending requests can be fetched by the system. |
| 203 */ | 203 */ |
| 204 // Add 1 sec to prevent delay from impacting short running tests | 204 // Add 1 sec to prevent delay from impacting short running tests |
| 205 int _nextPerformOperationDelayTime = | 205 int _nextPerformOperationDelayTime = |
| 206 new DateTime.now().millisecondsSinceEpoch + | 206 new DateTime.now().millisecondsSinceEpoch + |
| 207 1000; | 207 1000; |
| 208 | 208 |
| 209 /** | 209 /** |
| 210 * The current state of overlays from the client. This is used as the | |
| 211 * content cache for all contexts. | |
| 212 */ | |
| 213 ContentCache _overlayState = new ContentCache(); | |
| 214 | |
| 215 /** | |
| 210 * Initialize a newly created server to receive requests from and send | 216 * Initialize a newly created server to receive requests from and send |
| 211 * responses to the given [channel]. | 217 * responses to the given [channel]. |
| 212 * | 218 * |
| 213 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are | 219 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are |
| 214 * propagated up the call stack. The default is true to allow analysis | 220 * propagated up the call stack. The default is true to allow analysis |
| 215 * exceptions to show up in unit tests, but it should be set to false when | 221 * exceptions to show up in unit tests, but it should be set to false when |
| 216 * running a full analysis server. | 222 * running a full analysis server. |
| 217 */ | 223 */ |
| 218 AnalysisServer(this.channel, this.resourceProvider, | 224 AnalysisServer(this.channel, this.resourceProvider, |
| 219 PackageMapProvider packageMapProvider, this.index, | 225 PackageMapProvider packageMapProvider, this.index, |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 882 instrumentationService.shutdown(); | 888 instrumentationService.shutdown(); |
| 883 channel.close(); | 889 channel.close(); |
| 884 }); | 890 }); |
| 885 } | 891 } |
| 886 | 892 |
| 887 /** | 893 /** |
| 888 * Implementation for `analysis.updateContent`. | 894 * Implementation for `analysis.updateContent`. |
| 889 */ | 895 */ |
| 890 void updateContent(String id, Map<String, dynamic> changes) { | 896 void updateContent(String id, Map<String, dynamic> changes) { |
| 891 changes.forEach((file, change) { | 897 changes.forEach((file, change) { |
| 892 AnalysisContext analysisContext = getAnalysisContext(file); | 898 Source source = getSource(file); |
| 893 // TODO(paulberry): handle the case where a file is referred to by more | 899 String oldContents = _overlayState.getContents(source); |
|
Brian Wilkerson
2015/01/26 23:05:02
There is a subtle bug here that's being carried fo
| |
| 894 // than one context (e.g package A depends on package B using a local | 900 String newContents; |
| 895 // path, user has both packages open for editing in separate contexts, | 901 if (change is AddContentOverlay) { |
| 896 // and user modifies a file in package B). | 902 newContents = change.content; |
| 897 if (analysisContext != null) { | 903 } else if (change is ChangeContentOverlay) { |
| 898 Source source = getSource(file); | 904 if (oldContents == null) { |
| 899 if (change is AddContentOverlay) { | 905 // The client may only send a ChangeContentOverlay if there is |
| 900 analysisContext.setContents(source, change.content); | 906 // already an existing overlay for the source. |
| 901 } else if (change is ChangeContentOverlay) { | 907 throw new RequestFailure( |
| 902 // TODO(paulberry): an error should be generated if source is not | 908 new Response( |
| 903 // currently in the content cache. | 909 id, |
| 904 TimestampedData<String> oldContents = | 910 error: new RequestError( |
| 905 analysisContext.getContents(source); | 911 RequestErrorCode.INVALID_OVERLAY_CHANGE, |
| 906 String newContents; | 912 'Invalid overlay change'))); |
| 907 try { | |
| 908 newContents = | |
| 909 SourceEdit.applySequence(oldContents.data, change.edits); | |
| 910 } on RangeError { | |
| 911 throw new RequestFailure( | |
| 912 new Response( | |
| 913 id, | |
| 914 error: new RequestError( | |
| 915 RequestErrorCode.INVALID_OVERLAY_CHANGE, | |
| 916 'Invalid overlay change'))); | |
| 917 } | |
| 918 // TODO(paulberry): to aid in incremental processing it would be | |
| 919 // better to use setChangedContents. | |
| 920 analysisContext.setContents(source, newContents); | |
| 921 } else if (change is RemoveContentOverlay) { | |
| 922 analysisContext.setContents(source, null); | |
| 923 } else { | |
| 924 // Protocol parsing should have ensured that we never get here. | |
| 925 throw new AnalysisException('Illegal change type'); | |
| 926 } | 913 } |
| 927 schedulePerformAnalysisOperation(analysisContext); | 914 try { |
| 915 newContents = SourceEdit.applySequence(oldContents, change.edits); | |
| 916 } on RangeError { | |
| 917 throw new RequestFailure( | |
| 918 new Response( | |
| 919 id, | |
| 920 error: new RequestError( | |
| 921 RequestErrorCode.INVALID_OVERLAY_CHANGE, | |
| 922 'Invalid overlay change'))); | |
| 923 } | |
| 924 } else if (change is RemoveContentOverlay) { | |
| 925 newContents = null; | |
| 926 } else { | |
| 927 // Protocol parsing should have ensured that we never get here. | |
| 928 throw new AnalysisException('Illegal change type'); | |
| 929 } | |
| 930 _overlayState.setContents(source, newContents); | |
| 931 for (InternalAnalysisContext context in folderMap.values) { | |
| 932 if (context.handleContentsChanged( | |
| 933 source, | |
| 934 oldContents, | |
| 935 newContents, | |
| 936 true)) { | |
| 937 schedulePerformAnalysisOperation(context); | |
| 938 } | |
| 928 } | 939 } |
| 929 }); | 940 }); |
| 930 } | 941 } |
| 931 | 942 |
| 932 /** | 943 /** |
| 933 * Use the given updaters to update the values of the options in every | 944 * Use the given updaters to update the values of the options in every |
| 934 * existing analysis context. | 945 * existing analysis context. |
| 935 */ | 946 */ |
| 936 void updateOptions(List<OptionUpdater> optionUpdaters) { | 947 void updateOptions(List<OptionUpdater> optionUpdaters) { |
| 937 // | 948 // |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 } | 1058 } |
| 1048 | 1059 |
| 1049 /** | 1060 /** |
| 1050 * The stream that is notified when contexts are added or removed. | 1061 * The stream that is notified when contexts are added or removed. |
| 1051 */ | 1062 */ |
| 1052 Stream<ContextsChangedEvent> get onContextsChanged => | 1063 Stream<ContextsChangedEvent> get onContextsChanged => |
| 1053 _onContextsChangedController.stream; | 1064 _onContextsChangedController.stream; |
| 1054 | 1065 |
| 1055 @override | 1066 @override |
| 1056 void addContext(Folder folder, UriResolver packageUriResolver) { | 1067 void addContext(Folder folder, UriResolver packageUriResolver) { |
| 1057 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); | 1068 InternalAnalysisContext context = |
| 1069 AnalysisEngine.instance.createAnalysisContext(); | |
| 1070 context.contentCache = analysisServer._overlayState; | |
| 1058 analysisServer.folderMap[folder] = context; | 1071 analysisServer.folderMap[folder] = context; |
| 1059 context.sourceFactory = _createSourceFactory(packageUriResolver); | 1072 context.sourceFactory = _createSourceFactory(packageUriResolver); |
| 1060 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); | 1073 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); |
| 1061 _onContextsChangedController.add( | 1074 _onContextsChangedController.add( |
| 1062 new ContextsChangedEvent(added: [context])); | 1075 new ContextsChangedEvent(added: [context])); |
| 1063 analysisServer.schedulePerformAnalysisOperation(context); | 1076 analysisServer.schedulePerformAnalysisOperation(context); |
| 1064 } | 1077 } |
| 1065 | 1078 |
| 1066 @override | 1079 @override |
| 1067 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { | 1080 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 * [packageUriResolver]. | 1132 * [packageUriResolver]. |
| 1120 */ | 1133 */ |
| 1121 SourceFactory _createSourceFactory(UriResolver packageUriResolver) { | 1134 SourceFactory _createSourceFactory(UriResolver packageUriResolver) { |
| 1122 List<UriResolver> resolvers = <UriResolver>[ | 1135 List<UriResolver> resolvers = <UriResolver>[ |
| 1123 new DartUriResolver(analysisServer.defaultSdk), | 1136 new DartUriResolver(analysisServer.defaultSdk), |
| 1124 new ResourceUriResolver(resourceProvider), | 1137 new ResourceUriResolver(resourceProvider), |
| 1125 packageUriResolver]; | 1138 packageUriResolver]; |
| 1126 return new SourceFactory(resolvers); | 1139 return new SourceFactory(resolvers); |
| 1127 } | 1140 } |
| 1128 } | 1141 } |
| OLD | NEW |