Skip to content

Commit 26102c5

Browse files
srawlinsCommit Queue
authored andcommitted
DAS plugins: Wire up initial screen for new plugins.
This renames the old screen, "Legacy plugins" and adds a new screen, "Plugins". On the new plugins screen, we ask the plugins isolate(s) for their plugins details, and print the following, for eadh plugin: * the plugin's name * the names of the registered lint rules * the names of the registered warning rules * the IDs and "messages" of the registered assists * the IDs and "messages" and associated diagnostic codes of the registered quick fixes More to come in follow ups: * The resolved versions of plugin packages (coming from package_config.json) Change-Id: Ic3dc4c5bffa64fd4da4097c042a847cc064e41ce Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/447763 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 9342bac commit 26102c5

35 files changed

+1942
-100
lines changed

pkg/analysis_server/doc/api.html

Lines changed: 69 additions & 2 deletions
Large diffs are not rendered by default.

pkg/analysis_server/integration_test/support/protocol_matchers.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,19 @@ final Matcher isAnalysisStatus = LazyMatcher(
177177
),
178178
);
179179

180+
/// AssistDescription
181+
///
182+
/// {
183+
/// "id": String
184+
/// "message": String
185+
/// }
186+
final Matcher isAssistDescription = LazyMatcher(
187+
() => MatchesJsonObject('AssistDescription', {
188+
'id': isString,
189+
'message': isString,
190+
}),
191+
);
192+
180193
/// BulkFix
181194
///
182195
/// {
@@ -588,6 +601,21 @@ final Matcher isFileKind = MatchesEnum('FileKind', ['LIBRARY', 'PART']);
588601
/// String
589602
final Matcher isFilePath = isString;
590603

604+
/// FixDescription
605+
///
606+
/// {
607+
/// "id": String
608+
/// "message": String
609+
/// "codes": List<String>
610+
/// }
611+
final Matcher isFixDescription = LazyMatcher(
612+
() => MatchesJsonObject('FixDescription', {
613+
'id': isString,
614+
'message': isString,
615+
'codes': isListOf(isString),
616+
}),
617+
);
618+
591619
/// FlutterOutline
592620
///
593621
/// {
@@ -1358,6 +1386,25 @@ final Matcher isParameterKind = MatchesEnum('ParameterKind', [
13581386
'REQUIRED_POSITIONAL',
13591387
]);
13601388

1389+
/// PluginDetails
1390+
///
1391+
/// {
1392+
/// "name": String
1393+
/// "lintRules": List<String>
1394+
/// "warningRules": List<String>
1395+
/// "assists": List<AssistDescription>
1396+
/// "fixes": List<FixDescription>
1397+
/// }
1398+
final Matcher isPluginDetails = LazyMatcher(
1399+
() => MatchesJsonObject('PluginDetails', {
1400+
'name': isString,
1401+
'lintRules': isListOf(isString),
1402+
'warningRules': isListOf(isString),
1403+
'assists': isListOf(isAssistDescription),
1404+
'fixes': isListOf(isFixDescription),
1405+
}),
1406+
);
1407+
13611408
/// Position
13621409
///
13631410
/// {

pkg/analysis_server/lib/src/plugin/plugin_isolate.dart

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,16 @@ class PluginIsolate {
5353

5454
CaughtException? _exception;
5555

56+
bool isLegacy;
57+
5658
PluginIsolate(
5759
this._path,
5860
this.executionPath,
5961
this.packagesPath,
6062
this._notificationManager,
61-
this._instrumentationService,
62-
);
63+
this._instrumentationService, {
64+
required this.isLegacy,
65+
});
6366

6467
/// The data known about this plugin, for instrumentation and exception
6568
/// purposes.
@@ -141,6 +144,25 @@ class PluginIsolate {
141144
_notificationManager.handlePluginError(message);
142145
}
143146

147+
/// Requests plugin details from the plugin isolate.
148+
Future<PluginDetailsResult?> requestDetails() async {
149+
if (currentSession case PluginSession currentSession) {
150+
Response response;
151+
try {
152+
response = await currentSession
153+
.sendRequest(PluginDetailsParams())
154+
.timeout(const Duration(seconds: 5));
155+
} on TimeoutException {
156+
// TODO(srawlins): Return a `PluginDetailsResult` with a specific error?
157+
return null;
158+
}
159+
if (response.error != null) throw response.error!;
160+
return PluginDetailsResult.fromResponse(response);
161+
} else {
162+
return null;
163+
}
164+
}
165+
144166
/// If the plugin is currently running, sends a request based on the given
145167
/// [params] to the plugin.
146168
///

pkg/analysis_server/lib/src/plugin/plugin_manager.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,15 @@ class PluginManager {
127127
this.instrumentationService,
128128
);
129129

130-
/// Return a list of all of the plugins that are currently known.
130+
/// All of the legacy plugins that are currently known.
131+
List<PluginIsolate> get legacyPluginIsolates =>
132+
pluginIsolates.where((p) => p.isLegacy).toList();
133+
134+
/// All of the "new" plugins that are currently known.
135+
List<PluginIsolate> get newPluginIsolates =>
136+
pluginIsolates.where((p) => !p.isLegacy).toList();
137+
138+
/// All of the plugins that are currently known.
131139
List<PluginIsolate> get pluginIsolates => _pluginMap.values.toList();
132140

