下面列出了怎么用org.eclipse.lsp4j.ExecuteCommandParams的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Sends commands to execute to the server and applies the changes returned if the future returns a WorkspaceEdit
*
* @param commands The commands to execute
*/
public void executeCommands(List<Command> commands) {
pool(() -> {
if (editor.isDisposed()) {
return;
}
commands.stream().map(c -> {
ExecuteCommandParams params = new ExecuteCommandParams();
params.setArguments(c.getArguments());
params.setCommand(c.getCommand());
return requestManager.executeCommand(params);
}).filter(Objects::nonNull).forEach(f -> {
try {
f.get(getTimeout(EXECUTE_COMMAND), TimeUnit.MILLISECONDS);
wrapper.notifySuccess(Timeouts.EXECUTE_COMMAND);
} catch (TimeoutException te) {
LOG.warn(te);
wrapper.notifyFailure(Timeouts.EXECUTE_COMMAND);
} catch (JsonRpcException | ExecutionException | InterruptedException e) {
LOG.warn(e);
wrapper.crashed(e);
}
});
});
}
/** Expectation is that files '.n4js.projectstate' and 'src-gen/Module.js' are changed due to rebuild action. */
@Test
public void testCommandRebuild() throws Exception {
test("class A { foo(a: A) { } } class Main { main(a: A) { a.foo(null); } }");
// send command under test
ExecuteCommandParams cmdCleanParams = new ExecuteCommandParams(N4JSCommandService.N4JS_REBUILD,
Collections.emptyList());
CompletableFuture<Object> future = languageServer.executeCommand(cmdCleanParams);
future.join();
// wait for previous command to finish
joinServerRequests();
// evaluate
assertNoIssues();
FileTime prjStateTime = Files.readAttributes(prjStatePath, BasicFileAttributes.class).lastModifiedTime();
FileTime genFileTime = Files.readAttributes(genFileStatePath, BasicFileAttributes.class).lastModifiedTime();
assertNotEquals(FILE_TIME_MILLISECONDS, prjStateTime.toMillis());
assertNotEquals(FILE_TIME_MILLISECONDS, genFileTime.toMillis());
}
/**
* The build triggered by the rebuild command must send 'publishDiagnostics' events even for those resources that do
* not contain any issues, to ensure that any obsolete issues for those resources that might exist on client side
* are removed. Normally such obsolete issues should not exist (not at start up time, because LSP clients do not
* serialize issues; and not when rebuild is triggered manually, because an incremental build should have removed
* those issues); however, in case of bugs in the incremental builder or other special circumstances this may
* happen.
*/
@Test
public void testPublishDiagnosticsSentForModuleWithoutIssues() {
testWorkspaceManager.createTestProjectOnDisk(Pair.of("Main", "let x: string = 42; x;"));
startAndWaitForLspServer();
assertIssues(Pair.of("Main", Lists.newArrayList(
"(Error, [0:16 - 0:18], int is not a subtype of string.)")));
// fix the error on disk, but don't let the LSP server know (to avoid incremental build)
changeFileOnDiskWithoutNotification("Main", Pair.of("string", "number"));
// send command under test
ExecuteCommandParams params = new ExecuteCommandParams(N4JSCommandService.N4JS_REBUILD,
Collections.emptyList());
languageServer.executeCommand(params).join();
// wait for previous command to finish
joinServerRequests();
assertNoIssues();
}
public static void applyCodeAction(LSPBindings server, Either<Command, CodeAction> cmd) {
try {
Command command;
if (cmd.isLeft()) {
command = cmd.getLeft();
} else {
Utils.applyWorkspaceEdit(cmd.getRight().getEdit());
command = cmd.getRight().getCommand();
}
if (command != null) {
server.getWorkspaceService().executeCommand(new ExecuteCommandParams(command.getCommand(), command.getArguments())).get();
}
} catch (InterruptedException | ExecutionException ex) {
Exceptions.printStackTrace(ex);
}
}
@Test
public void testNotifyWithException() throws InterruptedException {
Semaphore waiter = new Semaphore(1);
waiter.acquire();
boolean[] wasThrown = new boolean[1];
doAnswer(i -> {
try {
throw new NullPointerException();
} finally {
wasThrown[0] = true;
waiter.release();
}
}).when(client).sendNotification((any()));
clientConnection.sendNotification(new ExecuteCommandParams("custom", Arrays.asList("foo", "bar")));
verify(client, timeout(1000)).sendNotification(any());
waiter.acquire();
waiter.release();
assertTrue(wasThrown[0]);
}
@Test
public void testNotifyWithWait() throws Exception {
Semaphore waiter = new Semaphore(1);
boolean[] wasCalled = new boolean[1];
waiter.acquire();
try {
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
waiter.acquire();
wasCalled[0] = true;
return null;
}
}).when(client).sendNotification(any());
clientConnection.sendNotification(new ExecuteCommandParams("custom", Arrays.asList("foo", "bar")));
verify(client, timeout(1000)).sendNotification(any());
assertFalse(wasCalled[0]);
} finally {
waiter.release();
}
}
/**
* Convenience method to wrap a 'nice', type-checked SyncHandler into a mockito
* {@link Answer}.
*/
private static <T> Answer<T> handler(SyncHandler h) {
return new Answer<T>() {
@SuppressWarnings("unchecked")
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
try {
Object[] args = invocation.getArguments();
assertEquals(1, args.length);
ExecuteCommandParams params = (ExecuteCommandParams) args[0];
return (T) CompletableFuture.completedFuture(h.executeClientCommand(params));
} catch (Throwable e) {
CompletableFuture<T> fail = new CompletableFuture<>();
fail.completeExceptionally(e);
return (T) fail;
}
}
};
}
protected void testExecuteCommand(final Procedure1<? super CommandServiceTest.TestExecuteCommandConfiguration> configurator) {
try {
@Extension
final CommandServiceTest.TestExecuteCommandConfiguration configuration = new CommandServiceTest.TestExecuteCommandConfiguration();
configurator.apply(configuration);
final String command = configuration.command;
final List<Object> args = configuration.args;
ExecuteCommandParams _executeCommandParams = new ExecuteCommandParams(command, args);
final CompletableFuture<Object> result = this.languageServer.executeCommand(_executeCommandParams);
if ((configuration.assertCommandResult != null)) {
final Object value = result.get();
configuration.assertCommandResult.accept(value);
}
} catch (Throwable _e) {
throw Exceptions.sneakyThrow(_e);
}
}
public Object executeCommand(ExecuteCommandParams params, ILanguageServerAccess access,
CancelIndicator cancelIndicator) {
Object result = null;
for (IExecutableCommandService service : registeredCommands.get(params.getCommand())) {
Object localResult = service.execute(params, access, cancelIndicator);
if (localResult != null) {
if (result != null) {
ExecutableCommandRegistry.LOG.error("Multiple commands '" + params.getCommand()
+ "' have been registered. All are executed but only one result will be send back.");
} else {
result = localResult;
}
}
}
return result;
}
private static boolean executeCommandServerSide(Project project, Command command, String languageServerId,
Document document) {
if (languageServerId == null) {
return false;
}
LanguageServersRegistry.LanguageServerDefinition languageServerDefinition = LanguageServersRegistry.getInstance()
.getDefinition(languageServerId);
if (languageServerDefinition == null) {
return false;
}
try {
CompletableFuture<LanguageServer> languageServerFuture = getLanguageServerForCommand(project, command, document,
languageServerDefinition);
if (languageServerFuture == null) {
return false;
}
// Server can handle command
languageServerFuture.thenAcceptAsync(server -> {
ExecuteCommandParams params = new ExecuteCommandParams();
params.setCommand(command.getCommand());
params.setArguments(command.getArguments());
server.getWorkspaceService().executeCommand(params);
});
return true;
} catch (IOException e) {
// log and let the code fall through for LSPEclipseUtils to handle
LOGGER.warn(e.getLocalizedMessage(), e);
return false;
}
}
@Override
protected void performTest(Project project, String moduleName, TestOrganizeImportsConfiguration config)
throws Exception {
FileURI uri = getFileURIFromModuleName(moduleName);
if (config.expectedIssues.isEmpty()) {
assertNoIssues();
} else {
assertIssues(Collections.singletonMap(uri, config.expectedIssues));
}
TextDocumentIdentifier id = new TextDocumentIdentifier(uri.toString());
Range range = new Range(new Position(0, 0), new Position(0, 0));
CodeActionContext context = new CodeActionContext();
CodeActionParams params = new CodeActionParams(id, range, context);
CompletableFuture<List<Either<Command, CodeAction>>> codeActionFuture = languageServer.codeAction(params);
List<Either<Command, CodeAction>> result = codeActionFuture.join();
Command organizeImportsCommand = result.stream()
.map(e -> e.isLeft() ? e.getLeft() : e.getRight().getCommand())
.filter(cmd -> cmd != null
&& Objects.equals(cmd.getCommand(), N4JSCommandService.N4JS_ORGANIZE_IMPORTS))
.findFirst().orElse(null);
Assert.assertNotNull("code action for organize imports not found", organizeImportsCommand);
ExecuteCommandParams execParams = new ExecuteCommandParams(
organizeImportsCommand.getCommand(),
organizeImportsCommand.getArguments());
CompletableFuture<Object> execFuture = languageServer.executeCommand(execParams);
execFuture.join();
joinServerRequests();
assertContentOfFileOnDisk(uri, config.expectedCode);
}
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (!ExecuteCommandParams.class.isAssignableFrom(typeToken.getRawType())) {
return null;
}
ExecutableCommandRegistry commandRegistry = languageServer.getCommandRegistry();
Map<String, Type[]> argumentTypes = Collections.emptyMap();
if (commandRegistry instanceof ExecuteCommandParamsDescriber) {
argumentTypes = ((ExecuteCommandParamsDescriber) commandRegistry).argumentTypes();
}
return (TypeAdapter<T>) new ExecuteCommandParamsTypeAdapter(argumentTypes, gson);
}
@Override
public void write(JsonWriter out, ExecuteCommandParams value) throws IOException {
out.beginObject();
out.name("command");
out.value(value.getCommand());
out.name("arguments");
out.beginArray();
for (Object argument : value.getArguments()) {
gson.toJson(argument, argument.getClass(), out);
}
out.endArray();
out.endObject();
}
@Override
public ExecuteCommandParams read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
ExecuteCommandParams result = new ExecuteCommandParams();
in.beginObject();
String command = null;
while (in.hasNext()) {
String name = in.nextName();
switch (name) {
case "command": {
command = in.nextString();
result.setCommand(command);
break;
}
case "arguments": {
result.setArguments(parseArguments(in, command));
break;
}
default:
in.skipValue();
}
}
in.endObject();
return result;
}
private Object execute(ExecuteCommandParams params, ILanguageServerAccess access,
CancelIndicator cancelIndicator) {
List<Object> actualArguments = new ArrayList<>();
actualArguments.addAll(params.getArguments());
actualArguments.add(access);
actualArguments.add(cancelIndicator);
try {
return method.invoke(N4JSCommandService.this, actualArguments.toArray());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
logInfo(">> workspace/executeCommand " + (params == null ? null : params.getCommand()));
return computeAsync((monitor) -> {
return commandHandler.executeCommand(params, monitor);
});
}
@Test
public void testExecuteCommand() {
WorkspaceExecuteCommandHandler handler = WorkspaceExecuteCommandHandler.getInstance();
ExecuteCommandParams params = new ExecuteCommandParams();
params.setCommand("testcommand1");
params.setArguments(Arrays.asList("hello", "world"));
Object result = handler.executeCommand(params, monitor);
assertEquals("testcommand1: helloworld0", result);
params.setCommand("testcommand2");
result = handler.executeCommand(params, monitor);
assertEquals("testcommand2: helloworld1", result);
}
@Test
public void testExecuteCommandNonexistingCommand() {
expectedEx.expect(ResponseErrorException.class);
expectedEx.expectMessage("No delegateCommandHandler for testcommand.not.existing");
WorkspaceExecuteCommandHandler handler = WorkspaceExecuteCommandHandler.getInstance();
ExecuteCommandParams params = new ExecuteCommandParams();
params.setCommand("testcommand.not.existing");
params.setArguments(Arrays.asList("hello", "world"));
Object result = handler.executeCommand(params, monitor);
}
@Test
public void testExecuteCommandThrowsExceptionCommand() {
expectedEx.expect(ResponseErrorException.class);
expectedEx.expectMessage("Unsupported");
WorkspaceExecuteCommandHandler handler = WorkspaceExecuteCommandHandler.getInstance();
ExecuteCommandParams params = new ExecuteCommandParams();
params.setCommand("testcommand.throwexception");
handler.executeCommand(params, monitor);
}
@Test
public void testExecuteCommandInvalidParameters() {
expectedEx.expect(ResponseErrorException.class);
expectedEx.expectMessage("The workspace/executeCommand has empty params or command");
WorkspaceExecuteCommandHandler handler = WorkspaceExecuteCommandHandler.getInstance();
ExecuteCommandParams params = null;
handler.executeCommand(params, monitor);
}
private static <T> Answer<T> handler(String command, SyncHandler h) {
return handler((ExecuteCommandParams params) -> {
if (params.getCommand().equals(command)) {
return h.executeClientCommand(params);
}
throw new IllegalArgumentException("Unknown command: " + params.getCommand());
});
}
public CompletableFuture<Object> executeCommand(ExecuteCommandParams params)
{
switch(params.getCommand())
{
case ICommandConstants.ADD_IMPORT:
{
return executeAddImportCommand(params);
}
case ICommandConstants.ADD_MXML_NAMESPACE:
{
return executeAddMXMLNamespaceCommand(params);
}
case ICommandConstants.ORGANIZE_IMPORTS_IN_URI:
{
return executeOrganizeImportsInUriCommand(params);
}
case ICommandConstants.ORGANIZE_IMPORTS_IN_DIRECTORY:
{
return executeOrganizeImportsInDirectoryCommand(params);
}
default:
{
System.err.println("Unknown command: " + params.getCommand());
return CompletableFuture.completedFuture(new Object());
}
}
}
/**
* Called when one of the commands registered in ActionScriptLanguageServer
* is executed.
*/
@Override
public CompletableFuture<Object> executeCommand(ExecuteCommandParams params)
{
if(params.getCommand().equals(ICommandConstants.QUICK_COMPILE))
{
return executeQuickCompileCommand(params);
}
ExecuteCommandProvider provider = new ExecuteCommandProvider(workspaceFolderManager,
fileTracker, compilerWorkspace, languageClient);
return provider.executeCommand(params);
}
@Override
public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, CancelIndicator cancelIndicator) {
if ("testlang.a".equals(params.getCommand())) {
return "a";
} else if ("testlang.b".equals(params.getCommand())) {
return "b";
} else if ("testlang.c".equals(params.getCommand())) {
return "c";
}
return null;
}
@Test
public void testRegistration() {
ExecutableCommandRegistry reg = new ExecutableCommandRegistry();
ClientCapabilities cap = new ClientCapabilities();
WorkspaceClientCapabilities workspaceClientCapabilities = new WorkspaceClientCapabilities();
ExecuteCommandCapabilities executeCommandCapabilities = new ExecuteCommandCapabilities();
executeCommandCapabilities.setDynamicRegistration(true);
workspaceClientCapabilities.setExecuteCommand(executeCommandCapabilities);
cap.setWorkspace(workspaceClientCapabilities);
reg.initialize(Collections.unmodifiableList(Lists.newArrayList(this)), cap, this);
Assert.assertEquals("static-command", Iterables.getFirst(reg.getCommands(), null));
ExecuteCommandParams staticCommandParams = new ExecuteCommandParams();
staticCommandParams.setCommand("static-command");
reg.executeCommand(staticCommandParams, null, null);
ExecuteCommandParams dynamicCommandParams = new ExecuteCommandParams();
dynamicCommandParams.setCommand("dynamic-command");
reg.executeCommand(dynamicCommandParams, null, null);
Assert.assertEquals(Collections.unmodifiableSet(Sets.newHashSet("static-command")), commandsExecuted);
commandsExecuted.clear();
IDisposable disposable = register.apply("dynamic-command");
ExecuteCommandParams dynamicCommandParams2 = new ExecuteCommandParams();
dynamicCommandParams2.setCommand("dynamic-command");
reg.executeCommand(dynamicCommandParams2, null, null);
Assert.assertEquals(Collections.unmodifiableSet(Sets.newHashSet("dynamic-command")), commandsExecuted);
commandsExecuted.clear();
disposable.dispose();
ExecuteCommandParams dynamicCommandParams3 = new ExecuteCommandParams();
dynamicCommandParams3.setCommand("dynamic-command");
reg.executeCommand(dynamicCommandParams3, null, null);
Assert.assertEquals(Collections.unmodifiableSet(new HashSet<>()), commandsExecuted);
}
/** Cleans and rebuilds entire workspace without waiting for LSP server to finish. */
protected CompletableFuture<Object> cleanBuildWithoutWait() {
ExecuteCommandParams params = new ExecuteCommandParams(N4JSCommandService.N4JS_REBUILD,
Collections.emptyList());
return languageServer.executeCommand(params);
}
@Override
public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
return lspExecutorService.submit("executeCommand", cancelIndicator -> executeCommand(params, cancelIndicator));
}
/**
* Execute the command. Runs in a read request.
*/
protected Object executeCommand(ExecuteCommandParams params, CancelIndicator cancelIndicator) {
return commandRegistry.executeCommand(params, access, cancelIndicator);
}
@Override
public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, CancelIndicator cancelIndicator) {
return handlers.get(params.getCommand()).execute(params, access, cancelIndicator);
}
@JsonRequest("workspace/executeClientCommand")
CompletableFuture<Object> executeClientCommand(ExecuteCommandParams params);