Skip to content

Commit

Permalink
analyzer_plugin: Introduce messages/types for plugin analysis status
Browse files Browse the repository at this point in the history
There is no code in this CL that _uses_ the new AnalysisStatus
Notification or type, but landing it is important, so that I can test
plugins which will use the analyzer_plugin package from pub.

Change-Id: I31f835d5f7b8bda3781a6962d37f1f769b22852e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404702
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Samuel Rawlins <[email protected]>
  • Loading branch information
srawlins authored and Commit Queue committed Jan 16, 2025
1 parent fa2f2dd commit f72576a
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 2 deletions.
2 changes: 2 additions & 0 deletions pkg/analyzer_plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
- Remove `elementName()` from `RangeFactory`. Use `fragmentName()` instead.
- Breaking changes to `DartFileEditBuilder` and `DartEditBuilder`.
- Breaking changes to `AnalyzerConverter`.
- Support for a plugin to send an `AnalysisStatus` notification, featuring an
`isAnalyzing` `bool` field.

## 0.12.0
- Breaking changes to `DartFileEditBuilder`: `convertFunctionFromSyncToAsync`
Expand Down
38 changes: 36 additions & 2 deletions pkg/analyzer_plugin/doc/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ <h2 class="domain"><a name="domain_plugin">plugin domain</a></h2>