133141
/// Stream emitting an event when known [pluginIsolates] change.
@@ -159,6 +167,7 @@ class PluginManager {
159167
null,
160168
_notificationManager,
161169
instrumentationService,
170+
isLegacy: isLegacyPlugin,
162171
);
163172
pluginIsolate.reportException(CaughtException(exception, stackTrace));
164173
_pluginMap[path] = pluginIsolate;
@@ -170,6 +179,7 @@ class PluginManager {
170179
pluginFiles.packageConfig.path,
171180
_notificationManager,
172181
instrumentationService,
182+
isLegacy: isLegacyPlugin,
173183
);
174184
_pluginMap[path] = pluginIsolate;
175185
try {

pkg/analysis_server/lib/src/plugin2/generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ environment:
7171
dependencies:
7272
# The version of the analysis_server_plugin package that matches the protocol
7373
# used by the active analysis_server.
74-
analysis_server_plugin: ^0.2.0
74+
analysis_server_plugin: ^0.3.0
7575
''');
7676

7777
for (var configuration in _configurations) {

pkg/analysis_server/lib/src/status/diagnostics.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import 'package:analysis_server/src/status/pages/exceptions_page.dart';
2929
import 'package:analysis_server/src/status/pages/feedback_page.dart';
3030
import 'package:analysis_server/src/status/pages/file_byte_store_timing_page.dart';
3131
import 'package:analysis_server/src/status/pages/fixes_page.dart';
32+
import 'package:analysis_server/src/status/pages/legacy_plugins_page.dart';
3233
import 'package:analysis_server/src/status/pages/lsp_capabilities_page.dart';
3334
import 'package:analysis_server/src/status/pages/lsp_client_page.dart';
3435
import 'package:analysis_server/src/status/pages/lsp_registrations_page.dart';
@@ -440,6 +441,7 @@ td.pre {
440441
var server = socketServer.analysisServer;
441442
if (server != null) {
442443
pages.add(PluginsPage(this, server));
444+
pages.add(LegacyPluginsPage(this, server));
443445
}
444446
if (server is LegacyAnalysisServer) {
445447
pages.add(ClientPage(this));
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/analysis_server.dart';
8+
import 'package:analysis_server/src/plugin/plugin_manager.dart';
9+
import 'package:analysis_server/src/status/diagnostics.dart';
10+
import 'package:analysis_server/src/status/utilities/string_extensions.dart';
11+
import 'package:analyzer/dart/analysis/context_root.dart';
12+
import 'package:path/path.dart' as path;
13+
14+
class LegacyPluginsPage extends DiagnosticPageWithNav {
15+
@override
16+
AnalysisServer server;
17+
18+
LegacyPluginsPage(DiagnosticsSite site, this.server)
19+
: super(
20+
site,
21+
'legacy-plugins',
22+
'Legacy Plugins',
23+
description: 'Legacy plugins in use.',
24+
);
25+
26+
@override
27+
Future<void> generateContent(Map<String, String> params) async {
28+
h3('Legacy analysis plugins');
29+
var plugins = server.pluginManager.legacyPluginIsolates;
30+
31+
if (plugins.isEmpty) {
32+
blankslate('No known legacy analysis plugins.');
33+
return;
34+
}
35+
36+
plugins.sort((a, b) => a.pluginId.compareTo(b.pluginId));
37+
for (var plugin in plugins) {
38+
var id = plugin.pluginId;
39+
var data = plugin.data;
40+
41+
var components = path.split(id);
42+
var length = components.length;
43+
var name = switch (length) {
44+
0 => 'unknown plugin',
45+
> 2 => components[length - 3],
46+
_ => components[length - 1],
47+
};
48+
h4(name);
49+
50+
_emitTable([
51+
['Bootstrap package path', id],
52+
if (plugin.executionPath case var executionPath?)
53+
['Execution path:', executionPath.wordBreakOnSlashes],
54+
if (plugin.packagesPath case var packagesPath?)
55+
['Packages file path', packagesPath.wordBreakOnSlashes],
56+
]);
57+
58+
if (data.name == null) {
59+
if (plugin.exception != null) {
60+
p('Not running due to:');
61+
pre(() {
62+
buf.write(plugin.exception);
63+
});
64+
} else {
65+
p(
66+
'Not running for unknown reason (no exception was caught while '
67+
'starting).',
68+
);
69+
}
70+
return;
71+
}
72+
73+
p('Name: ${data.name}');
74+
p('Version: ${data.version}');
75+
p('Associated contexts:');
76+
var contexts = plugin.contextRoots;
77+
if (contexts.isEmpty) {
78+
blankslate('none');
79+
} else {
80+
ul(contexts.toList(), (ContextRoot root) {
81+
buf.writeln(root.root);
82+
});
83+
}
84+
85+
p('Performance:');
86+
var responseTimes = PluginManager.pluginResponseTimes[plugin] ?? {};
87+
var entries = responseTimes.entries.toList();
88+
entries.sort((first, second) => first.key.compareTo(second.key));
89+
for (var entry in entries) {
90+
var requestName = entry.key;
91+
var data = entry.value;
92+
// TODO(brianwilkerson): Consider displaying these times as a graph,
93+
// similar to the one in CompletionPage.generateContent.
94+
var buffer = StringBuffer();
95+
buffer.write(requestName);
96+
buffer.write(' ');
97+
buffer.write(data.toAnalyticsString());
98+
p(buffer.toString());
99+
}
100+
}
101+
}
102+
103+
void _emitTable(List<List<String>> data) {
104+
buf.writeln('<table>');
105+
for (var row in data) {
106+
buf.writeln('<tr>');
107+
for (var value in row) {
108+
buf.writeln('<td>$value</td>');
109+
}
110+
buf.writeln('</tr>');
111+
}
112+
113+
buf.writeln('</table>');
114+
}
115+
}

0 commit comments

Comments
 (0)