| 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/protocol.dart'; | 11 import 'package:analysis_server/src/protocol.dart'; |
| 12 import 'package:analysis_server/src/resource.dart'; | 12 import 'package:analysis_server/src/resource.dart'; |
| 13 import 'package:analyzer/src/generated/ast.dart'; | 13 import 'package:analyzer/src/generated/ast.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart'; | 14 import 'package:analyzer/src/generated/engine.dart'; |
| 15 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
| 16 import 'package:analyzer/src/generated/java_core.dart'; | 16 import 'package:analyzer/src/generated/java_core.dart'; |
| 17 import 'package:analyzer/src/generated/source.dart'; |
| 17 import 'package:analyzer/src/generated/sdk.dart'; | 18 import 'package:analyzer/src/generated/sdk.dart'; |
| 18 import 'package:analyzer/src/generated/sdk_io.dart'; | 19 import 'package:analyzer/src/generated/sdk_io.dart'; |
| 19 import 'package:analyzer/src/generated/source_io.dart'; | 20 import 'package:analyzer/src/generated/source_io.dart'; |
| 20 | 21 |
| 21 /** | 22 /** |
| 22 * Instances of the class [AnalysisServer] implement a server that listens on a | 23 * Instances of the class [AnalysisServer] implement a server that listens on a |
| 23 * [CommunicationChannel] for analysis requests and process them. | 24 * [CommunicationChannel] for analysis requests and process them. |
| 24 */ | 25 */ |
| 25 class AnalysisServer { | 26 class AnalysisServer { |
| 26 /** | 27 /** |
| (...skipping 15 matching lines...) Expand all Loading... |
| 42 * The name of the parameter whose value is a source. | 43 * The name of the parameter whose value is a source. |
| 43 */ | 44 */ |
| 44 static const String SOURCE_PARAM = 'source'; | 45 static const String SOURCE_PARAM = 'source'; |
| 45 | 46 |
| 46 /** | 47 /** |
| 47 * The event name of the connected notification. | 48 * The event name of the connected notification. |
| 48 */ | 49 */ |
| 49 static const String CONNECTED_NOTIFICATION = 'server.connected'; | 50 static const String CONNECTED_NOTIFICATION = 'server.connected'; |
| 50 | 51 |
| 51 /** | 52 /** |
| 53 * The event name of the status notification. |
| 54 */ |
| 55 static const String STATUS_NOTIFICATION = 'server.status'; |
| 56 |
| 57 /** |
| 52 * The channel from which requests are received and to which responses should | 58 * The channel from which requests are received and to which responses should |
| 53 * be sent. | 59 * be sent. |
| 54 */ | 60 */ |
| 55 final ServerCommunicationChannel channel; | 61 final ServerCommunicationChannel channel; |
| 56 | 62 |
| 57 /** | 63 /** |
| 58 * The [ResourceProvider] using which paths are converted into [Resource]s. | 64 * The [ResourceProvider] using which paths are converted into [Resource]s. |
| 59 */ | 65 */ |
| 60 final ResourceProvider resourceProvider; | 66 final ResourceProvider resourceProvider; |
| 61 | 67 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 87 * The current default [DartSdk]. | 93 * The current default [DartSdk]. |
| 88 */ | 94 */ |
| 89 DartSdk defaultSdk = DirectoryBasedDartSdk.defaultSdk; | 95 DartSdk defaultSdk = DirectoryBasedDartSdk.defaultSdk; |
| 90 | 96 |
| 91 /** | 97 /** |
| 92 * A table mapping [Folder]s to the [PubFolder]s associated with them. | 98 * A table mapping [Folder]s to the [PubFolder]s associated with them. |
| 93 */ | 99 */ |
| 94 final Map<Folder, PubFolder> folderMap = <Folder, PubFolder>{}; | 100 final Map<Folder, PubFolder> folderMap = <Folder, PubFolder>{}; |
| 95 | 101 |
| 96 /** | 102 /** |
| 103 * The context identifier used in the last status notification. |
| 104 */ |
| 105 String lastStatusNotificationContextId = null; |
| 106 |
| 107 /** |
| 97 * A list of the analysis contexts for which analysis work needs to be | 108 * A list of the analysis contexts for which analysis work needs to be |
| 98 * performed. | 109 * performed. |
| 99 * | 110 * |
| 100 * Invariant: when this list is non-empty, there is exactly one pending call | 111 * Invariant: when this list is non-empty, there is exactly one pending call |
| 101 * to [performTask] on the event queue. When this list is empty, there are | 112 * to [performTask] on the event queue. When this list is empty, there are |
| 102 * no calls to [performTask] on the event queue. | 113 * no calls to [performTask] on the event queue. |
| 103 */ | 114 */ |
| 104 final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); | 115 final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); |
| 105 | 116 |
| 106 /** | 117 /** |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 return; | 201 return; |
| 191 } | 202 } |
| 192 // | 203 // |
| 193 // Look for a context that has work to be done and then perform one task. | 204 // Look for a context that has work to be done and then perform one task. |
| 194 // | 205 // |
| 195 List<ChangeNotice> notices = null; | 206 List<ChangeNotice> notices = null; |
| 196 // String contextId; | 207 // String contextId; |
| 197 try { | 208 try { |
| 198 AnalysisContext context = contextWorkQueue[0]; | 209 AnalysisContext context = contextWorkQueue[0]; |
| 199 // contextId = contextIdMap[context]; | 210 // contextId = contextIdMap[context]; |
| 211 // TODO(danrubel): Replace with context identifier or similar |
| 212 sendStatusNotification(context.toString()); |
| 200 AnalysisResult result = context.performAnalysisTask(); | 213 AnalysisResult result = context.performAnalysisTask(); |
| 201 notices = result.changeNotices; | 214 notices = result.changeNotices; |
| 202 } finally { | 215 } finally { |
| 203 if (notices == null) { | 216 if (notices == null) { |
| 204 // Either we have no more work to do for this context, or there was an | 217 // Either we have no more work to do for this context, or there was an |
| 205 // unhandled exception trying to perform the analysis. In either case, | 218 // unhandled exception trying to perform the analysis. In either case, |
| 206 // remove the context form the work queue so we won't try to do more | 219 // remove the context form the work queue so we won't try to do more |
| 207 // analysis on it. | 220 // analysis on it. |
| 208 contextWorkQueue.removeAt(0); | 221 contextWorkQueue.removeAt(0); |
| 209 } | 222 } |
| 210 // | 223 // |
| 211 // Schedule this method to be run again if there is any more work to be | 224 // Schedule this method to be run again if there is any more work to be |
| 212 // done. | 225 // done. |
| 213 // | 226 // |
| 214 if (!contextWorkQueue.isEmpty) { | 227 if (!contextWorkQueue.isEmpty) { |
| 215 _scheduleTask(); | 228 _scheduleTask(); |
| 216 } | 229 } |
| 217 } | 230 } |
| 218 // TODO(scheglov) implement for [PubFolder] | 231 // TODO(scheglov) implement for [PubFolder] |
| 219 // if (notices != null) { | 232 if (notices != null) { |
| 220 // sendNotices(contextId, notices); | 233 // sendNotices(contextId, notices); |
| 221 // } | 234 } else { |
| 235 sendStatusNotification(null); |
| 236 } |
| 222 } | 237 } |
| 223 | 238 |
| 224 // TODO(scheglov) rewrite for the new API. | 239 // TODO(scheglov) rewrite for the new API. |
| 225 // /** | 240 // /** |
| 226 // * Send the information in the given list of notices back to the client. | 241 // * Send the information in the given list of notices back to the client. |
| 227 // */ | 242 // */ |
| 228 // void sendNotices(String contextId, List<ChangeNotice> notices) { | 243 // void sendNotices(String contextId, List<ChangeNotice> notices) { |
| 229 // for (int i = 0; i < notices.length; i++) { | 244 // for (int i = 0; i < notices.length; i++) { |
| 230 // ChangeNotice notice = notices[i]; | 245 // ChangeNotice notice = notices[i]; |
| 231 // Notification notification = new Notification(ERROR_NOTIFICATION_NAME); | 246 // Notification notification = new Notification(ERROR_NOTIFICATION_NAME); |
| 232 // notification.setParameter(CONTEXT_ID_PARAM, contextId); | 247 // notification.setParameter(CONTEXT_ID_PARAM, contextId); |
| 233 // notification.setParameter(SOURCE_PARAM, notice.source.encoding); | 248 // notification.setParameter(SOURCE_PARAM, notice.source.encoding); |
| 234 // notification.setParameter(ERRORS_PARAM, notice.errors.map( | 249 // notification.setParameter(ERRORS_PARAM, notice.errors.map( |
| 235 // errorToJson).toList()); | 250 // errorToJson).toList()); |
| 236 // sendNotification(notification); | 251 // sendNotification(notification); |
| 237 // } | 252 // } |
| 238 // } | 253 // } |
| 239 | 254 |
| 240 /** | 255 /** |
| 256 * Send status notification to the client. The `contextId` indicates |
| 257 * the current context being analyzed or `null` if analysis is complete. |
| 258 */ |
| 259 void sendStatusNotification(String contextId) { |
| 260 if (contextId == lastStatusNotificationContextId) { |
| 261 return; |
| 262 } |
| 263 lastStatusNotificationContextId = contextId; |
| 264 Notification notification = new Notification(STATUS_NOTIFICATION); |
| 265 Map<String, Object> analysis = new Map(); |
| 266 if (contextId != null) { |
| 267 analysis['analyzing'] = true; |
| 268 // TODO(danrubel): replace contextId with real analysisTarget |
| 269 analysis['analysisTarget'] = contextId; |
| 270 } else { |
| 271 analysis['analyzing'] = false; |
| 272 } |
| 273 notification.params['analysis'] = analysis; |
| 274 channel.sendNotification(notification); |
| 275 } |
| 276 |
| 277 /** |
| 241 * Implementation for `server.setAnalysisRoots`. | 278 * Implementation for `server.setAnalysisRoots`. |
| 242 * | 279 * |
| 243 * TODO(scheglov) implement complete projects/contexts semantics. | 280 * TODO(scheglov) implement complete projects/contexts semantics. |
| 244 * | 281 * |
| 245 * The current implementation is intentionally simplified and expected | 282 * The current implementation is intentionally simplified and expected |
| 246 * that only folders are given each given folder corresponds to the exactly | 283 * that only folders are given each given folder corresponds to the exactly |
| 247 * one context. | 284 * one context. |
| 248 * | 285 * |
| 249 * So, we can start working in parallel on adding services and improving | 286 * So, we can start working in parallel on adding services and improving |
| 250 * projects/contexts support. | 287 * projects/contexts support. |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 /** | 490 /** |
| 454 * An enumeration of the services provided by the server domain. | 491 * An enumeration of the services provided by the server domain. |
| 455 */ | 492 */ |
| 456 class ServerService extends Enum2<ServerService> { | 493 class ServerService extends Enum2<ServerService> { |
| 457 static const ServerService STATUS = const ServerService('STATUS', 0); | 494 static const ServerService STATUS = const ServerService('STATUS', 0); |
| 458 | 495 |
| 459 static const List<ServerService> VALUES = const [STATUS]; | 496 static const List<ServerService> VALUES = const [STATUS]; |
| 460 | 497 |
| 461 const ServerService(String name, int ordinal) : super(name, ordinal); | 498 const ServerService(String name, int ordinal) : super(name, ordinal); |
| 462 } | 499 } |
| OLD | NEW |