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 | 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:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 13 import 'package:analyzer/src/generated/error.dart'; | 13 import 'package:analyzer/src/generated/error.dart'; |
| 14 import 'package:analyzer/src/generated/java_core.dart'; | 14 import 'package:analyzer/src/generated/java_core.dart'; |
| 15 import 'package:analyzer/src/generated/source.dart'; | |
| 15 | 16 |
| 16 /** | 17 /** |
| 17 * Instances of the class [AnalysisServer] implement a server that listens on a | 18 * Instances of the class [AnalysisServer] implement a server that listens on a |
| 18 * [CommunicationChannel] for analysis requests and process them. | 19 * [CommunicationChannel] for analysis requests and process them. |
| 19 */ | 20 */ |
| 20 class AnalysisServer { | 21 class AnalysisServer { |
| 21 /** | 22 /** |
| 22 * The name of the notification of new errors associated with a source. | 23 * The name of the notification of new errors associated with a source. |
| 23 */ | 24 */ |
| 24 static const String ERROR_NOTIFICATION_NAME = 'context.errors'; | 25 static const String ERROR_NOTIFICATION_NAME = 'context.errors'; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 37 * The name of the parameter whose value is a source. | 38 * The name of the parameter whose value is a source. |
| 38 */ | 39 */ |
| 39 static const String SOURCE_PARAM = 'source'; | 40 static const String SOURCE_PARAM = 'source'; |
| 40 | 41 |
| 41 /** | 42 /** |
| 42 * The event name of the connected notification. | 43 * The event name of the connected notification. |
| 43 */ | 44 */ |
| 44 static const String CONNECTED_NOTIFICATION = 'server.connected'; | 45 static const String CONNECTED_NOTIFICATION = 'server.connected'; |
| 45 | 46 |
| 46 /** | 47 /** |
| 48 * The event name of the status notification. | |
| 49 */ | |
| 50 static const String STATUS_NOTIFICATION = 'server.status'; | |
| 51 | |
| 52 /** | |
| 47 * The channel from which requests are received and to which responses should | 53 * The channel from which requests are received and to which responses should |
| 48 * be sent. | 54 * be sent. |
| 49 */ | 55 */ |
| 50 final ServerCommunicationChannel channel; | 56 final ServerCommunicationChannel channel; |
| 51 | 57 |
| 52 /** | 58 /** |
| 53 * A flag indicating whether the server is running. When false, contexts | 59 * A flag indicating whether the server is running. When false, contexts |
| 54 * will no longer be added to [contextWorkQueue], and [performTask] will | 60 * will no longer be added to [contextWorkQueue], and [performTask] will |
| 55 * discard any tasks it finds on [contextWorkQueue]. | 61 * discard any tasks it finds on [contextWorkQueue]. |
| 56 */ | 62 */ |
| 57 bool running; | 63 bool running; |
| 58 | 64 |
| 59 /** | 65 /** |
| 60 * A list of the request handlers used to handle the requests sent to this | 66 * A list of the request handlers used to handle the requests sent to this |
| 61 * server. | 67 * server. |
| 62 */ | 68 */ |
| 63 List<RequestHandler> handlers; | 69 List<RequestHandler> handlers; |
| 64 | 70 |
| 65 /** | 71 /** |
| 66 * A table mapping context id's to the analysis contexts associated with them. | 72 * A table mapping context id's to the analysis contexts associated with them. |
| 67 */ | 73 */ |
| 68 final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContex t>(); | 74 final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContex t>(); |
| 69 | 75 |
| 70 /** | 76 /** |
| 71 * A table mapping analysis contexts to the context id's associated with them. | 77 * A table mapping analysis contexts to the context id's associated with them. |
| 72 */ | 78 */ |
| 73 final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, Str ing>(); | 79 final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, Str ing>(); |
| 74 | 80 |
| 75 /** | 81 /** |
| 82 * The context identifier used in the last status notification. | |
| 83 */ | |
| 84 String lastStatusNotificationContextId = null; | |
| 85 | |
| 86 /** | |
| 76 * A list of the analysis contexts for which analysis work needs to be | 87 * A list of the analysis contexts for which analysis work needs to be |
| 77 * performed. | 88 * performed. |
| 78 * | 89 * |
| 79 * Invariant: when this list is non-empty, there is exactly one pending call | 90 * Invariant: when this list is non-empty, there is exactly one pending call |
| 80 * to [performTask] on the event queue. When this list is empty, there are | 91 * to [performTask] on the event queue. When this list is empty, there are |
| 81 * no calls to [performTask] on the event queue. | 92 * no calls to [performTask] on the event queue. |
| 82 */ | 93 */ |
| 83 final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); | 94 final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); |
| 84 | 95 |
| 85 /** | 96 /** |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 return; | 180 return; |
| 170 } | 181 } |
| 171 // | 182 // |
| 172 // Look for a context that has work to be done and then perform one task. | 183 // Look for a context that has work to be done and then perform one task. |
| 173 // | 184 // |
| 174 List<ChangeNotice> notices = null; | 185 List<ChangeNotice> notices = null; |
| 175 String contextId; | 186 String contextId; |
| 176 try { | 187 try { |
| 177 AnalysisContext context = contextWorkQueue[0]; | 188 AnalysisContext context = contextWorkQueue[0]; |
| 178 contextId = contextIdMap[context]; | 189 contextId = contextIdMap[context]; |
| 179 AnalysisResult result = context.performAnalysisTask(); | 190 AnalysisResult result = context.performAnalysisTask(); |
|
Paul Berry
2014/05/27 16:09:26
I think the call to sendStatusNotification(context
danrubel
2014/05/28 02:02:00
Good suggestion. Done.
| |
| 180 notices = result.changeNotices; | 191 notices = result.changeNotices; |
| 181 } finally { | 192 } finally { |
| 182 if (notices == null) { | 193 if (notices == null) { |
| 183 // Either we have no more work to do for this context, or there was an | 194 // Either we have no more work to do for this context, or there was an |
| 184 // unhandled exception trying to perform the analysis. In either case, | 195 // unhandled exception trying to perform the analysis. In either case, |
| 185 // remove the context form the work queue so we won't try to do more | 196 // remove the context form the work queue so we won't try to do more |
| 186 // analysis on it. | 197 // analysis on it. |
| 187 contextWorkQueue.removeAt(0); | 198 contextWorkQueue.removeAt(0); |
| 188 } | 199 } |
| 189 // | 200 // |
| 190 // Schedule this method to be run again if there is any more work to be | 201 // Schedule this method to be run again if there is any more work to be |
| 191 // done. | 202 // done. |
| 192 // | 203 // |
| 193 if (!contextWorkQueue.isEmpty) { | 204 if (!contextWorkQueue.isEmpty) { |
| 194 _scheduleTask(); | 205 _scheduleTask(); |
| 195 } | 206 } |
| 196 } | 207 } |
| 197 if (notices != null) { | 208 if (notices != null) { |
| 209 sendStatusNotification(contextId); | |
| 198 sendNotices(contextId, notices); | 210 sendNotices(contextId, notices); |
| 211 } else { | |
| 212 sendStatusNotification(null); | |
| 199 } | 213 } |
| 200 } | 214 } |
| 201 | 215 |
| 202 /** | 216 /** |
| 203 * Send the information in the given list of notices back to the client. | 217 * Send the information in the given list of notices back to the client. |
| 204 */ | 218 */ |
| 205 void sendNotices(String contextId, List<ChangeNotice> notices) { | 219 void sendNotices(String contextId, List<ChangeNotice> notices) { |
| 206 for (int i = 0; i < notices.length; i++) { | 220 for (int i = 0; i < notices.length; i++) { |
| 207 ChangeNotice notice = notices[i]; | 221 ChangeNotice notice = notices[i]; |
| 208 Notification notification = new Notification(ERROR_NOTIFICATION_NAME); | 222 Notification notification = new Notification(ERROR_NOTIFICATION_NAME); |
| 209 notification.setParameter(CONTEXT_ID_PARAM, contextId); | 223 notification.setParameter(CONTEXT_ID_PARAM, contextId); |
| 210 notification.setParameter(SOURCE_PARAM, notice.source.encoding); | 224 notification.setParameter(SOURCE_PARAM, notice.source.encoding); |
| 211 notification.setParameter(ERRORS_PARAM, notice.errors.map( | 225 notification.setParameter(ERRORS_PARAM, notice.errors.map( |
| 212 errorToJson).toList()); | 226 errorToJson).toList()); |
| 213 sendNotification(notification); | 227 sendNotification(notification); |
| 214 } | 228 } |
| 215 } | 229 } |
| 216 | 230 |
| 231 /** | |
| 232 * Send status notification to the client. The `contextId` indicates | |
| 233 * the current context being analyzed or `null` if analysis is complete. | |
| 234 */ | |
| 235 void sendStatusNotification(String contextId) { | |
| 236 if (contextId == lastStatusNotificationContextId) { | |
| 237 return; | |
| 238 } | |
| 239 lastStatusNotificationContextId = contextId; | |
| 240 Notification notification = new Notification(STATUS_NOTIFICATION); | |
| 241 Map<String, Object> analysis = new Map(); | |
| 242 if (contextId != null) { | |
| 243 analysis['analyzing'] = true; | |
| 244 // TODO(danrubel): replace contextId with real analysisTarget | |
| 245 analysis['analysisTarget'] = contextId; | |
| 246 } else { | |
| 247 analysis['analyzing'] = false; | |
| 248 } | |
| 249 notification.params['analysis'] = analysis; | |
| 250 channel.sendNotification(notification); | |
| 251 } | |
| 252 | |
| 217 static Map<String, Object> errorToJson(AnalysisError analysisError) { | 253 static Map<String, Object> errorToJson(AnalysisError analysisError) { |
| 218 // TODO(paulberry): move this function into the AnalysisError class. | 254 // TODO(paulberry): move this function into the AnalysisError class. |
| 219 | 255 |
| 220 // TODO(paulberry): we really shouldn't be exposing errorCode.ordinal | 256 // TODO(paulberry): we really shouldn't be exposing errorCode.ordinal |
| 221 // outside the analyzer, since the ordinal numbers change whenever we | 257 // outside the analyzer, since the ordinal numbers change whenever we |
| 222 // regenerate the analysis engine. | 258 // regenerate the analysis engine. |
| 223 Map<String, Object> result = { | 259 Map<String, Object> result = { |
| 224 'source': analysisError.source.encoding, | 260 'source': analysisError.source.encoding, |
| 225 'errorCode': (analysisError.errorCode as Enum).ordinal, | 261 'errorCode': (analysisError.errorCode as Enum).ordinal, |
| 226 'offset': analysisError.offset, | 262 'offset': analysisError.offset, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 /** | 303 /** |
| 268 * An enumeration of the services provided by the server domain. | 304 * An enumeration of the services provided by the server domain. |
| 269 */ | 305 */ |
| 270 class ServerService extends Enum2<ServerService> { | 306 class ServerService extends Enum2<ServerService> { |
| 271 static const ServerService STATUS = const ServerService('STATUS', 0); | 307 static const ServerService STATUS = const ServerService('STATUS', 0); |
| 272 | 308 |
| 273 static const List<ServerService> VALUES = const [STATUS]; | 309 static const List<ServerService> VALUES = const [STATUS]; |
| 274 | 310 |
| 275 const ServerService(String name, int ordinal) : super(name, ordinal); | 311 const ServerService(String name, int ordinal) : super(name, ordinal); |
| 276 } | 312 } |
| OLD | NEW |