[analysis_server] Record more granular timings for LSP textDocument/codeAction request

Change-Id: I29d16b4e4f077cc0bfa9bff6a930dce506ba100c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244100
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny 2022-05-09 18:35:43 +00:00 committed by Commit Bot
parent 934f4802bd
commit 091454876e
4 changed files with 85 additions and 36 deletions

View file

@ -21,6 +21,7 @@ import 'package:analyzer/dart/analysis/session.dart'
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart' show groupBy;
@ -118,7 +119,10 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
return endOffset.mapResult((endOffset) {
final offset = startOffset;
final length = endOffset - startOffset;
return _getCodeActions(
return message.performance.runAsync(
'getCodeActions',
(performance) => _getCodeActions(
performance,
shouldIncludeKind,
supportsLiteralCodeActions,
supportsApplyEdit,
@ -127,7 +131,9 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
params.range,
offset,
length,
unit);
unit,
),
);
});
});
});
@ -298,6 +304,7 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
}
Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
OperationPerformanceImpl performance,
bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiterals,
bool supportsWorkspaceApplyEdit,
@ -309,14 +316,26 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
ResolvedUnitResult unit,
) async {
final results = await Future.wait([
_getSourceActions(shouldIncludeKind, supportsLiterals,
supportsWorkspaceApplyEdit, path),
_getAssistActions(shouldIncludeKind, supportsLiterals, path, range,
offset, length, unit),
_getRefactorActions(
shouldIncludeKind, supportsLiterals, path, offset, length, unit),
_getFixActions(shouldIncludeKind, supportsLiterals, path, offset,
supportedDiagnosticTags, range, unit),
performance.runAsync(
'_getSourceActions',
(_) => _getSourceActions(shouldIncludeKind, supportsLiterals,
supportsWorkspaceApplyEdit, path),
),
performance.runAsync(
'_getAssistActions',
(_) => _getAssistActions(shouldIncludeKind, supportsLiterals, path,
range, offset, length, unit),
),
performance.runAsync(
'_getRefactorActions',
(_) => _getRefactorActions(
shouldIncludeKind, supportsLiterals, path, offset, length, unit),
),
performance.runAsync(
'_getFixActions',
(_) => _getFixActions(shouldIncludeKind, supportsLiterals, path, offset,
supportedDiagnosticTags, range, unit),
),
]);
final flatResults = results.expand((x) => x).toList();
@ -343,15 +362,15 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
final pluginFuture = _getPluginFixActions(unit, offset);
try {
var workspace = DartChangeWorkspace(
await server.currentSessions,
);
for (final error in unit.errors) {
// Server lineNumber is one-based so subtract one.
var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
if (errorLine < range.start.line || errorLine > range.end.line) {
continue;
}
var workspace = DartChangeWorkspace(
await server.currentSessions,
);
var context = DartFixContextImpl(
server.instrumentationService, workspace, unit, error);
final fixes = await fixContributor.computeFixes(context);

View file

@ -110,7 +110,7 @@ class CompletionHandler extends MessageHandler<CompletionParams, CompletionList>
CompletionPerformance? completionPerformance;
if (fileExtension == '.dart' && !unit.isError) {
final result = unit.result;
var performance = OperationPerformanceImpl('<root>');
var performance = message.performance;
serverResultsFuture = performance.runAsync(
'request',
(performance) async {

View file

@ -16,6 +16,7 @@ import 'package:analysis_server/src/lsp/progress.dart';
import 'package:analysis_server/src/request_handler_mixin.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/cancellation.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
@ -167,8 +168,8 @@ abstract class MessageHandler<P, R>
/// Handle the given [message]. If the [message] is a [RequestMessage], then the
/// return value will be sent back in a [ResponseMessage].
/// [NotificationMessage]s are not expected to return results.
FutureOr<ErrorOr<R>> handleMessage(
IncomingMessage message, CancellationToken token) {
FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message,
MessageInfo messageInfo, CancellationToken token) {
final reporter = LspJsonReporter('params');
final paramsJson = message.params as Map<String, Object?>?;
if (!jsonHandler.validateParams(paramsJson, reporter)) {
@ -183,7 +184,6 @@ abstract class MessageHandler<P, R>
final params =
paramsJson != null ? jsonHandler.convertParams(paramsJson) : null as P;
final messageInfo = MessageInfo(timeSinceRequest: message.timeSinceRequest);
return handle(params, messageInfo, token);
}
}
@ -195,7 +195,9 @@ class MessageInfo {
/// request or `null` if the client did not provide [clientRequestTime].
final int? timeSinceRequest;
MessageInfo({this.timeSinceRequest});
OperationPerformanceImpl performance;
MessageInfo({required this.performance, this.timeSinceRequest});
}
/// A message handler that handles all messages for a given server state.
@ -213,14 +215,15 @@ abstract class ServerStateMessageHandler {
/// Handle the given [message]. If the [message] is a [RequestMessage], then the
/// return value will be sent back in a [ResponseMessage].
/// [NotificationMessage]s are not expected to return results.
FutureOr<ErrorOr<Object?>> handleMessage(IncomingMessage message) async {
FutureOr<ErrorOr<Object?>> handleMessage(
IncomingMessage message, MessageInfo messageInfo) async {
final handler = _messageHandlers[message.method];
if (handler == null) {
return handleUnknownMessage(message);
}
if (message is! RequestMessage) {
return handler.handleMessage(message, _notCancelableToken);
return handler.handleMessage(message, messageInfo, _notCancelableToken);
}
// Create a cancellation token that will allow us to cancel this request if
@ -228,7 +231,7 @@ abstract class ServerStateMessageHandler {
// check the token after `await` points).
final token = _cancelHandler.createToken(message);
try {
final result = await handler.handleMessage(message, token);
final result = await handler.handleMessage(message, messageInfo, token);
// Do a final check before returning the result, because if the request was
// cancelled we can save the overhead of serialising everything to JSON
// and the client to deserialising the same in order to read the ID to see

View file

@ -350,31 +350,32 @@ class LspAnalysisServer extends AbstractAnalysisServer {
try {
if (message is ResponseMessage) {
handleClientResponse(message);
} else if (message is RequestMessage) {
} else if (message is IncomingMessage) {
final incomingMessage = message as IncomingMessage;
// Record performance information for the request.
final performance = OperationPerformanceImpl('<root>');
await performance.runAsync('request', (performance) async {
final requestPerformance = RequestPerformance(
operation: message.method.toString(),
operation: incomingMessage.method.toString(),
performance: performance,
requestLatency: message.timeSinceRequest,
requestLatency: incomingMessage.timeSinceRequest,
);
recentPerformance.requests.add(requestPerformance);
final result = await messageHandler.handleMessage(message);
if (result.isError) {
sendErrorResponse(message, result.error);
final messageInfo = MessageInfo(
performance: performance,
timeSinceRequest: incomingMessage.timeSinceRequest,
);
if (message is RequestMessage) {
await _handleRequestMessage(message, messageInfo);
} else if (message is NotificationMessage) {
await _handleNotificationMessage(message, messageInfo);
} else {
channel.sendResponse(ResponseMessage(
id: message.id,
result: result.result,
jsonrpc: jsonRpcVersion));
showErrorMessageToUser('Unknown incoming message type');
}
});
} else if (message is NotificationMessage) {
final result = await messageHandler.handleMessage(message);
if (result.isError) {
sendErrorResponse(message, result.error);
}
} else {
showErrorMessageToUser('Unknown message type');
}
@ -783,6 +784,32 @@ class LspAnalysisServer extends AbstractAnalysisServer {
];
}
Future<void> _handleNotificationMessage(
NotificationMessage message,
MessageInfo messageInfo,
) async {
final result = await messageHandler.handleMessage(message, messageInfo);
if (result.isError) {
sendErrorResponse(message, result.error);
}
}
Future<void> _handleRequestMessage(
RequestMessage message,
MessageInfo messageInfo,
) async {
final result = await messageHandler.handleMessage(message, messageInfo);
if (result.isError) {
sendErrorResponse(message, result.error);
} else {
channel.sendResponse(ResponseMessage(
id: message.id,
result: result.result,
jsonrpc: jsonRpcVersion,
));
}
}
void _onPluginsChanged() {
capabilitiesComputer.performDynamicRegistration();
}