[analysis_server] Rename "CodeAction" to CodeActionLiteral"

The term "CodeAction" is a bit overloaded. It could mean both an
individual result from the `textDocument/codeAction` request (which is a
`Command` or a `CodeAction`), or the `CodeAction` type defined in
the spec (which the spec refers to as a "Code Action literal").

To reduce confusion where we have similar APIs that operate on
"Code Actions" (CodeAction|Command), this renames the `CodeAction` class to
`CodeActionLiteral` and we will use the term `CodeAction` to mean either of
those types.

To make things simpler to review, this change _only_ renames the class, and also swaps the order of the types in some places that used `Either2<Command, CodeAction>` (which is opposite to the spec and some other code). Some further clean up will be done in a separate change.

Change-Id: Idcd8265f9229c3450004e68334e98a7b530330a4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425300
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny
2025-04-29 20:54:58 -07:00
committed by Commit Queue
parent 4cc31f8f4f
commit 9831fc4e98
19 changed files with 302 additions and 286 deletions
@@ -20,12 +20,12 @@ import 'package:analyzer/src/dart/analysis/results.dart' as engine;
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:meta/meta.dart';
typedef CodeActionWithPriority = ({CodeAction action, int priority});
typedef CodeActionWithPriority = ({CodeActionLiteral action, int priority});
typedef CodeActionWithPriorityAndIndex =
({CodeAction action, int priority, int index});
({CodeActionLiteral action, int priority, int index});
/// A base for classes that produce [CodeAction]s for the LSP handler.
/// A base for classes that produce [CodeActionLiteral]s for the LSP handler.
abstract class AbstractCodeActionsProducer
with RequestHandlerMixin<LspAnalysisServer> {
final File file;
@@ -68,13 +68,13 @@ abstract class AbstractCodeActionsProducer
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
@protected
CodeAction createAssistAction(
CodeActionLiteral createAssistAction(
protocol.SourceChange change,
String? loggedAssistId,
String path,
LineInfo lineInfo,
) {
return CodeAction(
return CodeActionLiteral(
title: change.message,
kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
diagnostics: const [],
@@ -111,14 +111,14 @@ abstract class AbstractCodeActionsProducer
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
@protected
CodeAction createFixAction(
CodeActionLiteral createFixAction(
protocol.SourceChange change,
String? loggedFixId,
Diagnostic diagnostic,
String path,
LineInfo lineInfo,
) {
return CodeAction(
return CodeActionLiteral(
title: change.message,
kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
diagnostics: [diagnostic],
@@ -180,11 +180,11 @@ abstract class AbstractCodeActionsProducer
OperationPerformance? performance,
);
Future<List<Either2<CodeAction, Command>>> getRefactorActions(
Future<List<Either2<CodeActionLiteral, Command>>> getRefactorActions(
OperationPerformance? performance,
);
Future<List<Either2<CodeAction, Command>>> getSourceActions();
Future<List<Either2<CodeActionLiteral, Command>>> getSourceActions();
/// Return the contents of the [file], or `null` if the file does not exist or
/// cannot be read.
@@ -16,7 +16,7 @@ import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/workspace/pub.dart';
import 'package:yaml/yaml.dart';
/// Produces [CodeAction]s from analysis options fixes.
/// Produces [CodeActionLiteral]s from analysis options fixes.
class AnalysisOptionsCodeActionsProducer extends AbstractCodeActionsProducer {
AnalysisOptionsCodeActionsProducer(
super.server,
@@ -111,12 +111,13 @@ class AnalysisOptionsCodeActionsProducer extends AbstractCodeActionsProducer {
}
@override
Future<List<Either2<CodeAction, Command>>> getRefactorActions(
Future<List<Either2<CodeActionLiteral, Command>>> getRefactorActions(
OperationPerformance? performance,
) async => [];
@override
Future<List<Either2<CodeAction, Command>>> getSourceActions() async => [];
Future<List<Either2<CodeActionLiteral, Command>>> getSourceActions() async =>
[];
YamlMap? _getOptions(SourceFactory sourceFactory, String content) {
var optionsProvider = AnalysisOptionsProvider(sourceFactory);
@@ -30,7 +30,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/utilities/extensions/ast.dart';
/// Produces [CodeAction]s from Dart source commands, fixes, assists and
/// Produces [CodeActionLiteral]s from Dart source commands, fixes, assists and
/// refactors from the server.
class DartCodeActionsProducer extends AbstractCodeActionsProducer {
ResolvedLibraryResult libraryResult;
@@ -58,9 +58,9 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
@override
String get name => 'ServerDartActionsComputer';
/// Helper to create a [CodeAction] or [Command] for the given arguments in
/// Helper to create a [CodeActionLiteral] or [Command] for the given arguments in
/// the current file based on client capabilities.
Either2<CodeAction, Command> createCommand(
Either2<CodeActionLiteral, Command> createCommand(
CodeActionKind actionKind,
String title,
String command,
@@ -87,7 +87,7 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
/// Helper to create refactors that execute commands provided with
/// the current file, location and document version.
Either2<CodeAction, Command> createRefactor(
Either2<CodeActionLiteral, Command> createRefactor(
CodeActionKind actionKind,
String name,
RefactoringKind refactorKind, [
@@ -263,7 +263,7 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
}
@override
Future<List<Either2<CodeAction, Command>>> getRefactorActions(
Future<List<Either2<CodeActionLiteral, Command>>> getRefactorActions(
OperationPerformance? performance,
) async {
// If the client does not support workspace/applyEdit, we won't be able to
@@ -272,7 +272,7 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
return const [];
}
var refactorActions = <Either2<CodeAction, Command>>[];
var refactorActions = <Either2<CodeActionLiteral, Command>>[];
var performanceTracker = RefactoringPerformance();
try {
@@ -293,7 +293,9 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
performance: performanceTracker,
);
var actions = await processor.compute();
refactorActions.addAll(actions.map(Either2<CodeAction, Command>.t1));
refactorActions.addAll(
actions.map(Either2<CodeActionLiteral, Command>.t1),
);
// Extracts
if (shouldIncludeKind(CodeActionKind.RefactorExtract)) {
@@ -469,7 +471,7 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
/// Gets "Source" CodeActions, which are actions that apply to whole files of
/// source such as Sort Members and Organise Imports.
@override
Future<List<Either2<CodeAction, Command>>> getSourceActions() async {
Future<List<Either2<CodeActionLiteral, Command>>> getSourceActions() async {
// If the client does not support workspace/applyEdit, we won't be able to
// run any of these.
if (!supportsApplyEdit) {
@@ -496,15 +498,15 @@ class DartCodeActionsProducer extends AbstractCodeActionsProducer {
/// Wraps a command in a CodeAction if the client supports it so that a
/// CodeActionKind can be supplied.
Either2<CodeAction, Command> _commandOrCodeAction(
Either2<CodeActionLiteral, Command> _commandOrCodeAction(
CodeActionKind kind,
Command command,
) {
return supportsLiterals
? Either2<CodeAction, Command>.t1(
CodeAction(title: command.title, kind: kind, command: command),
? Either2<CodeActionLiteral, Command>.t1(
CodeActionLiteral(title: command.title, kind: kind, command: command),
)
: Either2<CodeAction, Command>.t2(command);
: Either2<CodeActionLiteral, Command>.t2(command);
}
}
@@ -14,7 +14,7 @@ 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 [CodeAction]s from Plugin fixes and assists.
/// Produces [CodeActionLiteral]s from Plugin fixes and assists.
class PluginCodeActionsProducer extends AbstractCodeActionsProducer {
final AnalysisDriver? driver;
@@ -71,12 +71,13 @@ class PluginCodeActionsProducer extends AbstractCodeActionsProducer {
}
@override
Future<List<Either2<CodeAction, Command>>> getRefactorActions(
Future<List<Either2<CodeActionLiteral, Command>>> getRefactorActions(
OperationPerformance? performance,
) async => [];
@override
Future<List<Either2<CodeAction, Command>>> getSourceActions() async => [];
Future<List<Either2<CodeActionLiteral, Command>>> getSourceActions() async =>
[];
CodeActionWithPriority _convertAssist(plugin.PrioritizedSourceChange assist) {
return (
@@ -13,7 +13,7 @@ import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:yaml/yaml.dart';
/// Produces [CodeAction]s from Pubspec fixes.
/// Produces [CodeActionLiteral]s from Pubspec fixes.
class PubspecCodeActionsProducer extends AbstractCodeActionsProducer {
PubspecCodeActionsProducer(
super.server,
@@ -97,10 +97,11 @@ class PubspecCodeActionsProducer extends AbstractCodeActionsProducer {
}
@override
Future<List<Either2<CodeAction, Command>>> getRefactorActions(
Future<List<Either2<CodeActionLiteral, Command>>> getRefactorActions(
OperationPerformance? performance,
) async => [];
@override
Future<List<Either2<CodeAction, Command>>> getSourceActions() async => [];
Future<List<Either2<CodeActionLiteral, Command>>> getSourceActions() async =>
[];
}
@@ -219,7 +219,7 @@ class CodeActionHandler
];
var sorter = _CodeActionSorter(params.range, shouldIncludeKind);
var allActions = <Either2<CodeAction, Command>>[
var allActions = <Either2<CodeActionLiteral, Command>>[
// Like-kinded actions are grouped (and prioritized) together
// regardless of which producer they came from.
@@ -306,7 +306,7 @@ class _CodeActionSorter {
_CodeActionSorter(this.range, this.shouldIncludeKind);
List<Either2<CodeAction, Command>> sort(
List<Either2<CodeActionLiteral, Command>> sort(
List<CodeActionWithPriority> actions,
) {
var dedupedActions = _dedupeActions(actions, range.start);
@@ -325,16 +325,15 @@ class _CodeActionSorter {
return dedupedActionsWithIndex
.where((action) => shouldIncludeKind(action.action.kind))
.map((action) => Either2<CodeAction, Command>.t1(action.action))
.map((action) => Either2<CodeActionLiteral, Command>.t1(action.action))
.toList();
}
/// Creates a comparer for [CodeAction]s that compares the column distance from
/// Creates a comparer for [CodeActionLiteral]s that compares the column distance from
/// [pos].
int Function(CodeAction a, CodeAction b) _codeActionColumnDistanceComparer(
Position pos,
) {
Position posOf(CodeAction action) {
int Function(CodeActionLiteral a, CodeActionLiteral b)
_codeActionColumnDistanceComparer(Position pos) {
Position posOf(CodeActionLiteral action) {
var diagnostics = action.diagnostics;
return diagnostics != null && diagnostics.isNotEmpty
? diagnostics.first.range.start
@@ -423,7 +422,7 @@ class _CodeActionSorter {
// Build a new CodeAction that merges the diagnostics from each same
// code action onto a single one.
return (
action: CodeAction(
action: CodeActionLiteral(
title: first.title,
kind: first.kind,
// Merge diagnostics from all of the matching CodeActions.
@@ -40,9 +40,9 @@ class RefactoringProcessor {
/// Return a list containing one code action for each of the refactorings that
/// are available in the current context.
Future<List<CodeAction>> compute() async {
Future<List<CodeActionLiteral>> compute() async {
_timer.start();
var refactorings = <CodeAction>[];
var refactorings = <CodeActionLiteral>[];
for (var entry in RefactoringProcessor.generators.entries) {
var generator = entry.value;
var producer = generator(context);
@@ -83,7 +83,7 @@ class RefactoringProcessor {
);
refactorings.add(
CodeAction(
CodeActionLiteral(
title: producer.title,
kind: producer.kind,
command: Command(
@@ -15,8 +15,8 @@ import 'server_abstract.dart';
abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
/// Initializes the server with some basic configuration and expects to find
/// a [CodeAction] with [kind]/[command]/[title].
Future<CodeAction> expectAction(
/// a [CodeActionLiteral] with [kind]/[command]/[title].
Future<CodeActionLiteral> expectAction(
String content, {
CodeActionKind? kind,
String? command,
@@ -69,7 +69,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
}
/// Initializes the server with some basic configuration and expects not to
/// find a [CodeAction] with [kind]/[command]/[title].
/// find a [CodeActionLiteral] with [kind]/[command]/[title].
Future<void> expectNoAction(
String content, {
String? filePath,
@@ -106,8 +106,8 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
/// a matching command/args.
///
/// Throws if zero or more than one actions match.
CodeAction? findAction(
List<Either2<Command, CodeAction>> actions, {
CodeActionLiteral? findAction(
List<Either2<CodeActionLiteral, Command>> actions, {
String? title,
CodeActionKind? kind,
String? command,
@@ -122,15 +122,15 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
).singleOrNull;
}
List<CodeAction> findActions(
List<Either2<Command, CodeAction>> actions, {
List<CodeActionLiteral> findActions(
List<Either2<CodeActionLiteral, Command>> actions, {
String? title,
CodeActionKind? kind,
String? command,
List<Object>? commandArgs,
}) {
return actions
.map((action) => action.map((cmd) => null, (action) => action))
.map((action) => action.map((action) => action, (cmd) => null))
.where((action) => title == null || action?.title == title)
.where((action) => kind == null || action?.kind == kind)
// Some tests filter by only supplying a command, so if there is no
@@ -165,15 +165,15 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
.toList();
}
Either2<Command, CodeAction>? findCommand(
List<Either2<Command, CodeAction>> actions,
Either2<CodeActionLiteral, Command>? findCommand(
List<Either2<CodeActionLiteral, Command>> actions,
String commandID, [
String? wantedTitle,
]) {
for (var codeAction in actions) {
var id = codeAction.map(
(cmd) => cmd.command,
(action) => action.command?.command,
(cmd) => cmd.command,
);
var title = codeAction.map((cmd) => cmd.title, (action) => action.title);
if (id == commandID && (wantedTitle == null || wantedTitle == title)) {
@@ -199,7 +199,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
}
/// Initializes the server with some basic configuration and expects to find
/// a [CodeAction] with [kind]/[title] that applies edits resulting in
/// a [CodeActionLiteral] with [kind]/[title] that applies edits resulting in
/// [expected].
Future<LspChangeVerifier> verifyActionEdits(
String content,
@@ -450,7 +450,7 @@ void main() {
var codeActions = await getCodeActions(mainFileUri, range: range);
var codeActionKinds = codeActions.map(
(item) =>
item.map((command) => null, (action) => action.kind?.toString()),
item.map((action) => action.kind?.toString(), (command) => null),
);
expect(
@@ -261,8 +261,8 @@ void f() {
var results = await ofKind(kind);
for (var result in results) {
var resultKind = result.map(
(cmd) => throw 'Expected CodeAction, got Command: ${cmd.title}',
(action) => action.kind,
(cmd) => throw 'Expected CodeAction, got Command: ${cmd.title}',
);
expect('$resultKind', anyOf([equals('$kind'), startsWith('$kind.')]));
}
@@ -26,7 +26,7 @@ abstract class AbstractSourceCodeActionsTest extends AbstractCodeActionsTest {
/// one must be provided), uses [startOfDocPos] to avoid every test needing
/// to include a '^' marker.
@override
Future<List<Either2<Command, CodeAction>>> getCodeActions(
Future<List<Either2<CodeActionLiteral, Command>>> getCodeActions(
Uri fileUri, {
Range? range,
Position? position,
@@ -385,8 +385,8 @@ int minified(int x, int y) => min(x, y);
var actions = await getCodeActions(mainFileUri);
var action = findCommand(actions, Commands.organizeImports)!;
action.map(
(command) {},
(codeActionLiteral) => throw 'Expected command, got codeActionLiteral',
(command) {},
);
}
@@ -524,8 +524,8 @@ String b;
var actions = await getCodeActions(mainFileUri);
var action = findCommand(actions, Commands.sortMembers)!;
action.map(
(command) {},
(codeActionLiteral) => throw 'Expected command, got codeActionLiteral',
(command) {},
);
}
@@ -320,7 +320,7 @@ mixin LspRequestHelpersMixin {
return expectSuccessfulResponseTo(request, Location.fromJson);
}
Future<List<Either2<Command, CodeAction>>> getCodeActions(
Future<List<Either2<CodeActionLiteral, Command>>> getCodeActions(
Uri fileUri, {
Range? range,
Position? position,
@@ -352,10 +352,10 @@ mixin LspRequestHelpersMixin {
request,
_fromJsonList(
_generateFromJsonFor(
CodeActionLiteral.canParse,
CodeActionLiteral.fromJson,
Command.canParse,
Command.fromJson,
CodeAction.canParse,
CodeAction.fromJson,
),
),
);
@@ -1038,10 +1038,12 @@ mixin LspAnalysisServerTestMixin on LspRequestHelpersMixin, LspEditHelpersMixin
await sendNotificationToServer(notification);
}
Future<Object?> executeCodeAction(Either2<Command, CodeAction> codeAction) {
Future<Object?> executeCodeAction(
Either2<CodeActionLiteral, Command> codeAction,
) {
var command = codeAction.map(
(command) => command,
(codeAction) => codeAction.command!,
(command) => command,
);
return executeCommand(command);
}
@@ -32,7 +32,7 @@ class ^A {}
String get refactoringName => MoveTopLevelToFile.commandName;
/// Replaces the "Save URI" argument in [action].
void replaceSaveUriArgument(CodeAction action, Uri newFileUri) {
void replaceSaveUriArgument(CodeActionLiteral action, Uri newFileUri) {
var arguments = getRefactorCommandArguments(action);
// The filename is the first item we prompt for so is first in the
// arguments.
@@ -44,27 +44,27 @@ abstract class RefactoringTest extends AbstractCodeActionsTest {
}
/// Executes the refactor in [action].
Future<void> executeRefactor(CodeAction action) async {
Future<void> executeRefactor(CodeActionLiteral action) async {
await executeCommandForEdits(action.command!);
}
/// Expects to find a refactor [CodeAction] in [mainFileUri] at the offset of
/// Expects to find a refactor [CodeActionLiteral] in [mainFileUri] at the offset of
/// the marker with the title [title].
Future<CodeAction> expectCodeAction(String title) async {
Future<CodeActionLiteral> expectCodeAction(String title) async {
var action = await getCodeAction(title);
expect(action, isNotNull, reason: "Action '$title' should be included");
return action!;
}
/// Expects to not find a refactor [CodeAction] in [mainFileUri] at the offset
/// Expects to not find a refactor [CodeActionLiteral] in [mainFileUri] at the offset
/// of the marker with the title [title].
Future<void> expectNoCodeAction(String? title) async {
expect(await getCodeAction(title), isNull);
}
/// Attempts to find a refactor [CodeAction] in [mainFileUri] at the offset of
/// Attempts to find a refactor [CodeActionLiteral] in [mainFileUri] at the offset of
/// the marker with the title [title].
Future<CodeAction?> getCodeAction(String? title) async {
Future<CodeActionLiteral?> getCodeAction(String? title) async {
var codeActions = await getCodeActions(
mainFileUri,
position: _position,
@@ -73,15 +73,15 @@ abstract class RefactoringTest extends AbstractCodeActionsTest {
);
var commandOrCodeAction = findCommand(codeActions, refactoringName, title);
var codeAction = commandOrCodeAction?.map(
(command) => throw 'Expected CodeAction, got Command',
(codeAction) => codeAction,
(command) => throw 'Expected CodeAction, got Command',
);
return codeAction;
}
/// Unwraps the 'arguments' field from the arguments object (which is the
/// single argument for the command).
List<Object?> getRefactorCommandArguments(CodeAction action) {
List<Object?> getRefactorCommandArguments(CodeActionLiteral action) {
var commandArguments = action.command!.arguments as List<Object?>;
// Our refactor command uses a single object in its arguments so we can have
@@ -566,9 +566,9 @@ List<LspEntity> getCustomClasses() {
'Information about one of the arguments needed by the command.'
'\n\n'
'A list of parameters is sent in the `data` field of the '
'`CodeAction` returned by the server. The values of the parameters '
'should appear in the `args` field of the `Command` sent to the '
'server in the same order as the corresponding parameters.',
'`CodeActionLiteral` returned by the server. The values of the '
'parameters should appear in the `args` field of the `Command` sent '
'to the server in the same order as the corresponding parameters.',
),
interface(
'SaveUriCommandParameter',
@@ -433,7 +433,16 @@ class LspMetaModelCleaner {
'SignatureInformationParameterInformation',
'Pattern': 'LspPattern',
'URI': 'LSPUri',
// The term "CodeAction" is a bit overloaded. It could mean both an
// individual result from the textDocument/codeAction request (which is a
// `Command` or a `CodeAction`), or the `CodeAction` type defined in
// the spec (which the spec also refers to as a "Code Action literal").
//
// To reduce confusion where we have similar APIs that operate on
// "Code Actions" (CodeAction|Command), we rename `CodeAction` to
// `CodeActionLiteral` and use the term `CodeAction` to mean either of
// those types.
'CodeAction': 'CodeActionLiteral',
// In LSP 3.18, many types that were previously inline and got generated
// names have been extracted to their own definitions with hand-written
// names.
@@ -849,7 +849,7 @@ class ClosingLabel implements ToJsonable {
/// Information about one of the arguments needed by the command.
///
/// A list of parameters is sent in the `data` field of the `CodeAction`
/// A list of parameters is sent in the `data` field of the `CodeActionLiteral`
/// returned by the server. The values of the parameters should appear in the
/// `args` field of the `Command` sent to the server in the same order as the
/// corresponding parameters.
@@ -7441,7 +7441,8 @@ typedef ProgressToken = Either2<int, String>;
/// Result for a request to provide commands for the given text document and
/// range.
typedef TextDocumentCodeActionResult = List<Either2<CodeAction, Command>>?;
typedef TextDocumentCodeActionResult
= List<Either2<CodeActionLiteral, Command>>?;
/// Result for a request to provide code lens for the given text document.
typedef TextDocumentCodeLensResult = List<CodeLens>?;
@@ -9428,213 +9429,6 @@ class ClientSemanticTokensRequestOptions implements ToJsonable {
}
}
/// A code action represents a change that can be performed in code, e.g. to fix
/// a problem or to refactor code.
///
/// A CodeAction must set either `edit` and/or a `command`. If both are
/// supplied, the `edit` is applied first, then the `command` is executed.
class CodeAction implements ToJsonable {
static const jsonHandler = LspJsonHandler(
CodeAction.canParse,
CodeAction.fromJson,
);
/// A command this code action executes. If a code action provides an edit and
/// a command, first the edit is executed and then the command.
final Command? command;
/// A data entry field that is preserved on a code action between a
/// `textDocument/codeAction` and a `codeAction/resolve` request.
///
/// @since 3.16.0
final LSPAny data;
/// The diagnostics that this code action resolves.
final List<Diagnostic>? diagnostics;
/// Marks that the code action cannot currently be applied.
///
/// Clients should follow the following guidelines regarding disabled code
/// actions:
///
/// - Disabled code actions are not shown in automatic
/// [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
/// code action menus.
///
/// - Disabled actions are shown as faded out in the code action menu when
/// the user requests a more specific type
/// of code action, such as refactorings.
///
/// - If the user has a
/// [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
/// that auto applies a code action and only disabled code actions are
/// returned, the client should show the user an
/// error message with `reason` in the editor.
///
/// @since 3.16.0
final CodeActionDisabled? disabled;
/// The workspace edit this code action performs.
final WorkspaceEdit? edit;
/// Marks this as a preferred action. Preferred actions are used by the `auto
/// fix` command and can be targeted by keybindings.
///
/// A quick fix should be marked preferred if it properly addresses the
/// underlying error. A refactoring should be marked preferred if it is the
/// most reasonable choice of actions to take.
///
/// @since 3.15.0
final bool? isPreferred;
/// The kind of the code action.
///
/// Used to filter code actions.
final CodeActionKind? kind;
/// A short, human-readable, title for this code action.
final String title;
CodeAction({
this.command,
this.data,
this.diagnostics,
this.disabled,
this.edit,
this.isPreferred,
this.kind,
required this.title,
});
@override
int get hashCode => Object.hash(
command,
data,
lspHashCode(diagnostics),
disabled,
edit,
isPreferred,
kind,
title,
);
@override
bool operator ==(Object other) {
return other is CodeAction &&
other.runtimeType == CodeAction &&
command == other.command &&
data == other.data &&
const DeepCollectionEquality().equals(diagnostics, other.diagnostics) &&
disabled == other.disabled &&
edit == other.edit &&
isPreferred == other.isPreferred &&
kind == other.kind &&
title == other.title;
}
@override
Map<String, Object?> toJson() {
var result = <String, Object?>{};
if (command != null) {
result['command'] = command?.toJson();
}
if (data != null) {
result['data'] = data;
}
if (diagnostics != null) {
result['diagnostics'] =
diagnostics?.map((item) => item.toJson()).toList();
}
if (disabled != null) {
result['disabled'] = disabled?.toJson();
}
if (edit != null) {
result['edit'] = edit?.toJson();
}
if (isPreferred != null) {
result['isPreferred'] = isPreferred;
}
if (kind != null) {
result['kind'] = kind?.toJson();
}
result['title'] = title;
return result;
}
@override
String toString() => jsonEncoder.convert(toJson());
static bool canParse(Object? obj, LspJsonReporter reporter) {
if (obj is Map<String, Object?>) {
if (!_canParseCommand(obj, reporter, 'command',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseCodeActionDisabled(obj, reporter, 'disabled',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseBool(obj, reporter, 'isPreferred',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseCodeActionKind(obj, reporter, 'kind',
allowsUndefined: true, allowsNull: false)) {
return false;
}
return _canParseString(obj, reporter, 'title',
allowsUndefined: false, allowsNull: false);
} else {
reporter.reportError('must be of type CodeAction');
return false;
}
}
static CodeAction fromJson(Map<String, Object?> json) {
final commandJson = json['command'];
final command = commandJson != null
? Command.fromJson(commandJson as Map<String, Object?>)
: null;
final dataJson = json['data'];
final data = dataJson;
final diagnosticsJson = json['diagnostics'];
final diagnostics = (diagnosticsJson as List<Object?>?)
?.map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
.toList();
final disabledJson = json['disabled'];
final disabled = disabledJson != null
? CodeActionDisabled.fromJson(disabledJson as Map<String, Object?>)
: null;
final editJson = json['edit'];
final edit = editJson != null
? WorkspaceEdit.fromJson(editJson as Map<String, Object?>)
: null;
final isPreferredJson = json['isPreferred'];
final isPreferred = isPreferredJson as bool?;
final kindJson = json['kind'];
final kind =
kindJson != null ? CodeActionKind.fromJson(kindJson as String) : null;
final titleJson = json['title'];
final title = titleJson as String;
return CodeAction(
command: command,
data: data,
diagnostics: diagnostics,
disabled: disabled,
edit: edit,
isPreferred: isPreferred,
kind: kind,
title: title,
);
}
}
/// The Client Capabilities of a [CodeActionRequest].
class CodeActionClientCapabilities implements ToJsonable {
static const jsonHandler = LspJsonHandler(
@@ -10163,6 +9957,213 @@ class CodeActionKind implements ToJsonable {
static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
}
/// A code action represents a change that can be performed in code, e.g. to fix
/// a problem or to refactor code.
///
/// A CodeAction must set either `edit` and/or a `command`. If both are
/// supplied, the `edit` is applied first, then the `command` is executed.
class CodeActionLiteral implements ToJsonable {
static const jsonHandler = LspJsonHandler(
CodeActionLiteral.canParse,
CodeActionLiteral.fromJson,
);
/// A command this code action executes. If a code action provides an edit and
/// a command, first the edit is executed and then the command.
final Command? command;
/// A data entry field that is preserved on a code action between a
/// `textDocument/codeAction` and a `codeAction/resolve` request.
///
/// @since 3.16.0
final LSPAny data;
/// The diagnostics that this code action resolves.
final List<Diagnostic>? diagnostics;
/// Marks that the code action cannot currently be applied.
///
/// Clients should follow the following guidelines regarding disabled code
/// actions:
///
/// - Disabled code actions are not shown in automatic
/// [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
/// code action menus.
///
/// - Disabled actions are shown as faded out in the code action menu when
/// the user requests a more specific type
/// of code action, such as refactorings.
///
/// - If the user has a
/// [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
/// that auto applies a code action and only disabled code actions are
/// returned, the client should show the user an
/// error message with `reason` in the editor.
///
/// @since 3.16.0
final CodeActionDisabled? disabled;
/// The workspace edit this code action performs.
final WorkspaceEdit? edit;
/// Marks this as a preferred action. Preferred actions are used by the `auto
/// fix` command and can be targeted by keybindings.
///
/// A quick fix should be marked preferred if it properly addresses the
/// underlying error. A refactoring should be marked preferred if it is the
/// most reasonable choice of actions to take.
///
/// @since 3.15.0
final bool? isPreferred;
/// The kind of the code action.
///
/// Used to filter code actions.
final CodeActionKind? kind;
/// A short, human-readable, title for this code action.
final String title;
CodeActionLiteral({
this.command,
this.data,
this.diagnostics,
this.disabled,
this.edit,
this.isPreferred,
this.kind,
required this.title,
});
@override
int get hashCode => Object.hash(
command,
data,
lspHashCode(diagnostics),
disabled,
edit,
isPreferred,
kind,
title,
);
@override
bool operator ==(Object other) {
return other is CodeActionLiteral &&
other.runtimeType == CodeActionLiteral &&
command == other.command &&
data == other.data &&
const DeepCollectionEquality().equals(diagnostics, other.diagnostics) &&
disabled == other.disabled &&
edit == other.edit &&
isPreferred == other.isPreferred &&
kind == other.kind &&
title == other.title;
}
@override
Map<String, Object?> toJson() {
var result = <String, Object?>{};
if (command != null) {
result['command'] = command?.toJson();
}
if (data != null) {
result['data'] = data;
}
if (diagnostics != null) {
result['diagnostics'] =
diagnostics?.map((item) => item.toJson()).toList();
}
if (disabled != null) {
result['disabled'] = disabled?.toJson();
}
if (edit != null) {
result['edit'] = edit?.toJson();
}
if (isPreferred != null) {
result['isPreferred'] = isPreferred;
}
if (kind != null) {
result['kind'] = kind?.toJson();
}
result['title'] = title;
return result;
}
@override
String toString() => jsonEncoder.convert(toJson());
static bool canParse(Object? obj, LspJsonReporter reporter) {
if (obj is Map<String, Object?>) {
if (!_canParseCommand(obj, reporter, 'command',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseCodeActionDisabled(obj, reporter, 'disabled',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseBool(obj, reporter, 'isPreferred',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseCodeActionKind(obj, reporter, 'kind',
allowsUndefined: true, allowsNull: false)) {
return false;
}
return _canParseString(obj, reporter, 'title',
allowsUndefined: false, allowsNull: false);
} else {
reporter.reportError('must be of type CodeActionLiteral');
return false;
}
}
static CodeActionLiteral fromJson(Map<String, Object?> json) {
final commandJson = json['command'];
final command = commandJson != null
? Command.fromJson(commandJson as Map<String, Object?>)
: null;
final dataJson = json['data'];
final data = dataJson;
final diagnosticsJson = json['diagnostics'];
final diagnostics = (diagnosticsJson as List<Object?>?)
?.map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
.toList();
final disabledJson = json['disabled'];
final disabled = disabledJson != null
? CodeActionDisabled.fromJson(disabledJson as Map<String, Object?>)
: null;
final editJson = json['edit'];
final edit = editJson != null
? WorkspaceEdit.fromJson(editJson as Map<String, Object?>)
: null;
final isPreferredJson = json['isPreferred'];
final isPreferred = isPreferredJson as bool?;
final kindJson = json['kind'];
final kind =
kindJson != null ? CodeActionKind.fromJson(kindJson as String) : null;
final titleJson = json['title'];
final title = titleJson as String;
return CodeActionLiteral(
command: command,
data: data,
diagnostics: diagnostics,
disabled: disabled,
edit: edit,
isPreferred: isPreferred,
kind: kind,
title: title,
);
}
}
/// Provider options for a [CodeActionRequest].
class CodeActionOptions implements WorkDoneProgressOptions, ToJsonable {
static const jsonHandler = LspJsonHandler(