<h3>Requests</h3><dl><dt class="request"><a name="request_plugin.versionCheck">plugin.versionCheck</a></dt><dd><div class="box"><pre>request: {
"id": String
"method": "plugin.versionCheck"
Expand Down Expand Up @@ -262,6 +263,26 @@ <h4>parameters:</h4><dl><dt class="field"><b>isFatal: bool</b></dt><dd>
The stack trace associated with the generation of the error, used for
debugging the plugin.
</p>
</dd></dl></dd><dt class="notification"><a name="notification_plugin.status">plugin.status</a></dt><dd><div class="box"><pre>notification: {
"event": "plugin.status"
"params": {
"<b>analysis</b>": <span style="color:#999999">optional</span> <a href="#type_AnalysisStatus">AnalysisStatus</a>
}
}</pre></div>
<p>
Reports the current status of the plugin. Parameters are omitted if there
has been no change in the status represented by that parameter.
</p>
<p>
Only used for "new" analyzer plugins. Legacy plugins should not use
this type.
</p>

<h4>parameters:</h4><dl><dt class="field"><b>analysis: <a href="#type_AnalysisStatus">AnalysisStatus</a><span style="color:#999999"> (optional)</span></b></dt><dd>

<p>
The current status of analysis (whether analysis is being performed).
</p>
</dd></dl></dd></dl>
<h2 class="domain"><a name="domain_analysis">analysis domain</a></h2>
<p>
Expand Down Expand Up @@ -844,6 +865,7 @@ <h2 class="domain"><a name="types">Types</a></h2>




<dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
<p>
A directive to begin overlaying the contents of a file. The supplied
Expand Down Expand Up @@ -957,7 +979,19 @@ <h2 class="domain"><a name="types">Types</a></h2>
related to a specific list of files.
</p>

<dl><dt class="value">FOLDING</dt><dt class="value">HIGHLIGHTS</dt><dt class="value">NAVIGATION</dt><dt class="value">OCCURRENCES</dt><dt class="value">OUTLINE</dt></dl></dd><dt class="typeDefinition"><a name="type_ChangeContentOverlay">ChangeContentOverlay: object</a></dt><dd>
<dl><dt class="value">FOLDING</dt><dt class="value">HIGHLIGHTS</dt><dt class="value">NAVIGATION</dt><dt class="value">OCCURRENCES</dt><dt class="value">OUTLINE</dt></dl></dd><dt class="typeDefinition"><a name="type_AnalysisStatus">AnalysisStatus: object</a></dt><dd>
<p>
An indication of the current state of analysis.
</p>
<p>
Only used for "new" analyzer plugins. Legacy plugins should not use
this type.
</p>

<dl><dt class="field"><b>isAnalyzing: bool</b></dt><dd>

<p>True if analysis is currently being performed.</p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_ChangeContentOverlay">ChangeContentOverlay: object</a></dt><dd>
<p>
A directive to modify an existing file content overlay. One or more ranges
of text are deleted from the old file content overlay and replaced with
Expand Down Expand Up @@ -2379,6 +2413,6 @@ <h4>Feedback:</h4><dl><dt class="field"><b>offset: int</b></dt><dd>
</p>
</dd></dl></dd></dl>
<h2 class="domain"><a name="index">Index</a></h2>
<h3>Domains</h3><h4>plugin (<a href="#domain_plugin"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_plugin.versionCheck">versionCheck</a></li><li><a href="#request_plugin.shutdown">shutdown</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_plugin.error">error</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.handleWatchEvents">handleWatchEvents</a></li><li><a href="#request_analysis.setContextRoots">setContextRoots</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li></ul></div></div><h4>completion (<a href="#domain_completion"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul></div><h4>edit (<a href="#domain_edit"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getFixes">getFixes</a></li></ul></div><h3>Types (<a href="#types"></a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextRoot">ContextRoot</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PrioritizedSourceChange">PrioritizedSourceChange</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_WatchEvent">WatchEvent</a></li><li><a href="#type_WatchEventType">WatchEventType</a></li></ul></div><h3>Refactorings (<a href="#refactorings"></a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
<h3>Domains</h3><h4>plugin (<a href="#domain_plugin"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_plugin.versionCheck">versionCheck</a></li><li><a href="#request_plugin.shutdown">shutdown</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_plugin.error">error</a></li><li><a href="#notification_plugin.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.handleWatchEvents">handleWatchEvents</a></li><li><a href="#request_analysis.setContextRoots">setContextRoots</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li></ul></div></div><h4>completion (<a href="#domain_completion"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul></div><h4>edit (<a href="#domain_edit"></a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getFixes">getFixes</a></li></ul></div><h3>Types (<a href="#types"></a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextRoot">ContextRoot</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PrioritizedSourceChange">PrioritizedSourceChange</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_WatchEvent">WatchEvent</a></li><li><a href="#type_WatchEventType">WatchEventType</a></li></ul></div><h3>Refactorings (<a href="#refactorings"></a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
</body>
</html>
2 changes: 2 additions & 0 deletions pkg/analyzer_plugin/lib/protocol/protocol_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const String PLUGIN_NOTIFICATION_ERROR = 'plugin.error';
const String PLUGIN_NOTIFICATION_ERROR_IS_FATAL = 'isFatal';
const String PLUGIN_NOTIFICATION_ERROR_MESSAGE = 'message';
const String PLUGIN_NOTIFICATION_ERROR_STACK_TRACE = 'stackTrace';
const String PLUGIN_NOTIFICATION_STATUS = 'plugin.status';
const String PLUGIN_NOTIFICATION_STATUS_ANALYSIS = 'analysis';
const String PLUGIN_REQUEST_SHUTDOWN = 'plugin.shutdown';
const String PLUGIN_REQUEST_VERSION_CHECK = 'plugin.versionCheck';
const String PLUGIN_REQUEST_VERSION_CHECK_BYTE_STORE_PATH = 'byteStorePath';
Expand Down
121 changes: 121 additions & 0 deletions pkg/analyzer_plugin/lib/protocol/protocol_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,59 @@ class AnalysisSetSubscriptionsResult implements ResponseResult {
int get hashCode => 218088493;
}

/// AnalysisStatus
///
/// {
/// "isAnalyzing": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisStatus implements HasToJson {
/// True if analysis is currently being performed.
bool isAnalyzing;

AnalysisStatus(this.isAnalyzing);

factory AnalysisStatus.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json,
{ClientUriConverter? clientUriConverter}) {
json ??= {};
if (json is Map) {
bool isAnalyzing;
if (json.containsKey('isAnalyzing')) {
isAnalyzing = jsonDecoder.decodeBool(
'$jsonPath.isAnalyzing', json['isAnalyzing']);
} else {
throw jsonDecoder.mismatch(jsonPath, 'isAnalyzing');
}
return AnalysisStatus(isAnalyzing);
} else {
throw jsonDecoder.mismatch(jsonPath, 'AnalysisStatus', json);
}
}

@override
Map<String, Object> toJson({ClientUriConverter? clientUriConverter}) {
var result = <String, Object>{};
result['isAnalyzing'] = isAnalyzing;
return result;
}

@override
String toString() => json.encode(toJson(clientUriConverter: null));

@override
bool operator ==(other) {
if (other is AnalysisStatus) {
return isAnalyzing == other.isAnalyzing;
}
return false;
}

@override
int get hashCode => isAnalyzing.hashCode;
}

/// analysis.updateContent params
///
/// {
Expand Down Expand Up @@ -3623,6 +3676,74 @@ class PluginShutdownResult implements ResponseResult {
int get hashCode => 9389109;
}

/// plugin.status params
///
/// {
/// "analysis": optional AnalysisStatus
/// }
///
/// Clients may not extend, implement or mix-in this class.
class PluginStatusParams implements HasToJson {
/// The current status of analysis (whether analysis is being performed).
AnalysisStatus? analysis;

PluginStatusParams({this.analysis});

factory PluginStatusParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json,
{ClientUriConverter? clientUriConverter}) {
json ??= {};
if (json is Map) {
AnalysisStatus? analysis;
if (json.containsKey('analysis')) {
analysis = AnalysisStatus.fromJson(
jsonDecoder, '$jsonPath.analysis', json['analysis'],
clientUriConverter: clientUriConverter);
}
return PluginStatusParams(analysis: analysis);
} else {
throw jsonDecoder.mismatch(jsonPath, 'plugin.status params', json);
}
}

factory PluginStatusParams.fromNotification(Notification notification,
{ClientUriConverter? clientUriConverter}) {
return PluginStatusParams.fromJson(
ResponseDecoder(null), 'params', notification.params,
clientUriConverter: clientUriConverter);
}

@override
Map<String, Object> toJson({ClientUriConverter? clientUriConverter}) {
var result = <String, Object>{};
var analysis = this.analysis;
if (analysis != null) {
result['analysis'] =
analysis.toJson(clientUriConverter: clientUriConverter);
}
return result;
}

Notification toNotification({ClientUriConverter? clientUriConverter}) {
return Notification(
'plugin.status', toJson(clientUriConverter: clientUriConverter));
}

@override
String toString() => json.encode(toJson(clientUriConverter: null));

@override
bool operator ==(other) {
if (other is PluginStatusParams) {
return analysis == other.analysis;
}
return false;
}

@override
int get hashCode => analysis.hashCode;
}

