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

Allow build selected projects #2138

Merged
merged 1 commit into from
Jun 29, 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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.LinkedList;
Expand All @@ -34,6 +35,7 @@
import org.codehaus.plexus.util.DirectoryScanner;
import org.eclipse.buildship.core.internal.configuration.GradleProjectNature;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
Expand All @@ -58,6 +60,7 @@
import org.eclipse.jdt.ls.core.internal.managers.MavenProjectImporter;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.m2e.core.internal.IMavenConstants;

/**
Expand Down Expand Up @@ -585,4 +588,40 @@ private static boolean isBuildFileMarker(IMarker marker, IProject project) {
return false;
}

/**
* Get a collection of projects based on the given document identifiers. The belonging projects of those
* documents will be added to the returned collection.
* @param identifiers a list of the {@link org.eclipse.lsp4j.TextDocumentIdentifier}
*/
public static Collection<IProject> getProjectsFromDocumentIdentifiers(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);
}
}
return projects;
}

private static 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;
}
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Microsoft Corporation and others.
* Copyright (c) 2017-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
Expand All @@ -16,9 +16,14 @@
import static org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin.logException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
Expand All @@ -33,6 +38,7 @@
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.lsp4j.extended.ProjectBuildParams;

/**
* @author xuzho
Expand Down Expand Up @@ -85,6 +91,92 @@ public BuildWorkspaceStatus buildWorkspace(boolean forceReBuild, IProgressMonito
}
}

/**
* Build the belonging projects of the document identifiers in the <code>params</code>.
* @param params the project build parameter.
* @param monitor progress monitor.
* @return {@link org.eclipse.jdt.ls.core.internal.BuildWorkspaceStatus}
*/
public BuildWorkspaceStatus buildProjects(ProjectBuildParams params, IProgressMonitor monitor) {
Collection<IProject> projects = ProjectUtils.getProjectsFromDocumentIdentifiers(params.getIdentifiers());

if (projects.size() == 0) {
logError("Build projects fail: Cannot find projects from given uris.");
return BuildWorkspaceStatus.CANCELLED;
}

IBuildConfiguration[] configs = getBuildConfigurationsToBuild(projects);
try {
if (params.isFullBuild()) {
ResourcesPlugin.getWorkspace().build(configs, IncrementalProjectBuilder.CLEAN_BUILD, true, monitor);
ResourcesPlugin.getWorkspace().build(configs, IncrementalProjectBuilder.FULL_BUILD, true, monitor);
} else {
ResourcesPlugin.getWorkspace().build(configs, IncrementalProjectBuilder.INCREMENTAL_BUILD, true, monitor);
}
} catch (CoreException e) {
logException("Failed to build projects.", e);
return BuildWorkspaceStatus.FAILED;
} catch (OperationCanceledException e) {
return BuildWorkspaceStatus.CANCELLED;
}

for (IProject project : projects) {
if (project.equals(ProjectsManager.getDefaultProject())) {
continue;
}

try {
List<IMarker> markers = ResourceUtils.getErrorMarkers(project);
if (markers != null && markers.size() > 0) {
return BuildWorkspaceStatus.WITH_ERROR;
}
} catch (CoreException e) {
logException("Failed to get error markers from project: " + project.getName(), e);
return BuildWorkspaceStatus.FAILED;
}
}

return BuildWorkspaceStatus.SUCCEED;
}

/**
* return project build configs, which will be passed to the workspace for building.
* The Workspace is responsible for resolving references.
*/
protected IBuildConfiguration[] getBuildConfigurationsToBuild(Collection<IProject> projects) {
Set<IBuildConfiguration> configs = new HashSet<>();
for (IProject project : projects) {
if (project != null && hasBuilder(project)) {
try {
configs.add(project.getActiveBuildConfig());
} catch(CoreException e) {
logException("Failed to get build config.", e);
}
}
}
return configs.toArray(new IBuildConfiguration[configs.size()]);
}

/**
* Returns whether there are builders configured on the given project.
*
* @return <code>true</code> if it has builders,
* <code>false</code> if not, or if this couldn't be determined
*/
protected boolean hasBuilder(IProject project) {
if (!project.isAccessible())
return false;
try {
ICommand[] commands = project.getDescription().getBuildSpec();
if (commands.length > 0) {
return true;
}
} catch (CoreException e) {
logException("Failed to check project's builder.", e);
}
return false;
}

private static String convertMarker(IMarker marker) {
StringBuilder builder = new StringBuilder();
String message = marker.getAttribute(IMarker.MESSAGE, "<no message>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam;
import org.eclipse.lsp4j.extended.ProjectBuildParams;
import org.eclipse.lsp4j.jsonrpc.CompletableFutures;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.jsonrpc.services.JsonDelegate;
Expand Down Expand Up @@ -867,6 +868,13 @@ public CompletableFuture<BuildWorkspaceStatus> buildWorkspace(Either<Boolean, bo
return computeAsyncWithClientProgress((monitor) -> handler.buildWorkspace(rebuild, monitor));
}

@Override
public CompletableFuture<BuildWorkspaceStatus> buildProjects(ProjectBuildParams params) {
logInfo(">> java/buildProjects");
BuildWorkspaceHandler handler = new BuildWorkspaceHandler(pm);
return computeAsyncWithClientProgress((monitor) -> handler.buildProjects(params, monitor));
}

/* (non-Javadoc)
* @see org.eclipse.lsp4j.services.WorkspaceService#didChangeWorkspaceFolders(DidChangeWorkspaceFoldersParams)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@
package org.eclipse.jdt.ls.core.internal.handlers;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Collection;
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.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.lsp4j.TextDocumentIdentifier;

Expand All @@ -45,22 +40,7 @@ public ProjectConfigurationUpdateHandler(ProjectsManager projectManager) {
* 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);
}
}
Collection<IProject> projects = ProjectUtils.getProjectsFromDocumentIdentifiers(identifiers);

for (IProject project : projects) {
// most likely the handler is invoked intentionally by the user, that's why
Expand All @@ -72,15 +52,4 @@ public void updateConfigurations(List<TextDocumentIdentifier> identifiers) {
public void updateConfiguration(TextDocumentIdentifier param) {
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;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2019 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 Down Expand Up @@ -43,6 +43,7 @@
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.extended.ProjectConfigurationsUpdateParam;
import org.eclipse.lsp4j.extended.ProjectBuildParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
Expand Down Expand Up @@ -79,6 +80,9 @@ public interface JavaProtocolExtensions {
@JsonRequest
CompletableFuture<BuildWorkspaceStatus> buildWorkspace(Either<Boolean, boolean[]> forceReBuild);

@JsonRequest
CompletableFuture<BuildWorkspaceStatus> buildProjects(ProjectBuildParams params);

@JsonRequest
CompletableFuture<OverridableMethodsResponse> listOverridableMethods(CodeActionParams params);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*******************************************************************************
* 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 ProjectBuildParams {
/**
* The text document's identifiers.
*/
@NonNull
private List<TextDocumentIdentifier> identifiers;

/**
* Whether this is a full build or incremental build.
*/
private boolean isFullBuild;

public ProjectBuildParams() {
}

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

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

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

public boolean isFullBuild() {
return isFullBuild;
}

public void setFullBuild(boolean isFullBuild) {
this.isFullBuild = isFullBuild;
}

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

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

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProjectBuildParams other = (ProjectBuildParams) obj;
if (identifiers == null) {
if (other.identifiers != null)
return false;
} else if (!identifiers.equals(other.identifiers))
return false;
if (isFullBuild != other.isFullBuild)
return false;
return true;
}

}
Loading