Skip to content

Commit

Permalink
Use linked resource instead of filesystem
Browse files Browse the repository at this point in the history
For all metadata files, except the .project (which may be harder to
move).
This also copies some logic from the filesystem to ProjectsManager. We
cannot have the filesystem bundle requiring and referencing the main
jdt.ls bundle as this would cause classloading error.
  • Loading branch information
mickaelistria committed May 16, 2023
1 parent 9f5abe3 commit 5b73422
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.internal.preferences.EclipsePreferences;
import org.eclipse.core.internal.resources.CharsetManager;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.FileInfoMatcherDescription;
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 @@ -52,6 +54,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
Expand Down Expand Up @@ -343,6 +346,43 @@ public static IProject createJavaProject(IProject project, IProgressMonitor moni
return createJavaProject(project, null, "src", "bin", monitor);
}

/**
* The system property key to specify the file system mode.
*/
public static final String GENERATES_METADATA_FILES_AT_PROJECT_ROOT = "java.import.generatesMetadataFilesAtProjectRoot";
public static final IPath METADATA_FOLDER_PATH = ResourcesPlugin.getPlugin().getStateLocation().append(".projects");

/**
* Check whether the metadata files needs to be generated at project root.
*/
public static boolean generatesMetadataFilesAtProjectRoot() {
String property = System.getProperty(GENERATES_METADATA_FILES_AT_PROJECT_ROOT);
if (property == null) {
return true;
}
return Boolean.parseBoolean(property);
}

/**
* Get the redirected path of the input path. The path will be redirected to
* the workspace's metadata folder ({@link JLSFsUtils#METADATA_FOLDER_PATH}).
* @param projectName name of the project.
* @param path path needs to be redirected.
* @return the redirected path.
*/
public static IPath getMetaDataFilePath(String projectName, IPath path) {
if (path.segmentCount() == 1) {
return METADATA_FOLDER_PATH.append(projectName).append(path);
}

String lastSegment = path.lastSegment();
if (IProjectDescription.DESCRIPTION_FILE_NAME.equals(lastSegment)) {
return METADATA_FOLDER_PATH.append(projectName).append(lastSegment);
}

return null;
}

