Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1827)

Unified Diff: pkg/analyzer_plugin/lib/plugin/plugin.dart

Issue 2857233002: Implement more of the behavior of a plugin; refactor some API (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer_plugin/lib/plugin/plugin.dart
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index 77d056035b06015c127d1abc76d6124464479bf5..a6475ff41bd8559834040c0dbf71c835723a57f3 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -5,7 +5,7 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart'
- show AnalysisDriverScheduler, PerformanceLog;
+ show AnalysisDriverGeneric, AnalysisDriverScheduler, PerformanceLog;
import 'package:analyzer/src/dart/analysis/file_byte_store.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -16,6 +16,7 @@ import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
import 'package:analyzer_plugin/src/utilities/null_string_sink.dart';
import 'package:analyzer_plugin/utilities/subscriptions/subscription_manager.dart';
+import 'package:path/src/context.dart';
import 'package:pub_semver/pub_semver.dart';
/**
@@ -53,6 +54,13 @@ abstract class ServerPlugin {
AnalysisDriverScheduler analysisDriverScheduler;
/**
+ * A table mapping the current context roots to the analysis driver created
+ * for that root.
+ */
+ final Map<ContextRoot, AnalysisDriverGeneric> driverMap =
+ <ContextRoot, AnalysisDriverGeneric>{};
+
+ /**
* The performance log used by any analysis drivers that are created.
*/
final PerformanceLog performanceLog =
@@ -77,9 +85,17 @@ abstract class ServerPlugin {
*/
ServerPlugin(this.resourceProvider) {
analysisDriverScheduler = new AnalysisDriverScheduler(performanceLog);
+ analysisDriverScheduler.start();
}
/**
+ * Return the byte store used by any analysis drivers that are created, or
+ * `null` if the cache location isn't known because the 'plugin.version'
+ * request has not yet been received.
+ */
+ ByteStore get byteStore => _byteStore;
+
+ /**
* Return the communication channel being used to communicate with the
* analysis server, or `null` if the plugin has not been started.
*/
@@ -115,42 +131,116 @@ abstract class ServerPlugin {
}
/**
+ * Return the context root containing the file at the given [filePath].
+ */
+ ContextRoot contextRootContaining(String filePath) {
+ Context pathContext = resourceProvider.pathContext;
+
+ /**
+ * Return `true` if the given [child] is either the same as or within the
+ * given [parent].
+ */
+ bool isOrWithin(String parent, String child) {
+ return parent == child || pathContext.isWithin(parent, child);
+ }
+
+ /**
+ * Return `true` if the given context [root] contains the target [file].
+ */
+ bool ownsFile(ContextRoot root) {
+ if (isOrWithin(root.root, filePath)) {
+ List<String> excludedPaths = root.exclude;
+ for (String excludedPath in excludedPaths) {
+ if (isOrWithin(excludedPath, filePath)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ for (ContextRoot root in driverMap.keys) {
+ if (ownsFile(root)) {
+ return root;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Create an analysis driver that can analyze the files within the given
+ * [contextRoot].
+ */
+ AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot);
+
+ /**
* Handle an 'analysis.handleWatchEvents' request.
*/
AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents(
- Map<String, Object> parameters) =>
+ AnalysisHandleWatchEventsParams parameters) =>
null;
/**
* Handle an 'analysis.reanalyze' request.
*/
AnalysisReanalyzeResult handleAnalysisReanalyze(
- Map<String, Object> parameters) =>
+ AnalysisReanalyzeParams parameters) =>
null;
/**
* Handle an 'analysis.setContextBuilderOptions' request.
*/
AnalysisSetContextBuilderOptionsResult handleAnalysisSetContextBuilderOptions(
- Map<String, Object> parameters) =>
+ AnalysisSetContextBuilderOptionsParams parameters) =>
null;
/**
* Handle an 'analysis.setContextRoots' request.
*/
AnalysisSetContextRootsResult handleAnalysisSetContextRoots(
- Map<String, Object> parameters) {
- // TODO(brianwilkerson) Implement this so that implementors don't have to
- // figure out how to manage contexts.
- return null;
+ AnalysisSetContextRootsParams parameters) {
+ List<ContextRoot> contextRoots = parameters.roots;
+ List<ContextRoot> oldRoots = driverMap.keys.toList();
+ for (ContextRoot contextRoot in contextRoots) {
+ if (!oldRoots.remove(contextRoot)) {
+ // The context is new, so we create a driver for it. Creating the driver
+ // has the side-effect of adding it to the analysis driver scheduler.
+ AnalysisDriverGeneric driver = createAnalysisDriver(contextRoot);
+ driverMap[contextRoot] = driver;
+ }
+ }
+ for (ContextRoot contextRoot in oldRoots) {
+ // The context has been removed, so we remove its driver.
+ AnalysisDriverGeneric driver = driverMap.remove(contextRoot);
+ // The `dispose` method has the side-effect of removing the driver from
+ // the analysis driver scheduler.
+ driver.dispose();
+ }
+ return new AnalysisSetContextRootsResult();
}
/**
* Handle an 'analysis.setPriorityFiles' request.
*/
AnalysisSetPriorityFilesResult handleAnalysisSetPriorityFiles(
- Map<String, Object> parameters) =>
- new AnalysisSetPriorityFilesResult();
+ AnalysisSetPriorityFilesParams parameters) {
+ List<String> files = parameters.files;
+ Map<AnalysisDriverGeneric, List<String>> filesByDriver =
+ <AnalysisDriverGeneric, List<String>>{};
+ for (String file in files) {
+ ContextRoot contextRoot = contextRootContaining(file);
+ if (contextRoot != null) {
+ // TODO(brianwilkerson) Which driver should we use if there is no context root?
+ AnalysisDriverGeneric driver = driverMap[contextRoot];
+ filesByDriver.putIfAbsent(driver, () => <String>[]).add(file);
+ }
+ }
+ filesByDriver.forEach((AnalysisDriverGeneric driver, List<String> files) {
+ driver.priorityFiles = files;
+ });
+ return new AnalysisSetPriorityFilesResult();
+ }
/**
* Handle an 'analysis.setSubscriptions' request. Most subclasses should not
@@ -158,11 +248,8 @@ abstract class ServerPlugin {
* access the list of subscriptions for any given file.
*/
AnalysisSetSubscriptionsResult handleAnalysisSetSubscriptions(
- Map<String, Object> parameters) {
- Map<AnalysisService, List<String>> subscriptions = validateParameter(
- parameters,
- ANALYSIS_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS,
- 'analysis.setSubscriptions');
+ AnalysisSetSubscriptionsParams parameters) {
+ Map<AnalysisService, List<String>> subscriptions = parameters.subscriptions;
subscriptionManager.setSubscriptions(subscriptions);
// TODO(brianwilkerson) Cause any newly subscribed for notifications to be sent.
return new AnalysisSetSubscriptionsResult();
@@ -174,9 +261,8 @@ abstract class ServerPlugin {
* the current content of overlaid files.
*/
AnalysisUpdateContentResult handleAnalysisUpdateContent(
- Map<String, Object> parameters) {
- Map<String, Object> files = validateParameter(parameters,
- ANALYSIS_REQUEST_UPDATE_CONTENT_FILES, 'analysis.updateContent');
+ AnalysisUpdateContentParams parameters) {
+ Map<String, Object> files = parameters.files;
files.forEach((String filePath, Object overlay) {
// We don't need to get the correct URI because only the full path is
// used by the contentCache.
@@ -214,14 +300,14 @@ abstract class ServerPlugin {
* Handle a 'completion.getSuggestions' request.
*/
CompletionGetSuggestionsResult handleCompletionGetSuggestions(
- Map<String, Object> parameters) =>
+ CompletionGetSuggestionsParams parameters) =>
new CompletionGetSuggestionsResult(
-1, -1, const <CompletionSuggestion>[]);
/**
* Handle an 'edit.getAssists' request.
*/
- EditGetAssistsResult handleEditGetAssists(Map<String, Object> parameters) =>
+ EditGetAssistsResult handleEditGetAssists(EditGetAssistsParams parameters) =>
new EditGetAssistsResult(const <PrioritizedSourceChange>[]);
/**
@@ -230,20 +316,20 @@ abstract class ServerPlugin {
* method [handleEditGetRefactoring].
*/
EditGetAvailableRefactoringsResult handleEditGetAvailableRefactorings(
- Map<String, Object> parameters) =>
+ EditGetAvailableRefactoringsParams parameters) =>
new EditGetAvailableRefactoringsResult(const <RefactoringKind>[]);
/**
* Handle an 'edit.getFixes' request.
*/
- EditGetFixesResult handleEditGetFixes(Map<String, Object> parameters) =>
+ EditGetFixesResult handleEditGetFixes(EditGetFixesParams parameters) =>
new EditGetFixesResult(const <AnalysisErrorFixes>[]);
/**
* Handle an 'edit.getRefactoring' request.
*/
EditGetRefactoringResult handleEditGetRefactoring(
- Map<String, Object> parameters) =>
+ EditGetRefactoringParams parameters) =>
null;
/**
@@ -251,18 +337,16 @@ abstract class ServerPlugin {
* perform any required clean-up, but cannot prevent the plugin from shutting
* down.
*/
- PluginShutdownResult handlePluginShutdown(Map<String, Object> parameters) =>
+ PluginShutdownResult handlePluginShutdown(PluginShutdownParams parameters) =>
new PluginShutdownResult();
/**
* Handle a 'plugin.versionCheck' request.
*/
PluginVersionCheckResult handlePluginVersionCheck(
- Map<String, Object> parameters) {
- String byteStorePath = validateParameter(parameters,
- PLUGIN_REQUEST_VERSION_CHECK_BYTESTOREPATH, 'plugin.versionCheck');
- String versionString = validateParameter(parameters,
- PLUGIN_REQUEST_VERSION_CHECK_VERSION, 'plugin.versionCheck');
+ PluginVersionCheckParams parameters) {
+ String byteStorePath = parameters.byteStorePath;
+ String versionString = parameters.version;
Version serverVersion = new Version.parse(versionString);
_byteStore =
new MemoryCachingByteStore(new FileByteStore(byteStorePath), 64 * M);
@@ -296,33 +380,11 @@ abstract class ServerPlugin {
* Start this plugin by listening to the given communication [channel].
*/
void start(PluginCommunicationChannel channel) {
- this._channel = channel;
+ _channel = channel;
_channel.listen(_onRequest, onError: onError, onDone: onDone);
}
/**
- * Validate that the value in the map of [parameters] at the given [key] is of
- * the type [T]. If it is, return it. Otherwise throw a [RequestFailure] that
- * will cause an error to be returned to the server.
- */
- Object/*=T*/ validateParameter/*<T>*/(
- Map<String, Object> parameters, String key, String requestName) {
- Object value = parameters[key];
- // ignore: type_annotation_generic_function_parameter
- if (value is Object/*=T*/) {
- return value;
- }
- String message;
- if (value == null) {
- message = 'Missing parameter $key in $requestName';
- } else {
- message = 'Invalid value for $key in $requestName (${value.runtimeType})';
- }
- throw new RequestFailure(
- new RequestError(RequestErrorCode.INVALID_PARAMETER, message));
- }
-
- /**
* Compute the response that should be returned for the given [request], or
* `null` if the response has already been sent.
*/
@@ -330,48 +392,64 @@ abstract class ServerPlugin {
ResponseResult result = null;
switch (request.method) {
case ANALYSIS_REQUEST_HANDLE_WATCH_EVENTS:
- result = handleAnalysisHandleWatchEvents(request.params);
+ var params = new AnalysisHandleWatchEventsParams.fromRequest(request);
+ result = handleAnalysisHandleWatchEvents(params);
break;
case ANALYSIS_REQUEST_REANALYZE:
- result = handleAnalysisReanalyze(request.params);
+ var params = new AnalysisReanalyzeParams.fromRequest(request);
+ result = handleAnalysisReanalyze(params);
break;
case ANALYSIS_REQUEST_SET_CONTEXT_BUILDER_OPTIONS:
- result = handleAnalysisSetContextBuilderOptions(request.params);
+ var params =
+ new AnalysisSetContextBuilderOptionsParams.fromRequest(request);
+ result = handleAnalysisSetContextBuilderOptions(params);
break;
case ANALYSIS_REQUEST_SET_CONTEXT_ROOTS:
- result = handleAnalysisSetContextRoots(request.params);
+ var params = new AnalysisSetContextRootsParams.fromRequest(request);
+ result = handleAnalysisSetContextRoots(params);
break;
case ANALYSIS_REQUEST_SET_PRIORITY_FILES:
- result = handleAnalysisSetPriorityFiles(request.params);
+ var params = new AnalysisSetPriorityFilesParams.fromRequest(request);
+ result = handleAnalysisSetPriorityFiles(params);
break;
case ANALYSIS_REQUEST_SET_SUBSCRIPTIONS:
- result = handleAnalysisSetSubscriptions(request.params);
+ var params = new AnalysisSetSubscriptionsParams.fromRequest(request);
+ result = handleAnalysisSetSubscriptions(params);
break;
case ANALYSIS_REQUEST_UPDATE_CONTENT:
- result = handleAnalysisUpdateContent(request.params);
+ var params = new AnalysisUpdateContentParams.fromRequest(request);
+ result = handleAnalysisUpdateContent(params);
break;
case COMPLETION_REQUEST_GET_SUGGESTIONS:
- result = handleCompletionGetSuggestions(request.params);
+ var params = new CompletionGetSuggestionsParams.fromRequest(request);
+ result = handleCompletionGetSuggestions(params);
break;
case EDIT_REQUEST_GET_ASSISTS:
- result = handleEditGetAssists(request.params);
+ var params = new EditGetAssistsParams.fromRequest(request);
+ result = handleEditGetAssists(params);
break;
case EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS:
- result = handleEditGetAvailableRefactorings(request.params);
+ var params =
+ new EditGetAvailableRefactoringsParams.fromRequest(request);
+ result = handleEditGetAvailableRefactorings(params);
break;
case EDIT_REQUEST_GET_FIXES:
- result = handleEditGetFixes(request.params);
+ var params = new EditGetFixesParams.fromRequest(request);
+ result = handleEditGetFixes(params);
break;
case EDIT_REQUEST_GET_REFACTORING:
- result = handleEditGetRefactoring(request.params);
+ var params = new EditGetRefactoringParams.fromRequest(request);
+ result = handleEditGetRefactoring(params);
break;
case PLUGIN_REQUEST_SHUTDOWN:
- result = handlePluginShutdown(request.params);
+ var params = new PluginShutdownParams();
+ result = handlePluginShutdown(params);
_channel.sendResponse(result.toResponse(request.id));
_channel.close();
return null;
case PLUGIN_REQUEST_VERSION_CHECK:
- result = handlePluginVersionCheck(request.params);
+ var params = new PluginVersionCheckParams.fromRequest(request);
+ result = handlePluginVersionCheck(params);
break;
}
if (result == null) {

Powered by Google App Engine
This is Rietveld 408576698