Skip to content

Allow to update multiple projects at the same time #2131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls.
org.eclipse.jdt.ls.core.internal.text.correction;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.internal.gradle.checksums;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.filesystem;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.lsp4j.proposed;x-friends:="org.eclipse.jdt.ls.tests"
org.eclipse.lsp4j.proposed;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.lsp4j.extended;x-friends:="org.eclipse.jdt.ls.tests"
Bundle-ClassPath: lib/jsoup-1.14.2.jar,
lib/remark-1.2.0.jar,
.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
import org.eclipse.lsp4j.WillSaveTextDocumentParams;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam;
import org.eclipse.lsp4j.jsonrpc.CompletableFutures;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.jsonrpc.services.JsonDelegate;
Expand Down Expand Up @@ -843,6 +844,16 @@ public void projectConfigurationUpdate(TextDocumentIdentifier param) {
handler.updateConfiguration(param);
}

/* (non-Javadoc)
* @see org.eclipse.jdt.ls.core.internal.JavaProtocolExtensions#projectConfigurationsUpdate(org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam)
*/
@Override
public void projectConfigurationsUpdate(ProjectConfigurationsUpdateParam param) {
logInfo(">> java/projectConfigurationsUpdate");
ProjectConfigurationUpdateHandler handler = new ProjectConfigurationUpdateHandler(pm);
handler.updateConfigurations(param.getIdentifiers());
}

/* (non-Javadoc)
* @see org.eclipse.jdt.ls.core.internal.JavaProtocolExtensions#buildWorkspace(boolean)
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Red Hat Inc. and others.
* Copyright (c) 2016-2022 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
Expand All @@ -12,8 +12,17 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.handlers;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.lsp4j.TextDocumentIdentifier;

Expand All @@ -25,17 +34,53 @@ public class ProjectConfigurationUpdateHandler {

private ProjectsManager projectManager;

ProjectConfigurationUpdateHandler(ProjectsManager projectManager) {
public ProjectConfigurationUpdateHandler(ProjectsManager projectManager) {
this.projectManager = projectManager;
}

/**
* Update the projects' configurations (build files).
*
* @param identifiers the identifiers which may point to the projects' paths or
* files that belong to some projects in the workspace.
*/
public void updateConfigurations(List<TextDocumentIdentifier> identifiers) {
Set<IProject> projects = new HashSet<>();
for (TextDocumentIdentifier identifier : identifiers) {
IProject project = getProjectFromUri(identifier.getUri());
if (project != null) {
projects.add(project);
continue;
}
IFile file = JDTUtils.findFile(identifier.getUri());
if (file == null) {
continue;
}
project = file.getProject();
if (project != null) {
projects.add(project);
}
}

for (IProject project : projects) {
// most likely the handler is invoked intentionally by the user, that's why
// we force the update despite no changes of in build descriptor being made
projectManager.updateProject(project, true);
}
}

public void updateConfiguration(TextDocumentIdentifier param) {
IFile file = JDTUtils.findFile(param.getUri());
if (file == null) {
return;
updateConfigurations(Arrays.asList(param));
}

private IProject getProjectFromUri(String uri) {
IPath uriPath = ResourceUtils.canonicalFilePathFromURI(uri);
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : projects) {
if (project.getLocation().equals(uriPath)) {
return project;
}
}
// most likely the handler is invoked intentionally by the user, that's why
// we force the update despite no changes of in build descriptor being made
projectManager.updateProject(file.getProject(), true);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
Expand All @@ -61,11 +62,20 @@ public interface JavaProtocolExtensions {

/**
* Request a project configuration update
*
* @deprecated Please use {@link #projectConfigurationsUpdate(TextDocumentIdentifier)}.
* @param documentUri the document from which the project configuration will be updated
*/
@JsonNotification
void projectConfigurationUpdate(TextDocumentIdentifier documentUri);

/**
* Request multiple project configurations update
* @param documentUris the documents from which the project configuration will be updated
*/
@JsonNotification
void projectConfigurationsUpdate(ProjectConfigurationsUpdateParam params);

@JsonRequest
CompletableFuture<BuildWorkspaceStatus> buildWorkspace(Either<Boolean, boolean[]> forceReBuild);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2022 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.lsp4j.extended;

import java.util.List;

import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.validation.NonNull;
import org.eclipse.lsp4j.util.Preconditions;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;

@SuppressWarnings("all")
public class ProjectConfigurationsUpdateParam {
/**
* The text document's identifiers.
*/
@NonNull
private List<TextDocumentIdentifier> identifiers;

public ProjectConfigurationsUpdateParam() {
}

public ProjectConfigurationsUpdateParam(@NonNull final List<TextDocumentIdentifier> identifiers) {
this.identifiers = Preconditions.<List<TextDocumentIdentifier>>checkNotNull(identifiers, "identifiers");
}

@Pure
@NonNull
public List<TextDocumentIdentifier> getIdentifiers() {
return identifiers;
}

public void setIdentifiers(@NonNull final List<TextDocumentIdentifier> identifiers) {
this.identifiers = Preconditions.<List<TextDocumentIdentifier>>checkNotNull(identifiers, "identifiers");
}

@Override
@Pure
public String toString() {
ToStringBuilder b = new ToStringBuilder(this);
b.add("identifiers", this.identifiers);
return b.toString();
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((identifiers == null) ? 0 : identifiers.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProjectConfigurationsUpdateParam other = (ProjectConfigurationsUpdateParam) obj;
if (identifiers == null) {
if (other.identifiers != null)
return false;
} else if (!identifiers.equals(other.identifiers))
return false;
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2022 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.jdt.ls.core.internal.handlers;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.ls.core.internal.WorkspaceHelper;
import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam;
import org.junit.Test;

public class ProjectConfigurationUpdateHandlerTest extends AbstractProjectsManagerBasedTest {

@Test
public void testUpdateConfiguration() throws Exception {
importProjects("maven/multimodule");
ProjectsManager pm = mock(ProjectsManager.class);
when(pm.updateProject(any(IProject.class), anyBoolean())).thenReturn(null);
ProjectConfigurationUpdateHandler handler = new ProjectConfigurationUpdateHandler(pm);
IProject project = WorkspaceHelper.getProject("multimodule");
handler.updateConfiguration(new TextDocumentIdentifier(project.getLocationURI().toString()));
verify(pm, times(1)).updateProject(any(IProject.class), eq(true));
}

@Test
public void testUpdateConfigurations() throws Exception {
importProjects("maven/multimodule");
ProjectsManager pm = mock(ProjectsManager.class);
when(pm.updateProject(any(IProject.class), anyBoolean())).thenReturn(null);
ProjectConfigurationUpdateHandler handler = new ProjectConfigurationUpdateHandler(pm);
List<TextDocumentIdentifier> list = new ArrayList<>();
IProject project = WorkspaceHelper.getProject("module1");
list.add(new TextDocumentIdentifier(project.getLocationURI().toString()));
project = WorkspaceHelper.getProject("module2");
list.add(new TextDocumentIdentifier(project.getLocationURI().toString()));

ProjectConfigurationsUpdateParam param = new ProjectConfigurationsUpdateParam(list);

handler.updateConfigurations(param.getIdentifiers());
verify(pm, times(2)).updateProject(any(IProject.class), eq(true));
}
}