[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:
committed by
Commit Queue
parent
4cc31f8f4f
commit
9831fc4e98
+9
-9
@@ -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.
|
||||
|
||||
+3
-3
@@ -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.
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+209
-208
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user