Skip to content

Commit 200597c

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Refactor LSP CodeAction test helpers
No functional changes, just some refactoring of some test helpers to work on CodeActions (which are either CodeActionLiterals or Commands) instead of only CodeActionLiterals, to simplify reviewing a future CL with functional changes. Change-Id: I40455cbaae7b924444a2f50fcdc3600d6953ecb0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426940 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 57c4148 commit 200597c

File tree

1 file changed

+130
-63
lines changed

1 file changed

+130
-63
lines changed

pkg/analysis_server/test/lsp/code_actions_abstract.dart

Lines changed: 130 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import 'server_abstract.dart';
1818
abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
1919
/// Initializes the server with some basic configuration and expects to find
2020
/// a [CodeAction] with [kind]/[command]/[title].
21-
Future<CodeActionLiteral> expectCodeActionLiteral(
21+
Future<CodeAction> expectCodeAction(
2222
String content, {
2323
CodeActionKind? kind,
2424
String? command,
@@ -46,7 +46,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
4646
triggerKind: triggerKind,
4747
);
4848

49-
var action = findCodeActionLiteral(
49+
var action = findCodeAction(
5050
codeActions,
5151
kind: kind,
5252
command: command,
@@ -59,6 +59,31 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
5959
return action;
6060
}
6161

62+
/// Initializes the server with some basic configuration and expects to find
63+
/// a [CodeAction] with [kind]/[command]/[title].
64+
Future<CodeActionLiteral> expectCodeActionLiteral(
65+
String content, {
66+
CodeActionKind? kind,
67+
String? command,
68+
List<Object>? commandArgs,
69+
String? title,
70+
CodeActionTriggerKind? triggerKind,
71+
String? filePath,
72+
bool openTargetFile = false,
73+
}) async {
74+
var action = await expectCodeAction(
75+
content,
76+
kind: kind,
77+
command: command,
78+
commandArgs: commandArgs,
79+
title: title,
80+
triggerKind: triggerKind,
81+
filePath: filePath,
82+
openTargetFile: openTargetFile,
83+
);
84+
return action.asCodeActionLiteral;
85+
}
86+
6287
/// Expects that command [commandName] was logged to the analytics manager.
6388
void expectCommandLogged(String commandName) {
6489
expect(
@@ -71,7 +96,7 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
7196
}
7297

7398
/// Initializes the server with some basic configuration and expects not to
74-
/// find a [CodeActionLiteral] with [kind]/[command]/[title].
99+
/// find a [CodeAction] with [kind]/[command]/[title].
75100
Future<void> expectNoAction(
76101
String content, {
77102
String? filePath,
@@ -97,31 +122,25 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
97122
);
98123

99124
expect(
100-
findCodeActionLiteral(
101-
codeActions,
102-
kind: kind,
103-
command: command,
104-
title: title,
105-
),
125+
findCodeAction(codeActions, kind: kind, command: command, title: title),
106126
isNull,
107127
);
108128
}
109129

110-
/// Finds the single [CodeActionLiteral] matching [title], [kind] and
111-
/// [command].
130+
/// Finds the single [CodeAction] matching [title], [kind] and [command].
112131
///
113132
/// If [command] and/or [commandArgs] are supplied, ensures the result is
114133
/// either that command, or a literal code action with that command.
115134
///
116135
/// Returns `null` if there is not exactly one match.
117-
CodeActionLiteral? findCodeActionLiteral(
136+
CodeAction? findCodeAction(
118137
List<CodeAction> actions, {
119138
String? title,
120139
CodeActionKind? kind,
121140
String? command,
122141
List<Object>? commandArgs,
123142
}) {
124-
return findCodeActionLiterals(
143+
return findCodeActions(
125144
actions,
126145
title: title,
127146
kind: kind,
@@ -130,47 +149,76 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
130149
).singleOrNull;
131150
}
132151

133-
List<CodeActionLiteral> findCodeActionLiterals(
134-
List<Either2<CodeActionLiteral, Command>> actions, {
152+
/// Finds the single [CodeActionLiteral] matching [title], [kind] and [command].
153+
///
154+
/// If [command] and/or [commandArgs] are supplied, ensures the result is
155+
/// either that command, or a literal code action with that command.
156+
///
157+
/// Returns `null` if there is not exactly one match.
158+
CodeActionLiteral? findCodeActionLiteral(
159+
List<CodeAction> actions, {
160+
String? title,
161+
CodeActionKind? kind,
162+
String? command,
163+
List<Object>? commandArgs,
164+
}) {
165+
return findCodeAction(
166+
actions,
167+
title: title,
168+
kind: kind,
169+
command: command,
170+
commandArgs: commandArgs,
171+
)?.asCodeActionLiteral;
172+
}
173+
174+
List<CodeAction> findCodeActions(
175+
List<CodeAction> actions, {
135176
String? title,
136177
CodeActionKind? kind,
137178
String? command,
138179
List<Object>? commandArgs,
139180
}) {
140-
return actions
141-
.map((action) => action.map((action) => action, (cmd) => null))
142-
.where((action) => title == null || action?.title == title)
143-
.where((action) => kind == null || action?.kind == kind)
144-
// Some tests filter by only supplying a command, so if there is no
145-
// title given, filter by the command. If a title was given, don't
146-
// filter by the command and assert it below. This results in a better
147-
// failure message if the action existed by title but without the correct
148-
// command.
149-
.where(
150-
(action) =>
151-
title != null ||
152-
command == null ||
153-
action?.command?.command == command,
154-
)
155-
.map((action) {
156-
// Always expect a command (either to execute, or for logging)
157-
expect(action!.command, isNotNull);
158-
159-
if (command != null) {
160-
expect(action.command!.command, command);
161-
} else {
162-
// Expect an edit if we weren't looking for a command-action.
163-
expect(action.edit, isNotNull);
164-
}
165-
166-
if (commandArgs != null) {
167-
expect(action.command!.arguments, equals(commandArgs));
168-
}
169-
170-
return action;
171-
})
172-
.nonNulls
173-
.toList();
181+
return actions.where((action) {
182+
var actionLiteral = action.map((action) => action, (command) => null);
183+
var actionCommand = action.map(
184+
// Always expect a command (either to execute, or for logging)
185+
(action) => action.command!,
186+
(command) => command,
187+
);
188+
var actionTitle = actionLiteral?.title ?? actionCommand.title;
189+
var actionKind = actionLiteral?.kind;
190+
191+
if (title != null && actionTitle != title) {
192+
return false;
193+
}
194+
195+
if (kind != null && actionKind != kind) {
196+
return false;
197+
}
198+
199+
// Some tests filter by only supplying a command, so if there is no
200+
// title given, filter by the command. If a title was given, don't
201+
// filter by the command and assert it below. This results in a better
202+
// failure message if the action existed by title but without the correct
203+
// command.
204+
if (title == null &&
205+
command != null &&
206+
actionCommand.command != command) {
207+
return false;
208+
}
209+
210+
if (command != null) {
211+
expect(actionCommand.command, command);
212+
} else {
213+
// Expect an edit if we weren't looking for a command-action.
214+
expect(actionLiteral?.edit, isNotNull);
215+
}
216+
if (commandArgs != null) {
217+
expect(actionCommand.arguments, equals(commandArgs));
218+
}
219+
220+
return true;
221+
}).toList();
174222
}
175223

176224
CodeAction? findCommand(
@@ -203,6 +251,34 @@ abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest {
203251
registerBuiltInFixGenerators();
204252
}
205253

254+
/// Verifies that executing the given Code Action (either via a command or
255+
/// an inline edit) results in the files matching the expected content.
256+
Future<LspChangeVerifier> verifyCodeActionEdits(
257+
CodeAction action,
258+
String expectedContent, {
259+
ProgressToken? workDoneToken,
260+
}) async {
261+
var command = action.command;
262+
var edit = action.map((literal) => literal.edit, (_) => null);
263+
264+
// Verify the edits either by executing the command we expected, or
265+
// the edits attached directly to the code action.
266+
// Don't try to execute 'dart.logAction' because it will never produce
267+
// edits.
268+
if (command != null && command.command != Commands.logAction) {
269+
assert(edit == null, 'Got a command but also a literal edit');
270+
return await verifyCommandEdits(
271+
command,
272+
expectedContent,
273+
workDoneToken: workDoneToken,
274+
);
275+
} else if (edit != null) {
276+
return verifyEdit(edit, expectedContent);
277+
} else {
278+
throw 'CodeAction had neither a command or a literal edit';
279+
}
280+
}
281+
206282
/// Initializes the server with some basic configuration and expects to find
207283
/// a [CodeActionLiteral] with [kind]/[title] that applies edits resulting in
208284
/// [expected].
@@ -237,19 +313,10 @@ $expected''';
237313
openTargetFile: openTargetFile,
238314
);
239315

240-
// Verify the edits either by executing the command we expected, or
241-
// the edits attached directly to the code action.
242-
// Don't try to execute 'dart.logAction' because it will never produce
243-
// edits.
244-
if (command != null && command != Commands.logAction) {
245-
return await verifyCommandEdits(
246-
action.command!,
247-
expected,
248-
workDoneToken: commandWorkDoneToken,
249-
);
250-
} else {
251-
var edit = action.edit!;
252-
return verifyEdit(edit, expected);
253-
}
316+
return await verifyCodeActionEdits(
317+
CodeAction.t1(action),
318+
expected,
319+
workDoneToken: commandWorkDoneToken,
320+
);
254321
}
255322
}

0 commit comments

Comments
 (0)