| 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 | 8 |
| 9 import 'package:analysis_server/src/analysis_logger.dart'; | 9 import 'package:analysis_server/src/analysis_logger.dart'; |
| 10 import 'package:analysis_server/src/channel.dart'; | 10 import 'package:analysis_server/src/channel.dart'; |
| 11 import 'package:analysis_server/src/constants.dart'; | 11 import 'package:analysis_server/src/constants.dart'; |
| 12 import 'package:analysis_server/src/context_directory_manager.dart'; | 12 import 'package:analysis_server/src/context_directory_manager.dart'; |
| 13 import 'package:analysis_server/src/domain_analysis.dart'; | 13 import 'package:analysis_server/src/domain_analysis.dart'; |
| 14 import 'package:analysis_server/src/operation/operation.dart'; |
| 15 import 'package:analysis_server/src/operation/operation_queue.dart'; |
| 14 import 'package:analysis_server/src/protocol.dart'; | 16 import 'package:analysis_server/src/protocol.dart'; |
| 15 import 'package:analysis_server/src/resource.dart'; | 17 import 'package:analysis_server/src/resource.dart'; |
| 16 import 'package:analyzer/src/generated/ast.dart'; | 18 import 'package:analyzer/src/generated/ast.dart'; |
| 17 import 'package:analyzer/src/generated/engine.dart'; | 19 import 'package:analyzer/src/generated/engine.dart'; |
| 18 import 'package:analyzer/src/generated/error.dart'; | 20 import 'package:analyzer/src/generated/error.dart'; |
| 19 import 'package:analyzer/src/generated/java_core.dart'; | 21 import 'package:analyzer/src/generated/java_core.dart'; |
| 20 import 'package:analyzer/src/generated/source.dart'; | 22 import 'package:analyzer/src/generated/source.dart'; |
| 21 import 'package:analyzer/src/generated/sdk.dart'; | 23 import 'package:analyzer/src/generated/sdk.dart'; |
| 22 import 'package:analyzer/src/generated/sdk_io.dart'; | 24 import 'package:analyzer/src/generated/sdk_io.dart'; |
| 23 import 'package:analyzer/src/generated/source_io.dart'; | 25 import 'package:analyzer/src/generated/source_io.dart'; |
| 24 import 'package:analysis_server/src/computers.dart'; | 26 import 'package:analysis_server/src/computers.dart'; |
| 25 | 27 |
| 26 | 28 |
| 27 /** | 29 /** |
| 28 * An instance of [DirectoryBasedDartSdk] that is shared between | 30 * An instance of [DirectoryBasedDartSdk] that is shared between |
| 29 * [AnalysisServer] instances to improve performance. | 31 * [AnalysisServer] instances to improve performance. |
| 30 */ | 32 */ |
| 31 final DirectoryBasedDartSdk SHARED_SDK = DirectoryBasedDartSdk.defaultSdk; | 33 final DirectoryBasedDartSdk SHARED_SDK = DirectoryBasedDartSdk.defaultSdk; |
| 32 | 34 |
| 33 class AnalysisServerContextDirectoryManager extends ContextDirectoryManager { | 35 class AnalysisServerContextDirectoryManager extends ContextDirectoryManager { |
| 34 final AnalysisServer analysisServer; | 36 final AnalysisServer analysisServer; |
| 35 | 37 |
| 36 AnalysisServerContextDirectoryManager(this.analysisServer, ResourceProvider re
sourceProvider) | 38 AnalysisServerContextDirectoryManager(this.analysisServer, ResourceProvider re
sourceProvider) |
| 37 : super(resourceProvider); | 39 : super(resourceProvider); |
| 38 | 40 |
| 39 void addContext(Folder folder, File pubspecFile) { | 41 void addContext(Folder folder, File pubspecFile) { |
| 40 ContextDirectory contextDirectory = new ContextDirectory( | 42 ContextDirectory contextDirectory = new ContextDirectory( |
| 41 analysisServer.defaultSdk, folder, pubspecFile); | 43 analysisServer.defaultSdk, folder, pubspecFile); |
| 42 analysisServer.folderMap[folder] = contextDirectory; | 44 analysisServer.folderMap[folder] = contextDirectory; |
| 43 analysisServer.addContextToWorkQueue(contextDirectory.context); | 45 analysisServer.schedulePerformAnalysisOperation(contextDirectory.context); |
| 44 } | 46 } |
| 45 | 47 |
| 46 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { | 48 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
| 47 analysisServer.folderMap[contextFolder].context.applyChanges(changeSet); | 49 analysisServer.folderMap[contextFolder].context.applyChanges(changeSet); |
| 48 } | 50 } |
| 49 } | 51 } |
| 50 | 52 |
| 51 /** | 53 /** |
| 52 * Instances of the class [AnalysisServer] implement a server that listens on a | 54 * Instances of the class [AnalysisServer] implement a server that listens on a |
| 53 * [CommunicationChannel] for analysis requests and process them. | 55 * [CommunicationChannel] for analysis requests and process them. |
| 54 */ | 56 */ |
| 55 class AnalysisServer { | 57 class AnalysisServer { |
| 56 /** | 58 /** |
| 57 * The channel from which requests are received and to which responses should | 59 * The channel from which requests are received and to which responses should |
| 58 * be sent. | 60 * be sent. |
| 59 */ | 61 */ |
| 60 final ServerCommunicationChannel channel; | 62 final ServerCommunicationChannel channel; |
| 61 | 63 |
| 62 /** | 64 /** |
| 63 * [ContextDirectoryManager] which handles the mapping from analysis roots | 65 * [ContextDirectoryManager] which handles the mapping from analysis roots |
| 64 * to context directories. | 66 * to context directories. |
| 65 */ | 67 */ |
| 66 AnalysisServerContextDirectoryManager contextDirectoryManager; | 68 AnalysisServerContextDirectoryManager contextDirectoryManager; |
| 67 | 69 |
| 68 /** | 70 /** |
| 69 * A flag indicating whether the server is running. When false, contexts | 71 * A flag indicating whether the server is running. When false, contexts |
| 70 * will no longer be added to [contextWorkQueue], and [performTask] will | 72 * will no longer be added to [contextWorkQueue], and [performOperation] will |
| 71 * discard any tasks it finds on [contextWorkQueue]. | 73 * discard any tasks it finds on [contextWorkQueue]. |
| 72 */ | 74 */ |
| 73 bool running; | 75 bool running; |
| 74 | 76 |
| 75 /** | 77 /** |
| 76 * A list of the request handlers used to handle the requests sent to this | 78 * A list of the request handlers used to handle the requests sent to this |
| 77 * server. | 79 * server. |
| 78 */ | 80 */ |
| 79 List<RequestHandler> handlers; | 81 List<RequestHandler> handlers; |
| 80 | 82 |
| 81 // TODO(scheglov) remove once setAnalysisRoots() is completely implemented | |
| 82 // /** | |
| 83 // * A table mapping context id's to the analysis contexts associated with the
m. | |
| 84 // */ | |
| 85 // final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisCont
ext>(); | |
| 86 // | |
| 87 // /** | |
| 88 // * A table mapping analysis contexts to the context id's associated with the
m. | |
| 89 // */ | |
| 90 // final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, S
tring>(); | |
| 91 | |
| 92 /** | 83 /** |
| 93 * The current default [DartSdk]. | 84 * The current default [DartSdk]. |
| 94 */ | 85 */ |
| 95 DartSdk defaultSdk = SHARED_SDK; | 86 DartSdk defaultSdk = SHARED_SDK; |
| 96 | 87 |
| 97 /** | 88 /** |
| 98 * A table mapping [Folder]s to the [ContextDirectory]s associated with them. | 89 * A table mapping [Folder]s to the [ContextDirectory]s associated with them. |
| 99 */ | 90 */ |
| 100 final Map<Folder, ContextDirectory> folderMap = <Folder, ContextDirectory>{}; | 91 final Map<Folder, ContextDirectory> folderMap = <Folder, ContextDirectory>{}; |
| 101 | 92 |
| 102 /** | 93 /** |
| 103 * The context identifier used in the last status notification. | 94 * A queue of the operations to perform in this server. |
| 95 * |
| 96 * Invariant: when this queue is non-empty, there is exactly one pending call |
| 97 * to [performOperation] on the event queue. When this list is empty, there a
re |
| 98 * no calls to [performOperation] on the event queue. |
| 104 */ | 99 */ |
| 105 String lastStatusNotificationContextId = null; | 100 ServerOperationQueue operationQueue; |
| 106 | |
| 107 /** | |
| 108 * A list of the analysis contexts for which analysis work needs to be | |
| 109 * performed. | |
| 110 * | |
| 111 * Invariant: when this list is non-empty, there is exactly one pending call | |
| 112 * to [performTask] on the event queue. When this list is empty, there are | |
| 113 * no calls to [performTask] on the event queue. | |
| 114 */ | |
| 115 final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); | |
| 116 | 101 |
| 117 /** | 102 /** |
| 118 * A set of the [ServerService]s to send notifications for. | 103 * A set of the [ServerService]s to send notifications for. |
| 119 */ | 104 */ |
| 120 Set<ServerService> serverServices = new Set<ServerService>(); | 105 Set<ServerService> serverServices = new Set<ServerService>(); |
| 121 | 106 |
| 122 /** | 107 /** |
| 123 * A table mapping [AnalysisService]s to the file paths for which these | 108 * A table mapping [AnalysisService]s to the file paths for which these |
| 124 * notifications should be sent. | 109 * notifications should be sent. |
| 125 */ | 110 */ |
| 126 Map<AnalysisService, Set<String>> analysisServices = <AnalysisService, Set<Str
ing>>{}; | 111 Map<AnalysisService, Set<String>> analysisServices = <AnalysisService, Set<Str
ing>>{}; |
| 127 | 112 |
| 128 /** | 113 /** |
| 129 * Initialize a newly created server to receive requests from and send | 114 * Initialize a newly created server to receive requests from and send |
| 130 * responses to the given [channel]. | 115 * responses to the given [channel]. |
| 131 */ | 116 */ |
| 132 AnalysisServer(this.channel, ResourceProvider resourceProvider) { | 117 AnalysisServer(this.channel, ResourceProvider resourceProvider) { |
| 118 operationQueue = new ServerOperationQueue(this); |
| 133 contextDirectoryManager = new AnalysisServerContextDirectoryManager(this, re
sourceProvider); | 119 contextDirectoryManager = new AnalysisServerContextDirectoryManager(this, re
sourceProvider); |
| 134 AnalysisEngine.instance.logger = new AnalysisLogger(); | 120 AnalysisEngine.instance.logger = new AnalysisLogger(); |
| 135 running = true; | 121 running = true; |
| 136 Notification notification = new Notification(NOTIFICATION_CONNECTED); | 122 Notification notification = new Notification(NOTIFICATION_CONNECTED); |
| 137 channel.sendNotification(notification); | 123 channel.sendNotification(notification); |
| 138 channel.listen(handleRequest, onDone: done, onError: error); | 124 channel.listen(handleRequest, onDone: done, onError: error); |
| 139 } | 125 } |
| 140 | 126 |
| 141 /** | 127 /** |
| 142 * If [running] is true, add the given [context] to the list of analysis | 128 * Schedules analysis of the given context. |
| 143 * contexts for which analysis work needs to be performed, and ensure that | |
| 144 * the work will be performed. | |
| 145 */ | 129 */ |
| 146 void addContextToWorkQueue(AnalysisContext context) { | 130 void schedulePerformAnalysisOperation(AnalysisContext context) { |
| 147 if (!running) { | 131 scheduleOperation(new PerformAnalysisOperation(context, false)); |
| 148 return; | 132 } |
| 149 } | 133 |
| 150 if (!contextWorkQueue.contains(context)) { | 134 /** |
| 151 contextWorkQueue.add(context); | 135 * Schedules execution of the given [ServerOperation]. |
| 152 if (contextWorkQueue.length == 1) { | 136 */ |
| 153 // Work queue was previously empty, so schedule analysis. | 137 void scheduleOperation(ServerOperation operation) { |
| 154 _scheduleTask(); | 138 bool wasEmpty = operationQueue.isEmpty; |
| 155 } | 139 operationQueue.add(operation); |
| 140 if (wasEmpty) { |
| 141 _schedulePerformOperation(); |
| 156 } | 142 } |
| 157 } | 143 } |
| 158 | 144 |
| 159 /** | 145 /** |
| 160 * The socket from which requests are being read has been closed. | 146 * The socket from which requests are being read has been closed. |
| 161 */ | 147 */ |
| 162 void done() { | 148 void done() { |
| 163 running = false; | 149 running = false; |
| 164 } | 150 } |
| 165 | 151 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 185 } | 171 } |
| 186 } on RequestFailure catch (exception) { | 172 } on RequestFailure catch (exception) { |
| 187 channel.sendResponse(exception.response); | 173 channel.sendResponse(exception.response); |
| 188 return; | 174 return; |
| 189 } | 175 } |
| 190 } | 176 } |
| 191 channel.sendResponse(new Response.unknownRequest(request)); | 177 channel.sendResponse(new Response.unknownRequest(request)); |
| 192 } | 178 } |
| 193 | 179 |
| 194 /** | 180 /** |
| 195 * Perform the next available task. If a request was received that has not yet | 181 * Returns `true` if the given [AnalysisContext] is a priority one. |
| 196 * been performed, perform it next. Otherwise, look for some analysis that | |
| 197 * needs to be done and do that. Otherwise, do nothing. | |
| 198 */ | 182 */ |
| 199 void performTask() { | 183 bool isPriorityContext(AnalysisContext context) { |
| 184 // TODO(scheglov) implement support for priority sources/contexts |
| 185 return false; |
| 186 } |
| 187 |
| 188 /** |
| 189 * Perform the next available [ServerOperation]. |
| 190 */ |
| 191 void performOperation() { |
| 200 if (!running) { | 192 if (!running) { |
| 201 // An error has occurred, or the connection to the client has been | 193 // An error has occurred, or the connection to the client has been |
| 202 // closed, since performTask() was scheduled on the event queue. So | 194 // closed, since this method was scheduled on the event queue. So |
| 203 // don't do any analysis. Instead clear the work queue. | 195 // don't do anything. Instead clear the operation queue. |
| 204 contextWorkQueue.clear(); | 196 operationQueue.clear(); |
| 205 } | |
| 206 if (contextWorkQueue.isEmpty) { | |
| 207 // Nothing to do. | |
| 208 return; | 197 return; |
| 209 } | 198 } |
| 210 // | 199 // prepare next operation |
| 211 // Look for a context that has work to be done and then perform one task. | 200 ServerOperation operation = operationQueue.take(); |
| 212 // | 201 // perform the operation |
| 213 List<ChangeNotice> notices = null; | |
| 214 try { | 202 try { |
| 215 AnalysisContext context = contextWorkQueue[0]; | 203 operation.perform(this); |
| 216 // | 204 } catch (e) { |
| 217 // TODO(brianwilkerson) Add an optional function-valued parameter to | 205 // TODO(scheglov) decide how to handle exceptions |
| 218 // performAnalysisTask that will be called when the task has been computed | |
| 219 // but before it is performed and send notification in the function: | |
| 220 // | |
| 221 // AnalysisResult result = context.performAnalysisTask((taskDescription) { | |
| 222 // sendStatusNotification(context.toString(), taskDescription); | |
| 223 // }); | |
| 224 // | |
| 225 sendStatusNotification(context.toString()); | |
| 226 AnalysisResult result = context.performAnalysisTask(); | |
| 227 notices = result.changeNotices; | |
| 228 } finally { | 206 } finally { |
| 229 if (notices == null) { | 207 if (!operationQueue.isEmpty) { |
| 230 // Either we have no more work to do for this context, or there was an | 208 _schedulePerformOperation(); |
| 231 // unhandled exception trying to perform the analysis. In either case, | |
| 232 // remove the context form the work queue so we won't try to do more | |
| 233 // analysis on it. | |
| 234 contextWorkQueue.removeAt(0); | |
| 235 } else { | 209 } else { |
| 236 sendNotices(notices); | |
| 237 } | |
| 238 // | |
| 239 // Schedule this method to be run again if there is any more work to be | |
| 240 // done. | |
| 241 // | |
| 242 if (contextWorkQueue.isEmpty) { | |
| 243 sendStatusNotification(null); | 210 sendStatusNotification(null); |
| 244 } else { | |
| 245 _scheduleTask(); | |
| 246 } | 211 } |
| 247 } | 212 } |
| 248 } | 213 } |
| 249 | 214 |
| 250 /** | 215 /** |
| 216 * Perform analysis in the given [AnalysisContext]. |
| 217 */ |
| 218 void internalPerformAnalysis(AnalysisContext context) { |
| 219 // |
| 220 // TODO(brianwilkerson) Add an optional function-valued parameter to |
| 221 // performAnalysisTask that will be called when the task has been computed |
| 222 // but before it is performed and send notification in the function: |
| 223 // |
| 224 // AnalysisResult result = context.performAnalysisTask((taskDescription) { |
| 225 // sendStatusNotification(context.toString(), taskDescription); |
| 226 // }); |
| 227 // prepare results |
| 228 AnalysisResult result = context.performAnalysisTask(); |
| 229 List<ChangeNotice> notices = result.changeNotices; |
| 230 if (notices == null) { |
| 231 return; |
| 232 } |
| 233 // TODO(scheglov) remember known sources |
| 234 // TODO(scheglov) index units |
| 235 // TODO(scheglov) schedule notifications |
| 236 sendNotices(notices); |
| 237 // continue analysis |
| 238 operationQueue.add(new PerformAnalysisOperation(context, true)); |
| 239 } |
| 240 |
| 241 /** |
| 251 * Send the information in the given list of notices back to the client. | 242 * Send the information in the given list of notices back to the client. |
| 252 */ | 243 */ |
| 253 void sendNotices(List<ChangeNotice> notices) { | 244 void sendNotices(List<ChangeNotice> notices) { |
| 254 for (int i = 0; i < notices.length; i++) { | 245 for (int i = 0; i < notices.length; i++) { |
| 255 ChangeNotice notice = notices[i]; | 246 ChangeNotice notice = notices[i]; |
| 256 Source source = notice.source; | 247 Source source = notice.source; |
| 257 CompilationUnit dartUnit = notice.compilationUnit; | 248 CompilationUnit dartUnit = notice.compilationUnit; |
| 258 // TODO(scheglov) use default subscriptions | 249 // TODO(scheglov) use default subscriptions |
| 259 String file = source.fullName; | 250 String file = source.fullName; |
| 260 if (dartUnit != null) { | 251 if (dartUnit != null) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 287 } | 278 } |
| 288 | 279 |
| 289 /** | 280 /** |
| 290 * Send status notification to the client. The `contextId` indicates | 281 * Send status notification to the client. The `contextId` indicates |
| 291 * the current context being analyzed or `null` if analysis is complete. | 282 * the current context being analyzed or `null` if analysis is complete. |
| 292 */ | 283 */ |
| 293 void sendStatusNotification(String contextId) { | 284 void sendStatusNotification(String contextId) { |
| 294 // if (contextId == lastStatusNotificationContextId) { | 285 // if (contextId == lastStatusNotificationContextId) { |
| 295 // return; | 286 // return; |
| 296 // } | 287 // } |
| 297 lastStatusNotificationContextId = contextId; | 288 // lastStatusNotificationContextId = contextId; |
| 298 Notification notification = new Notification(NOTIFICATION_STATUS); | 289 Notification notification = new Notification(NOTIFICATION_STATUS); |
| 299 Map<String, Object> analysis = new Map(); | 290 Map<String, Object> analysis = new Map(); |
| 300 if (contextId != null) { | 291 if (contextId != null) { |
| 301 analysis['analyzing'] = true; | 292 analysis['analyzing'] = true; |
| 302 // TODO(danrubel): replace contextId with real analysisTarget | 293 // TODO(danrubel): replace contextId with real analysisTarget |
| 303 analysis['analysisTarget'] = contextId; | 294 analysis['analysisTarget'] = contextId; |
| 304 } else { | 295 } else { |
| 305 analysis['analyzing'] = false; | 296 analysis['analyzing'] = false; |
| 306 } | 297 } |
| 307 notification.params['analysis'] = analysis; | 298 notification.params['analysis'] = analysis; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 changes.forEach((file, change) { | 330 changes.forEach((file, change) { |
| 340 AnalysisContext analysisContext = _getAnalysisContext(file); | 331 AnalysisContext analysisContext = _getAnalysisContext(file); |
| 341 if (analysisContext != null) { | 332 if (analysisContext != null) { |
| 342 Source source = _getSource(file); | 333 Source source = _getSource(file); |
| 343 if (change.offset == null) { | 334 if (change.offset == null) { |
| 344 analysisContext.setContents(source, change.content); | 335 analysisContext.setContents(source, change.content); |
| 345 } else { | 336 } else { |
| 346 analysisContext.setChangedContents(source, change.content, | 337 analysisContext.setChangedContents(source, change.content, |
| 347 change.offset, change.oldLength, change.newLength); | 338 change.offset, change.oldLength, change.newLength); |
| 348 } | 339 } |
| 349 addContextToWorkQueue(analysisContext); | 340 schedulePerformAnalysisOperation(analysisContext); |
| 350 } | 341 } |
| 351 }); | 342 }); |
| 352 } | 343 } |
| 353 | 344 |
| 354 /** | 345 /** |
| 355 * Implementation for `analysis.setSubscriptions`. | 346 * Implementation for `analysis.setSubscriptions`. |
| 356 */ | 347 */ |
| 357 void setAnalysisSubscriptions(Map<AnalysisService, Set<String>> subscriptions)
{ | 348 void setAnalysisSubscriptions(Map<AnalysisService, Set<String>> subscriptions)
{ |
| 358 // send notifications for already analyzed sources | 349 // send notifications for already analyzed sources |
| 359 subscriptions.forEach((service, Set<String> newFiles) { | 350 subscriptions.forEach((service, Set<String> newFiles) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 Source unitSource = _getSource(path); | 404 Source unitSource = _getSource(path); |
| 414 List<Source> librarySources = context.getLibrariesContaining(unitSource); | 405 List<Source> librarySources = context.getLibrariesContaining(unitSource); |
| 415 if (librarySources.isEmpty) { | 406 if (librarySources.isEmpty) { |
| 416 return null; | 407 return null; |
| 417 } | 408 } |
| 418 // get a resolved unit | 409 // get a resolved unit |
| 419 return context.getResolvedCompilationUnit2(unitSource, librarySources[0]); | 410 return context.getResolvedCompilationUnit2(unitSource, librarySources[0]); |
| 420 } | 411 } |
| 421 | 412 |
| 422 /** | 413 /** |
| 423 * Return `true` if all tasks are finished in this [AnalysisServer]. | 414 * Return `true` if all operations have been performed in this [AnalysisServer
]. |
| 424 */ | 415 */ |
| 425 bool test_areTasksFinished() { | 416 bool test_areOperationsFinished() { |
| 426 return contextWorkQueue.isEmpty; | 417 return operationQueue.isEmpty; |
| 427 } | 418 } |
| 428 | 419 |
| 429 static Map<String, Object> errorToJson(AnalysisError analysisError) { | 420 static Map<String, Object> errorToJson(AnalysisError analysisError) { |
| 430 // TODO(paulberry): move this function into the AnalysisError class. | 421 // TODO(paulberry): move this function into the AnalysisError class. |
| 431 ErrorCode errorCode = analysisError.errorCode; | 422 ErrorCode errorCode = analysisError.errorCode; |
| 432 Map<String, Object> result = { | 423 Map<String, Object> result = { |
| 433 'file': analysisError.source.fullName, | 424 'file': analysisError.source.fullName, |
| 434 // TODO(scheglov) add Enum.fullName ? | 425 // TODO(scheglov) add Enum.fullName ? |
| 435 'errorCode': '${errorCode.runtimeType}.${(errorCode as Enum).name}', | 426 'errorCode': '${errorCode.runtimeType}.${(errorCode as Enum).name}', |
| 436 'offset': analysisError.offset, | 427 'offset': analysisError.offset, |
| 437 'length': analysisError.length, | 428 'length': analysisError.length, |
| 438 'message': analysisError.message | 429 'message': analysisError.message |
| 439 }; | 430 }; |
| 440 if (analysisError.correction != null) { | 431 if (analysisError.correction != null) { |
| 441 result['correction'] = analysisError.correction; | 432 result['correction'] = analysisError.correction; |
| 442 } | 433 } |
| 443 return result; | 434 return result; |
| 444 } | 435 } |
| 445 | 436 |
| 446 /** | 437 /** |
| 447 * Send the given [notification] to the client. | 438 * Send the given [notification] to the client. |
| 448 */ | 439 */ |
| 449 void sendNotification(Notification notification) { | 440 void sendNotification(Notification notification) { |
| 450 channel.sendNotification(notification); | 441 channel.sendNotification(notification); |
| 451 } | 442 } |
| 452 | 443 |
| 453 void _scheduleTask() { | 444 /** |
| 454 new Future(performTask).catchError((ex, st) { | 445 * Schedules [performOperation] exection. |
| 446 */ |
| 447 void _schedulePerformOperation() { |
| 448 new Future(performOperation).catchError((ex, st) { |
| 455 AnalysisEngine.instance.logger.logError("${ex}\n${st}"); | 449 AnalysisEngine.instance.logger.logError("${ex}\n${st}"); |
| 456 }); | 450 }); |
| 457 } | 451 } |
| 458 } | 452 } |
| 459 | 453 |
| 460 | 454 |
| 461 /** | 455 /** |
| 462 * An enumeration of the services provided by the analysis domain. | 456 * An enumeration of the services provided by the analysis domain. |
| 463 */ | 457 */ |
| 464 class AnalysisService extends Enum2<AnalysisService> { | 458 class AnalysisService extends Enum2<AnalysisService> { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 /** | 515 /** |
| 522 * An enumeration of the services provided by the server domain. | 516 * An enumeration of the services provided by the server domain. |
| 523 */ | 517 */ |
| 524 class ServerService extends Enum2<ServerService> { | 518 class ServerService extends Enum2<ServerService> { |
| 525 static const ServerService STATUS = const ServerService('STATUS', 0); | 519 static const ServerService STATUS = const ServerService('STATUS', 0); |
| 526 | 520 |
| 527 static const List<ServerService> VALUES = const [STATUS]; | 521 static const List<ServerService> VALUES = const [STATUS]; |
| 528 | 522 |
| 529 const ServerService(String name, int ordinal) : super(name, ordinal); | 523 const ServerService(String name, int ordinal) : super(name, ordinal); |
| 530 } | 524 } |
| OLD | NEW |