From 9016147db7472906cf168c636fc76fed243b49b6 Mon Sep 17 00:00:00 2001 From: "Victor V. Rubezhny" Date: Fri, 10 Aug 2018 09:32:14 +0200 Subject: [PATCH] New folders do not register in the jdt.ls workspace #10115 (#10665) Signed-off-by: Victor Rubezhny --- .../che/ide/ui/smartTree/NodeLoader.java | 6 +- .../util/JavaLanguageServerExtensionStub.java | 6 +- .../project/classpath/ClasspathResolver.java | 57 ++++++++++++------- .../che-plugin-java-plain-server/pom.xml | 4 ++ .../server/rest/ClasspathUpdaterService.java | 30 ++++++++-- .../JavaLanguageServerExtensionService.java | 16 +++++- .../JavaLanguageServerLauncher.java | 3 + .../ExecuteClientCommandProcessor.java | 37 +++++++++--- .../MoveJavaFileInNewSourceFolderTest.java | 1 - 9 files changed, 120 insertions(+), 40 deletions(-) diff --git a/ide/che-core-ide-ui/src/main/java/org/eclipse/che/ide/ui/smartTree/NodeLoader.java b/ide/che-core-ide-ui/src/main/java/org/eclipse/che/ide/ui/smartTree/NodeLoader.java index 43497e0221c..32cba49ed60 100644 --- a/ide/che-core-ide-ui/src/main/java/org/eclipse/che/ide/ui/smartTree/NodeLoader.java +++ b/ide/che-core-ide-ui/src/main/java/org/eclipse/che/ide/ui/smartTree/NodeLoader.java @@ -365,10 +365,8 @@ public Node getLastRequest() { @NotNull private Operation> interceptChildren(@NotNull final Node parent) { return children -> { - if (nodeInterceptors.isEmpty()) { - onLoadSuccess(parent, children); - return; - } + // In case of nodeInterceptors is empty we still need to call iterate(...) + // in order to call set parent on children and call onLoadSuccess(...) LinkedList sortedByPriorityQueue = new LinkedList<>(nodeInterceptors); sortedByPriorityQueue.sort(priorityComparator); diff --git a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/util/JavaLanguageServerExtensionStub.java b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/util/JavaLanguageServerExtensionStub.java index 245e915756a..93ef202a00d 100644 --- a/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/util/JavaLanguageServerExtensionStub.java +++ b/plugins/plugin-java-debugger/che-plugin-java-debugger-server/src/test/java/org/eclipse/che/plugin/jdb/server/util/JavaLanguageServerExtensionStub.java @@ -21,6 +21,7 @@ import org.eclipse.che.api.languageserver.FindServer; import org.eclipse.che.api.languageserver.LanguageServerInitializer; import org.eclipse.che.api.project.server.ProjectManager; +import org.eclipse.che.plugin.java.languageserver.ExecuteClientCommandJsonRpcTransmitter; import org.eclipse.che.plugin.java.languageserver.JavaLanguageServerExtensionService; import org.mockito.Mockito; @@ -38,7 +39,10 @@ public JavaLanguageServerExtensionStub() { RequestHandlerConfigurator.class, Mockito.withSettings().defaultAnswer(RETURNS_DEEP_STUBS)), mock(ProjectManager.class, Mockito.withSettings().defaultAnswer(RETURNS_DEEP_STUBS)), - mock(EventService.class, Mockito.withSettings().defaultAnswer(RETURNS_DEEP_STUBS))); + mock(EventService.class, Mockito.withSettings().defaultAnswer(RETURNS_DEEP_STUBS)), + mock( + ExecuteClientCommandJsonRpcTransmitter.class, + Mockito.withSettings().defaultAnswer(RETURNS_DEEP_STUBS))); } @Override diff --git a/plugins/plugin-java/che-plugin-java-ext-lang-client/src/main/java/org/eclipse/che/ide/ext/java/client/project/classpath/ClasspathResolver.java b/plugins/plugin-java/che-plugin-java-ext-lang-client/src/main/java/org/eclipse/che/ide/ext/java/client/project/classpath/ClasspathResolver.java index 3abc141a21a..9d8445be711 100644 --- a/plugins/plugin-java/che-plugin-java-ext-lang-client/src/main/java/org/eclipse/che/ide/ext/java/client/project/classpath/ClasspathResolver.java +++ b/plugins/plugin-java/che-plugin-java-ext-lang-client/src/main/java/org/eclipse/che/ide/ext/java/client/project/classpath/ClasspathResolver.java @@ -26,12 +26,15 @@ import java.util.List; import java.util.Set; import org.eclipse.che.api.promises.client.Promise; +import org.eclipse.che.api.promises.client.PromiseProvider; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.notification.NotificationManager; import org.eclipse.che.ide.api.resources.Project; import org.eclipse.che.ide.api.resources.Resource; import org.eclipse.che.ide.dto.DtoFactory; +import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient; import org.eclipse.che.ide.ext.java.shared.ClasspathEntryKind; +import org.eclipse.che.ide.project.node.ProjectClasspathChangedEvent; import org.eclipse.che.jdt.ls.extension.api.dto.ClasspathEntry; import org.eclipse.che.plugin.java.plain.client.service.ClasspathUpdaterServiceClient; @@ -41,10 +44,13 @@ * @author Valeriy Svydenko */ @Singleton -public class ClasspathResolver { +public class ClasspathResolver + implements ProjectClasspathChangedEvent.ProjectClasspathChangedHandler { private static final String WORKSPACE_PATH = "/projects"; private final ClasspathUpdaterServiceClient classpathUpdater; + private final JavaLanguageExtensionServiceClient extensionService; + private final PromiseProvider promiseProvider; private final NotificationManager notificationManager; private final EventBus eventBus; private final AppContext appContext; @@ -58,15 +64,21 @@ public class ClasspathResolver { @Inject public ClasspathResolver( ClasspathUpdaterServiceClient classpathUpdater, + JavaLanguageExtensionServiceClient extensionService, + PromiseProvider promiseProvider, NotificationManager notificationManager, EventBus eventBus, AppContext appContext, DtoFactory dtoFactory) { this.classpathUpdater = classpathUpdater; + this.extensionService = extensionService; + this.promiseProvider = promiseProvider; this.notificationManager = notificationManager; this.eventBus = eventBus; this.appContext = appContext; this.dtoFactory = dtoFactory; + + this.eventBus.addHandler(ProjectClasspathChangedEvent.getType(), this); } /** Reads and parses classpath entries. */ @@ -114,31 +126,18 @@ public Promise updateClasspath() { for (String path : sources) { entries.add(dtoFactory.createDto(ClasspathEntry.class).withPath(path).withEntryKind(SOURCE)); } + for (String path : projects) { entries.add(dtoFactory.createDto(ClasspathEntry.class).withPath(path).withEntryKind(PROJECT)); } Promise promise = classpathUpdater.setRawClasspath(optProject.getLocation().toString(), entries); - - promise - .then( - emptyResponse -> { - optProject - .synchronize() - .then( - resources -> { - eventBus.fireEvent( - new ClasspathChangedEvent( - optProject.getLocation().toString(), entries)); - }); - }) - .catchError( - error -> { - notificationManager.notify( - "Problems with updating classpath", error.getMessage(), FAIL, EMERGE_MODE); - }); - + promise.catchError( + error -> { + notificationManager.notify( + "Problems with updating classpath", error.getMessage(), FAIL, EMERGE_MODE); + }); return promise; } @@ -161,4 +160,22 @@ public Set getSources() { public Set getProjects() { return projects; } + + @Override + public void onProjectClasspathChanged(ProjectClasspathChangedEvent event) { + getEntriesFromServer(event.getProject()) + .then( + entries -> { + eventBus.fireEvent(new ClasspathChangedEvent(event.getProject(), entries)); + }); + } + + private Promise> getEntriesFromServer(String projectPath) { + return extensionService + .classpathTree(projectPath) + .catchErrorPromise( + error -> { + return promiseProvider.reject(error); + }); + } } diff --git a/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/pom.xml b/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/pom.xml index 879085a0465..db79eadab23 100644 --- a/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/pom.xml +++ b/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/pom.xml @@ -22,6 +22,10 @@ che-plugin-java-plain-server Che Plugin :: Java :: Plain :: Server + + com.google.code.gson + gson + com.google.inject guice diff --git a/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/src/main/java/org/eclipse/che/plugin/java/plain/server/rest/ClasspathUpdaterService.java b/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/src/main/java/org/eclipse/che/plugin/java/plain/server/rest/ClasspathUpdaterService.java index eac6d8023c4..f3f595cd637 100644 --- a/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/src/main/java/org/eclipse/che/plugin/java/plain/server/rest/ClasspathUpdaterService.java +++ b/plugins/plugin-java/che-plugin-java-plain/che-plugin-java-plain-server/src/main/java/org/eclipse/che/plugin/java/plain/server/rest/ClasspathUpdaterService.java @@ -13,10 +13,16 @@ import static org.eclipse.che.api.fs.server.WsPathUtils.absolutize; import static org.eclipse.che.api.languageserver.LanguageServiceUtils.prefixURI; +import static org.eclipse.che.api.languageserver.LanguageServiceUtils.removePrefixUri; +import static org.eclipse.che.api.languageserver.util.JsonUtil.convertToJson; +import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED; import com.google.inject.Inject; import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -33,6 +39,8 @@ import org.eclipse.che.api.project.shared.RegisteredProject; import org.eclipse.che.jdt.ls.extension.api.dto.ClasspathEntry; import org.eclipse.che.plugin.java.languageserver.JavaLanguageServerExtensionService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Service for updating classpath. @@ -41,6 +49,8 @@ */ @Path("jdt/classpath/update") public class ClasspathUpdaterService { + private static final Logger LOG = LoggerFactory.getLogger(ClasspathUpdaterService.class); + private final ProjectManager projectManager; private JavaLanguageServerExtensionService extensionService; @@ -67,12 +77,17 @@ public void updateClasspath( @QueryParam("projectpath") String projectPath, List entries) throws ServerException, ForbiddenException, ConflictException, NotFoundException, IOException, BadRequestException { - extensionService.updateClasspath(prefixURI(projectPath), entries); + try { + extensionService.updateClasspathWithResult(prefixURI(projectPath), entries).get(); + updateProjectConfig(projectPath).get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error(e.getMessage()); + } - updateProjectConfig(projectPath); + notifyClientOnProjectUpdate(projectPath); } - private void updateProjectConfig(String projectWsPath) + private CompletableFuture updateProjectConfig(String projectWsPath) throws IOException, ForbiddenException, ConflictException, NotFoundException, ServerException, BadRequestException { String wsPath = absolutize(projectWsPath); @@ -84,6 +99,13 @@ private void updateProjectConfig(String projectWsPath) NewProjectConfig projectConfig = new NewProjectConfigImpl( projectWsPath, project.getName(), project.getType(), project.getSource()); - projectManager.update(projectConfig); + RegisteredProject result = projectManager.update(projectConfig); + return CompletableFuture.completedFuture(result.getPath()); + } + + private void notifyClientOnProjectUpdate(String projectPath) { + List parameters = new ArrayList<>(); + parameters.add(removePrefixUri(convertToJson(projectPath).getAsString())); + extensionService.executeClientCommand(CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED, parameters); } } diff --git a/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerExtensionService.java b/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerExtensionService.java index 4ce75b15fd7..66c49806ed0 100644 --- a/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerExtensionService.java +++ b/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerExtensionService.java @@ -163,6 +163,7 @@ public class JavaLanguageServerExtensionService { private final ProjectManager projectManager; private final EventService eventService; private final LanguageServerInitializer initializer; + private final ExecuteClientCommandJsonRpcTransmitter clientCommandTransmitter; @Inject public JavaLanguageServerExtensionService( @@ -170,12 +171,14 @@ public JavaLanguageServerExtensionService( LanguageServerInitializer languageServerInitializer, RequestHandlerConfigurator requestHandler, ProjectManager projectManager, - EventService eventService) { + EventService eventService, + ExecuteClientCommandJsonRpcTransmitter clientCommandTransmitter) { this.registry = registry; this.initializer = languageServerInitializer; this.requestHandler = requestHandler; this.projectManager = projectManager; this.eventService = eventService; + this.clientCommandTransmitter = clientCommandTransmitter; this.gson = new GsonBuilder() .registerTypeAdapterFactory(new CollectionTypeAdapterFactory()) @@ -417,14 +420,16 @@ public List getResolvedClasspath(String projectUri) { * * @param projectUri project URI * @param entries classpath entries + * @return result of command execution */ - public void updateClasspath(String projectUri, List entries) { + public CompletableFuture updateClasspathWithResult( + String projectUri, List entries) { List fixedEntries = entries.stream().map(this::fixEntry).collect(Collectors.toList()); UpdateClasspathParameters params = new UpdateClasspathParameters(); params.setProjectUri(projectUri); params.setEntries(fixedEntries); - executeCommand(UPDATE_PROJECT_CLASSPATH, singletonList(params)); + return executeCommand(UPDATE_PROJECT_CLASSPATH, singletonList(params)); } private ClasspathEntry fixEntry(ClasspathEntry e) { @@ -1066,4 +1071,9 @@ private void iterate( iterate(child, childrenAccessor, elementHandler); } } + + public CompletableFuture executeClientCommand(String commandId, List parameters) { + ExecuteCommandParams params = new ExecuteCommandParams(commandId, parameters); + return clientCommandTransmitter.executeClientCommand(params); + } } diff --git a/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerLauncher.java b/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerLauncher.java index 2b1d01305ea..c0dc29876e9 100644 --- a/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerLauncher.java +++ b/plugins/plugin-java/che-plugin-java-server/src/main/java/org/eclipse/che/plugin/java/languageserver/JavaLanguageServerLauncher.java @@ -14,6 +14,7 @@ import static java.util.Collections.singletonList; import static org.eclipse.che.api.languageserver.LanguageServiceUtils.removePrefixUri; import static org.eclipse.che.api.languageserver.util.JsonUtil.convertToJson; +import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECT; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECTS_CLASSPATH; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECT_CONFIG; @@ -96,6 +97,7 @@ private void updateWorkspaceOnLSStarted() { registeredProject -> { if (!registeredProject.getProblems().isEmpty()) { try { + projectManager.update(registeredProject); eventService.publish(new ProjectUpdatedEvent(registeredProject.getPath())); } catch (ForbiddenException @@ -131,6 +133,7 @@ private ExecuteCommandParams convertParams(ExecuteCommandParams params) { String command = params.getCommand(); switch (command) { case CLIENT_UPDATE_PROJECTS_CLASSPATH: + case CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED: List fixedPathList = new ArrayList<>(params.getArguments().size()); for (Object uri : params.getArguments()) { fixedPathList.add(removePrefixUri(convertToJson(uri).getAsString())); diff --git a/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/service/ExecuteClientCommandProcessor.java b/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/service/ExecuteClientCommandProcessor.java index 41ffa8177f4..c05480d12a2 100644 --- a/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/service/ExecuteClientCommandProcessor.java +++ b/plugins/plugin-languageserver/che-plugin-languageserver-ide/src/main/java/org/eclipse/che/plugin/languageserver/ide/service/ExecuteClientCommandProcessor.java @@ -11,6 +11,7 @@ */ package org.eclipse.che.plugin.languageserver.ide.service; +import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECT; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECTS_CLASSPATH; import static org.eclipse.che.jdt.ls.extension.api.Commands.CLIENT_UPDATE_PROJECT_CONFIG; @@ -20,7 +21,10 @@ import com.google.inject.Singleton; import com.google.web.bindery.event.shared.EventBus; import java.util.List; +import org.eclipse.che.api.promises.client.Promise; +import org.eclipse.che.api.promises.client.PromiseProvider; import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.api.resources.Container; import org.eclipse.che.ide.project.ProjectServiceClient; import org.eclipse.che.ide.project.node.ProjectClasspathChangedEvent; import org.eclipse.che.ide.resource.Path; @@ -37,13 +41,18 @@ public class ExecuteClientCommandProcessor { private EventBus eventBus; private AppContext appContext; private final ProjectServiceClient projectService; + private final PromiseProvider promises; @Inject public ExecuteClientCommandProcessor( - EventBus eventBus, AppContext appContext, ProjectServiceClient projectService) { + EventBus eventBus, + AppContext appContext, + ProjectServiceClient projectService, + PromiseProvider promises) { this.eventBus = eventBus; this.appContext = appContext; this.projectService = projectService; + this.promises = promises; } public void execute(ExecuteCommandParams params) { @@ -59,20 +68,34 @@ public void execute(ExecuteCommandParams params) { case CLIENT_UPDATE_PROJECT_CONFIG: updateProjectConfig(stringValue(params.getArguments())); break; + case CLIENT_UPDATE_ON_PROJECT_CLASSPATH_CHANGED: + for (Object project : params.getArguments()) { + updateProject(stringValue(project)) + .then( + container -> { + eventBus.fireEvent( + new ProjectClasspathChangedEvent( + stringValue(container.getLocation().toString()))); + }); + } + break; default: break; } } - private void updateProject(String project) { - appContext + private Promise updateProject(String project) { + return appContext .getWorkspaceRoot() .getContainer(project) - .then( - container -> { - if (container.isPresent()) { - container.get().synchronize(); + .thenPromise( + optContainer -> { + if (optContainer.isPresent()) { + Container container = optContainer.get(); + container.synchronize(); + return promises.resolve(container); } + return promises.resolve(null); }); } diff --git a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/refactor/move/MoveJavaFileInNewSourceFolderTest.java b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/refactor/move/MoveJavaFileInNewSourceFolderTest.java index 50ea859d7cf..2a94f00b05f 100644 --- a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/refactor/move/MoveJavaFileInNewSourceFolderTest.java +++ b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/refactor/move/MoveJavaFileInNewSourceFolderTest.java @@ -77,7 +77,6 @@ public void checkMoveJavaClassInNewSourceFolder() { // create new folder and configure as source projectExplorer.waitAndSelectItem(PROJECT_NAME); createNewFolder(NEW_FOLDER_NAME); - projectExplorer.waitItem(PROJECT_NAME + "/" + NEW_FOLDER_NAME); projectExplorer.waitAndSelectItem(PROJECT_NAME + "/" + NEW_FOLDER_NAME); createNewFolder(NEW_SOURCE_FOLDER); projectExplorer.waitAndSelectItem(PATH_NEW_SOURCE_FOLDER);