blob: d10c35c9a849686060982f907f0f78c37ea4738e [file] [log] [blame]
// 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) {
for (var codeAction in actions) {
final codeActionLiteral =
codeAction.map((cmd) => null, (action) => action);
if (codeActionLiteral?.kind == actionKind &&
codeActionLiteral?.title == title) {
// We're specifically looking for an action that contains an edit.
assert(codeActionLiteral.command == null);
assert(codeActionLiteral.edit != null);
return codeActionLiteral;
}
}
return null;
}
/// 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 new ApplyWorkspaceEditResponse(true, null);
},
);
// 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));
}
}