| // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:analysis_server/lsp_protocol/protocol_generated.dart'; |
| import 'package:analysis_server/lsp_protocol/protocol_special.dart'; |
| import 'package:test/test.dart'; |
| |
| import 'server_abstract.dart'; |
| |
| abstract class AbstractCodeActionsTest extends AbstractLspAnalysisServerTest { |
| Future<void> checkCodeActionAvailable( |
| Uri uri, |
| String command, |
| String title, { |
| bool asCodeActionLiteral = false, |
| bool asCommand = false, |
| }) async { |
| final codeActions = await getCodeActions(uri.toString()); |
| final codeAction = findCommand(codeActions, command); |
| expect(codeAction, isNotNull); |
| |
| codeAction.map( |
| (command) { |
| if (!asCommand) { |
| throw 'Got Command but expected CodeAction literal'; |
| } |
| expect(command.title, equals(title)); |
| expect(command.arguments, equals([uri.toFilePath()])); |
| }, |
| (codeAction) { |
| if (!asCodeActionLiteral) { |
| throw 'Got CodeAction literal but expected Command'; |
| } |
| expect(codeAction, isNotNull); |
| expect(codeAction.title, equals(title)); |
| expect(codeAction.command.title, equals(title)); |
| expect(codeAction.command.arguments, equals([uri.toFilePath()])); |
| }, |
| ); |
| } |
| |
| Either2<Command, CodeAction> findCommand( |
| List<Either2<Command, CodeAction>> actions, String commandID, |
| [String wantedTitle]) { |
| for (var codeAction in actions) { |
| final id = codeAction.map( |
| (cmd) => cmd.command, (action) => action.command.command); |
| final title = |
| codeAction.map((cmd) => cmd.title, (action) => action.title); |
| if (id == commandID && (wantedTitle == null || wantedTitle == title)) { |
| return codeAction; |
| } |
| } |
| return null; |
| } |
| |
| CodeAction findEditAction(List<Either2<Command, CodeAction>> actions, |
| CodeActionKind actionKind, String title) { |
| return findEditActions(actions, actionKind, title) |
| .firstWhere((element) => true, orElse: () => null); |
| } |
| |
| List<CodeAction> findEditActions(List<Either2<Command, CodeAction>> actions, |
| CodeActionKind actionKind, String title) { |
| return actions |
| .map((action) => action.map((cmd) => null, (action) => action)) |
| .where((action) => action?.kind == actionKind && action?.title == title) |
| .map((action) { |
| // Expect matching actions to contain an edit and not a command. |
| assert(action.command == null); |
| assert(action.edit != null); |
| return action; |
| }).toList(); |
| } |
| |
| /// Verifies that executing the given code actions command on the server |
| /// results in an edit being sent in the client that updates the file to match |
| /// the expected content. |
| Future verifyCodeActionEdits(Either2<Command, CodeAction> codeAction, |
| String content, String expectedContent, |
| {bool expectDocumentChanges = false}) async { |
| final command = codeAction.map( |
| (command) => command, |
| (codeAction) => codeAction.command, |
| ); |
| |
| await verifyCommandEdits(command, content, expectedContent, |
| expectDocumentChanges: expectDocumentChanges); |
| } |
| |
| /// Verifies that executing the given command on the server results in an edit |
| /// being sent in the client that updates the file to match the expected |
| /// content. |
| Future<void> verifyCommandEdits( |
| Command command, String content, String expectedContent, |
| {bool expectDocumentChanges = false}) async { |
| ApplyWorkspaceEditParams editParams; |
| |
| final commandResponse = await handleExpectedRequest<Object, |
| ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>( |
| Method.workspace_applyEdit, |
| () => executeCommand(command), |
| handler: (edit) { |
| // When the server sends the edit back, just keep a copy and say we |
| // applied successfully (it'll be verified below). |
| editParams = edit; |
| return ApplyWorkspaceEditResponse(applied: true); |
| }, |
| ); |
| // Successful edits return an empty success() response. |
| expect(commandResponse, isNull); |
| |
| // Ensure the edit came back, and using the expected changes. |
| expect(editParams, isNotNull); |
| if (expectDocumentChanges) { |
| expect(editParams.edit.changes, isNull); |
| expect(editParams.edit.documentChanges, isNotNull); |
| } else { |
| expect(editParams.edit.changes, isNotNull); |
| expect(editParams.edit.documentChanges, isNull); |
| } |
| |
| // Ensure applying the changes will give us the expected content. |
| final contents = { |
| mainFilePath: withoutMarkers(content), |
| }; |
| |
| if (expectDocumentChanges) { |
| applyDocumentChanges(contents, editParams.edit.documentChanges); |
| } else { |
| applyChanges(contents, editParams.edit.changes); |
| } |
| expect(contents[mainFilePath], equals(expectedContent)); |
| } |
| } |