Skip to content

Commit

Permalink
Enhanced IBuildSupport usage to support other build tools such as baz…
Browse files Browse the repository at this point in the history
…el (#1694)

Based on #1674

* Refactored ExtensionsExtractor
* Use the ProjectUtils static methods in cases where we know exactly which build support we want to check against the project.

Signed-off-by: Siarhei Leanavets <siarhei_leanavets1@epam.com>
  • Loading branch information
LeonovecSergey committed Apr 14, 2021
1 parent 9130c92 commit d7a0f3c
Show file tree
Hide file tree
Showing 17 changed files with 364 additions and 126 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2021 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
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;

/**
* The class simplifies extracting extensions from the extension points.
*
* @author D.Bushenko
*
*/
public class ExtensionsExtractor {
public static <T> List<T> extractOrderedExtensions(final String namespace, final String extensionPointName) {

final var extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(namespace, extensionPointName);
final var configs = extensionPoint.getConfigurationElements();

Map<Integer, T> extensionMap = new TreeMap<>();

for (int i = 0; i < configs.length; i++) {
Integer order = Integer.valueOf(configs[i].getAttribute("order"));
extensionMap.put(order, makeExtension(configs[i]));
}
return extensionMap.values().stream().collect(Collectors.toUnmodifiableList());
}

@SuppressWarnings("unchecked")
private static <T> T makeExtension(IConfigurationElement config) {
try {
return (T) config.createExecutableExtension("class");

} catch (Exception ex) {
throw new IllegalArgumentException("Could not create the extension", ex);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -48,6 +49,9 @@
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ls.core.internal.managers.BuildSupportManager;
import org.eclipse.jdt.ls.core.internal.managers.IBuildSupport;
import org.eclipse.jdt.ls.core.internal.managers.InternalBuildSupports;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.m2e.core.internal.IMavenConstants;
Expand Down Expand Up @@ -91,7 +95,12 @@ public static boolean isGradleProject(IProject project) {
}

public static boolean isGeneralJavaProject(IProject project) {
return isJavaProject(project) && !isMavenProject(project) && !isGradleProject(project);
return isJavaProject(project) && isInternalBuildSupport(BuildSupportManager.find(project).orElse(null));
}

public static boolean isInternalBuildSupport(IBuildSupport buildSupport) {
return buildSupport != null && Arrays.stream(InternalBuildSupports.values())
.anyMatch(bsn -> Objects.equals(buildSupport.buildToolName(), bsn.toString()));
}

public static String getJavaSourceLevel(IProject project) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,24 @@
import org.eclipse.jdt.ls.core.internal.Messages;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.managers.BuildSupportManager;
import org.eclipse.jdt.ls.core.internal.managers.IBuildSupport;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;

public class BuildPathCommand {
public static final String UNSUPPORTED_ON_MAVEN = "Unsupported operation. Please use pom.xml file to manage the source directories of maven project.";
public static final String UNSUPPORTED_ON_GRADLE = "Unsupported operation. Please use build.gradle file to manage the source directories of gradle project.";
private static final String UNSUPPORTED_OPERATION = "Unsupported operation. Please use your build tool project file to manage the source directories of the project.";

private static String unsupportedOperationMessage(IProject targetProject) {
return BuildSupportManager.obtainBuildSupports().stream().filter(bs -> bs.applies(targetProject)).findFirst().map(IBuildSupport::unsupportedOperationMessage).orElse(UNSUPPORTED_OPERATION);
}

public static Result addToSourcePath(String sourceFolderUri) {
IPath sourceFolderPath = ResourceUtils.filePathFromURI(sourceFolderUri);
IProject targetProject = findBelongedProject(sourceFolderPath);

if (targetProject != null && !ProjectUtils.isGeneralJavaProject(targetProject)) {
String message = ProjectUtils.isGradleProject(targetProject) ? UNSUPPORTED_ON_GRADLE : UNSUPPORTED_ON_MAVEN;
return new Result(false, message);
return new Result(false, unsupportedOperationMessage(targetProject));
}

IPath projectLocation = null;
Expand Down Expand Up @@ -99,8 +104,7 @@ public static Result removeFromSourcePath(String sourceFolderUri) {
IPath sourceFolderPath = ResourceUtils.filePathFromURI(sourceFolderUri);
IProject targetProject = findBelongedProject(sourceFolderPath);
if (targetProject != null && !ProjectUtils.isGeneralJavaProject(targetProject)) {
String message = ProjectUtils.isGradleProject(targetProject) ? UNSUPPORTED_ON_GRADLE : UNSUPPORTED_ON_MAVEN;
return new Result(false, message);
return new Result(false, unsupportedOperationMessage(targetProject));
}

IPath projectLocation = null;
Expand Down Expand Up @@ -141,52 +145,58 @@ public static Result removeFromSourcePath(String sourceFolderUri) {
}

public static Result listSourcePaths() {
try {
List<SourcePath> sourcePathList = new ArrayList<>();
IProject[] projects = ProjectUtils.getAllProjects();
for (IProject project : projects) {
if (!ProjectsManager.DEFAULT_PROJECT_NAME.equals(project.getName()) && ProjectUtils.isJavaProject(project)) {
sourcePathList.addAll(tryAddProjectToSourcePath(project));
}
}

return new ListCommandResult(true, null, sourcePathList.toArray(new SourcePath[0]));

} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException("Failed to resolve the existing source paths in current workspace.", e);
return new ListCommandResult(false, e.getMessage());
}
}

private static List<SourcePath> tryAddProjectToSourcePath(IProject project) throws JavaModelException {
List<SourcePath> sourcePathList = new ArrayList<>();
IProject[] projects = ProjectUtils.getAllProjects();
for (IProject project : projects) {
if (!ProjectsManager.DEFAULT_PROJECT_NAME.equals(project.getName()) && ProjectUtils.isJavaProject(project)) {
try {
IPath[] paths = ProjectUtils.listSourcePaths(JavaCore.create(project));
for (IPath path : paths) {
IPath entryPath = path;
String projectName = project.getName();
String projectType = "General";
if (ProjectUtils.isMavenProject(project)) {
projectType = "Maven";
}

if (ProjectUtils.isGradleProject(project)) {
projectType = "Gradle";
}

IContainer projectRoot = project;
if (!ProjectUtils.isVisibleProject(project)) {
projectType = "Workspace";
IFolder workspaceLinkFolder = project.getFolder(ProjectUtils.WORKSPACE_LINK);
if (!workspaceLinkFolder.isLinked()) {
continue;
}

projectRoot = workspaceLinkFolder;
}

IPath relativePath = entryPath.makeRelativeTo(projectRoot.getFullPath());
IPath location = projectRoot.getRawLocation().append(relativePath);
IPath displayPath = getWorkspacePath(location);
sourcePathList.add(new SourcePath(location != null ? location.toOSString() : "",
displayPath != null ? displayPath.toOSString() : entryPath.toOSString(),
entryPath.toOSString(),
projectName,
projectType));
}
} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException("Failed to resolve the existing source paths in current workspace.", e);
return new ListCommandResult(false, e.getMessage());
IPath[] paths = ProjectUtils.listSourcePaths(JavaCore.create(project));

for (IPath path : paths) {
IPath entryPath = path;
String projectName = project.getName();
String projectType = determineProjectType(project);

IContainer projectRoot = project;
if (!ProjectUtils.isVisibleProject(project)) {
projectType = "Workspace";
IFolder workspaceLinkFolder = project.getFolder(ProjectUtils.WORKSPACE_LINK);
if (!workspaceLinkFolder.isLinked()) {
continue;
}

projectRoot = workspaceLinkFolder;
}

IPath relativePath = entryPath.makeRelativeTo(projectRoot.getFullPath());
IPath location = projectRoot.getRawLocation().append(relativePath);
IPath displayPath = getWorkspacePath(location);
sourcePathList.add(new SourcePath(location != null ? location.toOSString() : "",
displayPath != null ? displayPath.toOSString() : entryPath.toOSString(),
entryPath.toOSString(),
projectName,
projectType));
}

return new ListCommandResult(true, null, sourcePathList.toArray(new SourcePath[0]));
return sourcePathList;
}

private static String determineProjectType(IProject project) {
return BuildSupportManager.find(project).map(buildSupport -> buildSupport.buildToolName()).orElseGet(() -> "General");
}

private static String[] getInvisibleProjectRelativeSourcePaths(IJavaProject javaProject) throws JavaModelException {
Expand All @@ -199,10 +209,9 @@ private static String[] getInvisibleProjectRelativeSourcePaths(IJavaProject java
}
IPath[] paths = ProjectUtils.listSourcePaths(javaProject);
return Arrays.stream(paths)
.map(p -> p.makeRelativeTo(workspaceLinkFolder.getFullPath()).toString())
.toArray(String[]::new);
.map(p -> p.makeRelativeTo(workspaceLinkFolder.getFullPath()).toString())
.toArray(String[]::new);
}

private static IProject findBelongedProject(IPath sourceFolder) {
List<IProject> projects = Stream.of(ProjectUtils.getAllProjects()).filter(ProjectUtils::isJavaProject).sorted(new Comparator<IProject>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2021 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
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.managers;

import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.ls.core.internal.ExtensionsExtractor;
import org.eclipse.jdt.ls.core.internal.IConstants;

/**
* This is an orchestrator who is responsible for fetching and searching
* IBuildSupport objects.
*
* @author D.Bushenko
*
*/
public class BuildSupportManager {
private static final BuildSupportManager instance = new BuildSupportManager();
private List<IBuildSupport> lazyLoadedBuildSupportList;

private BuildSupportManager() {}

public static List<IBuildSupport> obtainBuildSupports() {
if (instance.lazyLoadedBuildSupportList == null) {
instance.lazyLoadedBuildSupportList = ExtensionsExtractor.extractOrderedExtensions(IConstants.PLUGIN_ID, "buildSupport");
}

return instance.lazyLoadedBuildSupportList;
}

public static Optional<IBuildSupport> find(IProject project) {
return instance.find(bs -> bs.applies(project));
}

public static Optional<IBuildSupport> find(String buildToolName) {
return instance.find(bs -> bs.buildToolName().equalsIgnoreCase(buildToolName));
}

private Optional<IBuildSupport> find(Predicate<? super IBuildSupport> predicate) {
return obtainBuildSupports().stream().filter(predicate).findFirst();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ public boolean applies(IProject project) {
return JavaLanguageServerPlugin.getProjectsManager().getDefaultProject().equals(project);
}

@Override
public String buildToolName() {
return InternalBuildSupports.DEFAULT.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,9 @@ public void discoverSource(IClassFile classFile, IProgressMonitor monitor) throw
}
}

@Override
public String buildToolName() {
return InternalBuildSupports.ECLIPSE.toString();
}

}
Loading

0 comments on commit d7a0f3c

Please sign in to comment.