Refactor, fix and simplify classpath infrastructure
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
sp_cleanup.add_missing_deprecated_annotations=true
|
||||
sp_cleanup.add_missing_methods=false
|
||||
sp_cleanup.add_missing_nls_tags=false
|
||||
sp_cleanup.add_missing_override_annotations=true
|
||||
sp_cleanup.add_missing_override_annotations_interface_methods=true
|
||||
sp_cleanup.add_serial_version_id=false
|
||||
sp_cleanup.always_use_blocks=true
|
||||
sp_cleanup.always_use_parentheses_in_expressions=false
|
||||
sp_cleanup.always_use_this_for_non_static_field_access=false
|
||||
sp_cleanup.always_use_this_for_non_static_method_access=false
|
||||
sp_cleanup.convert_functional_interfaces=false
|
||||
sp_cleanup.convert_to_enhanced_for_loop=false
|
||||
sp_cleanup.correct_indentation=false
|
||||
sp_cleanup.format_source_code=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
sp_cleanup.insert_inferred_type_arguments=false
|
||||
sp_cleanup.make_local_variable_final=true
|
||||
sp_cleanup.make_parameters_final=false
|
||||
sp_cleanup.make_private_fields_final=true
|
||||
sp_cleanup.make_type_abstract_if_missing_method=false
|
||||
sp_cleanup.make_variable_declarations_final=false
|
||||
sp_cleanup.never_use_blocks=false
|
||||
sp_cleanup.never_use_parentheses_in_expressions=true
|
||||
sp_cleanup.on_save_use_additional_actions=true
|
||||
sp_cleanup.organize_imports=false
|
||||
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
sp_cleanup.remove_private_constructors=true
|
||||
sp_cleanup.remove_redundant_type_arguments=false
|
||||
sp_cleanup.remove_trailing_whitespaces=true
|
||||
sp_cleanup.remove_trailing_whitespaces_all=true
|
||||
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
sp_cleanup.remove_unnecessary_casts=false
|
||||
sp_cleanup.remove_unnecessary_nls_tags=false
|
||||
sp_cleanup.remove_unused_imports=false
|
||||
sp_cleanup.remove_unused_local_variables=false
|
||||
sp_cleanup.remove_unused_private_fields=true
|
||||
sp_cleanup.remove_unused_private_members=false
|
||||
sp_cleanup.remove_unused_private_methods=true
|
||||
sp_cleanup.remove_unused_private_types=true
|
||||
sp_cleanup.sort_members=false
|
||||
sp_cleanup.sort_members_all=false
|
||||
sp_cleanup.use_anonymous_class_creation=false
|
||||
sp_cleanup.use_blocks=false
|
||||
sp_cleanup.use_blocks_only_for_return_and_throw=false
|
||||
sp_cleanup.use_lambda=true
|
||||
sp_cleanup.use_parentheses_in_expressions=false
|
||||
sp_cleanup.use_this_for_non_static_field_access=false
|
||||
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
sp_cleanup.use_this_for_non_static_method_access=false
|
||||
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
@@ -16,45 +16,52 @@ import java.nio.file.Path;
|
||||
import org.springframework.ide.vscode.commons.java.AbstractJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathFileBasedCache;
|
||||
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
/**
|
||||
* Implementation of Gradle Java project
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class GradleJavaProject extends AbstractJavaProject {
|
||||
|
||||
private DelegatingCachedClasspath<GradleProjectClasspath> classpath;
|
||||
private File projectDir;
|
||||
|
||||
public GradleJavaProject(GradleCore gradle, File projectDir, Path projectDataCache) {
|
||||
super(projectDataCache);
|
||||
|
||||
private final File projectDir;
|
||||
|
||||
private GradleJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File projectDir) {
|
||||
super(fileObserver, projectDir.toURI(), projectDataCache, classpath);
|
||||
this.projectDir = projectDir;
|
||||
File file = projectDataCache == null ? null
|
||||
}
|
||||
|
||||
public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir, Path projectDataCache) {
|
||||
File file = projectDataCache == null
|
||||
? null
|
||||
: projectDataCache.resolve(ClasspathFileBasedCache.CLASSPATH_DATA_CACHE_FILE).toFile();
|
||||
ClasspathFileBasedCache fileBasedCache = new ClasspathFileBasedCache(file);
|
||||
this.classpath = new DelegatingCachedClasspath<GradleProjectClasspath>(
|
||||
IClasspath classpath = new DelegatingCachedClasspath(
|
||||
() -> new GradleProjectClasspath(gradle, projectDir),
|
||||
fileBasedCache
|
||||
);
|
||||
return new GradleJavaProject(fileObserver, projectDataCache, classpath, projectDir);
|
||||
}
|
||||
|
||||
public GradleJavaProject(GradleCore gradle, File projectDir) {
|
||||
this(gradle, projectDir, null);
|
||||
if (!classpath.isCached()) {
|
||||
|
||||
public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir) {
|
||||
GradleJavaProject thiss = create(fileObserver, gradle, projectDir, null);
|
||||
if (!thiss.getClasspath().isCached()) {
|
||||
try {
|
||||
classpath.update();
|
||||
thiss.getClasspath().update();
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
return thiss;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
if (classpath.getName() == null) {
|
||||
if (getClasspath().getName() == null) {
|
||||
return projectDir.getName();
|
||||
} else {
|
||||
return super.getElementName();
|
||||
@@ -66,13 +73,17 @@ public class GradleJavaProject extends AbstractJavaProject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelegatingCachedClasspath<GradleProjectClasspath> getClasspath() {
|
||||
return classpath;
|
||||
public DelegatingCachedClasspath getClasspath() {
|
||||
return (DelegatingCachedClasspath) super.getClasspath();
|
||||
}
|
||||
|
||||
|
||||
boolean update() throws Exception {
|
||||
return classpath.update();
|
||||
return getClasspath().update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GradleJavaProject("+getElementName()+")";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,19 +21,19 @@ import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageExc
|
||||
|
||||
/**
|
||||
* Tests whether document belongs to a Gradle project
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class GradleProjectCache extends AbstractFileToProjectCache<GradleJavaProject> {
|
||||
|
||||
private GradleCore gradle;
|
||||
|
||||
|
||||
public GradleProjectCache(Sts4LanguageServer server, GradleCore gradle, boolean asyncUpdate, Path projectCacheFolder) {
|
||||
super(server, asyncUpdate, projectCacheFolder);
|
||||
this.gradle = gradle;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean update(GradleJavaProject project) {
|
||||
try {
|
||||
@@ -48,7 +48,7 @@ public class GradleProjectCache extends AbstractFileToProjectCache<GradleJavaPro
|
||||
@Override
|
||||
protected GradleJavaProject createProject(File gradleBuild) throws Exception {
|
||||
File gradleFile = gradleBuild.getParentFile();
|
||||
GradleJavaProject gradleJavaProject = new GradleJavaProject(gradle, gradleFile,
|
||||
GradleJavaProject gradleJavaProject = GradleJavaProject.create(getFileObserver(), gradle, gradleFile,
|
||||
projectCacheFolder == null ? null : gradleFile.toPath().resolve(projectCacheFolder)
|
||||
);
|
||||
performUpdate(gradleJavaProject, asyncUpdate, asyncUpdate);
|
||||
|
||||
@@ -25,13 +25,14 @@ import org.gradle.tooling.model.build.BuildEnvironment;
|
||||
import org.gradle.tooling.model.eclipse.EclipseExternalDependency;
|
||||
import org.gradle.tooling.model.eclipse.EclipseProject;
|
||||
import org.gradle.tooling.model.eclipse.EclipseProjectDependency;
|
||||
import org.gradle.tooling.model.eclipse.EclipseSourceDirectory;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexClasspath;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
|
||||
import org.springframework.ide.vscode.commons.javadoc.TypeUrlProviderFromContainerUrl;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
@@ -41,46 +42,46 @@ import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
/**
|
||||
* Implementation of {@link IClasspath} for Gradle projects
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class GradleProjectClasspath extends JandexClasspath {
|
||||
|
||||
public class GradleProjectClasspath implements IClasspath {
|
||||
|
||||
private static final String JAVA_HOME = "java.home";
|
||||
private static final String JAVA_RUNTIME_VERSION = "java.runtime.version";
|
||||
private static final String JAVA_BOOT_CLASS_PATH = "sun.boot.class.path";
|
||||
|
||||
|
||||
private EclipseProject project;
|
||||
private BuildEnvironment buildEnvironment;
|
||||
|
||||
|
||||
public GradleProjectClasspath(GradleCore gradle, File projectDir) throws GradleException {
|
||||
super();
|
||||
this.project = gradle.getModel(projectDir, EclipseProject.class);
|
||||
this.buildEnvironment = gradle.getModel(projectDir, BuildEnvironment.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JandexIndex[] getBaseIndices() {
|
||||
return new JandexIndex[] { new JandexIndex(getJreLibs().map(path -> path.toFile()).collect(Collectors.toList()),
|
||||
jarFile -> findIndexFile(jarFile), (classpathResource) -> {
|
||||
try {
|
||||
String javaVersion = getJavaRuntimeMinorVersion();
|
||||
if (javaVersion == null) {
|
||||
javaVersion = "8";
|
||||
}
|
||||
URL javadocUrl = new URL("https://docs.oracle.com/javase/" + javaVersion + "/docs/api/");
|
||||
return new HtmlJavadocProvider(
|
||||
(type) -> SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(javadocUrl, type.getFullyQualifiedName()));
|
||||
} catch (MalformedURLException e) {
|
||||
Log.log(e);
|
||||
return null;
|
||||
}
|
||||
}) };
|
||||
}
|
||||
|
||||
public EclipseProject getRootProject() {
|
||||
// @Override
|
||||
// protected JandexIndex[] getBaseIndices() {
|
||||
// return new JandexIndex[] { new JandexIndex(getJreLibs().map(path -> path.toFile()).collect(Collectors.toList()),
|
||||
// jarFile -> findIndexFile(jarFile), (classpathResource) -> {
|
||||
// try {
|
||||
// String javaVersion = getJavaRuntimeMinorVersion();
|
||||
// if (javaVersion == null) {
|
||||
// javaVersion = "8";
|
||||
// }
|
||||
// URL javadocUrl = new URL("https://docs.oracle.com/javase/" + javaVersion + "/docs/api/");
|
||||
// return new HtmlJavadocProvider(
|
||||
// (type) -> SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
// .sourceUrl(javadocUrl, type.getFullyQualifiedName()));
|
||||
// } catch (MalformedURLException e) {
|
||||
// Log.log(e);
|
||||
// return null;
|
||||
// }
|
||||
// }) };
|
||||
// }
|
||||
|
||||
private EclipseProject getRootProject() {
|
||||
EclipseProject root = project;
|
||||
if (root == null) {
|
||||
return root;
|
||||
@@ -99,7 +100,7 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
} else {
|
||||
Builder<CPE> entries = ImmutableList.builder();
|
||||
for (EclipseExternalDependency dep : project.getClasspath()) {
|
||||
entries.add(new CPE(Classpath.ENTRY_KIND_BINARY, dep.getFile().toPath().toString()));
|
||||
entries.add(new CPE(Classpath.ENTRY_KIND_BINARY, dep.getFile().getAbsolutePath()));
|
||||
}
|
||||
for (EclipseProjectDependency dep : project.getProjectDependencies()) {
|
||||
EclipseProject peer = findPeer(root, dep.getTargetProject().getName());
|
||||
@@ -109,50 +110,24 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
));
|
||||
}
|
||||
}
|
||||
for (EclipseSourceDirectory sf : project.getSourceDirectories()) {
|
||||
File sourceFolder = sf.getDirectory();
|
||||
String of = sf.getOutput();
|
||||
entries.add(CPE.source(sourceFolder.getAbsoluteFile(), new File(project.getProjectDirectory(), of)));
|
||||
}
|
||||
return entries.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private EclipseProject findPeer(EclipseProject root, String name) {
|
||||
return root.getChildren().stream().filter(p -> p.getName().equals(name)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
if (project == null) {
|
||||
return ImmutableList.of();
|
||||
} else {
|
||||
return ImmutableList.copyOf(project.getSourceDirectories().stream().map(sourceDirectory -> sourceDirectory.getDirectory()).flatMap(folder -> {
|
||||
try {
|
||||
return Files.walk(folder.toPath())
|
||||
.filter(path -> Files.isRegularFile(path))
|
||||
.map(path -> folder.toPath().relativize(path))
|
||||
.map(relativePath -> relativePath.toString())
|
||||
.filter(pathString -> !pathString.endsWith(".java") && !pathString.endsWith(".class"));
|
||||
} catch (IOException e) {
|
||||
return Stream.empty();
|
||||
}
|
||||
}).toArray(String[]::new));
|
||||
}
|
||||
}
|
||||
|
||||
public Path getOutputFolder() {
|
||||
return project == null ? null : project.getProjectDirectory().toPath().resolve(project.getOutputLocation().getPath());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return project == null ? null : project.getName();
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return project != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJavadocProvider createHtmlJavdocProvider(File classpathResource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getGradleVersion() throws GradleException {
|
||||
if (buildEnvironment == null) {
|
||||
throw new GradleException(new Exception("Cannot find Gradle version"));
|
||||
@@ -160,7 +135,7 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return buildEnvironment.getGradle().getGradleVersion();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public File getGradleHome() throws GradleException {
|
||||
if (buildEnvironment == null) {
|
||||
throw new GradleException(new Exception("Cannot find Gradle home folder"));
|
||||
@@ -168,11 +143,11 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return buildEnvironment.getGradle().getGradleUserHome();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getJavaRuntimeVersion() {
|
||||
return System.getProperty(JAVA_RUNTIME_VERSION);
|
||||
}
|
||||
|
||||
|
||||
public String getJavaRuntimeMinorVersion() {
|
||||
String fullVersion = getJavaRuntimeVersion();
|
||||
String[] tokenized = fullVersion.split("\\.");
|
||||
@@ -183,7 +158,7 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getJavaHome() {
|
||||
if (buildEnvironment == null) {
|
||||
return System.getProperty(JAVA_HOME);
|
||||
@@ -191,7 +166,7 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return buildEnvironment.getJava().getJavaHome().toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Stream<Path> getJreLibs() {
|
||||
String s = System.getProperty(JAVA_BOOT_CLASS_PATH);
|
||||
return Arrays.stream(s.split(File.pathSeparator))
|
||||
@@ -200,22 +175,7 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
.filter(f -> f.canRead())
|
||||
.map(f -> f.toPath());
|
||||
}
|
||||
|
||||
private File findIndexFile(File jarFile) {
|
||||
String suffix = null;
|
||||
String javaHome = getJavaHome();
|
||||
if (javaHome != null) {
|
||||
int index = javaHome.lastIndexOf('/');
|
||||
if (index != -1) {
|
||||
javaHome = javaHome.substring(0, index);
|
||||
}
|
||||
}
|
||||
if (jarFile.toString().startsWith(javaHome)) {
|
||||
suffix = getJavaRuntimeVersion();
|
||||
}
|
||||
return new File(JandexIndex.getIndexFolder().toString(), jarFile.getName() + "-" + suffix + ".jdx");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof GradleProjectClasspath) {
|
||||
@@ -224,20 +184,4 @@ public class GradleProjectClasspath extends JandexClasspath {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getSourceFolders() {
|
||||
return ImmutableList.copyOf(project.getSourceDirectories().stream()
|
||||
.map(dir -> dir.getDirectory().toPath().toString()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
return ClasspathData.from(getName(), getClasspathEntries(), getClasspathResources(), getOutputFolder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<URL> sourceContainer(File classpathResource) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,19 +37,21 @@ import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CP
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.ClasspathTestUtil.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Tests covering Gradle project data
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class GradleProjectTest {
|
||||
|
||||
|
||||
private Sts4LanguageServer server;
|
||||
private BasicFileObserver fileObserver;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
fileObserver = new BasicFileObserver();
|
||||
@@ -58,7 +60,7 @@ public class GradleProjectTest {
|
||||
when(workspaceService.getFileObserver()).thenReturn(fileObserver);
|
||||
when(server.getWorkspaceService()).thenReturn(workspaceService);
|
||||
}
|
||||
|
||||
|
||||
private static void writeContent(File file, String content) throws IOException {
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
@@ -68,39 +70,40 @@ public class GradleProjectTest {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private GradleJavaProject getGradleProject(String projectName) throws Exception {
|
||||
Path testProjectPath = Paths.get(GradleProjectTest.class.getResource("/" + projectName).toURI());
|
||||
return new GradleJavaProject(GradleCore.getDefault(), testProjectPath.toFile());
|
||||
return GradleJavaProject.create(fileObserver, GradleCore.getDefault(), testProjectPath.toFile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEclipseGradleProject() throws Exception {
|
||||
GradleJavaProject project = getGradleProject("empty-gradle-project");
|
||||
ImmutableList<CPE> calculatedClassPath = project.getClasspath().getClasspathEntries();
|
||||
assertEquals(48, calculatedClassPath.size());
|
||||
assertEquals(51, calculatedClassPath.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void outputFolder() throws Exception {
|
||||
GradleJavaProject project = getGradleProject("test-app-1");
|
||||
assertTrue(project.getClasspath().getOutputFolder().toString().contains("/bin"));
|
||||
String of = getOutputFolder(project).toString();
|
||||
assertTrue(of.endsWith("/bin") || of.endsWith("/bin/main"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void gradleClasspathResource() throws Exception {
|
||||
GradleJavaProject project = getGradleProject("test-app-1");
|
||||
List<String> resources = project.getClasspath().getClasspathResources();
|
||||
List<String> resources = project.getClasspathResources();
|
||||
assertArrayEquals(new String[] {"test-resource-1.txt"}, resources.toArray(new String[resources.size()]));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGradleFileChanges() throws Exception {
|
||||
Path testProjectPath = Paths.get(GradleProjectTest.class.getResource("/empty-gradle-project").toURI());
|
||||
File gradleFile = testProjectPath.resolve(GradleCore.GRADLE_BUILD_FILE).toFile();
|
||||
|
||||
|
||||
String gradelFileContents = Files.contentOf(gradleFile, Charset.defaultCharset());
|
||||
|
||||
|
||||
try {
|
||||
GradleProjectCache manager = new GradleProjectCache(server, GradleCore.getDefault(), false, null);
|
||||
IJavaProject[] projectChanged = new IJavaProject[] { null };
|
||||
@@ -108,7 +111,7 @@ public class GradleProjectTest {
|
||||
manager.addListener(new Listener() {
|
||||
@Override
|
||||
public void created(IJavaProject project) {}
|
||||
|
||||
|
||||
@Override
|
||||
public void changed(IJavaProject project) {
|
||||
projectChanged[0] = project;
|
||||
@@ -118,25 +121,25 @@ public class GradleProjectTest {
|
||||
projectDeleted[0] = project;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Get the project from cache
|
||||
GradleJavaProject cachedProject = manager.project(gradleFile);
|
||||
assertNotNull(cachedProject);
|
||||
|
||||
|
||||
ImmutableList<CPE> calculatedClassPath = cachedProject.getClasspath().getClasspathEntries();
|
||||
assertEquals(48, calculatedClassPath.size());
|
||||
|
||||
assertEquals(51, calculatedClassPath.size());
|
||||
|
||||
fileObserver.notifyFileChanged(gradleFile.toURI().toString());
|
||||
assertNull(projectChanged[0]);
|
||||
|
||||
|
||||
writeContent(gradleFile, Files.contentOf(testProjectPath.resolve("build.newgradle").toFile(), Charset.defaultCharset()));
|
||||
fileObserver.notifyFileChanged(gradleFile.toURI().toString());
|
||||
assertNotNull(projectChanged[0]);
|
||||
assertEquals(cachedProject, projectChanged[0]);
|
||||
calculatedClassPath = cachedProject.getClasspath().getClasspathEntries();
|
||||
assertEquals(49, calculatedClassPath.size());
|
||||
|
||||
|
||||
assertEquals(52, calculatedClassPath.size());
|
||||
|
||||
|
||||
fileObserver.notifyFileDeleted(gradleFile.toURI().toString());
|
||||
assertEquals(cachedProject, projectDeleted[0]);
|
||||
} finally {
|
||||
@@ -165,5 +168,5 @@ public class GradleProjectTest {
|
||||
GradleJavaProject gradleProject = (GradleJavaProject) project.get();
|
||||
assertEquals(new File(GradleProjectTest.class.getResource("/test-app-2").toURI()), gradleProject.getLocation());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,5 +23,11 @@
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding//src/test/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
sp_cleanup.add_missing_deprecated_annotations=true
|
||||
sp_cleanup.add_missing_methods=false
|
||||
sp_cleanup.add_missing_nls_tags=false
|
||||
sp_cleanup.add_missing_override_annotations=true
|
||||
sp_cleanup.add_missing_override_annotations_interface_methods=true
|
||||
sp_cleanup.add_serial_version_id=false
|
||||
sp_cleanup.always_use_blocks=true
|
||||
sp_cleanup.always_use_parentheses_in_expressions=false
|
||||
sp_cleanup.always_use_this_for_non_static_field_access=false
|
||||
sp_cleanup.always_use_this_for_non_static_method_access=false
|
||||
sp_cleanup.convert_functional_interfaces=false
|
||||
sp_cleanup.convert_to_enhanced_for_loop=false
|
||||
sp_cleanup.correct_indentation=false
|
||||
sp_cleanup.format_source_code=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
sp_cleanup.insert_inferred_type_arguments=false
|
||||
sp_cleanup.make_local_variable_final=true
|
||||
sp_cleanup.make_parameters_final=false
|
||||
sp_cleanup.make_private_fields_final=true
|
||||
sp_cleanup.make_type_abstract_if_missing_method=false
|
||||
sp_cleanup.make_variable_declarations_final=false
|
||||
sp_cleanup.never_use_blocks=false
|
||||
sp_cleanup.never_use_parentheses_in_expressions=true
|
||||
sp_cleanup.on_save_use_additional_actions=true
|
||||
sp_cleanup.organize_imports=false
|
||||
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
sp_cleanup.remove_private_constructors=true
|
||||
sp_cleanup.remove_redundant_type_arguments=false
|
||||
sp_cleanup.remove_trailing_whitespaces=true
|
||||
sp_cleanup.remove_trailing_whitespaces_all=true
|
||||
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
sp_cleanup.remove_unnecessary_casts=false
|
||||
sp_cleanup.remove_unnecessary_nls_tags=false
|
||||
sp_cleanup.remove_unused_imports=false
|
||||
sp_cleanup.remove_unused_local_variables=false
|
||||
sp_cleanup.remove_unused_private_fields=true
|
||||
sp_cleanup.remove_unused_private_members=false
|
||||
sp_cleanup.remove_unused_private_methods=true
|
||||
sp_cleanup.remove_unused_private_types=true
|
||||
sp_cleanup.sort_members=false
|
||||
sp_cleanup.sort_members_all=false
|
||||
sp_cleanup.use_anonymous_class_creation=false
|
||||
sp_cleanup.use_blocks=false
|
||||
sp_cleanup.use_blocks_only_for_return_and_throw=false
|
||||
sp_cleanup.use_lambda=true
|
||||
sp_cleanup.use_parentheses_in_expressions=false
|
||||
sp_cleanup.use_this_for_non_static_field_access=false
|
||||
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
sp_cleanup.use_this_for_non_static_method_access=false
|
||||
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
@@ -11,58 +11,73 @@
|
||||
package org.springframework.ide.vscode.commons.jandex;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathIndex;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.java.IType;
|
||||
import org.springframework.ide.vscode.commons.javadoc.JavaDocProviders;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.CollectorUtil;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.Disposables;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
/**
|
||||
* Classpath with Jandex Java index for searching types
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public abstract class JandexClasspath implements IClasspath {
|
||||
|
||||
public final class JandexClasspath implements ClasspathIndex {
|
||||
|
||||
public static JavadocProviderTypes providerType = JavadocProviderTypes.HTML;
|
||||
|
||||
|
||||
public enum JavadocProviderTypes {
|
||||
// JAVA_PARSER, //Used to be based on githb java parser. If need something back that can extract docs from source code, we have to implement
|
||||
// based on JDT parser. But at the moment this wasn't being used so just got removed.
|
||||
HTML
|
||||
}
|
||||
|
||||
|
||||
private Supplier<JandexIndex> javaIndex;
|
||||
|
||||
public JandexClasspath() {
|
||||
private final IClasspath classpath;
|
||||
private final FileObserver fileObserver;
|
||||
|
||||
public JandexClasspath(IClasspath classpath, FileObserver fileObserver) {
|
||||
this.fileObserver = fileObserver;
|
||||
this.classpath = classpath;
|
||||
this.javaIndex = Suppliers.synchronizedSupplier(Suppliers.memoize(() -> createIndex()));
|
||||
}
|
||||
|
||||
|
||||
protected JandexIndex createIndex() {
|
||||
Collection<Path> classpathEntries = ImmutableList.of();
|
||||
attachFolderListeners();
|
||||
Collection<File> classpathEntries = ImmutableList.of();
|
||||
try {
|
||||
classpathEntries = getClasspathEntryPaths();
|
||||
for (Path path : classpathEntries) {
|
||||
System.out.println(path);
|
||||
}
|
||||
classpathEntries = IClasspathUtil.getBinaryRoots(classpath);
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return new JandexIndex(classpathEntries.stream().map(p -> p.toFile()).collect(Collectors.toList()), jarFile -> findIndexFile(jarFile), classpathResource -> {
|
||||
return new JandexIndex(classpathEntries, jarFile -> findIndexFile(jarFile), classpathResource -> {
|
||||
switch (providerType) {
|
||||
// case JAVA_PARSER:
|
||||
// return createParserJavadocProvider(classpathResource);
|
||||
@@ -73,23 +88,63 @@ public abstract class JandexClasspath implements IClasspath {
|
||||
}
|
||||
}, getBaseIndices());
|
||||
}
|
||||
|
||||
|
||||
private Disposable.Composite subscriptions = Disposables.composite();
|
||||
|
||||
private void attachFolderListeners() {
|
||||
synchronized (this) {
|
||||
subscriptions.dispose();
|
||||
subscriptions = Disposables.composite();
|
||||
}
|
||||
for (File cpe : IClasspathUtil.getBinaryRoots(classpath)) {
|
||||
if (!cpe.toString().endsWith(".jar")) {
|
||||
final List<String> rebuildGlobPattern = Arrays.asList(cpe.toString().replace(File.separator, "/") + "/**/*.class");
|
||||
Disposable disposable = fileObserver.onAnyChange(rebuildGlobPattern, (uri) -> reindex());
|
||||
subscriptions.add(disposable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Composite toDispose = subscriptions;
|
||||
subscriptions = null;
|
||||
if (toDispose!=null) {
|
||||
toDispose.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private IJavadocProvider createHtmlJavdocProvider(File binaryClasspathRoot) {
|
||||
CPE cpe = IClasspathUtil.findEntryForBinaryRoot(classpath, binaryClasspathRoot);
|
||||
return JavaDocProviders.createFor(cpe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<URL> sourceContainer(File binaryClasspathRoot) {
|
||||
CPE cpe = IClasspathUtil.findEntryForBinaryRoot(classpath, binaryClasspathRoot);
|
||||
return cpe == null ? Optional.empty() : Optional.ofNullable(cpe.getSourceContainerUrl());
|
||||
}
|
||||
|
||||
protected JandexIndex[] getBaseIndices() {
|
||||
return new JandexIndex[0];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IType findType(String fqName) {
|
||||
return javaIndex.get().findType(fqName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter) {
|
||||
return javaIndex.get().fuzzySearchTypes(searchTerm, typeFilter);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
|
||||
return javaIndex.get().fuzzySearchPackages(searchTerm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<IType> allSubtypesOf(IType type) {
|
||||
return javaIndex.get().allSubtypesOf(type);
|
||||
}
|
||||
@@ -101,21 +156,35 @@ public abstract class JandexClasspath implements IClasspath {
|
||||
}
|
||||
return new File(indexFolder.toString(), jarFile.getName() + "-" + jarFile.lastModified() + ".jdx");
|
||||
}
|
||||
|
||||
|
||||
protected File getIndexFolder() {
|
||||
return JandexIndex.getIndexFolder();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<File> findClasspathResourceContainer(String fqName) {
|
||||
return javaIndex.get().findClasspathResourceForType(fqName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reindex() {
|
||||
|
||||
private void reindex() {
|
||||
this.javaIndex = Suppliers.synchronizedSupplier(Suppliers.memoize(() -> createIndex()));
|
||||
}
|
||||
|
||||
abstract protected IJavadocProvider createHtmlJavdocProvider(File classpathResource);
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
return IClasspathUtil.getSourceFolders(classpath)
|
||||
.flatMap(folder -> {
|
||||
try {
|
||||
return Files.walk(folder.toPath())
|
||||
.filter(path -> Files.isRegularFile(path))
|
||||
.map(path -> folder.toPath().relativize(path))
|
||||
.map(relativePath -> relativePath.toString())
|
||||
.filter(pathString -> !pathString.endsWith(".java") && !pathString.endsWith(".class"));
|
||||
} catch (IOException e) {
|
||||
return Stream.empty();
|
||||
}
|
||||
})
|
||||
.collect(CollectorUtil.toImmutableList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,19 +10,23 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
/**
|
||||
* Abstract java project. Has a folder to store some project calculated data to speed up access
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractJavaProject implements IJavaProject {
|
||||
|
||||
public abstract class AbstractJavaProject extends JavaProject {
|
||||
|
||||
final protected Path projectDataCache;
|
||||
|
||||
public AbstractJavaProject(Path projectDataCache) {
|
||||
|
||||
public AbstractJavaProject(FileObserver fileObserver, URI loactionUri, Path projectDataCache, IClasspath classpath) {
|
||||
super(fileObserver, loactionUri, classpath);
|
||||
this.projectDataCache = projectDataCache;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
@@ -20,7 +21,7 @@ public class BootProjectUtil {
|
||||
try {
|
||||
IClasspath cp = jp.getClasspath();
|
||||
if (cp!=null) {
|
||||
return cp.getClasspathEntryPaths().stream().anyMatch(cpe -> isBootEntry(cpe));
|
||||
return IClasspathUtil.getBinaryRoots(cp).stream().anyMatch(cpe -> isBootEntry(cpe));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
@@ -28,8 +29,8 @@ public class BootProjectUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isBootEntry(Path cpe) {
|
||||
String name = cpe.getFileName().toString();
|
||||
private static boolean isBootEntry(File cpe) {
|
||||
String name = cpe.getName();
|
||||
return name.endsWith(".jar") && name.startsWith("spring-boot");
|
||||
}
|
||||
|
||||
|
||||
@@ -10,39 +10,50 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class ClasspathData {
|
||||
public class ClasspathData implements IClasspath {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ClasspathData.class);
|
||||
|
||||
final public static ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(
|
||||
null,
|
||||
Collections.emptySet()
|
||||
);
|
||||
|
||||
final public static ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(),
|
||||
Collections.emptySet(), null);
|
||||
|
||||
private String name;
|
||||
private Set<CPE> classpathEntries;
|
||||
private Set<String> classpathResources;
|
||||
private String outputFolder;
|
||||
|
||||
public ClasspathData() {
|
||||
}
|
||||
public ClasspathData() {}
|
||||
|
||||
public ClasspathData(String name, Set<CPE> classpathEntries, Set<String> classpathResources, String outputFolder) {
|
||||
public ClasspathData(String name, Collection<CPE> classpathEntries) {
|
||||
this.name = name;
|
||||
this.classpathEntries = classpathEntries;
|
||||
this.classpathResources = classpathResources;
|
||||
this.outputFolder = outputFolder;
|
||||
this.classpathEntries = ImmutableSet.copyOf(classpathEntries);
|
||||
}
|
||||
|
||||
|
||||
public static ClasspathData from(IClasspath d) {
|
||||
Collection<CPE> entries = null;
|
||||
try {
|
||||
entries = d.getClasspathEntries();
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return new ClasspathData(
|
||||
d.getName(),
|
||||
entries==null ? ImmutableSet.of() : entries
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -51,6 +62,7 @@ public class ClasspathData {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CPE> getClasspathEntries() {
|
||||
return classpathEntries;
|
||||
}
|
||||
@@ -59,47 +71,38 @@ public class ClasspathData {
|
||||
this.classpathEntries = classpathEntries;
|
||||
}
|
||||
|
||||
public Set<String> getClasspathResources() {
|
||||
return classpathResources;
|
||||
}
|
||||
|
||||
public void setClasspathResources(Set<String> classpathResources) {
|
||||
this.classpathResources = classpathResources;
|
||||
}
|
||||
|
||||
public String getOutputFolder() {
|
||||
return outputFolder;
|
||||
}
|
||||
|
||||
public void setOutputFolder(String outputFolder) {
|
||||
this.outputFolder = outputFolder;
|
||||
}
|
||||
|
||||
public static ClasspathData getEmptyClasspathData() {
|
||||
return EMPTY_CLASSPATH_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ClasspathData) {
|
||||
ClasspathData other = (ClasspathData) obj;
|
||||
try {
|
||||
return Objects.equal(name, other.name) && Objects.equal(classpathEntries, other.classpathEntries)
|
||||
&& Objects.equal(classpathResources, other.classpathResources)
|
||||
&& Objects.equal(outputFolder, outputFolder);
|
||||
} catch (Throwable t) {
|
||||
Log.log(t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((classpathEntries == null) ? 0 : classpathEntries.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ClasspathData from(String name, Collection<CPE> classpathEntries,
|
||||
Collection<String> classpathResources, Path outputFolder) {
|
||||
return new ClasspathData(name,
|
||||
new LinkedHashSet<>(classpathEntries),
|
||||
new LinkedHashSet<>(classpathResources),
|
||||
outputFolder==null ? null : outputFolder.toString()
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ClasspathData other = (ClasspathData) obj;
|
||||
if (classpathEntries == null) {
|
||||
if (other.classpathEntries != null)
|
||||
return false;
|
||||
} else if (!classpathEntries.equals(other.classpathEntries))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -11,32 +11,22 @@
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class ClasspathFileBasedCache {
|
||||
|
||||
|
||||
public static final ClasspathFileBasedCache NULL = new ClasspathFileBasedCache(null);
|
||||
|
||||
|
||||
public static final String CLASSPATH_DATA_CACHE_FILE = "classpath-data.json";
|
||||
|
||||
private static final String OUTPUT_FOLDER_PROPERTY = "outputFolder";
|
||||
private static final String CLASSPATH_RESOURCES_PROPERTY = "classpathResources";
|
||||
private static final String CLASSPATH_ENTRIES_PROPERTY = "classpathEntries";
|
||||
private static final String NAME_PROPERTY = "name";
|
||||
|
||||
final private File file;
|
||||
|
||||
|
||||
public ClasspathFileBasedCache(File file) {
|
||||
super();
|
||||
this.file = file;
|
||||
@@ -63,7 +53,7 @@ public class ClasspathFileBasedCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isCached() {
|
||||
return file != null && file.exists();
|
||||
}
|
||||
@@ -80,7 +70,7 @@ public class ClasspathFileBasedCache {
|
||||
return ClasspathData.EMPTY_CLASSPATH_DATA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void delete() {
|
||||
if (file != null && file.exists()) {
|
||||
file.delete();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
public interface ClasspathIndex extends Disposable {
|
||||
|
||||
IType findType(String fqName);
|
||||
Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter);
|
||||
Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm);
|
||||
Flux<IType> allSubtypesOf(IType type);
|
||||
Optional<File> findClasspathResourceContainer(String fqName);
|
||||
|
||||
//Maybe the stuff below is another interface? Something that provides operations
|
||||
// on classpaths?
|
||||
|
||||
Optional<URL> sourceContainer(File binaryClasspathRoot);
|
||||
|
||||
/**
|
||||
* Classpath resources paths relative to the source folder path
|
||||
* @return classpath resource relative paths
|
||||
*/
|
||||
ImmutableList<String> getClasspathResources();
|
||||
|
||||
|
||||
}
|
||||
@@ -10,14 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
@@ -25,44 +19,41 @@ import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This wrapper around a classpath manages classpath data from and to a file-based cache (e.g. ".sts4-cache/classpath-data.json") with classpath data obtained
|
||||
* from a project (e.g., maven or gradle project) through an "update" operation.
|
||||
*
|
||||
* from a project (e.g., maven or gradle project) through an "update" operation.
|
||||
*
|
||||
* The cached classpath data is written to the file and loaded from it when instance of this classpath is created
|
||||
*
|
||||
*
|
||||
* NOTE: Classpath data may not be available until an actual update is requested on this wrapper.
|
||||
*
|
||||
*
|
||||
* As the wrapper is a classpath itself ,it delegates to the underlying classpath for classpath operations (e.g. getting classpath entries, resources, etc..). However, the data may not
|
||||
* be available until update is performed.
|
||||
*
|
||||
*
|
||||
* The wrapper caches some of classpath data such as
|
||||
* <li> Classpath entries </li>
|
||||
* <li> Classpath resources </li>
|
||||
* <li> Output folder </li>
|
||||
* <li> Projects' name </li>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Implementation is somewhat experimental at the moment...
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
* @param <T> a subclass of {@link IClasspath} the delegated to classpath created from current data
|
||||
*/
|
||||
public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspath {
|
||||
|
||||
public class DelegatingCachedClasspath implements IClasspath {
|
||||
|
||||
private AtomicReference<ClasspathData> cachedData;
|
||||
private Callable<T> classpathCreator;
|
||||
private AtomicReference<T> cachedClasspath;
|
||||
private Callable<IClasspath> classpathCreator;
|
||||
private AtomicReference<IClasspath> cachedClasspath;
|
||||
|
||||
private final ClasspathFileBasedCache fileBasedCache;
|
||||
|
||||
|
||||
public DelegatingCachedClasspath(Callable<T> delegateCreator, ClasspathFileBasedCache fileCache) {
|
||||
|
||||
|
||||
public DelegatingCachedClasspath(Callable<IClasspath> delegateCreator, ClasspathFileBasedCache fileCache) {
|
||||
super();
|
||||
Assert.isLegal(delegateCreator != null);
|
||||
this.fileBasedCache = fileCache != null ? fileCache : ClasspathFileBasedCache.NULL;
|
||||
@@ -74,8 +65,8 @@ public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspa
|
||||
private ClasspathData loadFileBasedCache(ClasspathFileBasedCache fileCache) {
|
||||
return fileCache != null ? fileCache.load() : ClasspathData.EMPTY_CLASSPATH_DATA;
|
||||
}
|
||||
|
||||
public T delegate() {
|
||||
|
||||
public IClasspath delegate() {
|
||||
return cachedClasspath.get();
|
||||
}
|
||||
|
||||
@@ -84,26 +75,15 @@ public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspa
|
||||
return cachedData.get().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getOutputFolder() {
|
||||
String of = cachedData.get().getOutputFolder();
|
||||
return of == null ? null : Paths.get(of);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<CPE> getClasspathEntries() throws Exception {
|
||||
return ImmutableList.copyOf(cachedData.get().getClasspathEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
return ImmutableList.copyOf(cachedData.get().getClasspathResources());
|
||||
}
|
||||
|
||||
public boolean isCached() {
|
||||
return fileBasedCache.isCached();
|
||||
}
|
||||
|
||||
|
||||
public boolean update() throws Exception {
|
||||
try {
|
||||
final ClasspathData newData = createClasspathData();
|
||||
@@ -119,74 +99,20 @@ public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspa
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
T t = cachedClasspath.get();
|
||||
return t != null && t.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IType findType(String fqName) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? null : t.findType(fqName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? Flux.empty() : t.fuzzySearchTypes(searchTerm, typeFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? Flux.empty() : t.fuzzySearchPackages(searchTerm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<IType> allSubtypesOf(IType type) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? Flux.empty() : t.allSubtypesOf(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
T newDelegate = classpathCreator.call();
|
||||
private ClasspathData createClasspathData() throws Exception {
|
||||
IClasspath newDelegate = classpathCreator.call();
|
||||
cachedClasspath.set(newDelegate);
|
||||
if (newDelegate != null) {
|
||||
ClasspathData data = newDelegate.createClasspathData();
|
||||
ClasspathData data = createClasspathData(newDelegate);
|
||||
if (data != null) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ClasspathData.EMPTY_CLASSPATH_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getSourceFolders() {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? ImmutableList.of() : t.getSourceFolders();
|
||||
private ClasspathData createClasspathData(IClasspath d) {
|
||||
return ClasspathData.from(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<File> findClasspathResourceContainer(String fqName) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? Optional.empty() : t.findClasspathResourceContainer(fqName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reindex() {
|
||||
T t = cachedClasspath.get();
|
||||
if (t != null) {
|
||||
t.reindex();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<URL> sourceContainer(File classpathResource) {
|
||||
T t = cachedClasspath.get();
|
||||
return t == null ? Optional.empty() : t.sourceContainer(classpathResource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,88 +10,30 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
/**
|
||||
* Classpath for a Java artifact
|
||||
*
|
||||
*
|
||||
* @author Kris De Volder
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public interface IClasspath {
|
||||
|
||||
String getName();
|
||||
|
||||
boolean exists();
|
||||
|
||||
IType findType(String fqName);
|
||||
|
||||
Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter);
|
||||
|
||||
Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm);
|
||||
|
||||
Flux<IType> allSubtypesOf(IType type);
|
||||
|
||||
Path getOutputFolder();
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger(IClasspath.class);
|
||||
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Classpath entries paths
|
||||
*
|
||||
*
|
||||
* @return collection of classpath entries in a form file/folder paths
|
||||
* @throws Exception
|
||||
*/
|
||||
Collection<CPE> getClasspathEntries() throws Exception;
|
||||
|
||||
/**
|
||||
* Classpath resources paths relative to the source folder path
|
||||
* @return classpath resource relative paths
|
||||
*/
|
||||
ImmutableList<String> getClasspathResources();
|
||||
|
||||
ImmutableList<String> getSourceFolders();
|
||||
|
||||
Optional<File> findClasspathResourceContainer(String fqName);
|
||||
|
||||
ClasspathData createClasspathData() throws Exception;
|
||||
|
||||
void reindex();
|
||||
|
||||
Optional<URL> sourceContainer(File classpathResource);
|
||||
|
||||
@Deprecated
|
||||
default Collection<Path> getClasspathEntryPaths() throws Exception {
|
||||
LinkedHashSet<Path> entries = new LinkedHashSet<>();
|
||||
for (CPE cpe : this.getClasspathEntries()) {
|
||||
if (Classpath.ENTRY_KIND_BINARY.equals(cpe.getKind())) {
|
||||
entries.add(Paths.get(cpe.getPath()));
|
||||
} else if (Classpath.ENTRY_KIND_SOURCE.equals(cpe.getKind())) {
|
||||
String of = cpe.getOutputFolder();
|
||||
if (of!=null) {
|
||||
entries.add(Paths.get(cpe.getOutputFolder()));
|
||||
} else {
|
||||
Path op = getOutputFolder();
|
||||
if (op!=null) {
|
||||
entries.add(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ImmutableList.copyOf(entries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class IClasspathUtil {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IClasspath.class);
|
||||
|
||||
public static CPE findEntryForBinaryRoot(IClasspath cp, File binaryClasspathtRoot) {
|
||||
try {
|
||||
for (CPE cpe : cp.getClasspathEntries()) {
|
||||
if (correspondsToBinaryLocation(cpe, binaryClasspathtRoot)) {
|
||||
return cpe;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<File> getBinaryRoots(IClasspath cp) {
|
||||
ImmutableList.Builder<File> roots = ImmutableList.builder();
|
||||
try {
|
||||
for (CPE cpe : cp.getClasspathEntries()) {
|
||||
File loc = binaryLocation(cpe);
|
||||
if (loc!=null) {
|
||||
roots.add(loc);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return roots.build();
|
||||
}
|
||||
|
||||
private static boolean correspondsToBinaryLocation(CPE cpe, File classpathEntryFile) {
|
||||
classpathEntryFile = canonicalFile(classpathEntryFile);
|
||||
File canonicalFile = binaryLocation(cpe);
|
||||
return Objects.equals(canonicalFile, classpathEntryFile);
|
||||
}
|
||||
|
||||
private static File binaryLocation(CPE cpe) {
|
||||
switch (cpe.getKind()) {
|
||||
case Classpath.ENTRY_KIND_BINARY:
|
||||
return canonicalFile(cpe.getPath());
|
||||
case Classpath.ENTRY_KIND_SOURCE:
|
||||
return canonicalFile(cpe.getOutputFolder());
|
||||
default:
|
||||
throw new IllegalStateException("Missing switch case?");
|
||||
}
|
||||
}
|
||||
|
||||
private static File canonicalFile(String _f) {
|
||||
if (_f!=null) {
|
||||
File f = new File(_f);
|
||||
return canonicalFile(f);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File canonicalFile(File f) {
|
||||
try {
|
||||
return f.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return f.getAbsoluteFile();
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream<File> getSourceFolders(IClasspath classpath) {
|
||||
try {
|
||||
if (classpath != null) {
|
||||
return classpath.getClasspathEntries().stream().filter(Classpath::isSource)
|
||||
.map(cpe -> new File(cpe.getPath()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
public static Stream<File> getOutputFolders(IClasspath classpath) {
|
||||
try {
|
||||
return classpath.getClasspathEntries().stream()
|
||||
.filter(Classpath::isSource)
|
||||
.map(cpe -> new File(cpe.getOutputFolder()));
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
@@ -10,27 +10,57 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
public interface IJavaProject extends IJavaElement {
|
||||
|
||||
|
||||
final static String PROJECT_CACHE_FOLDER = ".sts4-cache";
|
||||
|
||||
|
||||
IClasspath getClasspath();
|
||||
ClasspathIndex getIndex();
|
||||
|
||||
@Override
|
||||
default String getElementName() {
|
||||
return getClasspath().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IJavadoc getJavaDoc() {
|
||||
return null;
|
||||
default IType findType(String fqName) {
|
||||
return getIndex().findType(fqName);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean exists() {
|
||||
return getClasspath().exists();
|
||||
default Flux<IType> allSubtypesOf(IType targetType) {
|
||||
return getIndex().allSubtypesOf(targetType);
|
||||
}
|
||||
|
||||
default Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter) {
|
||||
return getIndex().fuzzySearchTypes(searchTerm, typeFilter);
|
||||
}
|
||||
|
||||
default Optional<URL> sourceContainer(File classpathResource) {
|
||||
return getIndex().sourceContainer(classpathResource);
|
||||
}
|
||||
|
||||
default List<String> getClasspathResources() {
|
||||
return getIndex().getClasspathResources();
|
||||
}
|
||||
|
||||
default Optional<File> findClasspathResourceContainer(String fqName) {
|
||||
return getIndex().findClasspathResourceContainer(fqName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default IJavadoc getJavaDoc() {
|
||||
//?? why is this here ??
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexClasspath;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
|
||||
public class JavaProject implements IJavaProject, Disposable {
|
||||
|
||||
private final IClasspath classpath;
|
||||
private ClasspathIndex index;
|
||||
private URI uri;
|
||||
private final FileObserver fileObserver;
|
||||
|
||||
public JavaProject(FileObserver fileObserver, URI uri, IClasspath classpath) {
|
||||
super();
|
||||
this.classpath = classpath;
|
||||
this.fileObserver = fileObserver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClasspath getClasspath() {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ClasspathIndex getIndex() {
|
||||
if (index==null) {
|
||||
index = new JandexClasspath(classpath, fileObserver);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public URI getLocationUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposable toDispose = null;
|
||||
synchronized (this) {
|
||||
toDispose = index;
|
||||
index = null;
|
||||
}
|
||||
if (toDispose!=null) {
|
||||
toDispose.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return new File(uri).exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.javadoc;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
|
||||
public class JavaDocProviders {
|
||||
|
||||
public static IJavadocProvider createFor(CPE classpathEntry) {
|
||||
if (classpathEntry!=null && classpathEntry.getJavadocContainerUrl() != null) {
|
||||
URL containerUrl = classpathEntry.getJavadocContainerUrl();
|
||||
|
||||
TypeUrlProviderFromContainerUrl urlProvider = isJarUrl(containerUrl)
|
||||
? TypeUrlProviderFromContainerUrl.JAR_JAVADOC_URL_PROVIDER
|
||||
: TypeUrlProviderFromContainerUrl.JAVADOC_FOLDER_URL_SUPPLIER;
|
||||
return new HtmlJavadocProvider(
|
||||
type -> urlProvider.url(classpathEntry.getJavadocContainerUrl(), type.getFullyQualifiedName())
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isJarUrl(URL containerUrl) {
|
||||
return containerUrl.toString().endsWith(".jar");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,44 +15,44 @@ import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SourceUrlProviderFromSourceContainer {
|
||||
public interface TypeUrlProviderFromContainerUrl {
|
||||
|
||||
static String extractTopLevelType(String fqName) {
|
||||
int innerTypeIdx = fqName.indexOf('$');
|
||||
return innerTypeIdx > 0 ? fqName.substring(0, innerTypeIdx) : fqName;
|
||||
}
|
||||
|
||||
public static final SourceUrlProviderFromSourceContainer JAR_SOURCE_URL_PROVIDER = (sourceContainerUrl, fqName) -> {
|
||||
StringBuilder sourceUrlStr = new StringBuilder();
|
||||
sourceUrlStr.append("jar:");
|
||||
sourceUrlStr.append(sourceContainerUrl);
|
||||
sourceUrlStr.append("!");
|
||||
sourceUrlStr.append('/');
|
||||
sourceUrlStr.append(extractTopLevelType(fqName).replaceAll("\\.", "/"));
|
||||
sourceUrlStr.append(".java");
|
||||
return new URL(sourceUrlStr.toString());
|
||||
public static final TypeUrlProviderFromContainerUrl JAR_SOURCE_URL_PROVIDER = (jarSourceUrl, fqName) -> {
|
||||
StringBuilder urlStr = new StringBuilder();
|
||||
urlStr.append("jar:");
|
||||
urlStr.append(jarSourceUrl);
|
||||
urlStr.append("!");
|
||||
urlStr.append('/');
|
||||
urlStr.append(extractTopLevelType(fqName).replaceAll("\\.", "/"));
|
||||
urlStr.append(".java");
|
||||
return new URL(urlStr.toString());
|
||||
|
||||
};
|
||||
|
||||
public static final SourceUrlProviderFromSourceContainer SOURCE_FOLDER_URL_SUPPLIER = (sourceContainerUrl, fqName) -> {
|
||||
public static final TypeUrlProviderFromContainerUrl SOURCE_FOLDER_URL_SUPPLIER = (sourceContainerUrl, fqName) -> {
|
||||
return Paths.get(sourceContainerUrl.toURI()).resolve(extractTopLevelType(fqName).replaceAll("\\.", "/") + ".java").toUri().toURL();
|
||||
};
|
||||
|
||||
public static final SourceUrlProviderFromSourceContainer JAR_JAVADOC_URL_PROVIDER = (javadocContainerUrl, fqName) -> {
|
||||
StringBuilder sourceUrlStr = new StringBuilder();
|
||||
sourceUrlStr.append("jar:");
|
||||
sourceUrlStr.append(javadocContainerUrl);
|
||||
sourceUrlStr.append("!");
|
||||
sourceUrlStr.append('/');
|
||||
public static final TypeUrlProviderFromContainerUrl JAR_JAVADOC_URL_PROVIDER = (javadocContainerUrl, fqName) -> {
|
||||
StringBuilder urlStr = new StringBuilder();
|
||||
urlStr.append("jar:");
|
||||
urlStr.append(javadocContainerUrl);
|
||||
urlStr.append("!");
|
||||
urlStr.append('/');
|
||||
// Inner classes are in separate Top.Nesting1.Nesting2.Nesting3.MyType.html files
|
||||
sourceUrlStr.append(fqName.replaceAll("\\.", "/").replaceAll("\\$", "."));
|
||||
sourceUrlStr.append(".html");
|
||||
return new URL(sourceUrlStr.toString());
|
||||
urlStr.append(fqName.replaceAll("\\.", "/").replaceAll("\\$", "."));
|
||||
urlStr.append(".html");
|
||||
return new URL(urlStr.toString());
|
||||
|
||||
};
|
||||
|
||||
public static final SourceUrlProviderFromSourceContainer JAVADOC_FOLDER_URL_SUPPLIER = (sourceContainerUrl, fqName) -> {
|
||||
String urlStr = sourceContainerUrl.toString();
|
||||
public static final TypeUrlProviderFromContainerUrl JAVADOC_FOLDER_URL_SUPPLIER = (javadocContainerUrl, fqName) -> {
|
||||
String urlStr = javadocContainerUrl.toString();
|
||||
StringBuilder sb = new StringBuilder(urlStr);
|
||||
if (!urlStr.endsWith("/")) {
|
||||
sb.append('/');
|
||||
@@ -62,6 +62,6 @@ public interface SourceUrlProviderFromSourceContainer {
|
||||
return new URL(sb.toString());
|
||||
};
|
||||
|
||||
URL sourceUrl(URL sourceContainerUrl, String fqName) throws Exception;
|
||||
URL url(URL containerUrl, String fqName) throws Exception;
|
||||
|
||||
}
|
||||
@@ -60,14 +60,6 @@ public abstract class AbstractFileToProjectCache<P extends IJavaProject> extends
|
||||
notifyProjectDeleted(project);
|
||||
dispose();
|
||||
}));
|
||||
|
||||
Path outputFolder = project.getClasspath().getOutputFolder();
|
||||
if (outputFolder != null) {
|
||||
final List<String> rebuildGlobPattern = Arrays.asList(outputFolder.toString().replace(File.separator, "/") + "/**/*.class");
|
||||
subscriptions.add(getFileObserver().onFileChanged(rebuildGlobPattern, (uri) -> project.getClasspath().reindex()));
|
||||
subscriptions.add(getFileObserver().onFileCreated(rebuildGlobPattern, (uri) -> project.getClasspath().reindex()));
|
||||
subscriptions.add(getFileObserver().onFileDeleted(rebuildGlobPattern, (uri) -> project.getClasspath().reindex()));
|
||||
}
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.jandex;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
public class JandexClasspathTest {
|
||||
|
||||
@Rule public TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
class TestProject {
|
||||
String name;
|
||||
File root;
|
||||
File testClassesFolder;
|
||||
File outputFolder;
|
||||
BasicFileObserver fileObserver = new BasicFileObserver();
|
||||
|
||||
TestProject(String name) throws Exception {
|
||||
this.name = name;
|
||||
this.root = new File(JandexClasspathTest.class.getResource("/" + name ).toURI());
|
||||
testClassesFolder = new File(root, "bin");
|
||||
this.outputFolder = folder.newFolder();
|
||||
}
|
||||
|
||||
void createClass(String fqName) throws Exception {
|
||||
String relativePath = fqName.replace('.', '/')+".class";
|
||||
File classFile = new File(testClassesFolder, relativePath);
|
||||
File target = new File(outputFolder, relativePath);
|
||||
target.getParentFile().mkdirs();
|
||||
Files.copy(classFile, target);
|
||||
fileObserver.notifyFileCreated(target.toURI().toString());
|
||||
}
|
||||
|
||||
ClasspathData getClasspath() {
|
||||
return new ClasspathData(name, ImmutableList.of(
|
||||
CPE.source(new File(root, "src"), outputFolder)
|
||||
));
|
||||
}
|
||||
|
||||
JandexClasspath getJandexClasspath() {
|
||||
return new JandexClasspath(getClasspath(), fileObserver);
|
||||
}
|
||||
|
||||
public void deleteClass(String fqName, BiConsumer<BasicFileObserver, String> eventNoficator) {
|
||||
String relativePath = fqName.replace('.', '/')+".class";
|
||||
File classFile = new File(outputFolder, relativePath);
|
||||
classFile.delete();
|
||||
eventNoficator.accept(fileObserver, classFile.toURI().toString());
|
||||
}
|
||||
|
||||
public void deleteClass(String fqName) {
|
||||
deleteClass(fqName, (fileObserver, path) -> fileObserver.notifyFileDeleted(path));
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void classfileChangesShouldTriggerReindexing() throws Exception {
|
||||
TestProject project = new TestProject("simple-java-project");
|
||||
project.createClass("demo.Hello");
|
||||
|
||||
JandexClasspath subject = project.getJandexClasspath();
|
||||
|
||||
assertNotNull(subject.findType("demo.Hello"));
|
||||
assertNull(subject.findType("demo.Goodbye"));
|
||||
|
||||
project.createClass("demo.Goodbye");
|
||||
|
||||
assertNotNull(subject.findType("demo.Hello"));
|
||||
assertNotNull(subject.findType("demo.Goodbye"));
|
||||
|
||||
project.deleteClass("demo.Hello");
|
||||
|
||||
assertNull(subject.findType("demo.Hello"));
|
||||
assertNotNull(subject.findType("demo.Goodbye"));
|
||||
|
||||
project.deleteClass("demo.Goodbye", (fileObserver, deletedFile) -> fileObserver.notifyFileChanged(deletedFile));
|
||||
|
||||
assertNull(subject.findType("demo.Hello"));
|
||||
assertNull(subject.findType("demo.Goodbye"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
2
headless-services/commons/commons-java/src/test/resources/simple-java-project/.gitignore
vendored
Normal file
2
headless-services/commons/commons-java/src/test/resources/simple-java-project/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
!bin/
|
||||
!*.class
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>simple-java-project</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,11 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
package demo;
|
||||
|
||||
public class Goodbye {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package demo;
|
||||
|
||||
public class Hello {
|
||||
|
||||
}
|
||||
@@ -1,20 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.jdt.ls;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
|
||||
public class Classpath {
|
||||
|
||||
public static final String ENTRY_KIND_SOURCE = "source";
|
||||
public static final String ENTRY_KIND_BINARY = "binary";
|
||||
|
||||
private List<CPE> entries;
|
||||
private String defaultOutputFolder;
|
||||
|
||||
public Classpath(List<CPE> entries, String defaultOutputFolder) {
|
||||
public Classpath(List<CPE> entries) {
|
||||
super();
|
||||
this.entries = entries;
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
public List<CPE> getEntries() {
|
||||
@@ -25,33 +36,34 @@ public class Classpath {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
public String getDefaultOutputFolder() {
|
||||
return defaultOutputFolder;
|
||||
}
|
||||
|
||||
public void setDefaultOutputFolder(String defaultOutputFolder) {
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Classpath [entries=" + entries + ", defaultOutputFolder=" + defaultOutputFolder + "]";
|
||||
return "Classpath [entries=" + entries + "]";
|
||||
}
|
||||
|
||||
public static class CPE {
|
||||
private String kind;
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* This only applies for 'source' entries.
|
||||
*/
|
||||
// TODO: it seems like a good idea to make all classpath entries the same in that they all have
|
||||
// - a place with source code
|
||||
// - a place with compiled code
|
||||
// - a place with java doc
|
||||
// So it seems like we should be able to chnage this so that the same named attribute is used
|
||||
// in both cases (rather then one be 'getOutputFolder' and one 'getPath' to obtain location of the compiled code).
|
||||
|
||||
private String kind;
|
||||
|
||||
private String path; // TODO: Change to File, Path or URL?
|
||||
private String outputFolder;
|
||||
private URL sourceContainerUrl;
|
||||
private URL javadocContainerUrl;
|
||||
private boolean isSystem = false;
|
||||
|
||||
public String getOutputFolder() {
|
||||
return outputFolder;
|
||||
}
|
||||
|
||||
public void setOutputFolder(String outputFolder) {
|
||||
Assert.isLegal(outputFolder==null || new File(outputFolder).isAbsolute());
|
||||
this.outputFolder = outputFolder;
|
||||
}
|
||||
|
||||
@@ -60,7 +72,7 @@ public class Classpath {
|
||||
public CPE(String kind, String path) {
|
||||
super();
|
||||
this.kind = kind;
|
||||
this.path = path;
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
@@ -76,16 +88,54 @@ public class Classpath {
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
Assert.isLegal(path == null || new File(path).isAbsolute());
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public URL getJavadocContainerUrl() {
|
||||
return javadocContainerUrl;
|
||||
}
|
||||
|
||||
public void setJavadocContainerUrl(URL javadocContainerUrl) {
|
||||
this.javadocContainerUrl = javadocContainerUrl;
|
||||
}
|
||||
|
||||
public URL getSourceContainerUrl() {
|
||||
return sourceContainerUrl;
|
||||
}
|
||||
|
||||
public void setSourceContainerUrl(URL sourceContainerUrl) {
|
||||
this.sourceContainerUrl = sourceContainerUrl;
|
||||
}
|
||||
|
||||
public static CPE binary(String path) {
|
||||
return new CPE(ENTRY_KIND_BINARY, path);
|
||||
}
|
||||
|
||||
public static CPE source(File sourceFolder, File outputFolder) {
|
||||
CPE cpe = new CPE(ENTRY_KIND_SOURCE, sourceFolder.getAbsolutePath());
|
||||
cpe.setOutputFolder(outputFolder.getAbsolutePath());
|
||||
return cpe;
|
||||
}
|
||||
|
||||
public boolean isSystem() {
|
||||
return isSystem;
|
||||
}
|
||||
|
||||
public void setSystem(boolean isSystem) {
|
||||
this.isSystem = isSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (isSystem ? 1231 : 1237);
|
||||
result = prime * result + ((javadocContainerUrl == null) ? 0 : javadocContainerUrl.hashCode());
|
||||
result = prime * result + ((kind == null) ? 0 : kind.hashCode());
|
||||
result = prime * result + ((outputFolder == null) ? 0 : outputFolder.hashCode());
|
||||
result = prime * result + ((path == null) ? 0 : path.hashCode());
|
||||
result = prime * result + ((sourceContainerUrl == null) ? 0 : sourceContainerUrl.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -98,6 +148,13 @@ public class Classpath {
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CPE other = (CPE) obj;
|
||||
if (isSystem != other.isSystem)
|
||||
return false;
|
||||
if (javadocContainerUrl == null) {
|
||||
if (other.javadocContainerUrl != null)
|
||||
return false;
|
||||
} else if (!javadocContainerUrl.equals(other.javadocContainerUrl))
|
||||
return false;
|
||||
if (kind == null) {
|
||||
if (other.kind != null)
|
||||
return false;
|
||||
@@ -113,12 +170,17 @@ public class Classpath {
|
||||
return false;
|
||||
} else if (!path.equals(other.path))
|
||||
return false;
|
||||
if (sourceContainerUrl == null) {
|
||||
if (other.sourceContainerUrl != null)
|
||||
return false;
|
||||
} else if (!sourceContainerUrl.equals(other.sourceContainerUrl))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CPE [kind=" + kind + ", path=" + path + ", outputFolder=" + outputFolder + "]";
|
||||
return "CPE [kind=" + kind + ", path=" + path + ", isSystem=" + isSystem + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
sp_cleanup.add_missing_deprecated_annotations=true
|
||||
sp_cleanup.add_missing_methods=false
|
||||
sp_cleanup.add_missing_nls_tags=false
|
||||
sp_cleanup.add_missing_override_annotations=true
|
||||
sp_cleanup.add_missing_override_annotations_interface_methods=true
|
||||
sp_cleanup.add_serial_version_id=false
|
||||
sp_cleanup.always_use_blocks=true
|
||||
sp_cleanup.always_use_parentheses_in_expressions=false
|
||||
sp_cleanup.always_use_this_for_non_static_field_access=false
|
||||
sp_cleanup.always_use_this_for_non_static_method_access=false
|
||||
sp_cleanup.convert_functional_interfaces=false
|
||||
sp_cleanup.convert_to_enhanced_for_loop=false
|
||||
sp_cleanup.correct_indentation=false
|
||||
sp_cleanup.format_source_code=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
sp_cleanup.insert_inferred_type_arguments=false
|
||||
sp_cleanup.make_local_variable_final=true
|
||||
sp_cleanup.make_parameters_final=false
|
||||
sp_cleanup.make_private_fields_final=true
|
||||
sp_cleanup.make_type_abstract_if_missing_method=false
|
||||
sp_cleanup.make_variable_declarations_final=false
|
||||
sp_cleanup.never_use_blocks=false
|
||||
sp_cleanup.never_use_parentheses_in_expressions=true
|
||||
sp_cleanup.on_save_use_additional_actions=true
|
||||
sp_cleanup.organize_imports=false
|
||||
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
sp_cleanup.remove_private_constructors=true
|
||||
sp_cleanup.remove_redundant_type_arguments=false
|
||||
sp_cleanup.remove_trailing_whitespaces=true
|
||||
sp_cleanup.remove_trailing_whitespaces_all=true
|
||||
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
sp_cleanup.remove_unnecessary_casts=false
|
||||
sp_cleanup.remove_unnecessary_nls_tags=false
|
||||
sp_cleanup.remove_unused_imports=false
|
||||
sp_cleanup.remove_unused_local_variables=false
|
||||
sp_cleanup.remove_unused_private_fields=true
|
||||
sp_cleanup.remove_unused_private_members=false
|
||||
sp_cleanup.remove_unused_private_methods=true
|
||||
sp_cleanup.remove_unused_private_types=true
|
||||
sp_cleanup.sort_members=false
|
||||
sp_cleanup.sort_members_all=false
|
||||
sp_cleanup.use_anonymous_class_creation=false
|
||||
sp_cleanup.use_blocks=false
|
||||
sp_cleanup.use_blocks_only_for_return_and_throw=false
|
||||
sp_cleanup.use_lambda=true
|
||||
sp_cleanup.use_parentheses_in_expressions=false
|
||||
sp_cleanup.use_this_for_non_static_field_access=false
|
||||
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
sp_cleanup.use_this_for_non_static_method_access=false
|
||||
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
@@ -57,7 +57,7 @@ import org.eclipse.aether.util.graph.visitor.CloningDependencyVisitor;
|
||||
import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
|
||||
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
|
||||
import org.springframework.ide.vscode.commons.javadoc.TypeUrlProviderFromContainerUrl;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
@@ -95,7 +95,7 @@ public class MavenCore {
|
||||
javaVersion = "8";
|
||||
}
|
||||
URL javadocUrl = new URL("https://docs.oracle.com/javase/" + javaVersion + "/docs/api/");
|
||||
return new HtmlJavadocProvider((type) -> SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER.sourceUrl(javadocUrl, type.getFullyQualifiedName()));
|
||||
return new HtmlJavadocProvider((type) -> TypeUrlProviderFromContainerUrl.JAVADOC_FOLDER_URL_SUPPLIER.url(javadocUrl, type.getFullyQualifiedName()));
|
||||
} catch (MalformedURLException e) {
|
||||
Log.log(e);
|
||||
return null;
|
||||
|
||||
@@ -16,7 +16,9 @@ import java.nio.file.Path;
|
||||
import org.springframework.ide.vscode.commons.java.AbstractJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathFileBasedCache;
|
||||
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
/**
|
||||
@@ -27,35 +29,40 @@ import org.springframework.ide.vscode.commons.util.Log;
|
||||
*/
|
||||
public class MavenJavaProject extends AbstractJavaProject {
|
||||
|
||||
private DelegatingCachedClasspath<MavenProjectClasspath> classpath;
|
||||
private File pom;
|
||||
|
||||
public MavenJavaProject(MavenCore maven, File pom, Path projectDataCache) {
|
||||
super(projectDataCache);
|
||||
private final File pom;
|
||||
|
||||
private MavenJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File pom) {
|
||||
super(fileObserver, pom.getParentFile().toURI(), projectDataCache, classpath);
|
||||
this.pom = pom;
|
||||
File file = projectDataCache == null ? null
|
||||
}
|
||||
|
||||
public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, Path projectDataCache) {
|
||||
File file = projectDataCache == null
|
||||
? null
|
||||
: projectDataCache.resolve(ClasspathFileBasedCache.CLASSPATH_DATA_CACHE_FILE).toFile();
|
||||
ClasspathFileBasedCache fileBasedCache = new ClasspathFileBasedCache(file);
|
||||
this.classpath = new DelegatingCachedClasspath<>(
|
||||
DelegatingCachedClasspath classpath = new DelegatingCachedClasspath(
|
||||
() -> new MavenProjectClasspath(maven, pom),
|
||||
fileBasedCache
|
||||
);
|
||||
);
|
||||
return new MavenJavaProject(fileObserver, projectDataCache, classpath, pom);
|
||||
}
|
||||
|
||||
public MavenJavaProject(MavenCore maven, File pom) {
|
||||
this(maven, pom, null);
|
||||
if (!classpath.isCached()) {
|
||||
public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom) {
|
||||
MavenJavaProject thiss = create(fileObserver, maven, pom, null);
|
||||
if (!thiss.getClasspath().isCached()) {
|
||||
try {
|
||||
classpath.update();
|
||||
thiss.getClasspath().update();
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
return thiss;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
if (classpath.getName() == null) {
|
||||
if (getClasspath().getName() == null) {
|
||||
return pom.getParentFile().getName();
|
||||
} else {
|
||||
return super.getElementName();
|
||||
@@ -63,12 +70,12 @@ public class MavenJavaProject extends AbstractJavaProject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelegatingCachedClasspath<MavenProjectClasspath> getClasspath() {
|
||||
return classpath;
|
||||
public DelegatingCachedClasspath getClasspath() {
|
||||
return (DelegatingCachedClasspath) super.getClasspath();
|
||||
}
|
||||
|
||||
boolean update() throws Exception {
|
||||
return classpath.update();
|
||||
return getClasspath().update();
|
||||
}
|
||||
|
||||
public File pom() {
|
||||
@@ -77,7 +84,6 @@ public class MavenJavaProject extends AbstractJavaProject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MavenJavaProject("+classpath.getName()+")";
|
||||
return "MavenJavaProject("+getElementName()+")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class MavenProjectCache extends AbstractFileToProjectCache<MavenJavaProje
|
||||
|
||||
@Override
|
||||
protected MavenJavaProject createProject(File pomFile) throws Exception {
|
||||
MavenJavaProject mavenJavaProject = new MavenJavaProject(
|
||||
MavenJavaProject mavenJavaProject = MavenJavaProject.create(getFileObserver(),
|
||||
maven,
|
||||
pomFile,
|
||||
projectCacheFolder == null ? null : pomFile.getParentFile().toPath().resolve(projectCacheFolder)
|
||||
|
||||
@@ -21,52 +21,54 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.artifact.repository.ArtifactRepository;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.util.DirectoryScanner;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexClasspath;
|
||||
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
|
||||
import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
|
||||
import org.springframework.ide.vscode.commons.javadoc.TypeUrlProviderFromContainerUrl;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenException;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.RunnableWithException;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.internal.Streams;
|
||||
|
||||
/**
|
||||
* Classpath for a maven project
|
||||
*
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class MavenProjectClasspath extends JandexClasspath {
|
||||
|
||||
public class MavenProjectClasspath implements IClasspath {
|
||||
|
||||
private MavenCore maven;
|
||||
private File pom;
|
||||
private MavenClasspathData cachedData;
|
||||
|
||||
private ClasspathData cachedData;
|
||||
|
||||
MavenProjectClasspath(MavenCore maven, File pom) throws Exception {
|
||||
super();
|
||||
this.maven = maven;
|
||||
this.pom = pom;
|
||||
this.cachedData = createClasspathData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JandexIndex[] getBaseIndices() {
|
||||
return new JandexIndex[] { maven.getJavaIndexForJreLibs() };
|
||||
}
|
||||
|
||||
private final MavenProject createMavenProject() throws MavenException {
|
||||
try {
|
||||
@@ -77,42 +79,115 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
return maven.readProject(pom, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public File getPomFile() {
|
||||
return pom;
|
||||
}
|
||||
|
||||
|
||||
MavenCore maven() {
|
||||
return maven;
|
||||
}
|
||||
|
||||
|
||||
public boolean exists() {
|
||||
return pom.exists();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return cachedData != null ? cachedData.getName() : null;
|
||||
}
|
||||
|
||||
|
||||
private ImmutableList<CPE> resolveClasspathEntries(MavenProject project) throws Exception {
|
||||
return ImmutableList.copyOf(
|
||||
Stream.concat(
|
||||
projectDependencies(project).stream().map(a -> a.getFile().toPath()),
|
||||
projectOutput(project).stream().map(f -> f.toPath())
|
||||
)
|
||||
.map(path -> new CPE(Classpath.ENTRY_KIND_BINARY, path.toString()))
|
||||
.collect(Collectors.toList()));
|
||||
LinkedHashSet<CPE> entries = new LinkedHashSet<>();
|
||||
safe(() -> maven.getJreLibs().forEach(path -> safe(() -> {
|
||||
CPE cpe = CPE.binary(path.toString());
|
||||
String javaVersion = maven.getJavaRuntimeMinorVersion();
|
||||
if (javaVersion == null) {
|
||||
javaVersion = "8";
|
||||
}
|
||||
cpe.setJavadocContainerUrl(new URL("https://docs.oracle.com/javase/" + javaVersion + "/docs/api/"));
|
||||
cpe.setSystem(true);
|
||||
entries.add(cpe);
|
||||
})));
|
||||
//Add jar dependencies...
|
||||
for (Artifact a : projectDependencies(project)) {
|
||||
File f = a.getFile();
|
||||
if (f!=null) {
|
||||
CPE cpe = CPE.binary(a.getFile().toPath().toString());
|
||||
safe(() -> { //add javadoc
|
||||
Artifact jdoc = maven.getJavadoc(a, project.getRemoteArtifactRepositories());
|
||||
if (jdoc!=null) {
|
||||
cpe.setJavadocContainerUrl(jdoc.getFile().toURI().toURL());
|
||||
}
|
||||
});
|
||||
safe(() -> { //add source
|
||||
Artifact source = maven.getSources(a, project.getRemoteArtifactRepositories());
|
||||
if (source!=null) {
|
||||
cpe.setSourceContainerUrl(source.getFile().toURI().toURL());
|
||||
}
|
||||
});
|
||||
entries.add(cpe);
|
||||
}
|
||||
}
|
||||
//Add source folders...
|
||||
{ //main/java
|
||||
File sourceFolder = new File(project.getBuild().getSourceDirectory());
|
||||
File outputFolder = new File(project.getBuild().getOutputDirectory());
|
||||
CPE cpe = CPE.source(sourceFolder, outputFolder);
|
||||
safe(() -> {
|
||||
String reportingDir = project.getModel().getReporting().getOutputDirectory();
|
||||
if (reportingDir!=null) {
|
||||
File apidocs = new File(new File(reportingDir), "apidocs");
|
||||
cpe.setJavadocContainerUrl(apidocs.toURI().toURL());
|
||||
}
|
||||
});
|
||||
entries.add(cpe);
|
||||
}
|
||||
{ //main/resources
|
||||
for (Resource resource : project.getBuild().getResources()) {
|
||||
File sourceFolder = new File(resource.getDirectory());
|
||||
String targetPath = resource.getTargetPath();
|
||||
if (targetPath==null) {
|
||||
targetPath = project.getBuild().getOutputDirectory();
|
||||
}
|
||||
entries.add(CPE.source(sourceFolder, new File(targetPath)));
|
||||
}
|
||||
}
|
||||
{ //test/resources
|
||||
for (Resource resource : project.getBuild().getTestResources()) {
|
||||
File sourceFolder = new File(resource.getDirectory());
|
||||
String targetPath = resource.getTargetPath();
|
||||
if (targetPath==null) {
|
||||
targetPath = project.getBuild().getTestOutputDirectory();
|
||||
}
|
||||
entries.add(CPE.source(sourceFolder, targetPath==null ? null : new File(targetPath)));
|
||||
}
|
||||
}
|
||||
{ //test/java
|
||||
File sourceFolder = new File(project.getBuild().getTestSourceDirectory());
|
||||
File outputFolder = new File(project.getBuild().getTestOutputDirectory());
|
||||
CPE cpe = CPE.source(sourceFolder, outputFolder);
|
||||
safe(() -> {
|
||||
String reportingDir = project.getModel().getReporting().getOutputDirectory();
|
||||
if (reportingDir!=null) {
|
||||
File apidocs = new File(new File(reportingDir), "apidocs");
|
||||
cpe.setJavadocContainerUrl(apidocs.toURI().toURL());
|
||||
}
|
||||
});
|
||||
entries.add(cpe);
|
||||
}
|
||||
return ImmutableList.copyOf(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<CPE> getClasspathEntries() throws Exception {
|
||||
return cachedData != null ? ImmutableList.copyOf(cachedData.getClasspathEntries()) : ImmutableList.of();
|
||||
}
|
||||
|
||||
|
||||
private Set<Artifact> projectDependencies(MavenProject project) {
|
||||
return project == null ? Collections.emptySet() : project.getArtifacts();
|
||||
}
|
||||
|
||||
|
||||
private List<File> projectOutput(MavenProject project) {
|
||||
if (project == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -120,133 +195,22 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
return Arrays.asList(new File(project.getBuild().getOutputDirectory()), new File(project.getBuild().getTestOutputDirectory()));
|
||||
}
|
||||
}
|
||||
|
||||
private Path resolveOutputFolder(MavenProject project) {
|
||||
return project == null ? null : new File(project.getBuild().getOutputDirectory()).toPath();
|
||||
}
|
||||
|
||||
public Path getOutputFolder() {
|
||||
if (cachedData!=null) {
|
||||
String of = cachedData.getOutputFolder();
|
||||
return of == null ? null : Paths.get(of);
|
||||
|
||||
private static void safe(RunnableWithException do_stuff) {
|
||||
try {
|
||||
do_stuff.run();
|
||||
} catch (Exception e) {
|
||||
// log.error("", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ImmutableList<String> resolveClasspathResources(MavenProject project) {
|
||||
if (project == null) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
return ImmutableList.copyOf(project.getBuild().getResources().stream().filter(resource -> new File(resource.getDirectory()).exists()).flatMap(resource -> {
|
||||
DirectoryScanner scanner = new DirectoryScanner();
|
||||
scanner.setBasedir(resource.getDirectory());
|
||||
if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) {
|
||||
scanner.setIncludes(resource.getIncludes().toArray(new String[resource.getIncludes().size()]));
|
||||
}
|
||||
if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) {
|
||||
scanner.setExcludes(resource.getExcludes().toArray(new String[resource.getExcludes().size()]));
|
||||
}
|
||||
scanner.setCaseSensitive(false);
|
||||
scanner.scan();
|
||||
return Arrays.stream(scanner.getIncludedFiles());
|
||||
}).toArray(String[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
return cachedData != null ? ImmutableList.copyOf(cachedData.getClasspathResources()) : ImmutableList.of();
|
||||
}
|
||||
|
||||
/*
|
||||
* Roaster lib is experiment to generate javadoc from source. Commented out for now since roaster lib is taken out
|
||||
*/
|
||||
// private IJavadocProvider createRoasterJavadocProvider(File classpathResource) {
|
||||
// if (classpathResource.isDirectory()) {
|
||||
// if (classpathResource.toString().startsWith(project.getBuild().getOutputDirectory())) {
|
||||
// return new RoasterJavadocProvider(type -> {
|
||||
// return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER
|
||||
// .sourceUrl(new File(project.getBuild().getSourceDirectory()).toURI().toURL(), type);
|
||||
// });
|
||||
// } else if (classpathResource.toString().startsWith(project.getBuild().getTestOutputDirectory())) {
|
||||
// return new RoasterJavadocProvider(type -> {
|
||||
// return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER
|
||||
// .sourceUrl(new File(project.getBuild().getTestSourceDirectory()).toURI().toURL(), type);
|
||||
// });
|
||||
// } else {
|
||||
// throw new IllegalArgumentException("Cannot find source folder for " + classpathResource);
|
||||
// }
|
||||
// } else {
|
||||
// // Assume it's a JAR file
|
||||
// return new RoasterJavadocProvider(type -> {
|
||||
// try {
|
||||
// Artifact artifact = getArtifactFromJarFile(classpathResource).get();
|
||||
// URL sourceContainer = maven.getSources(artifact).getFile().toURI().toURL();
|
||||
// return SourceUrlProviderFromSourceContainer.JAR_SOURCE_URL_PROVIDER.sourceUrl(sourceContainer,
|
||||
// type);
|
||||
// } catch (MavenException e) {
|
||||
// Log.log("Failed to find sources JAR for " + classpathResource, e);
|
||||
// } catch (MalformedURLException e) {
|
||||
// Log.log("Invalid URL for sources JAR for " + classpathResource, e);
|
||||
// }
|
||||
// return null;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
private ClasspathData createClasspathData() throws Exception {
|
||||
MavenProject project = createMavenProject();
|
||||
|
||||
@Override
|
||||
public Optional<URL> sourceContainer(File classpathResource) {
|
||||
if (cachedData == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return cachedData.artifacts.stream().filter(a -> classpathResource.equals(a.getFile())).findFirst().map(artifact -> {
|
||||
try {
|
||||
return maven.getSources(artifact, cachedData.remoteArtifactRepositories).getFile().toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
Log.log("Invalid URL for sources JAR for " + classpathResource, e);
|
||||
return null;
|
||||
} catch (MavenException e) {
|
||||
Log.log("Failed to find sources JAR for " + classpathResource, e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
ImmutableList<CPE> entries = resolveClasspathEntries(project);
|
||||
String name = project.getArtifact().getArtifactId();
|
||||
|
||||
@Override
|
||||
protected IJavadocProvider createHtmlJavdocProvider(File classpathResource) {
|
||||
if (cachedData == null) {
|
||||
return null;
|
||||
}
|
||||
if (classpathResource.isDirectory()) {
|
||||
if (classpathResource.toString().startsWith(cachedData.outputDirectory)) {
|
||||
return new HtmlJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(cachedData.reportingOutputDirectory, "apidocs").toURI().toURL(), type.getFullyQualifiedName());
|
||||
});
|
||||
} else if (classpathResource.toString().startsWith(cachedData.testOutputDirectory)) {
|
||||
return new HtmlJavadocProvider(type -> {
|
||||
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
|
||||
.sourceUrl(new File(cachedData.reportingOutputDirectory, "apidocs").toURI().toURL(), type.getFullyQualifiedName());
|
||||
});
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot find source folder for " + classpathResource);
|
||||
}
|
||||
} else {
|
||||
// Assume it's a JAR file
|
||||
return new HtmlJavadocProvider(type -> {
|
||||
try {
|
||||
Artifact artifact = cachedData.artifacts.stream().filter(a -> classpathResource.equals(a.getFile())).findFirst().get();
|
||||
URL sourceContainer = maven.getJavadoc(artifact, cachedData.remoteArtifactRepositories).getFile().toURI().toURL();
|
||||
return SourceUrlProviderFromSourceContainer.JAR_JAVADOC_URL_PROVIDER.sourceUrl(sourceContainer,
|
||||
type.getFullyQualifiedName());
|
||||
} catch (MavenException e) {
|
||||
Log.log("Failed to find sources JAR for " + classpathResource, e);
|
||||
} catch (MalformedURLException e) {
|
||||
Log.log("Invalid URL for sources JAR for " + classpathResource, e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return new ClasspathData(name, new LinkedHashSet<>(entries));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,95 +229,4 @@ public class MavenProjectClasspath extends JandexClasspath {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getSourceFolders() {
|
||||
return cachedData != null ? ImmutableList.of(cachedData.sourceDirectory) : ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MavenClasspathData createClasspathData() throws Exception {
|
||||
MavenProject project = createMavenProject();
|
||||
|
||||
ImmutableList<CPE> entries = resolveClasspathEntries(project);
|
||||
String name = project.getArtifact().getArtifactId();
|
||||
ImmutableList<String> resources = resolveClasspathResources(project);
|
||||
Path outputFolder = resolveOutputFolder(project);
|
||||
|
||||
MavenClasspathData data = new MavenClasspathData(name, new LinkedHashSet<>(entries),
|
||||
new LinkedHashSet<>(resources), outputFolder);
|
||||
|
||||
data.outputDirectory = project.getBuild().getOutputDirectory();
|
||||
data.reportingOutputDirectory = project.getModel().getReporting().getOutputDirectory();
|
||||
data.testOutputDirectory = project.getBuild().getTestOutputDirectory();
|
||||
data.testSourceDirectory = project.getBuild().getTestSourceDirectory();
|
||||
data.artifacts = project.getArtifacts();
|
||||
data.remoteArtifactRepositories = project.getRemoteArtifactRepositories();
|
||||
data.sourceDirectory = project.getBuild().getSourceDirectory();
|
||||
return data;
|
||||
}
|
||||
|
||||
static class MavenClasspathData extends ClasspathData {
|
||||
|
||||
private String testSourceDirectory;
|
||||
private List<ArtifactRepository> remoteArtifactRepositories;
|
||||
private Set<Artifact> artifacts;
|
||||
private String testOutputDirectory;
|
||||
private String reportingOutputDirectory;
|
||||
private String outputDirectory;
|
||||
private String sourceDirectory;
|
||||
|
||||
public MavenClasspathData(String name, Set<CPE> classpathEntries, Set<String> classpathResources,
|
||||
Path outputFolder) {
|
||||
super(name, classpathEntries, classpathResources, outputFolder == null ? null : outputFolder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!super.equals(obj))
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MavenClasspathData other = (MavenClasspathData) obj;
|
||||
if (artifacts == null) {
|
||||
if (other.artifacts != null)
|
||||
return false;
|
||||
} else if (!artifacts.equals(other.artifacts))
|
||||
return false;
|
||||
if (outputDirectory == null) {
|
||||
if (other.outputDirectory != null)
|
||||
return false;
|
||||
} else if (!outputDirectory.equals(other.outputDirectory))
|
||||
return false;
|
||||
if (remoteArtifactRepositories == null) {
|
||||
if (other.remoteArtifactRepositories != null)
|
||||
return false;
|
||||
} else if (!remoteArtifactRepositories.equals(other.remoteArtifactRepositories))
|
||||
return false;
|
||||
if (reportingOutputDirectory == null) {
|
||||
if (other.reportingOutputDirectory != null)
|
||||
return false;
|
||||
} else if (!reportingOutputDirectory.equals(other.reportingOutputDirectory))
|
||||
return false;
|
||||
if (sourceDirectory == null) {
|
||||
if (other.sourceDirectory != null)
|
||||
return false;
|
||||
} else if (!sourceDirectory.equals(other.sourceDirectory))
|
||||
return false;
|
||||
if (testOutputDirectory == null) {
|
||||
if (other.testOutputDirectory != null)
|
||||
return false;
|
||||
} else if (!testOutputDirectory.equals(other.testOutputDirectory))
|
||||
return false;
|
||||
if (testSourceDirectory == null) {
|
||||
if (other.testSourceDirectory != null)
|
||||
return false;
|
||||
} else if (!testSourceDirectory.equals(other.testSourceDirectory))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,19 +28,22 @@ import org.springframework.ide.vscode.commons.java.IMethod;
|
||||
import org.springframework.ide.vscode.commons.java.IType;
|
||||
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
public class HtmlJavadocTest {
|
||||
|
||||
private static FileObserver fileObserver = new BasicFileObserver();
|
||||
private static Supplier<MavenJavaProject> projectSupplier = Suppliers.memoize(() -> {
|
||||
Path testProjectPath;
|
||||
try {
|
||||
JandexClasspath.providerType = JavadocProviderTypes.HTML;
|
||||
testProjectPath = Paths.get(HtmlJavadocTest.class.getResource("/gs-rest-service-cors-boot-1.4.1-with-classpath-file").toURI());
|
||||
MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute();
|
||||
return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
@@ -52,7 +55,7 @@ public class HtmlJavadocTest {
|
||||
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("java.util.Map");
|
||||
IType type = project.findType("java.util.Map");
|
||||
assertNotNull(type);
|
||||
String expected = String.join("\n",
|
||||
"<div class=\"block\">An object that maps keys to values. A map cannot contain duplicate keys;",
|
||||
@@ -68,7 +71,7 @@ public class HtmlJavadocTest {
|
||||
Assume.assumeTrue(javaVersionHigherThan(6));
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("java.util.ArrayList");
|
||||
IType type = project.findType("java.util.ArrayList");
|
||||
assertNotNull(type);
|
||||
IMethod method = type.getMethod("<init>", Stream.empty());
|
||||
assertNotNull(method);
|
||||
@@ -86,7 +89,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testEmptyJavadocClass() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("hello.Application");
|
||||
IType type = project.findType("hello.Application");
|
||||
assertNotNull(type);
|
||||
assertNull(type.getJavaDoc());
|
||||
}
|
||||
@@ -95,7 +98,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testFieldAndMethodJavadocForJar() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("org.springframework.boot.SpringApplication");
|
||||
IType type = project.findType("org.springframework.boot.SpringApplication");
|
||||
assertNotNull(type);
|
||||
|
||||
IField field = type.getField("BANNER_LOCATION_PROPERTY_VALUE");
|
||||
@@ -135,7 +138,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testInnerClassJavadocForOutputFolder() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("hello.Greeting$TestInnerClass");
|
||||
IType type = project.findType("hello.Greeting$TestInnerClass");
|
||||
assertNotNull(type);
|
||||
IJavadoc javaDoc = type.getJavaDoc();
|
||||
assertNotNull(javaDoc);
|
||||
@@ -168,7 +171,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testInnerClassLevel2_JavadocForOutputFolder() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("hello.Greeting$TestInnerClass$TestInnerClassLevel2");
|
||||
IType type = project.findType("hello.Greeting$TestInnerClass$TestInnerClassLevel2");
|
||||
assertNotNull(type);
|
||||
IJavadoc javaDoc = type.getJavaDoc();
|
||||
assertNotNull(javaDoc);
|
||||
@@ -200,7 +203,7 @@ public class HtmlJavadocTest {
|
||||
@Test
|
||||
public void html_testJavadocOutputFolder() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
IType type = project.getClasspath().findType("hello.Greeting");
|
||||
IType type = project.findType("hello.Greeting");
|
||||
|
||||
assertNotNull(type);
|
||||
String expected = "<div class=\"block\">Comment for Greeting class</div>";
|
||||
@@ -237,7 +240,7 @@ public class HtmlJavadocTest {
|
||||
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("java.util.ArrayList");
|
||||
IType type = project.findType("java.util.ArrayList");
|
||||
assertNotNull(type);
|
||||
IMethod method = type.getMethod("size", Stream.empty());
|
||||
assertNotNull(method);
|
||||
@@ -258,7 +261,7 @@ public class HtmlJavadocTest {
|
||||
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("java.util.Map$Entry");
|
||||
IType type = project.findType("java.util.Map$Entry");
|
||||
assertNotNull(type);
|
||||
String expected = String.join("\n",
|
||||
"<div class=\"block\">A map entry (key-value pair). The <tt>Map.entrySet</tt> method returns",
|
||||
@@ -272,7 +275,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testNoJavadocClass() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();;
|
||||
|
||||
IType type = project.getClasspath().findType("hello.GreetingController");
|
||||
IType type = project.findType("hello.GreetingController");
|
||||
assertNotNull(type);
|
||||
assertNull(type.getJavaDoc());
|
||||
}
|
||||
@@ -281,7 +284,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testNoJavadocField() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("hello.GreetingController");
|
||||
IType type = project.findType("hello.GreetingController");
|
||||
assertNotNull(type);
|
||||
IField field = type.getField("template");
|
||||
assertNotNull(field);
|
||||
@@ -302,7 +305,7 @@ public class HtmlJavadocTest {
|
||||
public void html_testNoJavadocMethod() throws Exception {
|
||||
MavenJavaProject project = projectSupplier.get();
|
||||
|
||||
IType type = project.getClasspath().findType("hello.Application");
|
||||
IType type = project.findType("hello.Application");
|
||||
assertNotNull(type);
|
||||
IMethod method = type.getMethod("corsConfigurer", Stream.empty());
|
||||
assertNotNull(method);
|
||||
|
||||
@@ -32,6 +32,8 @@ import org.springframework.ide.vscode.commons.java.IPrimitiveType;
|
||||
import org.springframework.ide.vscode.commons.java.IType;
|
||||
import org.springframework.ide.vscode.commons.java.IVoidType;
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
@@ -39,15 +41,19 @@ import com.google.common.cache.LoadingCache;
|
||||
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.ClasspathTestUtil.*;
|
||||
|
||||
public class JavaIndexTest {
|
||||
|
||||
private static BasicFileObserver fileObserver = new BasicFileObserver();
|
||||
|
||||
private static LoadingCache<String, MavenJavaProject> mavenProjectsCache = CacheBuilder.newBuilder().build(new CacheLoader<String, MavenJavaProject>() {
|
||||
|
||||
@Override
|
||||
public MavenJavaProject load(String projectName) throws Exception {
|
||||
Path testProjectPath = Paths.get(DependencyTreeTest.class.getResource("/" + projectName).toURI());
|
||||
MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute();
|
||||
return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
}
|
||||
|
||||
});
|
||||
@@ -85,28 +91,28 @@ public class JavaIndexTest {
|
||||
@Test
|
||||
public void findClassInJar() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("org.springframework.test.web.client.ExpectedCount");
|
||||
IType type = project.findType("org.springframework.test.web.client.ExpectedCount");
|
||||
assertNotNull(type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findClassInOutputFolder() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("hello.Greeting");
|
||||
IType type = project.findType("hello.Greeting");
|
||||
assertNotNull(type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classNotFound() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("hello.NonExistentClass");
|
||||
IType type = project.findType("hello.NonExistentClass");
|
||||
assertNull(type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voidMethodNoParams() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("java.util.ArrayList");
|
||||
IType type = project.findType("java.util.ArrayList");
|
||||
assertNotNull(type);
|
||||
IMethod m = type.getMethod("clear", Stream.empty());
|
||||
assertEquals("clear", m.getElementName());
|
||||
@@ -117,7 +123,7 @@ public class JavaIndexTest {
|
||||
@Test
|
||||
public void voidConstructor() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("java.util.ArrayList");
|
||||
IType type = project.findType("java.util.ArrayList");
|
||||
assertNotNull(type);
|
||||
IMethod m = type.getMethod("<init>", Stream.empty());
|
||||
assertEquals(type.getElementName(), m.getElementName());
|
||||
@@ -128,7 +134,7 @@ public class JavaIndexTest {
|
||||
@Test
|
||||
public void constructorMethodWithParams() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
IType type = project.getClasspath().findType("java.util.ArrayList");
|
||||
IType type = project.findType("java.util.ArrayList");
|
||||
assertNotNull(type);
|
||||
IMethod m = type.getMethod("<init>", Stream.of(IPrimitiveType.INT));
|
||||
assertEquals(m.getDeclaringType().getElementName(), m.getElementName());
|
||||
@@ -139,7 +145,7 @@ public class JavaIndexTest {
|
||||
@Test
|
||||
public void testFindJarResource() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
Optional<File> jar = project.getClasspath().findClasspathResourceContainer("org.springframework.boot.autoconfigure.SpringBootApplication");
|
||||
Optional<File> jar = project.findClasspathResourceContainer("org.springframework.boot.autoconfigure.SpringBootApplication");
|
||||
assertTrue(jar.isPresent());
|
||||
assertEquals("spring-boot-autoconfigure-1.4.1.RELEASE.jar", jar.get().getName());
|
||||
}
|
||||
@@ -147,9 +153,9 @@ public class JavaIndexTest {
|
||||
@Test
|
||||
public void testFindJavaResource() throws Exception {
|
||||
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
|
||||
Optional<File> file = project.getClasspath().findClasspathResourceContainer("hello.GreetingController");
|
||||
Optional<File> file = project.findClasspathResourceContainer("hello.GreetingController");
|
||||
assertTrue(file.isPresent());
|
||||
assertTrue(file.get().exists());
|
||||
assertEquals(project.getClasspath().getOutputFolder().toString(), file.get().toString());
|
||||
assertEquals(getOutputFolder(project).toString(), file.get().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public class MavenProjectCacheTest {
|
||||
assertNotNull(cachedProject);
|
||||
|
||||
ImmutableList<CPE> calculatedClassPath = cachedProject.getClasspath().getClasspathEntries();
|
||||
assertEquals(48, calculatedClassPath.size());
|
||||
assertEquals(50, calculatedClassPath.stream().filter(cpe -> !cpe.isSystem()).count());
|
||||
|
||||
fileObserver.notifyFileChanged(pomFile.toURI().toString());
|
||||
assertNull(projectChanged[0]);
|
||||
@@ -144,7 +144,7 @@ public class MavenProjectCacheTest {
|
||||
assertNotNull(projectChanged[0]);
|
||||
assertEquals(cachedProject, projectChanged[0]);
|
||||
calculatedClassPath = cachedProject.getClasspath().getClasspathEntries();
|
||||
assertEquals(49, calculatedClassPath.size());
|
||||
assertEquals(51, calculatedClassPath.stream().filter(cpe -> !cpe.isSystem()).count());
|
||||
|
||||
fileObserver.notifyFileDeleted(pomFile.toURI().toString());
|
||||
assertEquals(cachedProject, projectDeleted[0]);
|
||||
@@ -190,7 +190,7 @@ public class MavenProjectCacheTest {
|
||||
}).get(30, TimeUnit.SECONDS);
|
||||
|
||||
assertTrue(classpathCacheFile.exists());
|
||||
assertEquals(48, project.getClasspath().getClasspathEntries().size());
|
||||
assertEquals(50, project.getClasspath().getClasspathEntries().stream().filter(cpe -> !cpe.isSystem()).count());
|
||||
|
||||
progressDone.set(false);
|
||||
|
||||
@@ -199,7 +199,7 @@ public class MavenProjectCacheTest {
|
||||
|
||||
// Check loaded from cache file
|
||||
project = cache.project(pomFile);
|
||||
assertEquals(48, project.getClasspath().getClasspathEntries().size());
|
||||
assertEquals(50, project.getClasspath().getClasspathEntries().stream().filter(cpe -> !cpe.isSystem()).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>${reactor-version}</version>
|
||||
</dependency>
|
||||
<!-- HTM -> Markdown converter -->
|
||||
<dependency>
|
||||
<groupId>com.kotcrab.remark</groupId>
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
|
||||
/**
|
||||
* Basic implementation of File Observer interface
|
||||
*
|
||||
@@ -87,10 +89,26 @@ public class BasicFileObserver implements FileObserver {
|
||||
Path path = Paths.get(URI.create(uri));
|
||||
registry.values().stream()
|
||||
.filter(pair -> pair.left.stream()
|
||||
.filter(matcher -> matcher.matches(path))
|
||||
.filter(matcher ->
|
||||
matcher.matches(path)
|
||||
)
|
||||
.findFirst()
|
||||
.isPresent())
|
||||
.forEach(pair -> pair.right.accept(uri));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Disposable onAnyChange(List<String> globPattern, Consumer<String> handler) {
|
||||
String[] ids = {
|
||||
onFileChanged(globPattern, handler),
|
||||
onFileCreated(globPattern, handler),
|
||||
onFileDeleted(globPattern, handler)
|
||||
};
|
||||
return () -> {
|
||||
for (String id : ids) {
|
||||
unsubscribe(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ package org.springframework.ide.vscode.commons.util;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
|
||||
/**
|
||||
* Object able to add/remove {@link FileListener} objects and fire events via these listeners
|
||||
*
|
||||
@@ -28,5 +30,7 @@ public interface FileObserver {
|
||||
String onFileDeleted(List<String> globPattern, Consumer<String> handler);
|
||||
|
||||
boolean unsubscribe(String subscriptionId);
|
||||
|
||||
Disposable onAnyChange(List<String> globPattern, Consumer<String> handler);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.languageserver.testharness;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
|
||||
public class ClasspathTestUtil {
|
||||
|
||||
public static Path getOutputFolder(IJavaProject jp) throws Exception {
|
||||
for (CPE cpe : jp.getClasspath().getClasspathEntries()) {
|
||||
if (Classpath.isSource(cpe)) {
|
||||
if (cpe.getPath().endsWith("main/java")) {
|
||||
return Paths.get(cpe.getOutputFolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.jdt.ls.commons.classpath;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
|
||||
public class Classpath {
|
||||
|
||||
|
||||
public static final String ENTRY_KIND_SOURCE = "source";
|
||||
public static final String ENTRY_KIND_BINARY = "binary";
|
||||
public static final String OUTPUT_LOCATION = "output_location";
|
||||
|
||||
private List<CPE> entries;
|
||||
private String defaultOutputFolder;
|
||||
|
||||
public Classpath(List<CPE> entries, String defaultOutputFolder) {
|
||||
public Classpath(List<CPE> entries) {
|
||||
super();
|
||||
this.entries = entries;
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
public List<CPE> getEntries() {
|
||||
@@ -25,38 +36,43 @@ public class Classpath {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
public String getDefaultOutputFolder() {
|
||||
return defaultOutputFolder;
|
||||
}
|
||||
|
||||
public void setDefaultOutputFolder(String defaultOutputFolder) {
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Classpath [entries=" + entries + ", defaultOutputFolder=" + defaultOutputFolder + "]";
|
||||
return "Classpath [entries=" + entries + "]";
|
||||
}
|
||||
|
||||
public static class CPE {
|
||||
|
||||
// TODO: it seems like a good idea to make all classpath entries the same in that they all have
|
||||
// - a place with source code
|
||||
// - a place with compiled code
|
||||
// - a place with java doc
|
||||
// So it seems like we should be able to chnage this so that the same named attribute is used
|
||||
// in both cases (rather then one be 'getOutputFolder' and one 'getPath' to obtain location of the compiled code).
|
||||
|
||||
private String kind;
|
||||
private String path;
|
||||
|
||||
private String path; // TODO: Change to File, Path or URL?
|
||||
private String outputFolder;
|
||||
private URL sourceContainerUrl;
|
||||
private URL javadocContainerUrl;
|
||||
private boolean isSystem = false;
|
||||
|
||||
public String getOutputFolder() {
|
||||
return outputFolder;
|
||||
}
|
||||
|
||||
public void setOutputFolder(String outputFolder) {
|
||||
Assert.isLegal(new File(outputFolder).isAbsolute());
|
||||
this.outputFolder = outputFolder;
|
||||
}
|
||||
|
||||
public CPE() {}
|
||||
|
||||
public CPE(String kind, String path) {
|
||||
private CPE(String kind, String path) {
|
||||
super();
|
||||
this.kind = kind;
|
||||
this.path = path;
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
@@ -72,13 +88,47 @@ public class Classpath {
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
Assert.isLegal(path == null || new File(path).isAbsolute());
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CPE [kind=" + kind + ", path=" + path + ", outputFolder=" + outputFolder + "]";
|
||||
public URL getJavadocContainerUrl() {
|
||||
return javadocContainerUrl;
|
||||
}
|
||||
|
||||
public void setJavadocContainerUrl(URL javadocContainerUrl) {
|
||||
this.javadocContainerUrl = javadocContainerUrl;
|
||||
}
|
||||
|
||||
public URL getSourceContainerUrl() {
|
||||
return sourceContainerUrl;
|
||||
}
|
||||
|
||||
public void setSourceContainerUrl(URL sourceContainerUrl) {
|
||||
this.sourceContainerUrl = sourceContainerUrl;
|
||||
}
|
||||
|
||||
public static CPE binary(String path) {
|
||||
return new CPE(ENTRY_KIND_BINARY, path);
|
||||
}
|
||||
|
||||
public static CPE source(File sourceFolder, File outputFolder) {
|
||||
CPE cpe = new CPE(ENTRY_KIND_SOURCE, sourceFolder.getAbsolutePath());
|
||||
cpe.setOutputFolder(outputFolder.getAbsolutePath());
|
||||
return cpe;
|
||||
}
|
||||
|
||||
public boolean isSystem() {
|
||||
return isSystem;
|
||||
}
|
||||
|
||||
public void setSystem(boolean isSystem) {
|
||||
this.isSystem = isSystem;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSource(CPE e) {
|
||||
return e!=null && Classpath.ENTRY_KIND_SOURCE.equals(e.getKind());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class ClasspathUtil {
|
||||
switch (kind) {
|
||||
case Classpath.ENTRY_KIND_BINARY: {
|
||||
String path = entry.getPath().toString();
|
||||
CPE cpe = new CPE(kind, path);
|
||||
CPE cpe = CPE.binary(path);
|
||||
cpEntries.add(cpe);
|
||||
break;
|
||||
}
|
||||
@@ -49,15 +49,15 @@ public class ClasspathUtil {
|
||||
IPath absoluteSourcePath = resolveWorkspacePath(sourcePath);
|
||||
//log("absoluteSourcePath =" + absoluteSourcePath);
|
||||
if (absoluteSourcePath!=null) {
|
||||
CPE cpe = new CPE(kind, absoluteSourcePath.toString());
|
||||
IPath of = entry.getOutputLocation();
|
||||
//log("outputFolder =" + of);
|
||||
IPath absoluteOutFolder;
|
||||
if (of!=null) {
|
||||
IPath absoluteOutFolder = resolveWorkspacePath(of);
|
||||
//log("absoluteOutFolder =" + absoluteOutFolder);
|
||||
cpe.setOutputFolder(absoluteOutFolder.toString());
|
||||
absoluteOutFolder = resolveWorkspacePath(of);
|
||||
} else {
|
||||
absoluteOutFolder = resolveWorkspacePath(javaProject.getOutputLocation());
|
||||
}
|
||||
cpEntries.add(cpe);
|
||||
cpEntries.add(CPE.source(absoluteSourcePath.toFile(), absoluteOutFolder.toFile()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -66,8 +66,7 @@ public class ClasspathUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
Classpath classpath = new Classpath(cpEntries, resolveWorkspacePath(javaProject.getOutputLocation()).toString());
|
||||
log("classpath.outputFolder=" + classpath.getDefaultOutputFolder());
|
||||
Classpath classpath = new Classpath(cpEntries);
|
||||
log("classpath=" + classpath.getEntries().size() + " entries");
|
||||
return classpath;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyA
|
||||
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
|
||||
@@ -267,8 +268,8 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
try {
|
||||
IClasspath classpath = project.getClasspath();
|
||||
if (classpath!=null) {
|
||||
return classpath.getClasspathEntryPaths().stream().anyMatch(cpe -> {
|
||||
String name = cpe.getFileName().toString();
|
||||
return IClasspathUtil.getBinaryRoots(classpath).stream().anyMatch(cpe -> {
|
||||
String name = cpe.getName();
|
||||
return name.startsWith("spring-boot-actuator-");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +28,7 @@ import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.ReferenceParams;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.ReferencesHandler;
|
||||
@@ -125,10 +127,11 @@ public class BootJavaReferencesHandler implements ReferencesHandler {
|
||||
private String[] getClasspathEntries(IDocument doc) throws Exception {
|
||||
IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(doc.getUri())).get();
|
||||
IClasspath classpath = project.getClasspath();
|
||||
Stream<Path> classpathEntries = classpath.getClasspathEntryPaths().stream();
|
||||
Stream<File> classpathEntries = IClasspathUtil.getBinaryRoots(classpath).stream();
|
||||
return classpathEntries
|
||||
.filter(path -> path.toFile().exists())
|
||||
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
|
||||
.filter(file -> file.exists())
|
||||
.map(file -> file.getAbsolutePath())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,9 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
|
||||
import org.springframework.ide.vscode.commons.javadoc.TypeUrlProviderFromContainerUrl;
|
||||
import org.springframework.ide.vscode.commons.util.text.Region;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -59,7 +60,7 @@ public abstract class AbstractSourceLinks implements SourceLinks {
|
||||
|
||||
@Override
|
||||
public Optional<String> sourceLinkUrlForFQName(IJavaProject project, String fqName) {
|
||||
Optional<File> classpathResource = project.getClasspath().findClasspathResourceContainer(fqName);
|
||||
Optional<File> classpathResource = project.getIndex().findClasspathResourceContainer(fqName);
|
||||
if (classpathResource.isPresent()) {
|
||||
File file = classpathResource.get();
|
||||
if (file.isDirectory()) {
|
||||
@@ -83,10 +84,10 @@ public abstract class AbstractSourceLinks implements SourceLinks {
|
||||
|
||||
private Optional<String> javaSourceLinkUrl(IJavaProject project, String fqName, File containerFolder) {
|
||||
IClasspath classpath = project.getClasspath();
|
||||
return project.getClasspath().getSourceFolders().stream()
|
||||
return IClasspathUtil.getSourceFolders(classpath)
|
||||
.map(sourceFolder -> {
|
||||
try {
|
||||
return Paths.get(sourceFolder).toUri().toURL();
|
||||
return sourceFolder.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
LOG.get().warn("Failed to convert source folder " + sourceFolder + "to URI." + fqName, e);
|
||||
return null;
|
||||
@@ -94,7 +95,7 @@ public abstract class AbstractSourceLinks implements SourceLinks {
|
||||
})
|
||||
.map(url -> {
|
||||
try {
|
||||
return SourceUrlProviderFromSourceContainer.SOURCE_FOLDER_URL_SUPPLIER.sourceUrl(url, fqName);
|
||||
return TypeUrlProviderFromContainerUrl.SOURCE_FOLDER_URL_SUPPLIER.url(url, fqName);
|
||||
} catch (Exception e) {
|
||||
LOG.get().warn("Failed to determine source URL from url=" + url + " fqName=" + fqName, e);
|
||||
return null;
|
||||
@@ -163,10 +164,10 @@ public abstract class AbstractSourceLinks implements SourceLinks {
|
||||
private Optional<CompilationUnit> findCUForFQNameFromJar(IJavaProject project, File jarFile, String clientSourceUri, String fqName) {
|
||||
Optional<CompilationUnit> cu = findCUfromCache(clientSourceUri);
|
||||
if (cu == null) {
|
||||
cu = project.getClasspath().sourceContainer(jarFile)
|
||||
cu = project.sourceContainer(jarFile)
|
||||
.map(url -> {
|
||||
try {
|
||||
return SourceUrlProviderFromSourceContainer.JAR_SOURCE_URL_PROVIDER.sourceUrl(url, fqName);
|
||||
return TypeUrlProviderFromContainerUrl.JAR_SOURCE_URL_PROVIDER.url(url, fqName);
|
||||
} catch (Exception e) {
|
||||
LOG.get().warn("Failed to determine source URL from url=" + url + " fqName=" + fqName, e);
|
||||
return null;
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -27,6 +27,7 @@ import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
@@ -172,10 +173,10 @@ public final class CompilationUnitCache {
|
||||
return new String[0];
|
||||
} else {
|
||||
IClasspath classpath = project.getClasspath();
|
||||
Stream<Path> classpathEntries = classpath.getClasspathEntryPaths().stream();
|
||||
Stream<File> classpathEntries = IClasspathUtil.getBinaryRoots(classpath).stream();
|
||||
return classpathEntries
|
||||
.filter(path -> path.toFile().exists())
|
||||
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
|
||||
.filter(file -> file.exists())
|
||||
.map(file -> file.getAbsolutePath()).toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformati
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
@@ -619,10 +620,11 @@ public class SpringIndexer {
|
||||
|
||||
private String[] getClasspathEntries(IJavaProject project) throws Exception {
|
||||
IClasspath classpath = project.getClasspath();
|
||||
Stream<Path> classpathEntries = classpath.getClasspathEntryPaths().stream();
|
||||
Stream<File> classpathEntries = IClasspathUtil.getBinaryRoots(classpath).stream();
|
||||
return classpathEntries
|
||||
.filter(path -> path.toFile().exists())
|
||||
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
|
||||
.filter(file -> file.exists())
|
||||
.map(file -> file.getAbsolutePath())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
@@ -18,6 +19,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
|
||||
@@ -83,9 +85,12 @@ public class SpringResource {
|
||||
private String projectRelativePath(String pathStr) {
|
||||
Path path = Paths.get(pathStr);
|
||||
IClasspath classpath = project.getClasspath();
|
||||
Path outputFolder = classpath.getOutputFolder();
|
||||
if (path.startsWith(outputFolder)) {
|
||||
return outputFolder.relativize(path).toString();
|
||||
Iterable<File> ofs = () -> IClasspathUtil.getOutputFolders(classpath).iterator();
|
||||
for (File _outputFolder : ofs) {
|
||||
Path outputFolder = _outputFolder.toPath();
|
||||
if (path.startsWith(outputFolder)) {
|
||||
return outputFolder.relativize(path).toString();
|
||||
}
|
||||
}
|
||||
return pathStr;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.jdt.ls;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -32,6 +33,7 @@ import org.springframework.ide.vscode.commons.java.ClasspathData;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
|
||||
import org.springframework.ide.vscode.commons.java.JavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListener;
|
||||
@@ -39,6 +41,7 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguage
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.CollectorUtil;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.UriUtil;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
@@ -53,7 +56,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
private CompletableFuture<Void> initialized = new CompletableFuture<Void>();
|
||||
|
||||
private SimpleLanguageServer server;
|
||||
private Map<String, JdtLsProject> table = new HashMap<String, JdtLsProject>();
|
||||
private Map<String, JavaProject> table = new HashMap<String, JavaProject>();
|
||||
private Logger log = LoggerFactory.getLogger(JdtLsProjectCache.class);
|
||||
private List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
@@ -70,20 +73,24 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
@Override
|
||||
public void changed(Event event) {
|
||||
initialized.thenRun(() -> {
|
||||
synchronized (table) {
|
||||
String uri = UriUtil.normalize(event.projectUri);
|
||||
if (event.deleted) {
|
||||
JdtLsProject deleted = table.remove(uri);
|
||||
notifyDelete(deleted);
|
||||
} else {
|
||||
JdtLsProject newProject = new JdtLsProject(event.name, uri, event.classpath);
|
||||
JdtLsProject oldProject = table.put(uri, newProject);
|
||||
if (oldProject != null) {
|
||||
notifyChanged(newProject);
|
||||
try {
|
||||
synchronized (table) {
|
||||
String uri = UriUtil.normalize(event.projectUri);
|
||||
if (event.deleted) {
|
||||
JavaProject deleted = table.remove(uri);
|
||||
notifyDelete(deleted);
|
||||
} else {
|
||||
notifyCreated(newProject);
|
||||
JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()));
|
||||
JavaProject oldProject = table.put(uri, newProject);
|
||||
if (oldProject != null) {
|
||||
notifyChanged(newProject);
|
||||
} else {
|
||||
notifyCreated(newProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -106,6 +113,10 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
);
|
||||
}
|
||||
|
||||
private FileObserver getFileObserver() {
|
||||
return server.getWorkspaceService().getFileObserver();
|
||||
}
|
||||
|
||||
private boolean isOldJdt(Throwable e) {
|
||||
return ExceptionUtil.getMessage(e).contains("'sts.java.addClasspathListener' not supported");
|
||||
}
|
||||
@@ -142,7 +153,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
});
|
||||
}
|
||||
|
||||
private void notifyCreated(JdtLsProject newProject) {
|
||||
private void notifyCreated(JavaProject newProject) {
|
||||
logEvent("Created", newProject);
|
||||
synchronized (listeners) {
|
||||
for (Listener listener : listeners) {
|
||||
@@ -151,16 +162,17 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyDelete(JdtLsProject deleted) {
|
||||
private void notifyDelete(JavaProject deleted) {
|
||||
logEvent("Deleted", deleted);
|
||||
synchronized (listeners) {
|
||||
for (Listener listener : listeners) {
|
||||
listener.deleted(deleted);
|
||||
}
|
||||
}
|
||||
deleted.dispose();
|
||||
}
|
||||
|
||||
private void notifyChanged(JdtLsProject newProject) {
|
||||
private void notifyChanged(JavaProject newProject) {
|
||||
logEvent("Changed", newProject);
|
||||
synchronized (listeners) {
|
||||
for (Listener listener : listeners) {
|
||||
@@ -169,7 +181,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
}
|
||||
}
|
||||
|
||||
private void logEvent(String type, JdtLsProject newProject) {
|
||||
private void logEvent(String type, JavaProject newProject) {
|
||||
try {
|
||||
log.info("Project "+type+": " + newProject.getLocationUri());
|
||||
log.info("Classpath has "+newProject.getClasspath().getClasspathEntries().size()+" entries");
|
||||
@@ -190,7 +202,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
}
|
||||
|
||||
synchronized (table) {
|
||||
for (Entry<String, JdtLsProject> e : table.entrySet()) {
|
||||
for (Entry<String, JavaProject> e : table.entrySet()) {
|
||||
String projectUri = e.getKey();
|
||||
log.debug("projectUri = '{}'", projectUri);
|
||||
if (UriUtil.contains(projectUri, uri) ) {
|
||||
@@ -206,98 +218,4 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private class JdtLsProject implements IJavaProject {
|
||||
|
||||
private final JdtClasspath classpath;
|
||||
|
||||
public JdtLsProject(String name, String projectUri, Classpath classpath) {
|
||||
this.classpath = new JdtClasspath(name, projectUri, classpath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClasspath getClasspath() {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
public String getLocationUri() {
|
||||
return classpath.projectUri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class JdtClasspath extends JandexClasspath {
|
||||
|
||||
private Classpath classpath;
|
||||
private String name;
|
||||
private String projectUri;
|
||||
|
||||
|
||||
public JdtClasspath(String name, String uri, Classpath classpath) {
|
||||
this.name = name;
|
||||
this.projectUri = uri;
|
||||
this.classpath = classpath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return new File(projectUri).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getOutputFolder() {
|
||||
return Paths.get(classpath.getDefaultOutputFolder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CPE> getClasspathEntries() throws Exception {
|
||||
return classpath.getEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getClasspathResources() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getSourceFolders() {
|
||||
ImmutableList.Builder<String> sourceEntries = ImmutableList.builder();
|
||||
try {
|
||||
for (CPE e : getClasspathEntries()) {
|
||||
if (Classpath.isSource(e)) {
|
||||
sourceEntries.add(e.getPath());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return sourceEntries.build();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClasspathData createClasspathData() throws Exception {
|
||||
// We should not be needing this as we dont use DelegatingCachedClasspath
|
||||
throw new UnsupportedOperationException("Not supported for JDT classpath: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<URL> sourceContainer(File classpathResource) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJavadocProvider createHtmlJavdocProvider(File classpathResource) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -131,11 +131,11 @@ public class ClassReferenceProvider extends CachingValueProvider {
|
||||
|
||||
@Override
|
||||
protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String query) {
|
||||
IType targetType = target == null || target.isEmpty() ? javaProject.getClasspath().findType("java.lang.Object") : javaProject.getClasspath().findType(target);
|
||||
IType targetType = target == null || target.isEmpty() ? javaProject.findType("java.lang.Object") : javaProject.findType(target);
|
||||
if (targetType == null) {
|
||||
return Flux.empty();
|
||||
}
|
||||
Set<IType> allSubclasses = javaProject.getClasspath()
|
||||
Set<IType> allSubclasses = javaProject
|
||||
.allSubtypesOf(targetType)
|
||||
.filter(t -> Flags.isPublic(t.getFlags()) && !concrete || !isAbstract(t))
|
||||
.collect(Collectors.toSet())
|
||||
@@ -143,7 +143,7 @@ public class ClassReferenceProvider extends CachingValueProvider {
|
||||
if (allSubclasses.isEmpty()) {
|
||||
return Flux.empty();
|
||||
} else {
|
||||
return javaProject.getClasspath()
|
||||
return javaProject
|
||||
.fuzzySearchTypes(query, type -> allSubclasses.contains(type))
|
||||
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
|
||||
.flatMapIterable(l -> l)
|
||||
|
||||
@@ -37,10 +37,10 @@ public class LoggerNameProvider extends CachingValueProvider {
|
||||
@Override
|
||||
protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String query) {
|
||||
return Flux.concat(
|
||||
javaProject.getClasspath()
|
||||
javaProject.getIndex()
|
||||
.fuzzySearchPackages(query)
|
||||
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())),
|
||||
javaProject.getClasspath()
|
||||
javaProject.getIndex()
|
||||
.fuzzySearchTypes(query, null)
|
||||
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2()))
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.zip.ZipEntry;
|
||||
import org.springframework.ide.vscode.boot.configurationmetadata.ConfigurationMetadataRepository;
|
||||
import org.springframework.ide.vscode.boot.configurationmetadata.ConfigurationMetadataRepositoryJsonBuilder;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
public class PropertiesLoader {
|
||||
@@ -55,14 +56,12 @@ public class PropertiesLoader {
|
||||
|
||||
public ConfigurationMetadataRepository load(IClasspath classPath) {
|
||||
try {
|
||||
classPath.getClasspathEntryPaths().forEach(entry -> {
|
||||
//Log.info("Indexing "+entry);
|
||||
File fileEntry = entry.toFile();
|
||||
IClasspathUtil.getBinaryRoots(classPath).forEach(fileEntry -> {
|
||||
if (fileEntry.exists()) {
|
||||
if (fileEntry.isDirectory()) {
|
||||
loadFromOutputFolder(entry);
|
||||
loadFromOutputFolder(fileEntry.toPath());
|
||||
} else {
|
||||
loadFromJar(entry);
|
||||
loadFromJar(fileEntry.toPath());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -63,7 +63,11 @@ public class ResourceHintProvider implements ValueProviderStrategy {
|
||||
private static class ClasspathHints extends CachingValueProvider {
|
||||
@Override
|
||||
protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String query) {
|
||||
return Flux.fromStream(javaProject.getClasspath().getClasspathResources().stream().distinct().map(r -> r.replaceAll("\\\\", "/")).map(StsValueHint::create));
|
||||
return Flux.fromStream(
|
||||
javaProject.getClasspathResources().stream()
|
||||
.distinct().map(r -> r.replaceAll("\\\\", "/"))
|
||||
.map(StsValueHint::create)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public class StsValueHint {
|
||||
try {
|
||||
IJavaProject jp = typeUtil.getJavaProject();
|
||||
if (jp!=null) {
|
||||
IType type = jp.getClasspath().findType(fqName);
|
||||
IType type = jp.findType(fqName);
|
||||
if (type!=null) {
|
||||
return create(type);
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ public class TypeUtil {
|
||||
private IType findType(String typeName) {
|
||||
try {
|
||||
if (javaProject!=null) {
|
||||
return javaProject.getClasspath().findType(typeName);
|
||||
return javaProject.findType(typeName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AutowiredHoverProviderTest {
|
||||
.build();
|
||||
|
||||
MavenJavaProject jp = projects.mavenProject("empty-boot-15-web-app", FOO_INTERFACE);
|
||||
assertTrue(jp.getClasspath().findType("com.example.Foo").exists());
|
||||
assertTrue(jp.findType("com.example.Foo").exists());
|
||||
harness.useProject(projects.mavenProject("empty-boot-15-web-app"));
|
||||
harness.intialize(null);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class BeanInjectedIntoHoverProviderTest {
|
||||
.build();
|
||||
|
||||
MavenJavaProject jp = projects.mavenProject("empty-boot-15-web-app", FOO_INTERFACE);
|
||||
assertTrue(jp.getClasspath().findType("hello.Foo").exists());
|
||||
assertTrue(jp.findType("hello.Foo").exists());
|
||||
harness.useProject(jp);
|
||||
harness.intialize(null);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class ComponentInjectionsHoverProviderTest {
|
||||
.build();
|
||||
|
||||
MavenJavaProject jp = projects.mavenProject("empty-boot-15-web-app", EXTRA_TYPES);
|
||||
assertTrue(jp.getClasspath().findType("com.example.Foo").exists());
|
||||
assertTrue(jp.findType("com.example.Foo").exists());
|
||||
harness.useProject(jp);
|
||||
harness.intialize(null);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.JavaProject;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -52,12 +53,7 @@ public class CompilationUnitCacheTest {
|
||||
public void cu_cached() throws Exception {
|
||||
harness = BootJavaLanguageServerHarness.builder()
|
||||
.mockDefaults().build();
|
||||
harness.useProject(new IJavaProject() {
|
||||
@Override
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
});
|
||||
harness.useProject(ProjectsHarness.dummyProject());
|
||||
harness.intialize(null);
|
||||
|
||||
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
|
||||
@@ -94,12 +90,7 @@ public class CompilationUnitCacheTest {
|
||||
public void cu_cache_invalidated_by_doc_change() throws Exception {
|
||||
harness = BootJavaLanguageServerHarness.builder()
|
||||
.mockDefaults().build();
|
||||
harness.useProject(new IJavaProject() {
|
||||
@Override
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
});
|
||||
harness.useProject(ProjectsHarness.dummyProject());
|
||||
harness.intialize(null);
|
||||
|
||||
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
|
||||
@@ -125,12 +116,7 @@ public class CompilationUnitCacheTest {
|
||||
public void cu_cache_invalidated_by_doc_close() throws Exception {
|
||||
harness = BootJavaLanguageServerHarness.builder()
|
||||
.mockDefaults().build();
|
||||
harness.useProject(new IJavaProject() {
|
||||
@Override
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
});
|
||||
harness.useProject(ProjectsHarness.dummyProject());
|
||||
harness.intialize(null);
|
||||
|
||||
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
|
||||
|
||||
@@ -24,6 +24,8 @@ import org.springframework.ide.vscode.boot.java.links.VSCodeSourceLinks;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenBuilder;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
@@ -43,7 +45,7 @@ public class VSCodeSourceLinksTest {
|
||||
public MavenJavaProject load(String projectName) throws Exception {
|
||||
Path testProjectPath = Paths.get(VSCodeSourceLinksTest.class.getResource("/test-projects/" + projectName).toURI());
|
||||
MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute();
|
||||
return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
return MavenJavaProject.create(new BasicFileObserver(), MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -68,8 +68,8 @@ public class TypeUtilTest {
|
||||
@Test
|
||||
public void testGetProperties() throws Exception {
|
||||
useProject("enums-boot-1.3.2-app");
|
||||
assertNotNull(project.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(project.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(project.findType("demo.Color"));
|
||||
assertNotNull(project.findType("demo.ColorData"));
|
||||
|
||||
|
||||
Type data = TypeParser.parse("demo.ColorData");
|
||||
|
||||
@@ -40,10 +40,13 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguage
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.Editor;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.ClasspathTestUtil.*;
|
||||
|
||||
/**
|
||||
* Boot App Properties Editor tests
|
||||
*
|
||||
@@ -220,7 +223,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
|
||||
@Test public void testPredefinedProject() throws Exception {
|
||||
IJavaProject p = createPredefinedMavenProject("tricky-getters-boot-1.3.1-app");
|
||||
IType type = p.getClasspath().findType("demo.DemoApplication");
|
||||
IType type = p.findType("demo.DemoApplication");
|
||||
assertNotNull(type);
|
||||
}
|
||||
|
||||
@@ -229,7 +232,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
|
||||
//Check some assumptions about the initial state of the test project (if these checks fail then
|
||||
// the test may be 'vacuous' since the things we are testing for already exist beforehand.
|
||||
Path metadataFile = p.getClasspath().getOutputFolder().resolve(PropertiesLoader.PROJECT_META_DATA_LOCATIONS[0]);
|
||||
Path metadataFile = getOutputFolder(p).resolve(PropertiesLoader.PROJECT_META_DATA_LOCATIONS[0]);
|
||||
assertTrue(metadataFile.toFile().isFile());
|
||||
assertContains("\"name\": \"foo.counter\"", Files.toString(metadataFile.toFile(), Charset.forName("UTF8")));
|
||||
}
|
||||
@@ -294,7 +297,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("boot-1.2.1-app-properties-list-of-pojo");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Foo"));
|
||||
assertNotNull(p.findType("demo.Foo"));
|
||||
|
||||
Editor editor = newEditor(
|
||||
"token.bad.guy=problem\n"+
|
||||
@@ -319,7 +322,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("boot-1.2.1-app-properties-list-of-pojo");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Foo"));
|
||||
assertNotNull(p.findType("demo.Foo"));
|
||||
|
||||
assertCompletionsVariations("volder.foo.l<*>", "volder.foo.list[<*>");
|
||||
assertCompletionsDisplayStringAndDetail("volder.foo.list[0].<*>",
|
||||
@@ -468,7 +471,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
data("foo.colors", "java.util.List<demo.Color>", null, "A foonky list");
|
||||
|
||||
@@ -491,7 +494,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
data("foo.color", "demo.Color", null, "A foonky colour");
|
||||
|
||||
@@ -510,7 +513,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
data("foo.color", "demo.Color", null, "A foonky colour");
|
||||
Editor editor = newEditor(
|
||||
@@ -533,7 +536,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
assertCompletionsVariations("foo.nam<*>",
|
||||
"foo.name-colors.<*>",
|
||||
@@ -552,7 +555,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
useProject(p);
|
||||
data("foo.name-colors", "java.util.Map<java.lang.String,demo.Color>", null, "Map with colors in its values");
|
||||
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
Editor editor = newEditor(
|
||||
"foo.name-colors.jacket=BLUE\n" +
|
||||
@@ -571,8 +574,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
useProject(p);
|
||||
data("foo.color-names", "java.util.Map<demo.Color,java.lang.String>", null, "Map with colors in its keys");
|
||||
data("foo.color-data", "java.util.Map<demo.Color,demo.ColorData>", null, "Map with colors in its keys, and pojo in values");
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
//Map Enum -> String:
|
||||
assertCompletionsVariations("foo.colnam<*>", "foo.color-names.<*>");
|
||||
@@ -611,8 +614,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
Editor editor = newEditor(
|
||||
"foo.color-names.RED=Rood\n"+
|
||||
@@ -631,8 +634,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
assertCompletion("foo.dat<*>", "foo.data.<*>");
|
||||
|
||||
@@ -666,8 +669,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
Editor editor = newEditor(
|
||||
"foo.data.bogus=Something\n" +
|
||||
@@ -701,8 +704,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
data("atommap", "java.util.Map<java.lang.String,java.lang.Integer>", null, "map of atomic data");
|
||||
data("objectmap", "java.util.Map<java.lang.String,java.lang.Object>", null, "map of atomic object (recursive map)");
|
||||
@@ -741,8 +744,8 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.getClasspath().findType("demo.ColorData"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.ColorData"));
|
||||
|
||||
Editor editor = newEditor(
|
||||
"foo.color-names.BLUE.dot=Blauw\n"+
|
||||
@@ -767,7 +770,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.ClothingSize"));
|
||||
assertNotNull(p.findType("demo.ClothingSize"));
|
||||
|
||||
data("simple.pants.size", "demo.ClothingSize", null, "The simple pant's size");
|
||||
|
||||
@@ -811,7 +814,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.ClothingSize"));
|
||||
assertNotNull(p.findType("demo.ClothingSize"));
|
||||
|
||||
data("simple.pants.size", "demo.ClothingSize", null, "The simple pant's size");
|
||||
|
||||
@@ -1414,7 +1417,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
data("my.colors", collectionType+"<demo.Color>", null, "Ooh! nice colors!");
|
||||
|
||||
|
||||
@@ -585,7 +585,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
|
||||
@Test public void testReconcileBeanPropName() throws Exception {
|
||||
IJavaProject p = createPredefinedMavenProject("boot-1.2.1-app-properties-list-of-pojo");
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Foo"));
|
||||
assertNotNull(p.findType("demo.Foo"));
|
||||
data("some-foo", "demo.Foo", null, "some Foo pojo property");
|
||||
Editor editor = newEditor(
|
||||
"some-foo:\n" +
|
||||
@@ -617,7 +617,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
|
||||
@Test public void testReconcilePojoArray() throws Exception {
|
||||
IJavaProject p = createPredefinedMavenProject("boot-1.2.1-app-properties-list-of-pojo");
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Foo"));
|
||||
assertNotNull(p.findType("demo.Foo"));
|
||||
|
||||
{
|
||||
Editor editor = newEditor(
|
||||
@@ -694,7 +694,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
|
||||
@Test public void testEnumPropertyReconciling() throws Exception {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.Color"));
|
||||
assertNotNull(p.findType("demo.Color"));
|
||||
|
||||
data("foo.color", "demo.Color", null, "A foonky colour");
|
||||
Editor editor = newEditor(
|
||||
@@ -1876,7 +1876,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
|
||||
@Ignore @Test public void testEnumsInLowerCaseContentAssist() throws Exception {
|
||||
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
|
||||
useProject(p);
|
||||
assertNotNull(p.getClasspath().findType("demo.ClothingSize"));
|
||||
assertNotNull(p.findType("demo.ClothingSize"));
|
||||
|
||||
data("simple.pants.size", "demo.ClothingSize", null, "The simple pant's size");
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.project.harness;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Assert;
|
||||
@@ -20,10 +21,13 @@ import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents
|
||||
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.composable.ComposableLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.LSFactory;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
|
||||
@@ -135,9 +139,16 @@ public class BootJavaLanguageServerHarness extends LanguageServerHarness<Composa
|
||||
indexHarness.useProject(p);
|
||||
}
|
||||
|
||||
public Path getOutputFolder() {
|
||||
return getProjectFinder().find(null).get().getClasspath().getOutputFolder();
|
||||
public Path getOutputFolder() throws Exception {
|
||||
IClasspath classpath = getProjectFinder().find(null).get().getClasspath();
|
||||
for (CPE cpe : classpath.getClasspathEntries()) {
|
||||
if (Classpath.isSource(cpe)) {
|
||||
if (cpe.getPath().endsWith("main/java")) {
|
||||
return Paths.get(cpe.getOutputFolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,16 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.JavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenBuilder;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.IOUtil;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
@@ -40,10 +46,12 @@ import reactor.util.function.Tuples;
|
||||
*/
|
||||
public class ProjectsHarness {
|
||||
|
||||
public static final ProjectsHarness INSTANCE = new ProjectsHarness();;
|
||||
public static final ProjectsHarness INSTANCE = new ProjectsHarness(new BasicFileObserver());
|
||||
|
||||
public Cache<Object, IJavaProject> cache = CacheBuilder.newBuilder().concurrencyLevel(1).build();
|
||||
|
||||
private final FileObserver fileObserver;
|
||||
|
||||
/**
|
||||
* A callback that is given a chance to make changes to test project contents before the test project
|
||||
* is created from it.
|
||||
@@ -81,8 +89,13 @@ public class ProjectsHarness {
|
||||
MAVEN
|
||||
// GRADLE?
|
||||
}
|
||||
|
||||
public static final IJavaProject dummyProject() throws URISyntaxException {
|
||||
return new JavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), new DelegatingCachedClasspath(() -> null, null));
|
||||
}
|
||||
|
||||
private ProjectsHarness() {
|
||||
private ProjectsHarness(FileObserver fileObserver) {
|
||||
this.fileObserver = fileObserver;
|
||||
}
|
||||
|
||||
public IJavaProject project(ProjectType type, String name, ProjectCustomizer customizer) throws Exception {
|
||||
@@ -100,7 +113,7 @@ public class ProjectsHarness {
|
||||
switch (type) {
|
||||
case MAVEN:
|
||||
MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute();
|
||||
return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
|
||||
default:
|
||||
throw new IllegalStateException("Bug!!! Missing case");
|
||||
}
|
||||
@@ -129,4 +142,5 @@ public class ProjectsHarness {
|
||||
public MavenJavaProject mavenProject(String name) throws Exception {
|
||||
return (MavenJavaProject) project(ProjectType.MAVEN, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user