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:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 */ | 172 */ |
| 173 final DartSdk defaultSdk; | 173 final DartSdk defaultSdk; |
| 174 | 174 |
| 175 /** | 175 /** |
| 176 * A table mapping [Folder]s to the [AnalysisContext]s associated with them. | 176 * A table mapping [Folder]s to the [AnalysisContext]s associated with them. |
| 177 */ | 177 */ |
| 178 final Map<Folder, AnalysisContext> folderMap = | 178 final Map<Folder, AnalysisContext> folderMap = |
| 179 new HashMap<Folder, AnalysisContext>(); | 179 new HashMap<Folder, AnalysisContext>(); |
| 180 | 180 |
| 181 /** | 181 /** |
| 182 * True if a call to [performOperation] is currently executing, or there is a | |
| 183 * pending future which will execute [performOperation]. | |
| 184 */ | |
| 185 bool operationLoopRunning = false; | |
| 186 | |
| 187 /** | |
| 182 * A queue of the operations to perform in this server. | 188 * A queue of the operations to perform in this server. |
| 183 * | |
| 184 * Invariant: when this queue is non-empty, there is exactly one pending call | |
| 185 * to [performOperation] on the event queue. When this list is empty, there a re | |
| 186 * no calls to [performOperation] on the event queue. | |
| 187 */ | 189 */ |
| 188 ServerOperationQueue operationQueue; | 190 ServerOperationQueue operationQueue; |
| 189 | 191 |
| 190 /** | 192 /** |
| 191 * A set of the [ServerService]s to send notifications for. | 193 * A set of the [ServerService]s to send notifications for. |
| 192 */ | 194 */ |
| 193 Set<ServerService> serverServices = new HashSet<ServerService>(); | 195 Set<ServerService> serverServices = new HashSet<ServerService>(); |
| 194 | 196 |
| 195 /** | 197 /** |
| 196 * A table mapping [AnalysisService]s to the file paths for which these | 198 * A table mapping [AnalysisService]s to the file paths for which these |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 void fileAnalyzed(ChangeNotice notice) { | 263 void fileAnalyzed(ChangeNotice notice) { |
| 262 if (contextDirectoryManager.isInAnalysisRoot(notice.source.fullName)) { | 264 if (contextDirectoryManager.isInAnalysisRoot(notice.source.fullName)) { |
| 263 _onFileAnalyzedController.add(notice); | 265 _onFileAnalyzedController.add(notice); |
| 264 } | 266 } |
| 265 } | 267 } |
| 266 | 268 |
| 267 /** | 269 /** |
| 268 * Schedules execution of the given [ServerOperation]. | 270 * Schedules execution of the given [ServerOperation]. |
| 269 */ | 271 */ |
| 270 void scheduleOperation(ServerOperation operation) { | 272 void scheduleOperation(ServerOperation operation) { |
| 271 bool wasEmpty = operationQueue.isEmpty; | |
| 272 addOperation(operation); | 273 addOperation(operation); |
| 273 if (wasEmpty) { | 274 if (!operationLoopRunning) { |
| 274 _schedulePerformOperation(); | 275 _schedulePerformOperation(); |
| 276 operationLoopRunning = true; | |
| 275 } | 277 } |
| 276 } | 278 } |
| 277 | 279 |
| 278 /** | 280 /** |
| 279 * Schedules analysis of the given context. | 281 * Schedules analysis of the given context. |
| 280 */ | 282 */ |
| 281 void schedulePerformAnalysisOperation(AnalysisContext context) { | 283 void schedulePerformAnalysisOperation(AnalysisContext context) { |
| 282 _onAnalysisStartedController.add(context); | 284 _onAnalysisStartedController.add(context); |
| 283 scheduleOperation(new PerformAnalysisOperation(context, false)); | 285 scheduleOperation(new PerformAnalysisOperation(context, false)); |
| 284 } | 286 } |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 */ | 480 */ |
| 479 bool isPriorityContext(AnalysisContext context) { | 481 bool isPriorityContext(AnalysisContext context) { |
| 480 // TODO(scheglov) implement support for priority sources/contexts | 482 // TODO(scheglov) implement support for priority sources/contexts |
| 481 return false; | 483 return false; |
| 482 } | 484 } |
| 483 | 485 |
| 484 /** | 486 /** |
| 485 * Perform the next available [ServerOperation]. | 487 * Perform the next available [ServerOperation]. |
| 486 */ | 488 */ |
| 487 void performOperation() { | 489 void performOperation() { |
| 490 assert(operationLoopRunning); | |
| 488 if (!running) { | 491 if (!running) { |
| 489 // An error has occurred, or the connection to the client has been | 492 // An error has occurred, or the connection to the client has been |
| 490 // closed, since this method was scheduled on the event queue. So | 493 // closed, since this method was scheduled on the event queue. So |
| 491 // don't do anything. Instead clear the operation queue. | 494 // don't do anything. Instead clear the operation queue. |
| 492 operationQueue.clear(); | 495 operationQueue.clear(); |
| 496 operationLoopRunning = false; | |
| 493 return; | 497 return; |
| 494 } | 498 } |
| 495 // prepare next operation | 499 // prepare next operation |
| 496 ServerOperation operation = operationQueue.take(); | 500 ServerOperation operation = operationQueue.take(); |
| 501 if (operation == null) { | |
| 502 // This can happen if the operation queue is cleared while the operation | |
| 503 // loop is in progress. No problem; we just need to exit the operation | |
| 504 // loop and wait for the next operation to be added. | |
| 505 operationLoopRunning = false; | |
| 506 return; | |
| 507 } | |
| 497 sendStatusNotification(operation); | 508 sendStatusNotification(operation); |
| 498 // perform the operation | 509 // perform the operation |
| 499 try { | 510 try { |
| 500 operation.perform(this); | 511 operation.perform(this); |
| 501 } catch (exception, stackTrace) { | 512 } catch (exception, stackTrace) { |
| 502 AnalysisEngine.instance.logger.logError("${exception}\n${stackTrace}"); | 513 AnalysisEngine.instance.logger.logError("${exception}\n${stackTrace}"); |
| 503 if (rethrowExceptions) { | 514 if (rethrowExceptions) { |
| 504 throw new AnalysisException( | 515 throw new AnalysisException( |
| 505 'Unexpected exception during analysis', | 516 'Unexpected exception during analysis', |
| 506 new CaughtException(exception, stackTrace)); | 517 new CaughtException(exception, stackTrace)); |
| 507 } | 518 } |
| 508 _sendServerErrorNotification(exception, stackTrace); | 519 _sendServerErrorNotification(exception, stackTrace); |
| 509 shutdown(); | 520 shutdown(); |
| 510 } finally { | 521 } finally { |
| 511 if (!operationQueue.isEmpty) { | 522 if (!operationQueue.isEmpty) { |
| 512 _schedulePerformOperation(); | 523 _schedulePerformOperation(); |
| 513 } else { | 524 } else { |
| 514 sendStatusNotification(null); | 525 sendStatusNotification(null); |
| 515 _onAnalysisCompleteController.add(null); | 526 _onAnalysisCompleteController.add(null); |
| 527 operationLoopRunning = false; | |
|
Brian Wilkerson
2014/10/28 20:37:14
If an exception occurs in sendStatusNotification,
| |
| 516 } | 528 } |
| 517 } | 529 } |
| 518 } | 530 } |
| 519 | 531 |
| 520 /** | 532 /** |
| 521 * Trigger reanalysis of all files from disk. | 533 * Trigger reanalysis of all files from disk. |
| 522 */ | 534 */ |
| 523 void reanalyze() { | 535 void reanalyze() { |
| 524 // Clear any operations that are pending. | 536 // Clear any operations that are pending. |
| 525 operationQueue.clear(); | 537 operationQueue.clear(); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 // send the notification | 947 // send the notification |
| 936 channel.sendNotification( | 948 channel.sendNotification( |
| 937 new ServerErrorParams( | 949 new ServerErrorParams( |
| 938 true, | 950 true, |
| 939 exceptionString, | 951 exceptionString, |
| 940 stackTraceString).toNotification()); | 952 stackTraceString).toNotification()); |
| 941 } | 953 } |
| 942 } | 954 } |
| 943 | 955 |
| 944 typedef void OptionUpdater(AnalysisOptionsImpl options); | 956 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| OLD | NEW |