Skip to content
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

Add new API 'onWillUpdate()' to IBuildSupport #2836

Merged
merged 3 commits into from
Oct 8, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,9 @@ public ProjectConfigurationUpdateHandler(ProjectsManager projectManager) {
*/
public void updateConfigurations(List<TextDocumentIdentifier> identifiers) {
Collection<IProject> projects = ProjectUtils.getProjectsFromDocumentIdentifiers(identifiers);

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);
}
// 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.updateProjects(projects, true);
}

public void updateConfiguration(TextDocumentIdentifier param) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ default boolean isBuildLikeFileName(String fileName) {
return false;
}

/**
* Implementors can put preparation work into this method. This method will be invoked before {@code update(...)}.
*/
default void onWillUpdate(Collection<IProject> projects, IProgressMonitor monitor) throws CoreException {
// do nothing
}

/**
*
* @param resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public interface IProjectsManager {
*/
Job updateProject(IProject project, boolean force);

/**
* Update a set of project configurations.
*/
Job updateProjects(Collection<IProject> projects, boolean force);

/**
* Check whether the resource is a build file.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -446,6 +448,14 @@ public IStatus runInWorkspace(IProgressMonitor monitor) {
return job;
}

@Override
public Job updateProjects(Collection<IProject> projects, boolean force) {
JavaLanguageServerPlugin.sendStatus(ServiceStatus.Message, "Updating project configurations...");
UpdateProjectsWorkspaceJob job = new UpdateProjectsWorkspaceJob(projects, force);
job.schedule();
return job;
}

@Override
public Optional<IBuildSupport> getBuildSupport(IProject project) {
return buildSupports().filter(bs -> bs.applies(project)).findFirst();
Expand All @@ -467,7 +477,7 @@ public boolean useDefaultVM(IProject project, IVMInstall defaultVM) {
return false;
}

private Stream<IBuildSupport> buildSupports() {
protected Stream<IBuildSupport> buildSupports() {
return Stream.of(new EclipseBuildSupport());
}

Expand Down Expand Up @@ -632,4 +642,96 @@ public void reportProjectsStatus() {
}
}

class UpdateProjectsWorkspaceJob extends WorkspaceJob {

private final Collection<IProject> projects;
private final boolean force;

public UpdateProjectsWorkspaceJob(Collection<IProject> projects, boolean force) {
super("Updating project configurations");
this.projects = projects;
this.force = force;
}

@Override
public boolean belongsTo(Object family) {
return IConstants.UPDATE_PROJECT_FAMILY.equals(family) || IConstants.JOBS_FAMILY.equals(family);
}

@Override
public IStatus runInWorkspace(IProgressMonitor monitor) {
long start = System.currentTimeMillis();
MultiStatus status = new MultiStatus(IConstants.PLUGIN_ID, 0, "Update project configurations");
for (Entry<IBuildSupport, List<IProject>> entry : groupByBuildSupport(projects).entrySet()) {
IStatus onWillUpdateStatus = onWillConfigurationUpdate(entry.getKey(),
entry.getValue(), monitor);

// if onWillUpdate() failed, skip updating the projects.
if (!onWillUpdateStatus.isOK()) {
status.add(onWillUpdateStatus);
continue;
}

for (IProject project : entry.getValue()) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
updateProject(entry.getKey(), project, force, status, monitor);
}
}

onDidConfigurationUpdated(status, monitor);
long elapsed = System.currentTimeMillis() - start;
JavaLanguageServerPlugin.logInfo("Projects updated in " + elapsed + " ms");
return status;
}

private Map<IBuildSupport, List<IProject>> groupByBuildSupport(Collection<IProject> projects) {
Map<IBuildSupport, List<IProject>> groupByBuildSupport = new HashMap<>();
List<IBuildSupport> buildSupports = buildSupports().toList();
for (IProject project : projects) {
Optional<IBuildSupport> buildSupport = buildSupports.stream()
.filter(bs -> bs.applies(project)).findFirst();
if (buildSupport.isPresent()) {
IBuildSupport bs = buildSupport.get();
groupByBuildSupport.computeIfAbsent(bs, k -> new ArrayList<>()).add(project);
}
}
return groupByBuildSupport;
}

private IStatus onWillConfigurationUpdate(IBuildSupport buildSupport, Collection<IProject> projects,
IProgressMonitor monitor) {
try {
buildSupport.onWillUpdate(projects, monitor);
return Status.OK_STATUS;
} catch (CoreException e) {
JavaLanguageServerPlugin.log(e);
return StatusFactory.newErrorStatus("Failed to prepare update from " + buildSupport.buildToolName(), e);
}
}

private void updateProject(IBuildSupport buildSupport, IProject project, boolean force,
MultiStatus status, IProgressMonitor monitor) {
try {
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
buildSupport.update(project, force, monitor);
project.deleteMarkers(BUILD_FILE_MARKER_TYPE, false, IResource.DEPTH_ONE);
} catch (CoreException e) {
JavaLanguageServerPlugin.log(e);
status.add(StatusFactory.newErrorStatus("Error updating " + project.getName(), e));
}
}

private void onDidConfigurationUpdated(MultiStatus status, IProgressMonitor monitor) {
try {
registerWatchers(true);
updateEncoding(monitor);
reportProjectsStatus();
} catch (CoreException e) {
JavaLanguageServerPlugin.log(e);
status.add(StatusFactory.newErrorStatus("Error updating encoding", e));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ public class ProjectConfigurationUpdateHandlerTest extends AbstractProjectsManag
public void testUpdateConfiguration() throws Exception {
importProjects("maven/multimodule");
ProjectsManager pm = mock(ProjectsManager.class);
when(pm.updateProject(any(IProject.class), anyBoolean())).thenReturn(null);
when(pm.updateProjects(any(), 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));
verify(pm, times(1)).updateProjects(any(), 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);
when(pm.updateProjects(any(), anyBoolean())).thenReturn(null);
ProjectConfigurationUpdateHandler handler = new ProjectConfigurationUpdateHandler(pm);
List<TextDocumentIdentifier> list = new ArrayList<>();
IProject project = WorkspaceHelper.getProject("module1");
Expand All @@ -60,6 +60,6 @@ public void testUpdateConfigurations() throws Exception {
ProjectConfigurationsUpdateParam param = new ProjectConfigurationsUpdateParam(list);

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