/// plugin.versionCheck params
///
/// {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,22 @@ abstract class IntegrationTestMixin {
/// Stream controller for [onPluginError].
late StreamController<PluginErrorParams> _onPluginError;

/// Reports the current status of the plugin. Parameters are omitted if there
/// has been no change in the status represented by that parameter.
///
/// Only used for "new" analyzer plugins. Legacy plugins should not use this
/// type.
///
/// Parameters
///
/// analysis: AnalysisStatus (optional)
///
/// The current status of analysis (whether analysis is being performed).
late Stream<PluginStatusParams> onPluginStatus;

/// Stream controller for [onPluginStatus].
late StreamController<PluginStatusParams> _onPluginStatus;

/// Return the navigation information associated with the given region of the
/// given file. If the navigation information for the given file has not yet
/// been computed, or the most recently computed navigation information for
Expand Down Expand Up @@ -661,6 +677,8 @@ abstract class IntegrationTestMixin {
void initializeInttestMixin() {
_onPluginError = StreamController<PluginErrorParams>(sync: true);
onPluginError = _onPluginError.stream.asBroadcastStream();
_onPluginStatus = StreamController<PluginStatusParams>(sync: true);
onPluginStatus = _onPluginStatus.stream.asBroadcastStream();
_onAnalysisErrors = StreamController<AnalysisErrorsParams>(sync: true);
onAnalysisErrors = _onAnalysisErrors.stream.asBroadcastStream();
_onAnalysisFolding = StreamController<AnalysisFoldingParams>(sync: true);
Expand Down Expand Up @@ -688,6 +706,11 @@ abstract class IntegrationTestMixin {
_onPluginError
.add(PluginErrorParams.fromJson(decoder, 'params', params));
break;
case 'plugin.status':
outOfTestExpect(params, isPluginStatusParams);
_onPluginStatus
.add(PluginStatusParams.fromJson(decoder, 'params', params));
break;
case 'analysis.errors':
outOfTestExpect(params, isAnalysisErrorsParams);
_onAnalysisErrors
Expand Down
Loading

0 comments on commit f72576a

Please sign in to comment.