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 fdef53a210d98f8781b5ffbd40ad5849f0a45019..b630245c30299476efb86461eca4db60cff2eab6 100644 |
--- a/pkg/analysis_server/lib/src/analysis_server.dart |
+++ b/pkg/analysis_server/lib/src/analysis_server.dart |
@@ -14,6 +14,7 @@ import 'package:analysis_server/plugin/protocol/protocol.dart' |
hide AnalysisOptions, Element; |
import 'package:analysis_server/src/analysis_logger.dart'; |
import 'package:analysis_server/src/channel/channel.dart'; |
+import 'package:analysis_server/src/computer/new_notifications.dart'; |
import 'package:analysis_server/src/context_manager.dart'; |
import 'package:analysis_server/src/operation/operation.dart'; |
import 'package:analysis_server/src/operation/operation_analysis.dart'; |
@@ -32,6 +33,9 @@ import 'package:analyzer/instrumentation/instrumentation.dart'; |
import 'package:analyzer/plugin/resolver_provider.dart'; |
import 'package:analyzer/source/pub_package_map_provider.dart'; |
import 'package:analyzer/src/context/builder.dart'; |
+import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
+import 'package:analyzer/src/dart/analysis/file_byte_store.dart'; |
+import 'package:analyzer/src/dart/analysis/driver.dart' as nd; |
import 'package:analyzer/src/dart/ast/utilities.dart'; |
import 'package:analyzer/src/generated/engine.dart'; |
import 'package:analyzer/src/generated/sdk.dart'; |
@@ -307,6 +311,14 @@ class AnalysisServer { |
*/ |
PubSummaryManager pubSummaryManager; |
+ ByteStore byteStore; |
+ |
+ /** |
+ * A table mapping [Folder]s to the [AnalysisDriver]s associated with them. |
+ */ |
+ final Map<Folder, nd.AnalysisDriver> driverMap = |
Brian Wilkerson
2016/10/31 15:42:58
I would prefer to see this added to ContextManager
scheglov
2016/10/31 16:54:20
Done.
|
+ new HashMap<Folder, nd.AnalysisDriver>(); |
+ |
/** |
* Initialize a newly created server to receive requests from and send |
* responses to the given [channel]. |
@@ -341,6 +353,9 @@ class AnalysisServer { |
options.finerGrainedInvalidation; |
defaultContextOptions.generateImplicitErrors = false; |
operationQueue = new ServerOperationQueue(); |
+ byteStore = new MemoryCachingByteStore( |
+ new FileByteStore(resourceProvider.getStateLocation('analysis-driver')), |
+ 1024); |
if (useSingleContextManager) { |
contextManager = new SingleContextManager(resourceProvider, sdkManager, |
packageResolverProvider, analyzedFilesGlobs, defaultContextOptions); |
@@ -352,7 +367,8 @@ class AnalysisServer { |
packageMapProvider, |
analyzedFilesGlobs, |
instrumentationService, |
- defaultContextOptions); |
+ defaultContextOptions, |
+ options.enableNewAnalysisDriver); |
} |
this.fileResolverProvider = fileResolverProvider; |
this.packageResolverProvider = packageResolverProvider; |
@@ -1086,6 +1102,10 @@ class AnalysisServer { |
*/ |
void setAnalysisSubscriptions( |
Map<AnalysisService, Set<String>> subscriptions) { |
+ if (options.enableNewAnalysisDriver) { |
+ // TODO(scheglov) implement for the new analysis driver |
+ return; |
+ } |
// send notifications for already analyzed sources |
subscriptions.forEach((service, Set<String> newFiles) { |
Set<String> oldFiles = analysisServices[service]; |
@@ -1175,6 +1195,13 @@ class AnalysisServer { |
* Set the priority files to the given [files]. |
*/ |
void setPriorityFiles(String requestId, List<String> files) { |
+ if (options.enableNewAnalysisDriver) { |
+ driverMap.values.forEach((driver){ |
+ driver.priorityFiles = files; |
+ }); |
+ // TODO(scheglov) implement for the new analysis driver |
Brian Wilkerson
2016/10/31 15:42:58
The formatting of the lines above the comment look
scheglov
2016/10/31 16:54:20
I think it's done.
I'm removing the comment.
|
+ return; |
+ } |
// Note: when a file is a priority file, that information needs to be |
// propagated to all contexts that analyze the file, so that all contexts |
// will be able to do incremental resolution of the file. See |
@@ -1294,6 +1321,45 @@ class AnalysisServer { |
* Implementation for `analysis.updateContent`. |
*/ |
void updateContent(String id, Map<String, dynamic> changes) { |
+ if (options.enableNewAnalysisDriver) { |
+ changes.forEach((file, change) { |
+ Source source = resourceProvider.getFile(file).createSource(); |
+ // Prepare the new contents. |
+ String oldContents = overlayState.getContents(source); |
+ String newContents; |
+ if (change is AddContentOverlay) { |
+ newContents = change.content; |
+ } else if (change is ChangeContentOverlay) { |
+ if (oldContents == null) { |
+ // The client may only send a ChangeContentOverlay if there is |
+ // already an existing overlay for the source. |
+ throw new RequestFailure(new Response(id, |
+ error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, |
+ 'Invalid overlay change'))); |
+ } |
+ try { |
+ newContents = SourceEdit.applySequence(oldContents, change.edits); |
+ } on RangeError { |
+ throw new RequestFailure(new Response(id, |
+ error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, |
+ 'Invalid overlay change'))); |
+ } |
+ } else if (change is RemoveContentOverlay) { |
+ newContents = null; |
+ } else { |
+ // Protocol parsing should have ensured that we never get here. |
+ throw new AnalysisException('Illegal change type'); |
+ } |
+ |
+ overlayState.setContents(source, newContents); |
+ |
+ driverMap.values.forEach((driver) { |
+ driver.changeFile(file); |
+ }); |
+ // TODO(scheglov) implement other cases |
+ }); |
+ return; |
+ } |
changes.forEach((file, change) { |
ContextSourcePair contextSource = getContextSourcePair(file); |
Source source = contextSource.source; |
@@ -1406,6 +1472,10 @@ class AnalysisServer { |
* existing analysis context. |
*/ |
void updateOptions(List<OptionUpdater> optionUpdaters) { |
+ if (options.enableNewAnalysisDriver) { |
+ // TODO(scheglov) implement for the new analysis driver |
+ return; |
+ } |
// |
// Update existing contexts. |
// |
@@ -1549,6 +1619,7 @@ class AnalysisServer { |
class AnalysisServerOptions { |
bool enableIncrementalResolutionApi = false; |
bool enableIncrementalResolutionValidation = false; |
+ bool enableNewAnalysisDriver = false; |
bool enablePubSummaryManager = false; |
bool finerGrainedInvalidation = false; |
bool noErrorNotification = false; |
@@ -1598,6 +1669,49 @@ class ServerContextManagerCallbacks extends ContextManagerCallbacks { |
ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider); |
@override |
+ nd.AnalysisDriver addAnalysisDriver(Folder folder, AnalysisOptions options) { |
+ SourceFactory sourceFactory; |
+ AnalysisOptions analysisOptions; |
+ { |
+ ContextBuilder builder = createContextBuilder(folder, options); |
+ AnalysisContext context = builder.buildContext(folder.path); |
+ sourceFactory = context.sourceFactory; |
+ analysisOptions = context.analysisOptions; |
+ context.dispose(); |
+ } |
+ nd.AnalysisDriver analysisDriver = new nd.AnalysisDriver( |
+ new nd.PerformanceLog(io.stdout), |
+ resourceProvider, |
+ analysisServer.byteStore, |
+ analysisServer.overlayState, |
+ sourceFactory, |
+ analysisOptions); |
+ analysisDriver.name = folder.shortName; |
+ analysisDriver.status.listen((status) { |
+ // TODO(scheglov) send server status |
+ }); |
+ analysisDriver.results.listen((result) { |
+ new_sendErrorNotification(analysisServer, result); |
+// { |
Brian Wilkerson
2016/10/31 15:42:58
Add a comment explaining why this code was left in
scheglov
2016/10/31 16:54:20
Done.
|
+// var unit = result.unit; |
+// if (unit != null) { |
+// print('[results][${analysisDriver.name}] ${result.path}'); |
+// sendAnalysisNotificationHighlights(analysisServer, result.path, unit); |
+// { |
+// NavigationCollectorImpl collector = |
+// computeSimpleDartNavigation(unit); |
+// var params = new protocol.AnalysisNavigationParams(result.path, |
+// collector.regions, collector.targets, collector.files); |
+// analysisServer.sendNotification(params.toNotification()); |
+// } |
+// } |
+// } |
+ }); |
+ analysisServer.driverMap[folder] = analysisDriver; |
+ return analysisDriver; |
+ } |
+ |
+ @override |
AnalysisContext addContext(Folder folder, AnalysisOptions options) { |
ContextBuilder builder = createContextBuilder(folder, options); |
AnalysisContext context = builder.buildContext(folder.path); |
@@ -1612,15 +1726,31 @@ class ServerContextManagerCallbacks extends ContextManagerCallbacks { |
@override |
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
- AnalysisContext context = analysisServer.folderMap[contextFolder]; |
- if (context != null) { |
- context.applyChanges(changeSet); |
- analysisServer.schedulePerformAnalysisOperation(context); |
- List<String> flushedFiles = new List<String>(); |
- for (Source source in changeSet.removedSources) { |
- flushedFiles.add(source.fullName); |
+ if (analysisServer.options.enableNewAnalysisDriver) { |
+ nd.AnalysisDriver analysisDriver = |
+ analysisServer.driverMap[contextFolder]; |
+ if (analysisDriver != null) { |
+ changeSet.addedSources.forEach((source) { |
+ analysisDriver.addFile(source.fullName); |
+ }); |
+ changeSet.changedSources.forEach((source) { |
+ analysisDriver.changeFile(source.fullName); |
+ }); |
+ changeSet.removedSources.forEach((source) { |
+ analysisDriver.removeFile(source.fullName); |
+ }); |
+ } |
+ } else { |
+ AnalysisContext context = analysisServer.folderMap[contextFolder]; |
+ if (context != null) { |
+ context.applyChanges(changeSet); |
+ analysisServer.schedulePerformAnalysisOperation(context); |
+ List<String> flushedFiles = new List<String>(); |
+ for (Source source in changeSet.removedSources) { |
+ flushedFiles.add(source.fullName); |
+ } |
+ sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); |
} |
- sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); |
} |
} |