Chromium Code Reviews| Index: pkg/analysis_server/lib/src/analysis_server.dart |
| diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart |
| index ef7bfcb458cc3c9a7f9c8aec542791f906d3bdc3..377915328ec4d64e3f7bdc402c771bad23776b06 100644 |
| --- a/pkg/analysis_server/lib/src/analysis_server.dart |
| +++ b/pkg/analysis_server/lib/src/analysis_server.dart |
| @@ -11,6 +11,8 @@ import 'package:analysis_server/src/channel.dart'; |
| import 'package:analysis_server/src/constants.dart'; |
| import 'package:analysis_server/src/context_directory_manager.dart'; |
| import 'package:analysis_server/src/domain_analysis.dart'; |
| +import 'package:analysis_server/src/operation/operation.dart'; |
| +import 'package:analysis_server/src/operation/operation_queue.dart'; |
| import 'package:analysis_server/src/protocol.dart'; |
| import 'package:analysis_server/src/resource.dart'; |
| import 'package:analyzer/src/generated/ast.dart'; |
| @@ -40,7 +42,7 @@ class AnalysisServerContextDirectoryManager extends ContextDirectoryManager { |
| ContextDirectory contextDirectory = new ContextDirectory( |
| analysisServer.defaultSdk, folder, pubspecFile); |
| analysisServer.folderMap[folder] = contextDirectory; |
| - analysisServer.addContextToWorkQueue(contextDirectory.context); |
| + analysisServer.schedulePerformAnalysisOperation(contextDirectory.context, false); |
| } |
| void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
| @@ -78,17 +80,6 @@ class AnalysisServer { |
| */ |
| List<RequestHandler> handlers; |
| - // TODO(scheglov) remove once setAnalysisRoots() is completely implemented |
| -// /** |
| -// * A table mapping context id's to the analysis contexts associated with them. |
| -// */ |
| -// final Map<String, AnalysisContext> contextMap = new Map<String, AnalysisContext>(); |
| -// |
| -// /** |
| -// * A table mapping analysis contexts to the context id's associated with them. |
| -// */ |
| -// final Map<AnalysisContext, String> contextIdMap = new Map<AnalysisContext, String>(); |
| - |
| /** |
| * The current default [DartSdk]. |
| */ |
| @@ -104,15 +95,7 @@ class AnalysisServer { |
| */ |
| String lastStatusNotificationContextId = null; |
| - /** |
| - * A list of the analysis contexts for which analysis work needs to be |
| - * performed. |
| - * |
| - * Invariant: when this list is non-empty, there is exactly one pending call |
|
Paul Berry
2014/06/02 16:04:41
Why is this comment being deleted? Is your intent
scheglov
2014/06/02 17:56:59
Restored for the operation queue field.
|
| - * to [performTask] on the event queue. When this list is empty, there are |
| - * no calls to [performTask] on the event queue. |
| - */ |
| - final List<AnalysisContext> contextWorkQueue = new List<AnalysisContext>(); |
| + final ServerOperationQueue operationQueue = new ServerOperationQueue(); |
| /** |
| * A set of the [ServerService]s to send notifications for. |
| @@ -139,21 +122,17 @@ class AnalysisServer { |
| } |
| /** |
| - * If [running] is true, add the given [context] to the list of analysis |
| - * contexts for which analysis work needs to be performed, and ensure that |
| - * the work will be performed. |
| + * Schedules analysis of the given context. |
| + * |
| + * [isContinue] is `true` if the new operation is continuation of analysis of |
| + * the same context which was analyzed before. |
| */ |
| - void addContextToWorkQueue(AnalysisContext context) { |
| - if (!running) { |
| - return; |
| - } |
| - if (!contextWorkQueue.contains(context)) { |
| - contextWorkQueue.add(context); |
| - if (contextWorkQueue.length == 1) { |
| - // Work queue was previously empty, so schedule analysis. |
| - _scheduleTask(); |
| - } |
| - } |
| + void schedulePerformAnalysisOperation(AnalysisContext context, bool isContinue) { |
| +// bool isPriority = priorityContexts.contains(contextId); |
| + // TODO(scheglov) support for priority sources |
| + bool isPriority = false; |
| + operationQueue.add(new PerformAnalysisOperation(context, isPriority, isContinue)); |
| + _scheduleTask(); |
|
Brian Wilkerson
2014/06/02 14:32:18
I believe that this will cause the event queue to
Paul Berry
2014/06/02 16:04:41
I'm not sure we even need a closure. I think it i
|
| } |
| /** |
| @@ -192,54 +171,47 @@ class AnalysisServer { |
| } |
| /** |
| - * Perform the next available task. If a request was received that has not yet |
| - * been performed, perform it next. Otherwise, look for some analysis that |
| - * needs to be done and do that. Otherwise, do nothing. |
| + * Perform the next available [ServerOperation]. |
| */ |
| void performTask() { |
| if (!running) { |
| - // An error has occurred, or the connection to the client has been |
| - // closed, since performTask() was scheduled on the event queue. So |
| - // don't do any analysis. Instead clear the work queue. |
| - contextWorkQueue.clear(); |
|
Paul Berry
2014/06/02 16:04:41
Why are we getting rid of this code? Was it incor
scheglov
2014/06/02 17:56:59
Restored.
|
| + return; |
| } |
| - if (contextWorkQueue.isEmpty) { |
| - // Nothing to do. |
| + // prepare next operation |
| + ServerOperation operation = operationQueue.take(); |
| + if (operation == null) { |
| return; |
| } |
| - // |
| - // Look for a context that has work to be done and then perform one task. |
| - // |
| - List<ChangeNotice> notices = null; |
| -// String contextId; |
| + // perform the operation |
| try { |
| - AnalysisContext context = contextWorkQueue[0]; |
| -// contextId = contextIdMap[context]; |
| - // TODO(danrubel): Replace with context identifier or similar |
| - sendStatusNotification(context.toString()); |
| - AnalysisResult result = context.performAnalysisTask(); |
| - notices = result.changeNotices; |
| - } finally { |
|
Paul Berry
2014/06/02 16:04:41
Why are we dropping this logic? I believe that sc
scheglov
2014/06/02 17:56:59
Restored in performTask/performOperation.
|
| - if (notices == null) { |
| - // Either we have no more work to do for this context, or there was an |
| - // unhandled exception trying to perform the analysis. In either case, |
| - // remove the context form the work queue so we won't try to do more |
| - // analysis on it. |
| - contextWorkQueue.removeAt(0); |
| - } |
| - // |
| - // Schedule this method to be run again if there is any more work to be |
| - // done. |
| - // |
| - if (!contextWorkQueue.isEmpty) { |
| - _scheduleTask(); |
| - } |
| + operation.perform(this); |
| + } catch (e) { |
| + // TODO(scheglov) decide how to handle exceptions |
| + } |
| + // schedule this method again |
| + _scheduleTask(); |
|
Brian Wilkerson
2014/06/02 14:32:18
This method should only get scheduled if the queue
scheglov
2014/06/02 17:56:59
Done.
|
| + } |
| + |
| + /** |
| + * Perform analysis in the given [AnalysisContext]. |
| + */ |
| + void internalPerformAnalysis(AnalysisContext context) { |
|
Brian Wilkerson
2014/06/02 14:32:18
I would prefer a style in which the code to perfor
scheglov
2014/06/02 17:56:59
Me too, but I'm afraid we have to expose too much
Brian Wilkerson
2014/06/02 18:21:03
I'd like to start with doing it the better way unt
|
| + // prepare results |
| + AnalysisResult result = context.performAnalysisTask(); |
| + List<ChangeNotice> notices = result.changeNotices; |
| + if (notices == null) { |
| + return; |
| } |
| + // TODO(scheglov) remember known sources |
| + // TODO(scheglov) index units |
| + // TODO(scheglov) schedule notifications |
| if (notices != null) { |
| sendNotices(notices); |
| } else { |
| sendStatusNotification(null); |
| } |
| + // schedule analysis again |
| + schedulePerformAnalysisOperation(context, true); |
|
Brian Wilkerson
2014/06/02 14:32:18
We need to take the "continuation" flag into accou
scheglov
2014/06/02 17:56:59
We do use it - PerformAnalysisOperation returns di
Brian Wilkerson
2014/06/02 18:21:03
I meant, if we are continuing analysis of a contex
scheglov
2014/06/02 18:32:25
Well, it is added to the tail of the ANALYSIS_CONT
|
| } |
| /** |
| @@ -341,7 +313,7 @@ class AnalysisServer { |
| analysisContext.setChangedContents(source, change.content, |
| change.offset, change.oldLength, change.newLength); |
| } |
| - addContextToWorkQueue(analysisContext); |
| + schedulePerformAnalysisOperation(analysisContext, false); |
| } |
| }); |
| } |
| @@ -418,7 +390,7 @@ class AnalysisServer { |
| * Return `true` if all tasks are finished in this [AnalysisServer]. |
| */ |
| bool test_areTasksFinished() { |
| - return contextWorkQueue.isEmpty; |
| + return operationQueue.isEmpty; |
| } |
| static Map<String, Object> errorToJson(AnalysisError analysisError) { |