blob: 5e754ab5990c291f1ac75ac042143aca75d7750f [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/handlers/code_actions/abstract_code_actions_producer.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
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:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
import 'package:collection/collection.dart';
/// Produces [CodeActionLiteral]s from Plugin fixes and assists.
class PluginCodeActionsProducer extends AbstractCodeActionsProducer {
final AnalysisDriver? driver;
PluginCodeActionsProducer(
super.server,
super.file,
super.lineInfo, {
required super.offset,
required super.length,
required super.shouldIncludeKind,
required super.capabilities,
required super.analysisOptions,
}) : driver = server.getAnalysisDriver(file.path);
@override
String get name => 'PluginActionsComputer';
@override
Future<List<CodeActionWithPriority>> getAssistActions({
OperationPerformance? performance,
}) async {
// These assists are only provided as literal CodeActions.
if (!supportsLiterals) {
return [];
}
var requestParams = plugin.EditGetAssistsParams(path, offset, length);
var responses = await _sendPluginRequest(requestParams);
return responses
.map((response) => plugin.EditGetAssistsResult.fromResponse(response))
.expand((response) => response.assists)
.map(_convertAssist)
.toList();
}
@override
Future<List<CodeActionWithPriority>> getFixActions(
OperationPerformance? performance,
) async {
// These fixes are only provided as literal CodeActions.
if (!supportsLiterals) {
return [];
}
var requestParams = plugin.EditGetFixesParams(path, offset);
var responses = await _sendPluginRequest(requestParams);
return responses
.map((response) => plugin.EditGetFixesResult.fromResponse(response))
.expand((response) => response.fixes)
.map(_convertFixes)
.flattenedToList;
}
@override
Future<List<CodeAction>> getRefactorActions(
OperationPerformance? performance,
) async => [];
@override
Future<List<CodeAction>> getSourceActions() async => [];
CodeActionWithPriority _convertAssist(plugin.PrioritizedSourceChange assist) {
return (
action: createAssistAction(
assist.change,
'assist from plugin',
path,
lineInfo,
),
priority: assist.priority,
);
}
Iterable<CodeActionWithPriority> _convertFixes(
plugin.AnalysisErrorFixes fixes,
) {
var diagnostic = pluginToDiagnostic(
server.uriConverter,
(_) => lineInfo,
fixes.error,
supportedTags: supportedDiagnosticTags,
clientSupportsCodeDescription: supportsCodeDescription,
);
return fixes.fixes.map(
(fix) => (
action: createFixAction(
fix.change,
'fix from plugin',
diagnostic,
path,
lineInfo,
),
priority: fix.priority,
),
);
}
Future<List<plugin.Response>> _sendPluginRequest(
plugin.RequestParams requestParams,
) async {
var driver = this.driver;
if (driver == null) {
return [];
}
var pluginFutures = server.broadcastRequestToPlugins(requestParams, driver);
return waitForResponses(pluginFutures, requestParameters: requestParams);
}
}