| 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 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'; |
| 11 import 'package:analyzer/src/generated/source.dart'; | 11 import 'package:analyzer/src/generated/source.dart'; |
| 12 import 'package:analyzer_plugin/channel/channel.dart'; | 12 import 'package:analyzer_plugin/channel/channel.dart'; |
| 13 import 'package:analyzer_plugin/protocol/protocol.dart'; | 13 import 'package:analyzer_plugin/protocol/protocol.dart'; |
| 14 import 'package:analyzer_plugin/protocol/protocol_constants.dart'; | 14 import 'package:analyzer_plugin/protocol/protocol_constants.dart'; |
| 15 import 'package:analyzer_plugin/protocol/protocol_generated.dart'; | 15 import 'package:analyzer_plugin/protocol/protocol_generated.dart'; |
| 16 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart'; | 16 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart'; |
| 17 import 'package:analyzer_plugin/src/utilities/null_string_sink.dart'; | 17 import 'package:analyzer_plugin/src/utilities/null_string_sink.dart'; |
| 18 import 'package:analyzer_plugin/utilities/subscriptions/subscription_manager.dar
t'; | 18 import 'package:analyzer_plugin/utilities/subscriptions/subscription_manager.dar
t'; |
| 19 import 'package:path/src/context.dart'; |
| 19 import 'package:pub_semver/pub_semver.dart'; | 20 import 'package:pub_semver/pub_semver.dart'; |
| 20 | 21 |
| 21 /** | 22 /** |
| 22 * The abstract superclass of any class implementing a plugin for the analysis | 23 * The abstract superclass of any class implementing a plugin for the analysis |
| 23 * server. | 24 * server. |
| 24 * | 25 * |
| 25 * Clients may not implement or mix-in this class, but are expected to extend | 26 * Clients may not implement or mix-in this class, but are expected to extend |
| 26 * it. | 27 * it. |
| 27 */ | 28 */ |
| 28 abstract class ServerPlugin { | 29 abstract class ServerPlugin { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 46 * The object used to manage analysis subscriptions. | 47 * The object used to manage analysis subscriptions. |
| 47 */ | 48 */ |
| 48 final SubscriptionManager subscriptionManager = new SubscriptionManager(); | 49 final SubscriptionManager subscriptionManager = new SubscriptionManager(); |
| 49 | 50 |
| 50 /** | 51 /** |
| 51 * The scheduler used by any analysis drivers that are created. | 52 * The scheduler used by any analysis drivers that are created. |
| 52 */ | 53 */ |
| 53 AnalysisDriverScheduler analysisDriverScheduler; | 54 AnalysisDriverScheduler analysisDriverScheduler; |
| 54 | 55 |
| 55 /** | 56 /** |
| 57 * A table mapping the current context roots to the analysis driver created |
| 58 * for that root. |
| 59 */ |
| 60 final Map<ContextRoot, AnalysisDriverGeneric> driverMap = |
| 61 <ContextRoot, AnalysisDriverGeneric>{}; |
| 62 |
| 63 /** |
| 56 * The performance log used by any analysis drivers that are created. | 64 * The performance log used by any analysis drivers that are created. |
| 57 */ | 65 */ |
| 58 final PerformanceLog performanceLog = | 66 final PerformanceLog performanceLog = |
| 59 new PerformanceLog(new NullStringSink()); | 67 new PerformanceLog(new NullStringSink()); |
| 60 | 68 |
| 61 /** | 69 /** |
| 62 * The byte store used by any analysis drivers that are created, or `null` if | 70 * The byte store used by any analysis drivers that are created, or `null` if |
| 63 * the cache location isn't known because the 'plugin.version' request has not | 71 * the cache location isn't known because the 'plugin.version' request has not |
| 64 * yet been received. | 72 * yet been received. |
| 65 */ | 73 */ |
| 66 ByteStore _byteStore; | 74 ByteStore _byteStore; |
| 67 | 75 |
| 68 /** | 76 /** |
| 69 * The file content overlay used by any analysis drivers that are created. | 77 * The file content overlay used by any analysis drivers that are created. |
| 70 */ | 78 */ |
| 71 final FileContentOverlay fileContentOverlay = new FileContentOverlay(); | 79 final FileContentOverlay fileContentOverlay = new FileContentOverlay(); |
| 72 | 80 |
| 73 /** | 81 /** |
| 74 * Initialize a newly created analysis server plugin. If a resource [provider] | 82 * Initialize a newly created analysis server plugin. If a resource [provider] |
| 75 * is given, then it will be used to access the file system. Otherwise a | 83 * is given, then it will be used to access the file system. Otherwise a |
| 76 * resource provider that accesses the physical file system will be used. | 84 * resource provider that accesses the physical file system will be used. |
| 77 */ | 85 */ |
| 78 ServerPlugin(this.resourceProvider) { | 86 ServerPlugin(this.resourceProvider) { |
| 79 analysisDriverScheduler = new AnalysisDriverScheduler(performanceLog); | 87 analysisDriverScheduler = new AnalysisDriverScheduler(performanceLog); |
| 88 analysisDriverScheduler.start(); |
| 80 } | 89 } |
| 81 | 90 |
| 82 /** | 91 /** |
| 92 * Return the byte store used by any analysis drivers that are created, or |
| 93 * `null` if the cache location isn't known because the 'plugin.version' |
| 94 * request has not yet been received. |
| 95 */ |
| 96 ByteStore get byteStore => _byteStore; |
| 97 |
| 98 /** |
| 83 * Return the communication channel being used to communicate with the | 99 * Return the communication channel being used to communicate with the |
| 84 * analysis server, or `null` if the plugin has not been started. | 100 * analysis server, or `null` if the plugin has not been started. |
| 85 */ | 101 */ |
| 86 PluginCommunicationChannel get channel => _channel; | 102 PluginCommunicationChannel get channel => _channel; |
| 87 | 103 |
| 88 /** | 104 /** |
| 89 * Return the user visible information about how to contact the plugin authors | 105 * Return the user visible information about how to contact the plugin authors |
| 90 * with any problems that are found, or `null` if there is no contact info. | 106 * with any problems that are found, or `null` if there is no contact info. |
| 91 */ | 107 */ |
| 92 String get contactInfo => null; | 108 String get contactInfo => null; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 108 String get version; | 124 String get version; |
| 109 | 125 |
| 110 /** | 126 /** |
| 111 * Handle the fact that the file with the given [path] has been modified. | 127 * Handle the fact that the file with the given [path] has been modified. |
| 112 */ | 128 */ |
| 113 void contentChanged(String path) { | 129 void contentChanged(String path) { |
| 114 // Ignore changes to files. | 130 // Ignore changes to files. |
| 115 } | 131 } |
| 116 | 132 |
| 117 /** | 133 /** |
| 134 * Return the context root containing the file at the given [filePath]. |
| 135 */ |
| 136 ContextRoot contextRootContaining(String filePath) { |
| 137 Context pathContext = resourceProvider.pathContext; |
| 138 |
| 139 /** |
| 140 * Return `true` if the given [child] is either the same as or within the |
| 141 * given [parent]. |
| 142 */ |
| 143 bool isOrWithin(String parent, String child) { |
| 144 return parent == child || pathContext.isWithin(parent, child); |
| 145 } |
| 146 |
| 147 /** |
| 148 * Return `true` if the given context [root] contains the target [file]. |
| 149 */ |
| 150 bool ownsFile(ContextRoot root) { |
| 151 if (isOrWithin(root.root, filePath)) { |
| 152 List<String> excludedPaths = root.exclude; |
| 153 for (String excludedPath in excludedPaths) { |
| 154 if (isOrWithin(excludedPath, filePath)) { |
| 155 return false; |
| 156 } |
| 157 } |
| 158 return true; |
| 159 } |
| 160 return false; |
| 161 } |
| 162 |
| 163 for (ContextRoot root in driverMap.keys) { |
| 164 if (ownsFile(root)) { |
| 165 return root; |
| 166 } |
| 167 } |
| 168 return null; |
| 169 } |
| 170 |
| 171 /** |
| 172 * Create an analysis driver that can analyze the files within the given |
| 173 * [contextRoot]. |
| 174 */ |
| 175 AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot); |
| 176 |
| 177 /** |
| 118 * Handle an 'analysis.handleWatchEvents' request. | 178 * Handle an 'analysis.handleWatchEvents' request. |
| 119 */ | 179 */ |
| 120 AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents( | 180 AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents( |
| 121 Map<String, Object> parameters) => | 181 AnalysisHandleWatchEventsParams parameters) => |
| 122 null; | 182 null; |
| 123 | 183 |
| 124 /** | 184 /** |
| 125 * Handle an 'analysis.reanalyze' request. | 185 * Handle an 'analysis.reanalyze' request. |
| 126 */ | 186 */ |
| 127 AnalysisReanalyzeResult handleAnalysisReanalyze( | 187 AnalysisReanalyzeResult handleAnalysisReanalyze( |
| 128 Map<String, Object> parameters) => | 188 AnalysisReanalyzeParams parameters) => |
| 129 null; | 189 null; |
| 130 | 190 |
| 131 /** | 191 /** |
| 132 * Handle an 'analysis.setContextBuilderOptions' request. | 192 * Handle an 'analysis.setContextBuilderOptions' request. |
| 133 */ | 193 */ |
| 134 AnalysisSetContextBuilderOptionsResult handleAnalysisSetContextBuilderOptions( | 194 AnalysisSetContextBuilderOptionsResult handleAnalysisSetContextBuilderOptions( |
| 135 Map<String, Object> parameters) => | 195 AnalysisSetContextBuilderOptionsParams parameters) => |
| 136 null; | 196 null; |
| 137 | 197 |
| 138 /** | 198 /** |
| 139 * Handle an 'analysis.setContextRoots' request. | 199 * Handle an 'analysis.setContextRoots' request. |
| 140 */ | 200 */ |
| 141 AnalysisSetContextRootsResult handleAnalysisSetContextRoots( | 201 AnalysisSetContextRootsResult handleAnalysisSetContextRoots( |
| 142 Map<String, Object> parameters) { | 202 AnalysisSetContextRootsParams parameters) { |
| 143 // TODO(brianwilkerson) Implement this so that implementors don't have to | 203 List<ContextRoot> contextRoots = parameters.roots; |
| 144 // figure out how to manage contexts. | 204 List<ContextRoot> oldRoots = driverMap.keys.toList(); |
| 145 return null; | 205 for (ContextRoot contextRoot in contextRoots) { |
| 206 if (!oldRoots.remove(contextRoot)) { |
| 207 // The context is new, so we create a driver for it. Creating the driver |
| 208 // has the side-effect of adding it to the analysis driver scheduler. |
| 209 AnalysisDriverGeneric driver = createAnalysisDriver(contextRoot); |
| 210 driverMap[contextRoot] = driver; |
| 211 } |
| 212 } |
| 213 for (ContextRoot contextRoot in oldRoots) { |
| 214 // The context has been removed, so we remove its driver. |
| 215 AnalysisDriverGeneric driver = driverMap.remove(contextRoot); |
| 216 // The `dispose` method has the side-effect of removing the driver from |
| 217 // the analysis driver scheduler. |
| 218 driver.dispose(); |
| 219 } |
| 220 return new AnalysisSetContextRootsResult(); |
| 146 } | 221 } |
| 147 | 222 |
| 148 /** | 223 /** |
| 149 * Handle an 'analysis.setPriorityFiles' request. | 224 * Handle an 'analysis.setPriorityFiles' request. |
| 150 */ | 225 */ |
| 151 AnalysisSetPriorityFilesResult handleAnalysisSetPriorityFiles( | 226 AnalysisSetPriorityFilesResult handleAnalysisSetPriorityFiles( |
| 152 Map<String, Object> parameters) => | 227 AnalysisSetPriorityFilesParams parameters) { |
| 153 new AnalysisSetPriorityFilesResult(); | 228 List<String> files = parameters.files; |
| 229 Map<AnalysisDriverGeneric, List<String>> filesByDriver = |
| 230 <AnalysisDriverGeneric, List<String>>{}; |
| 231 for (String file in files) { |
| 232 ContextRoot contextRoot = contextRootContaining(file); |
| 233 if (contextRoot != null) { |
| 234 // TODO(brianwilkerson) Which driver should we use if there is no contex
t root? |
| 235 AnalysisDriverGeneric driver = driverMap[contextRoot]; |
| 236 filesByDriver.putIfAbsent(driver, () => <String>[]).add(file); |
| 237 } |
| 238 } |
| 239 filesByDriver.forEach((AnalysisDriverGeneric driver, List<String> files) { |
| 240 driver.priorityFiles = files; |
| 241 }); |
| 242 return new AnalysisSetPriorityFilesResult(); |
| 243 } |
| 154 | 244 |
| 155 /** | 245 /** |
| 156 * Handle an 'analysis.setSubscriptions' request. Most subclasses should not | 246 * Handle an 'analysis.setSubscriptions' request. Most subclasses should not |
| 157 * override this method, but should instead use the [subscriptionManager] to | 247 * override this method, but should instead use the [subscriptionManager] to |
| 158 * access the list of subscriptions for any given file. | 248 * access the list of subscriptions for any given file. |
| 159 */ | 249 */ |
| 160 AnalysisSetSubscriptionsResult handleAnalysisSetSubscriptions( | 250 AnalysisSetSubscriptionsResult handleAnalysisSetSubscriptions( |
| 161 Map<String, Object> parameters) { | 251 AnalysisSetSubscriptionsParams parameters) { |
| 162 Map<AnalysisService, List<String>> subscriptions = validateParameter( | 252 Map<AnalysisService, List<String>> subscriptions = parameters.subscriptions; |
| 163 parameters, | |
| 164 ANALYSIS_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS, | |
| 165 'analysis.setSubscriptions'); | |
| 166 subscriptionManager.setSubscriptions(subscriptions); | 253 subscriptionManager.setSubscriptions(subscriptions); |
| 167 // TODO(brianwilkerson) Cause any newly subscribed for notifications to be s
ent. | 254 // TODO(brianwilkerson) Cause any newly subscribed for notifications to be s
ent. |
| 168 return new AnalysisSetSubscriptionsResult(); | 255 return new AnalysisSetSubscriptionsResult(); |
| 169 } | 256 } |
| 170 | 257 |
| 171 /** | 258 /** |
| 172 * Handle an 'analysis.updateContent' request. Most subclasses should not | 259 * Handle an 'analysis.updateContent' request. Most subclasses should not |
| 173 * override this method, but should instead use the [contentCache] to access | 260 * override this method, but should instead use the [contentCache] to access |
| 174 * the current content of overlaid files. | 261 * the current content of overlaid files. |
| 175 */ | 262 */ |
| 176 AnalysisUpdateContentResult handleAnalysisUpdateContent( | 263 AnalysisUpdateContentResult handleAnalysisUpdateContent( |
| 177 Map<String, Object> parameters) { | 264 AnalysisUpdateContentParams parameters) { |
| 178 Map<String, Object> files = validateParameter(parameters, | 265 Map<String, Object> files = parameters.files; |
| 179 ANALYSIS_REQUEST_UPDATE_CONTENT_FILES, 'analysis.updateContent'); | |
| 180 files.forEach((String filePath, Object overlay) { | 266 files.forEach((String filePath, Object overlay) { |
| 181 // We don't need to get the correct URI because only the full path is | 267 // We don't need to get the correct URI because only the full path is |
| 182 // used by the contentCache. | 268 // used by the contentCache. |
| 183 Source source = resourceProvider.getFile(filePath).createSource(); | 269 Source source = resourceProvider.getFile(filePath).createSource(); |
| 184 if (overlay is AddContentOverlay) { | 270 if (overlay is AddContentOverlay) { |
| 185 fileContentOverlay[source.fullName] = overlay.content; | 271 fileContentOverlay[source.fullName] = overlay.content; |
| 186 } else if (overlay is ChangeContentOverlay) { | 272 } else if (overlay is ChangeContentOverlay) { |
| 187 String fileName = source.fullName; | 273 String fileName = source.fullName; |
| 188 String oldContents = fileContentOverlay[fileName]; | 274 String oldContents = fileContentOverlay[fileName]; |
| 189 String newContents; | 275 String newContents; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 207 } | 293 } |
| 208 contentChanged(filePath); | 294 contentChanged(filePath); |
| 209 }); | 295 }); |
| 210 return new AnalysisUpdateContentResult(); | 296 return new AnalysisUpdateContentResult(); |
| 211 } | 297 } |
| 212 | 298 |
| 213 /** | 299 /** |
| 214 * Handle a 'completion.getSuggestions' request. | 300 * Handle a 'completion.getSuggestions' request. |
| 215 */ | 301 */ |
| 216 CompletionGetSuggestionsResult handleCompletionGetSuggestions( | 302 CompletionGetSuggestionsResult handleCompletionGetSuggestions( |
| 217 Map<String, Object> parameters) => | 303 CompletionGetSuggestionsParams parameters) => |
| 218 new CompletionGetSuggestionsResult( | 304 new CompletionGetSuggestionsResult( |
| 219 -1, -1, const <CompletionSuggestion>[]); | 305 -1, -1, const <CompletionSuggestion>[]); |
| 220 | 306 |
| 221 /** | 307 /** |
| 222 * Handle an 'edit.getAssists' request. | 308 * Handle an 'edit.getAssists' request. |
| 223 */ | 309 */ |
| 224 EditGetAssistsResult handleEditGetAssists(Map<String, Object> parameters) => | 310 EditGetAssistsResult handleEditGetAssists(EditGetAssistsParams parameters) => |
| 225 new EditGetAssistsResult(const <PrioritizedSourceChange>[]); | 311 new EditGetAssistsResult(const <PrioritizedSourceChange>[]); |
| 226 | 312 |
| 227 /** | 313 /** |
| 228 * Handle an 'edit.getAvailableRefactorings' request. Subclasses that override | 314 * Handle an 'edit.getAvailableRefactorings' request. Subclasses that override |
| 229 * this method in order to participate in refactorings must also override the | 315 * this method in order to participate in refactorings must also override the |
| 230 * method [handleEditGetRefactoring]. | 316 * method [handleEditGetRefactoring]. |
| 231 */ | 317 */ |
| 232 EditGetAvailableRefactoringsResult handleEditGetAvailableRefactorings( | 318 EditGetAvailableRefactoringsResult handleEditGetAvailableRefactorings( |
| 233 Map<String, Object> parameters) => | 319 EditGetAvailableRefactoringsParams parameters) => |
| 234 new EditGetAvailableRefactoringsResult(const <RefactoringKind>[]); | 320 new EditGetAvailableRefactoringsResult(const <RefactoringKind>[]); |
| 235 | 321 |
| 236 /** | 322 /** |
| 237 * Handle an 'edit.getFixes' request. | 323 * Handle an 'edit.getFixes' request. |
| 238 */ | 324 */ |
| 239 EditGetFixesResult handleEditGetFixes(Map<String, Object> parameters) => | 325 EditGetFixesResult handleEditGetFixes(EditGetFixesParams parameters) => |
| 240 new EditGetFixesResult(const <AnalysisErrorFixes>[]); | 326 new EditGetFixesResult(const <AnalysisErrorFixes>[]); |
| 241 | 327 |
| 242 /** | 328 /** |
| 243 * Handle an 'edit.getRefactoring' request. | 329 * Handle an 'edit.getRefactoring' request. |
| 244 */ | 330 */ |
| 245 EditGetRefactoringResult handleEditGetRefactoring( | 331 EditGetRefactoringResult handleEditGetRefactoring( |
| 246 Map<String, Object> parameters) => | 332 EditGetRefactoringParams parameters) => |
| 247 null; | 333 null; |
| 248 | 334 |
| 249 /** | 335 /** |
| 250 * Handle a 'plugin.shutdown' request. Subclasses can override this method to | 336 * Handle a 'plugin.shutdown' request. Subclasses can override this method to |
| 251 * perform any required clean-up, but cannot prevent the plugin from shutting | 337 * perform any required clean-up, but cannot prevent the plugin from shutting |
| 252 * down. | 338 * down. |
| 253 */ | 339 */ |
| 254 PluginShutdownResult handlePluginShutdown(Map<String, Object> parameters) => | 340 PluginShutdownResult handlePluginShutdown(PluginShutdownParams parameters) => |
| 255 new PluginShutdownResult(); | 341 new PluginShutdownResult(); |
| 256 | 342 |
| 257 /** | 343 /** |
| 258 * Handle a 'plugin.versionCheck' request. | 344 * Handle a 'plugin.versionCheck' request. |
| 259 */ | 345 */ |
| 260 PluginVersionCheckResult handlePluginVersionCheck( | 346 PluginVersionCheckResult handlePluginVersionCheck( |
| 261 Map<String, Object> parameters) { | 347 PluginVersionCheckParams parameters) { |
| 262 String byteStorePath = validateParameter(parameters, | 348 String byteStorePath = parameters.byteStorePath; |
| 263 PLUGIN_REQUEST_VERSION_CHECK_BYTESTOREPATH, 'plugin.versionCheck'); | 349 String versionString = parameters.version; |
| 264 String versionString = validateParameter(parameters, | |
| 265 PLUGIN_REQUEST_VERSION_CHECK_VERSION, 'plugin.versionCheck'); | |
| 266 Version serverVersion = new Version.parse(versionString); | 350 Version serverVersion = new Version.parse(versionString); |
| 267 _byteStore = | 351 _byteStore = |
| 268 new MemoryCachingByteStore(new FileByteStore(byteStorePath), 64 * M); | 352 new MemoryCachingByteStore(new FileByteStore(byteStorePath), 64 * M); |
| 269 return new PluginVersionCheckResult( | 353 return new PluginVersionCheckResult( |
| 270 isCompatibleWith(serverVersion), name, version, fileGlobsToAnalyze, | 354 isCompatibleWith(serverVersion), name, version, fileGlobsToAnalyze, |
| 271 contactInfo: contactInfo); | 355 contactInfo: contactInfo); |
| 272 } | 356 } |
| 273 | 357 |
| 274 /** | 358 /** |
| 275 * Return `true` if this plugin is compatible with an analysis server that is | 359 * Return `true` if this plugin is compatible with an analysis server that is |
| (...skipping 13 matching lines...) Expand all Loading... |
| 289 /** | 373 /** |
| 290 * The method that is called when an error has occurred in the analysis | 374 * The method that is called when an error has occurred in the analysis |
| 291 * server. This method will not be invoked under normal conditions. | 375 * server. This method will not be invoked under normal conditions. |
| 292 */ | 376 */ |
| 293 void onError(Object exception, StackTrace stackTrace) {} | 377 void onError(Object exception, StackTrace stackTrace) {} |
| 294 | 378 |
| 295 /** | 379 /** |
| 296 * Start this plugin by listening to the given communication [channel]. | 380 * Start this plugin by listening to the given communication [channel]. |
| 297 */ | 381 */ |
| 298 void start(PluginCommunicationChannel channel) { | 382 void start(PluginCommunicationChannel channel) { |
| 299 this._channel = channel; | 383 _channel = channel; |
| 300 _channel.listen(_onRequest, onError: onError, onDone: onDone); | 384 _channel.listen(_onRequest, onError: onError, onDone: onDone); |
| 301 } | 385 } |
| 302 | 386 |
| 303 /** | 387 /** |
| 304 * Validate that the value in the map of [parameters] at the given [key] is of | |
| 305 * the type [T]. If it is, return it. Otherwise throw a [RequestFailure] that | |
| 306 * will cause an error to be returned to the server. | |
| 307 */ | |
| 308 Object/*=T*/ validateParameter/*<T>*/( | |
| 309 Map<String, Object> parameters, String key, String requestName) { | |
| 310 Object value = parameters[key]; | |
| 311 // ignore: type_annotation_generic_function_parameter | |
| 312 if (value is Object/*=T*/) { | |
| 313 return value; | |
| 314 } | |
| 315 String message; | |
| 316 if (value == null) { | |
| 317 message = 'Missing parameter $key in $requestName'; | |
| 318 } else { | |
| 319 message = 'Invalid value for $key in $requestName (${value.runtimeType})'; | |
| 320 } | |
| 321 throw new RequestFailure( | |
| 322 new RequestError(RequestErrorCode.INVALID_PARAMETER, message)); | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * Compute the response that should be returned for the given [request], or | 388 * Compute the response that should be returned for the given [request], or |
| 327 * `null` if the response has already been sent. | 389 * `null` if the response has already been sent. |
| 328 */ | 390 */ |
| 329 Response _getResponse(Request request) { | 391 Response _getResponse(Request request) { |
| 330 ResponseResult result = null; | 392 ResponseResult result = null; |
| 331 switch (request.method) { | 393 switch (request.method) { |
| 332 case ANALYSIS_REQUEST_HANDLE_WATCH_EVENTS: | 394 case ANALYSIS_REQUEST_HANDLE_WATCH_EVENTS: |
| 333 result = handleAnalysisHandleWatchEvents(request.params); | 395 var params = new AnalysisHandleWatchEventsParams.fromRequest(request); |
| 396 result = handleAnalysisHandleWatchEvents(params); |
| 334 break; | 397 break; |
| 335 case ANALYSIS_REQUEST_REANALYZE: | 398 case ANALYSIS_REQUEST_REANALYZE: |
| 336 result = handleAnalysisReanalyze(request.params); | 399 var params = new AnalysisReanalyzeParams.fromRequest(request); |
| 400 result = handleAnalysisReanalyze(params); |
| 337 break; | 401 break; |
| 338 case ANALYSIS_REQUEST_SET_CONTEXT_BUILDER_OPTIONS: | 402 case ANALYSIS_REQUEST_SET_CONTEXT_BUILDER_OPTIONS: |
| 339 result = handleAnalysisSetContextBuilderOptions(request.params); | 403 var params = |
| 404 new AnalysisSetContextBuilderOptionsParams.fromRequest(request); |
| 405 result = handleAnalysisSetContextBuilderOptions(params); |
| 340 break; | 406 break; |
| 341 case ANALYSIS_REQUEST_SET_CONTEXT_ROOTS: | 407 case ANALYSIS_REQUEST_SET_CONTEXT_ROOTS: |
| 342 result = handleAnalysisSetContextRoots(request.params); | 408 var params = new AnalysisSetContextRootsParams.fromRequest(request); |
| 409 result = handleAnalysisSetContextRoots(params); |
| 343 break; | 410 break; |
| 344 case ANALYSIS_REQUEST_SET_PRIORITY_FILES: | 411 case ANALYSIS_REQUEST_SET_PRIORITY_FILES: |
| 345 result = handleAnalysisSetPriorityFiles(request.params); | 412 var params = new AnalysisSetPriorityFilesParams.fromRequest(request); |
| 413 result = handleAnalysisSetPriorityFiles(params); |
| 346 break; | 414 break; |
| 347 case ANALYSIS_REQUEST_SET_SUBSCRIPTIONS: | 415 case ANALYSIS_REQUEST_SET_SUBSCRIPTIONS: |
| 348 result = handleAnalysisSetSubscriptions(request.params); | 416 var params = new AnalysisSetSubscriptionsParams.fromRequest(request); |
| 417 result = handleAnalysisSetSubscriptions(params); |
| 349 break; | 418 break; |
| 350 case ANALYSIS_REQUEST_UPDATE_CONTENT: | 419 case ANALYSIS_REQUEST_UPDATE_CONTENT: |
| 351 result = handleAnalysisUpdateContent(request.params); | 420 var params = new AnalysisUpdateContentParams.fromRequest(request); |
| 421 result = handleAnalysisUpdateContent(params); |
| 352 break; | 422 break; |
| 353 case COMPLETION_REQUEST_GET_SUGGESTIONS: | 423 case COMPLETION_REQUEST_GET_SUGGESTIONS: |
| 354 result = handleCompletionGetSuggestions(request.params); | 424 var params = new CompletionGetSuggestionsParams.fromRequest(request); |
| 425 result = handleCompletionGetSuggestions(params); |
| 355 break; | 426 break; |
| 356 case EDIT_REQUEST_GET_ASSISTS: | 427 case EDIT_REQUEST_GET_ASSISTS: |
| 357 result = handleEditGetAssists(request.params); | 428 var params = new EditGetAssistsParams.fromRequest(request); |
| 429 result = handleEditGetAssists(params); |
| 358 break; | 430 break; |
| 359 case EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS: | 431 case EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS: |
| 360 result = handleEditGetAvailableRefactorings(request.params); | 432 var params = |
| 433 new EditGetAvailableRefactoringsParams.fromRequest(request); |
| 434 result = handleEditGetAvailableRefactorings(params); |
| 361 break; | 435 break; |
| 362 case EDIT_REQUEST_GET_FIXES: | 436 case EDIT_REQUEST_GET_FIXES: |
| 363 result = handleEditGetFixes(request.params); | 437 var params = new EditGetFixesParams.fromRequest(request); |
| 438 result = handleEditGetFixes(params); |
| 364 break; | 439 break; |
| 365 case EDIT_REQUEST_GET_REFACTORING: | 440 case EDIT_REQUEST_GET_REFACTORING: |
| 366 result = handleEditGetRefactoring(request.params); | 441 var params = new EditGetRefactoringParams.fromRequest(request); |
| 442 result = handleEditGetRefactoring(params); |
| 367 break; | 443 break; |
| 368 case PLUGIN_REQUEST_SHUTDOWN: | 444 case PLUGIN_REQUEST_SHUTDOWN: |
| 369 result = handlePluginShutdown(request.params); | 445 var params = new PluginShutdownParams(); |
| 446 result = handlePluginShutdown(params); |
| 370 _channel.sendResponse(result.toResponse(request.id)); | 447 _channel.sendResponse(result.toResponse(request.id)); |
| 371 _channel.close(); | 448 _channel.close(); |
| 372 return null; | 449 return null; |
| 373 case PLUGIN_REQUEST_VERSION_CHECK: | 450 case PLUGIN_REQUEST_VERSION_CHECK: |
| 374 result = handlePluginVersionCheck(request.params); | 451 var params = new PluginVersionCheckParams.fromRequest(request); |
| 452 result = handlePluginVersionCheck(params); |
| 375 break; | 453 break; |
| 376 } | 454 } |
| 377 if (result == null) { | 455 if (result == null) { |
| 378 return new Response(request.id, | 456 return new Response(request.id, |
| 379 error: RequestErrorFactory.unknownRequest(request)); | 457 error: RequestErrorFactory.unknownRequest(request)); |
| 380 } | 458 } |
| 381 return result.toResponse(request.id); | 459 return result.toResponse(request.id); |
| 382 } | 460 } |
| 383 | 461 |
| 384 /** | 462 /** |
| (...skipping 11 matching lines...) Expand all Loading... |
| 396 response = new Response(id, | 474 response = new Response(id, |
| 397 error: new RequestError( | 475 error: new RequestError( |
| 398 RequestErrorCode.PLUGIN_ERROR, exception.toString(), | 476 RequestErrorCode.PLUGIN_ERROR, exception.toString(), |
| 399 stackTrace: stackTrace.toString())); | 477 stackTrace: stackTrace.toString())); |
| 400 } | 478 } |
| 401 if (response != null) { | 479 if (response != null) { |
| 402 _channel.sendResponse(response); | 480 _channel.sendResponse(response); |
| 403 } | 481 } |
| 404 } | 482 } |
| 405 } | 483 } |
| OLD | NEW |