Refactor, fix and simplify classpath infrastructure

This commit is contained in:
Kris De Volder
2018-04-30 10:10:56 -07:00
parent aa1cb03f12
commit 16a56a5fdc
69 changed files with 1518 additions and 993 deletions

View File

@@ -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-");
});
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}
/**

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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)

View File

@@ -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()))
)

View File

@@ -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());
}
}
});

View File

@@ -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)
);
}
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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" +

View File

@@ -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());
}
});

View File

@@ -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");

View File

@@ -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!");

View File

@@ -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");

View File

@@ -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;
}
}

View File

@@ -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);
}
}