public static IProject createJavaProject(IProject project, IPath projectLocation, String src, String bin, IProgressMonitor monitor) throws CoreException, OperationCanceledException {
if (project.exists()) {
return project;
Expand All @@ -355,6 +395,20 @@ public static IProject createJavaProject(IProject project, IPath projectLocation
}
project.create(description, monitor);
project.open(monitor);
if (!generatesMetadataFilesAtProjectRoot()) {
IFile classpathFile = project.getFile(IJavaProject.CLASSPATH_FILE_NAME);
if (!classpathFile.exists()) {
classpathFile.createLink(getMetaDataFilePath(classpathFile.getProject().getName(), classpathFile.getProjectRelativePath()).toFile().toURI(), IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor());
}
IFile factorypathFile = project.getFile(".factorypath");
if (!factorypathFile.exists()) {
factorypathFile.createLink(getMetaDataFilePath(classpathFile.getProject().getName(), factorypathFile.getProjectRelativePath()).toFile().toURI(), IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor());
}
IFolder settingsFolder = project.getFolder(EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME);
if (!settingsFolder.exists()) {
settingsFolder.createLink(getMetaDataFilePath(classpathFile.getProject().getName(), settingsFolder.getProjectRelativePath()).toFile().toURI(), IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor());
}
}

//Turn into Java project
description = project.getDescription();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.internal.filesystem.local.LocalFile;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
Expand Down Expand Up @@ -56,11 +57,9 @@ public String[] childNames(int options, IProgressMonitor monitor) {
}

Set<String> childNameSet = new LinkedHashSet<>(Arrays.asList(childNames));
for (String fileName : JLSFsUtils.METADATA_NAMES) {
if (!childNameSet.contains(fileName) &&
JLSFsUtils.METADATA_FOLDER_PATH.append(projectName).append(fileName).toFile().exists()) {
childNameSet.add(fileName);
}
if (!childNameSet.contains(IProjectDescription.DESCRIPTION_FILE_NAME) &&
JLSFsUtils.METADATA_FOLDER_PATH.append(projectName).append(IProjectDescription.DESCRIPTION_FILE_NAME).toFile().exists()) {
childNameSet.add(IProjectDescription.DESCRIPTION_FILE_NAME);
}

return childNameSet.toArray(String[]::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,6 @@ private JLSFsUtils() {}

static final String FACTORY_PATH = ".factorypath";

/**
* The metadata files
*/
static final Set<String> METADATA_NAMES = new HashSet<>(Arrays.asList(
IProjectDescription.DESCRIPTION_FILE_NAME,
EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME,
IJavaProject.CLASSPATH_FILE_NAME,
FACTORY_PATH
));

/**
* Determine whether the resource should be stored in workspace's metadata folder.
* <p>
Expand All @@ -77,9 +67,6 @@ static boolean shouldStoreInMetadataArea(IPath location) {
// do not redirect if the file already exists on disk
if (location.toFile().exists()) {
return false;
} else if (location.lastSegment().endsWith(EclipsePreferences.PREFS_FILE_EXTENSION)) {
location = location.removeLastSegments(1);
return !location.toFile().exists();
}

return true;
Expand All @@ -95,15 +82,11 @@ static boolean isProjectMetadataFile(IPath location) {
return false;
}

if (location.lastSegment().endsWith(EclipsePreferences.PREFS_FILE_EXTENSION)) {
location = location.removeLastSegments(1);
}

if (location.segmentCount() < 2) {
return false;
}

if (!METADATA_NAMES.contains(location.lastSegment())) {
if (IProjectDescription.DESCRIPTION_FILE_NAME.equals(location.lastSegment())) {
return false;
}

Expand All @@ -116,9 +99,6 @@ static boolean isProjectMetadataFile(IPath location) {
* @param filePath the file path.
*/
static IPath getContainerPath(IPath filePath) {
if (filePath.lastSegment().endsWith(EclipsePreferences.PREFS_FILE_EXTENSION)) {
filePath = filePath.removeLastSegments(1);
}
return filePath.removeLastSegments(1);
}

Expand Down Expand Up @@ -152,12 +132,8 @@ static IPath getMetaDataFilePath(String projectName, IPath path) {
}

String lastSegment = path.lastSegment();
if (METADATA_NAMES.contains(lastSegment)) {
if (IProjectDescription.DESCRIPTION_FILE_NAME.equals(lastSegment)) {
return METADATA_FOLDER_PATH.append(projectName).append(lastSegment);
} else if (lastSegment.endsWith(EclipsePreferences.PREFS_FILE_EXTENSION)) {
return METADATA_FOLDER_PATH.append(projectName)
.append(EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME)
.append(lastSegment);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManagerTest;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager.CHANGE_TYPE;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -51,7 +53,7 @@ public static Collection<String> data(){

@Before
public void setUp() {
System.setProperty(JLSFsUtils.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
System.setProperty(ProjectsManager.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.WorkspaceHelper;
import org.eclipse.jdt.ls.core.internal.managers.AbstractGradleBasedTest;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager.CHANGE_TYPE;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences.FeatureStatus;
import org.junit.Before;
Expand All @@ -62,7 +63,7 @@ public static Collection<String> data(){

@Before
public void setup() throws Exception {
System.setProperty(JLSFsUtils.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
System.setProperty(ProjectsManager.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
}

@Test
Expand All @@ -77,33 +78,33 @@ public void testMetadataFileLocation() throws Exception {
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath projectDescriptionPath = FileUtil.toPath(projectDescription.getLocationURI());
assertTrue(projectDescriptionPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

IFile preferencesFile = project.getFile(EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath preferencesPath = FileUtil.toPath(preferencesFile.getLocationURI());
assertTrue(preferencesPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

// then we check the sub-module
project = WorkspaceHelper.getProject("app");
projectDescription = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
projectDescriptionPath = FileUtil.toPath(projectDescription.getLocationURI());
assertTrue(projectDescriptionPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

IFile classpath = project.getFile(IJavaProject.CLASSPATH_FILE_NAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath classpathPath = FileUtil.toPath(classpath.getLocationURI());
assertTrue(classpathPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(classpathPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(classpathPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

preferencesFile = project.getFile(EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
preferencesPath = FileUtil.toPath(preferencesFile.getLocationURI());
assertTrue(preferencesPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.ls.core.internal.TestVMType;
import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -49,7 +50,7 @@ public static Collection<String> data(){

@Before
public void setUp() {
System.setProperty(JLSFsUtils.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
System.setProperty(ProjectsManager.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, fsMode);
}

@Test
Expand All @@ -61,19 +62,17 @@ public void testMetadataFileLocation() throws Exception {
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath projectDescriptionPath = FileUtil.toPath(projectDescription.getLocationURI());
assertTrue(projectDescriptionPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(projectDescriptionPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

IFile classpath = project.getFile(IJavaProject.CLASSPATH_FILE_NAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath classpathPath = FileUtil.toPath(classpath.getLocationURI());
IPath classpathPath = classpath.getLocation();
assertTrue(classpathPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(classpathPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(classpathPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());

IFile preferencesFile = project.getFile(EclipsePreferences.DEFAULT_PREFERENCES_DIRNAME);
// workaround to get the correct path, see: https://github.com/eclipse/eclipse.jdt.ls/pull/1900
IPath preferencesPath = FileUtil.toPath(preferencesFile.getLocationURI());
IPath preferencesPath = preferencesFile.getLocation();
assertTrue(preferencesPath.toFile().exists());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertEquals(project.getLocation().isPrefixOf(preferencesPath), ProjectsManager.generatesMetadataFilesAtProjectRoot());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.junit.Test;

public class JLSFsUtilsTest {
@Test
public void testGeneratesMetadataFilesAtProjectRoot() {
System.setProperty(JLSFsUtils.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, "true");
assertTrue(JLSFsUtils.generatesMetadataFilesAtProjectRoot());
System.setProperty(ProjectsManager.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, "true");
assertTrue(ProjectsManager.generatesMetadataFilesAtProjectRoot());
}

@Test
public void testNotGeneratesMetadataFilesAtProjectRoot() {
System.setProperty(JLSFsUtils.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, "false");
assertFalse(JLSFsUtils.generatesMetadataFilesAtProjectRoot());
System.setProperty(ProjectsManager.GENERATES_METADATA_FILES_AT_PROJECT_ROOT, "false");
assertFalse(ProjectsManager.generatesMetadataFilesAtProjectRoot());
}

@Test
public void testGeneratesMetadataFilesAtProjectRootWhenNotSet() {
assertTrue(JLSFsUtils.generatesMetadataFilesAtProjectRoot());
assertTrue(ProjectsManager.generatesMetadataFilesAtProjectRoot());
}
}
Loading

0 comments on commit 5b73422

Please sign in to comment.