@@ -18,7 +18,7 @@ import 'server_abstract.dart';
1818abstract 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