Skip to content

Commit

Permalink
Issue 8721 - Update Libraries, etc. based on JDT notifications eclips…
Browse files Browse the repository at this point in the history
…e-che#8721

Draft - DO NOT MERGE

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
  • Loading branch information
vrubezhny committed Apr 26, 2018
1 parent d1c3957 commit 737c445
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public final class Constants {
public static final String PROGRESS_OUTPUT_UNSUBSCRIBE = "progressOutput/unsubscribe";
public static final String PROGRESS_OUTPUT_SUBSCRIBE = "progressOutput/subscribe";

public static final String EXECUTE_CLIENT_COMMAND = "workspace/executeClientCommand";
public static final String EXECUTE_CLIENT_COMMAND_UNSUBSCRIBE =
"workspace/executeClientCommand/unsubscribe";
public static final String EXECUTE_CLIENT_COMMAND_SUBSCRIBE =
"workspace/executeClientCommand/subscribe";

private Constants() {
throw new UnsupportedOperationException("Unused constructor.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.java.languageserver;

import static org.eclipse.che.ide.ext.java.shared.Constants.EXECUTE_CLIENT_COMMAND;

import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.languageserver.server.dto.DtoServerImpls;
import org.eclipse.che.api.languageserver.server.dto.DtoServerImpls.ExecuteCommandParamsDto;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Transmits 'workspace/executeClientCommand' over the JSON-RPC */
@Singleton
public class ExecuteClientCommandJsonRpcTransmitter {
private final Set<String> endpointIds = new CopyOnWriteArraySet<>();

private final RequestTransmitter requestTransmitter;

private static final Logger LOG =
LoggerFactory.getLogger(ExecuteClientCommandJsonRpcTransmitter.class);

@Inject
public ExecuteClientCommandJsonRpcTransmitter(RequestTransmitter requestTransmitter) {
this.requestTransmitter = requestTransmitter;
}

@Inject
private void subscribe(EventService eventService, RequestTransmitter requestTransmitter) {
LOG.info("subscribe() is invoked");
eventService.subscribe(
event ->
endpointIds.forEach(
endpointId -> {
LOG.info("subscribe() is invoked for endpointID " + endpointId);
requestTransmitter
.newRequest()
.endpointId(endpointId)
.methodName(EXECUTE_CLIENT_COMMAND)
.paramsAsDto(new ExecuteCommandParamsDto(event))
.sendAndSkipResult();
}),
ExecuteCommandParams.class);
}

@Inject
private void configureSubscribeHandler(RequestHandlerConfigurator requestHandler) {
LOG.info("configureSubscribeHandler() is invoked");
requestHandler
.newConfiguration()
.methodName("workspace/executeClientCommand/subscribe")
.noParams()
.noResult()
.withConsumer(endpointIds::add);
}

@Inject
private void configureUnSubscribeHandler(RequestHandlerConfigurator requestHandler) {
LOG.info("configureUnSubscribeHandler() is invoked");
requestHandler
.newConfiguration()
.methodName("workspace/executeClientCommand/unsubscribe")
.noParams()
.noResult()
.withConsumer(endpointIds::remove);
}

public CompletableFuture<Object> executeClientCommand(ExecuteCommandParams requestParams) {
LOG.info("executeClientCommand() is invoked");

ExecuteCommandParamsDto paramsDto =
(ExecuteCommandParamsDto) DtoServerImpls.makeDto(requestParams);

CompletableFuture<Object> result = new CompletableFuture<>();
for (String endpointId : endpointIds) {
requestTransmitter
.newRequest()
.endpointId(endpointId)
.methodName("workspace/executeClientCommand")
.paramsAsDto(paramsDto)
.sendAndSkipResult();
}
result.complete(null);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
*/
package org.eclipse.che.plugin.java.languageserver;

import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;

public interface JavaLanguageClient {
/**
Expand All @@ -28,4 +31,7 @@ public interface JavaLanguageClient {
*/
@JsonNotification("language/progressReport")
void sendProgressReport(ProgressReport report);

@JsonRequest("workspace/executeClientCommand")
CompletableFuture<Object> executeClientCommand(ExecuteCommandParams params);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import org.eclipse.che.api.languageserver.exception.LanguageServerException;
import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncherTemplate;
import org.eclipse.che.api.languageserver.registry.DocumentFilter;
import org.eclipse.che.api.languageserver.registry.LanguageServerDescription;
import org.eclipse.che.api.languageserver.service.FileContentAccess;
import org.eclipse.che.api.languageserver.util.DynamicWrapper;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.LanguageServer;
Expand All @@ -43,10 +45,14 @@ public class JavaLanguageServerLauncher extends LanguageServerLauncherTemplate {

private final Path launchScript;
private ProcessorJsonRpcCommunication processorJsonRpcCommunication;
private ExecuteClientCommandJsonRpcTransmitter executeCliendCommandTransmitter;

@Inject
public JavaLanguageServerLauncher(ProcessorJsonRpcCommunication processorJsonRpcCommunication) {
public JavaLanguageServerLauncher(
ProcessorJsonRpcCommunication processorJsonRpcCommunication,
ExecuteClientCommandJsonRpcTransmitter executeCliendCommandTransmitter) {
this.processorJsonRpcCommunication = processorJsonRpcCommunication;
this.executeCliendCommandTransmitter = executeCliendCommandTransmitter;
launchScript = Paths.get(System.getenv("HOME"), "che/ls-java/launch.sh");
}

Expand Down Expand Up @@ -94,6 +100,10 @@ public void sendProgressReport(ProgressReport report) {
processorJsonRpcCommunication.sendProgressNotification(report);
}

public CompletableFuture<Object> executeClientCommand(ExecuteCommandParams params) {
return executeCliendCommandTransmitter.executeClientCommand(params);
}

protected Process startLanguageServerProcess(String fileUri) throws LanguageServerException {
ProcessBuilder processBuilder = new ProcessBuilder(launchScript.toString());
processBuilder.directory(launchScript.getParent().toFile());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.che.plugin.languageserver.ide.navigation.workspace.FindSymbolAction;
import org.eclipse.che.plugin.languageserver.ide.registry.LanguageServerRegistry;
import org.eclipse.che.plugin.languageserver.ide.rename.LSRenameAction;
import org.eclipse.che.plugin.languageserver.ide.service.ExecuteClientCommandReceiver;
import org.eclipse.che.plugin.languageserver.ide.service.PublishDiagnosticsReceiver;
import org.eclipse.che.plugin.languageserver.ide.service.ShowMessageJsonRpcReceiver;
import org.eclipse.che.plugin.languageserver.ide.service.TextDocumentServiceClient;
Expand All @@ -60,19 +61,22 @@ public LanguageServerExtension(
EventBus eventBus,
AppContext appContext,
ShowMessageJsonRpcReceiver showMessageJsonRpcReceiver,
PublishDiagnosticsReceiver publishDiagnosticsReceiver) {
PublishDiagnosticsReceiver publishDiagnosticsReceiver,
ExecuteClientCommandReceiver executeClientCommandReceiver) {
eventBus.addHandler(
WsAgentServerRunningEvent.TYPE,
e -> {
languageServerFileTypeRegister.start();
showMessageJsonRpcReceiver.subscribe();
publishDiagnosticsReceiver.subscribe();
executeClientCommandReceiver.subscribe();
});

if (appContext.getWorkspace().getStatus() == RUNNING) {
languageServerFileTypeRegister.start();
showMessageJsonRpcReceiver.subscribe();
publishDiagnosticsReceiver.subscribe();
executeClientCommandReceiver.subscribe();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.che.plugin.languageserver.ide.editor.signature.LanguageServerSignatureHelpFactory;
import org.eclipse.che.plugin.languageserver.ide.location.OpenLocationPresenterFactory;
import org.eclipse.che.plugin.languageserver.ide.rename.node.RenameNodeFactory;
import org.eclipse.che.plugin.languageserver.ide.service.ExecuteClientCommandReceiver;
import org.eclipse.che.plugin.languageserver.ide.service.PublishDiagnosticsReceiver;
import org.eclipse.che.plugin.languageserver.ide.service.ShowMessageJsonRpcReceiver;

Expand All @@ -46,5 +47,6 @@ protected void configure() {

bind(PublishDiagnosticsReceiver.class).asEagerSingleton();
bind(ShowMessageJsonRpcReceiver.class).asEagerSingleton();
bind(ExecuteClientCommandReceiver.class).asEagerSingleton();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.languageserver.ide.navigation.workspace;

import static java.util.stream.Collectors.toSet;

import com.google.inject.Inject;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.inject.Singleton;
import org.eclipse.che.api.languageserver.shared.model.ExtendedExecuteCommandParams;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.util.loging.Log;

@Singleton
public class UpdateProjectClasspathHandler {

private final AppContext appContext;

@Inject
public UpdateProjectClasspathHandler(AppContext appContext) {
this.appContext = appContext;
}

/**
* Updates the tree of projects which were modified.
*
* @param dto describes a projects which were modified
*/
public void handleUpdate(ExtendedExecuteCommandParams params) {
List<Object> updatedProjects = params.getArguments();
Set<String> projectToRefresh = computeUniqueHiLevelProjects(updatedProjects);
Log.info(
getClass(),
"Updating projects..."
+ (projectToRefresh == null ? " null " : "" + projectToRefresh.size())
+ " from "
+ (updatedProjects == null ? " null " : "" + updatedProjects.size()));

for (final String path : projectToRefresh) {
Log.info(getClass(), "Updating project: " + path);

appContext
.getWorkspaceRoot()
.getContainer(path)
.then(
container -> {
Log.info(UpdateProjectClasspathHandler.class, "Updating project: " + path);
if (container.isPresent()) {
container.get().synchronize();
}
})
.catchError(
error -> {
Log.error(UpdateProjectClasspathHandler.class, error.getCause());
});
}
Log.info(getClass(), "Updating projects finished");
}

private Set<String> computeUniqueHiLevelProjects(List<Object> updatedProjects) {
return updatedProjects
.stream()
.filter(Objects::nonNull)
.map(each -> each.toString())
// .filter(each -> shouldBeUpdated(updatedProjects, each))
.collect(toSet());
}

private boolean shouldBeUpdated(List<Object> updatedProjects, String project) {
for (Object each : updatedProjects) {
if (!project.equals(each) && project.startsWith(String.valueOf(each))) {
Log.info(getClass(), "shouldBeUpdated(" + project + ") == " + false);
return false;
}
}
Log.info(getClass(), "shouldBeUpdated(" + project + ") == " + true);
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.languageserver.ide.service;

import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECTS_CLASSPATH;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.languageserver.shared.model.ExtendedExecuteCommandParams;
import org.eclipse.che.ide.util.loging.Log;
import org.eclipse.che.plugin.languageserver.ide.navigation.workspace.UpdateProjectClasspathHandler;

/**
* A processor for incoming <code>workspace/ClasspathChanged</code> notifications sent by a language
* server.
*
* @author V. Rubezhny
*/
@Singleton
public class ExecuteClientCommandProcessor {

private UpdateProjectClasspathHandler updateClasspathHandler;

@Inject
public ExecuteClientCommandProcessor(UpdateProjectClasspathHandler updateClasspathHandler) {
this.updateClasspathHandler = updateClasspathHandler;
}

public void execute(ExtendedExecuteCommandParams params) {
Log.info(
getClass(),
"workspace/executeClientCommand " + (params == null ? "-empty-" : params.getCommand()));
if (CLIENT_UPDATE_PROJECTS_CLASSPATH.equals(params.getCommand())) {
updateClasspathHandler.handleUpdate(params);
}
}
}
Loading

0 comments on commit 737c445

Please sign in to comment.