diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java index 6381f0b36..a4ff7c56f 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -13,12 +13,14 @@ package org.springframework.ide.vscode.commons.gradle; import java.io.File; import java.nio.file.Path; -import org.springframework.ide.vscode.commons.java.LegacyJavaProject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; 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.java.LegacyJavaProject; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.util.FileObserver; -import org.springframework.ide.vscode.commons.util.Log; /** * Implementation of Gradle Java project @@ -28,11 +30,13 @@ import org.springframework.ide.vscode.commons.util.Log; */ public class GradleJavaProject extends LegacyJavaProject { - private GradleJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File projectDir) { - super(fileObserver, projectDir.toURI(), projectDataCache, classpath); + private static final Logger log = LoggerFactory.getLogger(GradleJavaProject.class); + + private GradleJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File projectDir, JavadocService javadocService) { + super(fileObserver, projectDir.toURI(), projectDataCache, classpath, javadocService); } - public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir, Path projectDataCache) { + public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir, Path projectDataCache, JavadocService javadocService) { File file = projectDataCache == null ? null : projectDataCache.resolve(ClasspathFileBasedCache.CLASSPATH_DATA_CACHE_FILE).toFile(); @@ -41,16 +45,16 @@ public class GradleJavaProject extends LegacyJavaProject { () -> new GradleProjectClasspath(gradle, projectDir), fileBasedCache ); - return new GradleJavaProject(fileObserver, projectDataCache, classpath, projectDir); + return new GradleJavaProject(fileObserver, projectDataCache, classpath, projectDir, javadocService); } - public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir) { - GradleJavaProject thiss = create(fileObserver, gradle, projectDir, null); + public static GradleJavaProject create(FileObserver fileObserver, GradleCore gradle, File projectDir, JavadocService javadocService) { + GradleJavaProject thiss = create(fileObserver, gradle, projectDir, null, javadocService); if (!thiss.getClasspath().isCached()) { try { thiss.getClasspath().update(); } catch (Exception e) { - Log.log(e); + log.error("", e); } } return thiss; diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java index 02007a78b..34abe7d7a 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -17,6 +17,7 @@ import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.java.AbstractFileToProjectCache; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException; /** @@ -28,10 +29,12 @@ import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageExc public class GradleProjectCache extends AbstractFileToProjectCache { private GradleCore gradle; + private JavadocService javadocService; - public GradleProjectCache(Sts4LanguageServer server, GradleCore gradle, boolean asyncUpdate, Path projectCacheFolder) { + public GradleProjectCache(Sts4LanguageServer server, GradleCore gradle, boolean asyncUpdate, Path projectCacheFolder, JavadocService javadocService) { super(server, asyncUpdate, projectCacheFolder); this.gradle = gradle; + this.javadocService = javadocService; } @Override @@ -49,7 +52,8 @@ public class GradleProjectCache extends AbstractFileToProjectCache JavaDocProviders.createFor(cpe)); } @Test @@ -105,7 +106,7 @@ public class GradleProjectTest { String gradelFileContents = Files.contentOf(gradleFile, Charset.defaultCharset()); try { - GradleProjectCache manager = new GradleProjectCache(server, GradleCore.getDefault(), false, null); + GradleProjectCache manager = createProjectCache(); IJavaProject[] projectChanged = new IJavaProject[] { null }; IJavaProject[] projectDeleted = new IJavaProject[] { null }; manager.addListener(new Listener() { @@ -147,9 +148,13 @@ public class GradleProjectTest { } } + private GradleProjectCache createProjectCache() { + return new GradleProjectCache(server, GradleCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); + } + @Test public void findGradleProjectWithStandardBuildFile() throws Exception { - GradleProjectFinder finder = new GradleProjectFinder(new GradleProjectCache(server, GradleCore.getDefault(), false, null)); + GradleProjectFinder finder = new GradleProjectFinder(createProjectCache()); File sourceFile = new File(GradleProjectTest.class.getResource("/test-app-1/src/main/java/Library.java").toURI()); Optional project = finder.find(sourceFile); assertTrue(project.isPresent()); @@ -160,7 +165,7 @@ public class GradleProjectTest { @Test public void findGradleProjectWithNonStandardBuildFile() throws Exception { - GradleProjectFinder finder = new GradleProjectFinder(new GradleProjectCache(server, GradleCore.getDefault(), false, null)); + GradleProjectFinder finder = new GradleProjectFinder(createProjectCache()); File sourceFile = new File(GradleProjectTest.class.getResource("/test-app-2/src/main/java/Library.java").toURI()); Optional project = finder.find(sourceFile); assertTrue(project.isPresent()); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java index 23e734c01..cbbf6db29 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexIndex.java @@ -20,12 +20,8 @@ import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ide.vscode.commons.java.IAnnotation; -import org.springframework.ide.vscode.commons.java.IField; import org.springframework.ide.vscode.commons.java.IJavadocProvider; -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 com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -43,30 +39,6 @@ public class JandexIndex extends BasicJandexIndex { IJavadocProvider createJavadocProvider(File jarContainer); } - private static final IJavadocProvider ABSENT_JAVADOC_PROVIDER = new IJavadocProvider() { - - @Override - public IJavadoc getJavadoc(IType type) { - return null; - } - - @Override - public IJavadoc getJavadoc(IField field) { - return null; - } - - @Override - public IJavadoc getJavadoc(IMethod method) { - return null; - } - - @Override - public IJavadoc getJavadoc(IAnnotation method) { - return null; - } - - }; - private JavadocProviderFactory javadocProviderFactory; private Cache javadocProvidersCache = CacheBuilder.newBuilder().build(); @@ -101,7 +73,7 @@ public class JandexIndex extends BasicJandexIndex { if (javadocProviderFactory != null) { provider = javadocProviderFactory.createJavadocProvider(classpathResource); } - return provider == null ? ABSENT_JAVADOC_PROVIDER : provider; + return provider == null ? IJavadocProvider.NULL : provider; }); } catch (ExecutionException e) { log.error("Failed to retrieve javadoc provider for resource " + classpathResource, e); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IJavadocProvider.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IJavadocProvider.java index 8ecc47799..9747108a4 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IJavadocProvider.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IJavadocProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -13,12 +13,37 @@ package org.springframework.ide.vscode.commons.java; import org.springframework.ide.vscode.commons.javadoc.IJavadoc; public interface IJavadocProvider { - + IJavadoc getJavadoc(IType type); - + IJavadoc getJavadoc(IField field); - + IJavadoc getJavadoc(IMethod method); IJavadoc getJavadoc(IAnnotation annotation); + + final static IJavadocProvider NULL = new IJavadocProvider() { + + @Override + public IJavadoc getJavadoc(IType type) { + return null; + } + + @Override + public IJavadoc getJavadoc(IField field) { + return null; + } + + @Override + public IJavadoc getJavadoc(IMethod method) { + return null; + } + + @Override + public IJavadoc getJavadoc(IAnnotation method) { + return null; + } + + }; + } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/JavaProject.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/JavaProject.java index 0220a6139..01150d681 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/JavaProject.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/JavaProject.java @@ -15,6 +15,8 @@ import java.net.URI; import org.springframework.ide.vscode.commons.jandex.JandexClasspath; import org.springframework.ide.vscode.commons.jandex.JandexIndex.JavadocProviderFactory; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.util.FileObserver; import reactor.core.Disposable; @@ -27,12 +29,15 @@ public class JavaProject implements IJavaProject, Disposable { private final FileObserver fileObserver; private final JavadocProviderFactory javadocProviderFactory; - public JavaProject(FileObserver fileObserver, URI uri, IClasspath classpath, JavadocProviderFactory javadocProviderFactory) { + public JavaProject(FileObserver fileObserver, URI uri, IClasspath classpath, JavadocService javadocService) { super(); this.classpath = classpath; this.fileObserver = fileObserver; this.uri = uri; - this.javadocProviderFactory = javadocProviderFactory; + this.javadocProviderFactory = (classpathResource) -> { + CPE cpe = IClasspathUtil.findEntryForBinaryRoot(classpath, classpathResource); + return javadocService.javadocProvider(uri.toString(), cpe); + }; } @Override diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/LegacyJavaProject.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/LegacyJavaProject.java index f7e130a2f..31398b865 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/LegacyJavaProject.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/LegacyJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -13,8 +13,7 @@ package org.springframework.ide.vscode.commons.java; import java.net.URI; import java.nio.file.Path; -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.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.util.FileObserver; /** @@ -30,11 +29,8 @@ public class LegacyJavaProject extends JavaProject { final protected Path projectDataCache; - public LegacyJavaProject(FileObserver fileObserver, URI loactionUri, Path projectDataCache, IClasspath classpath) { - super(fileObserver, loactionUri, classpath, classpathResource -> { - CPE cpe = IClasspathUtil.findEntryForBinaryRoot(classpath, classpathResource); - return JavaDocProviders.createFor(cpe); - }); + public LegacyJavaProject(FileObserver fileObserver, URI loactionUri, Path projectDataCache, IClasspath classpath, JavadocService javadocService) { + super(fileObserver, loactionUri, classpath, javadocService); this.projectDataCache = projectDataCache; } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/HtmlJavadoc.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/HtmlJavadoc.java index fcb856b0f..81504a305 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/HtmlJavadoc.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/HtmlJavadoc.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016, 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 @@ -15,18 +15,13 @@ import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.Renderables; public class HtmlJavadoc implements IJavadoc { - + private String html; - + public HtmlJavadoc(String html) { this.html = html; } - @Override - public String raw() { - throw new UnsupportedOperationException("Not yet implemnted"); - } - @Override public Renderable getRenderable() { return Renderables.htmlBlob(html); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/IJavadoc.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/IJavadoc.java index 074e702e1..4fda2d828 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/IJavadoc.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/IJavadoc.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016, 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 @@ -14,9 +14,7 @@ package org.springframework.ide.vscode.commons.javadoc; import org.springframework.ide.vscode.commons.util.Renderable; public interface IJavadoc { - - String raw(); - + Renderable getRenderable(); - + } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/JdtLsJavadocProvider.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/JdtLsJavadocProvider.java index 181cb6b0f..461485d22 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/JdtLsJavadocProvider.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/JdtLsJavadocProvider.java @@ -47,11 +47,6 @@ public class JdtLsJavadocProvider implements IJavadocProvider { final Renderable renderableDoc = Renderables.mdBlob(md); return new IJavadoc() { - @Override - public String raw() { - throw new UnsupportedOperationException("Raw content unavailable"); - } - @Override public Renderable getRenderable() { return renderableDoc; diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavadocService.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavadocService.java new file mode 100644 index 000000000..5ec443158 --- /dev/null +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavadocService.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * 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.java; + +import org.springframework.ide.vscode.commons.java.IJavadocProvider; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; + +public interface JavadocService { + + IJavadocProvider javadocProvider(String projectUri, CPE classpathEntry); + +} diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java index 924a39fbf..4c92f858b 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenJavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Pivotal, Inc. + * Copyright (c) 2016, 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 @@ -13,13 +13,15 @@ package org.springframework.ide.vscode.commons.maven.java; import java.io.File; import java.nio.file.Path; -import org.springframework.ide.vscode.commons.java.LegacyJavaProject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; 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.java.LegacyJavaProject; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.maven.MavenCore; import org.springframework.ide.vscode.commons.util.FileObserver; -import org.springframework.ide.vscode.commons.util.Log; /** * Wrapper for Maven Core project @@ -29,14 +31,16 @@ import org.springframework.ide.vscode.commons.util.Log; */ public class MavenJavaProject extends LegacyJavaProject { + private static final Logger log = LoggerFactory.getLogger(MavenJavaProject.class); + private final File pom; - private MavenJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File pom) { - super(fileObserver, pom.getParentFile().toURI(), projectDataCache, classpath); + private MavenJavaProject(FileObserver fileObserver, Path projectDataCache, IClasspath classpath, File pom, JavadocService javadocService) { + super(fileObserver, pom.getParentFile().toURI(), projectDataCache, classpath, javadocService); this.pom = pom; } - public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, Path projectDataCache) { + public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, Path projectDataCache, JavadocService javadocService) { File file = projectDataCache == null ? null : projectDataCache.resolve(ClasspathFileBasedCache.CLASSPATH_DATA_CACHE_FILE).toFile(); @@ -45,16 +49,16 @@ public class MavenJavaProject extends LegacyJavaProject { () -> new MavenProjectClasspath(maven, pom), fileBasedCache ); - return new MavenJavaProject(fileObserver, projectDataCache, classpath, pom); + return new MavenJavaProject(fileObserver, projectDataCache, classpath, pom, javadocService); } - public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom) { - MavenJavaProject thiss = create(fileObserver, maven, pom, null); + public static MavenJavaProject create(FileObserver fileObserver, MavenCore maven, File pom, JavadocService javadocService) { + MavenJavaProject thiss = create(fileObserver, maven, pom, null, javadocService); if (!thiss.getClasspath().isCached()) { try { thiss.getClasspath().update(); } catch (Exception e) { - Log.log(e); + log.error("", e); } } return thiss; diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java index 6dad6c2f1..e8a5de70f 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 Pivotal, Inc. + * Copyright (c) 2016, 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 @@ -17,6 +17,7 @@ import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.MessageType; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; import org.springframework.ide.vscode.commons.languageserver.java.AbstractFileToProjectCache; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException; import org.springframework.ide.vscode.commons.maven.MavenCore; @@ -28,10 +29,12 @@ import org.springframework.ide.vscode.commons.maven.MavenCore; public class MavenProjectCache extends AbstractFileToProjectCache { private MavenCore maven; - - public MavenProjectCache(Sts4LanguageServer server, MavenCore maven, boolean asyncUpdate, Path projectCacheFolder) { + private JavadocService javadocService; + + public MavenProjectCache(Sts4LanguageServer server, MavenCore maven, boolean asyncUpdate, Path projectCacheFolder, JavadocService javadocService) { super(server, asyncUpdate, projectCacheFolder); this.maven = maven; + this.javadocService = javadocService; } @Override @@ -48,9 +51,10 @@ public class MavenProjectCache extends AbstractFileToProjectCache JavaDocProviders.createFor(cpe)); } catch (Exception e) { return null; } diff --git a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java index 6fca11381..665872e3f 100644 --- a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java +++ b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/JavaIndexTest.java @@ -32,6 +32,7 @@ import org.springframework.ide.vscode.commons.java.IMethod; 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.javadoc.JavaDocProviders; import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject; import org.springframework.ide.vscode.commons.util.BasicFileObserver; @@ -51,7 +52,7 @@ public class JavaIndexTest { 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 MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile(), (uri, cpe) -> JavaDocProviders.createFor(cpe)); } }); diff --git a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java index ac665d248..e7c840324 100644 --- a/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java +++ b/headless-services/commons/commons-maven/src/test/java/org/springframework/ide/vscode/commons/maven/MavenProjectCacheTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -44,6 +44,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.ide.vscode.commons.java.ClasspathFileBasedCache; import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.javadoc.JavaDocProviders; import org.springframework.ide.vscode.commons.languageserver.DiagnosticService; import org.springframework.ide.vscode.commons.languageserver.ProgressService; import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer; @@ -59,7 +60,7 @@ import com.google.common.collect.ImmutableList; /** * Tests for {@link MavenProjectCache} - * + * * @author Alex Boyko * */ @@ -109,7 +110,7 @@ public class MavenProjectCacheTest { @Test public void testPomFileChanges() throws Exception { - MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), false, null); + MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); IJavaProject[] projectChanged = new IJavaProject[] { null }; IJavaProject[] projectDeleted = new IJavaProject[] { null }; cache.addListener(new Listener() { @@ -175,7 +176,7 @@ public class MavenProjectCacheTest { assertFalse(classpathCacheFile.exists()); - MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder); + MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder, (uri, cpe) -> JavaDocProviders.createFor(cpe)); MavenJavaProject project = cache.project(pomFile); assertTrue(project.getClasspath().getClasspathEntries().isEmpty()); @@ -195,7 +196,7 @@ public class MavenProjectCacheTest { progressDone.set(false); // Reset the cache - cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder); + cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder, (uri, cpe) -> JavaDocProviders.createFor(cpe)); // Check loaded from cache file project = cache.project(pomFile); @@ -225,7 +226,7 @@ public class MavenProjectCacheTest { DiagnosticService diagnosticService = mock(DiagnosticService.class); when(server.getDiagnosticService()).thenReturn(diagnosticService); - MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder); + MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder, (uri, cpe) -> JavaDocProviders.createFor(cpe)); MavenJavaProject project = cache.project(pomFile); assertTrue(project.getClasspath().getClasspathEntries().isEmpty()); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/BootLanguageServerParams.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/BootLanguageServerParams.java index d0e69a23c..327876984 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/BootLanguageServerParams.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/BootLanguageServerParams.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -18,8 +18,9 @@ import java.util.Optional; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider; import org.springframework.ide.vscode.boot.java.utils.SpringLiveHoverWatchdog; -import org.springframework.ide.vscode.boot.jdt.ls.JdtLsProjectCache; import org.springframework.ide.vscode.boot.jdt.ls.JavaProjectsService; +import org.springframework.ide.vscode.boot.jdt.ls.JavaProjectsServiceWithFallback; +import org.springframework.ide.vscode.boot.jdt.ls.JdtLsProjectCache; import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider; import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider; import org.springframework.ide.vscode.boot.metadata.types.TypeUtil; @@ -29,11 +30,14 @@ import org.springframework.ide.vscode.commons.gradle.GradleProjectCache; import org.springframework.ide.vscode.commons.gradle.GradleProjectFinder; import org.springframework.ide.vscode.commons.java.BootProjectUtil; import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.java.IJavadocProvider; +import org.springframework.ide.vscode.commons.javadoc.JavaDocProviders; import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.java.CompositeProjectOvserver; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; -import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener; +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.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.maven.MavenCore; @@ -83,7 +87,11 @@ public class BootLanguageServerParams { public static LSFactory createDefault() { return (SimpleLanguageServer server) -> { // Initialize project finders, project caches and project observers - JdtLsProjectCache jdtProjectCache = new JdtLsProjectCache(server, () -> createFallbackProjectCache(server)); + JavaProjectsService jdtProjectCache = new JavaProjectsServiceWithFallback( + server, + new JdtLsProjectCache(server), + () -> createFallbackProjectCache(server) + ); DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(jdtProjectCache, jdtProjectCache); indexProvider.setProgressService(server.getProgressService()); @@ -101,10 +109,12 @@ public class BootLanguageServerParams { private static JavaProjectsService createFallbackProjectCache(SimpleLanguageServer server) { CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder(); - MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER)); + JavadocService javadocService = (uri, cpe) -> JavaDocProviders.createFor(cpe); + + MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER), javadocService); javaProjectFinder.addJavaProjectFinder(new MavenProjectFinder(mavenProjectCache)); - GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER)); + GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER), javadocService); javaProjectFinder.addJavaProjectFinder(new GradleProjectFinder(gradleProjectCache)); CompositeProjectOvserver projectObserver = new CompositeProjectOvserver(Arrays.asList(mavenProjectCache, gradleProjectCache)); @@ -125,6 +135,11 @@ public class BootLanguageServerParams { public Optional find(TextDocumentIdentifier doc) { return javaProjectFinder.find(doc); } + + @Override + public IJavadocProvider javadocProvider(String projectUri, CPE cpe) { + return javadocService.javadocProvider(projectUri, cpe); + } }; } @@ -132,11 +147,11 @@ public class BootLanguageServerParams { return (SimpleLanguageServer server) -> { // Initialize project finders, project caches and project observers CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder(); - MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), false, null); + MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); mavenProjectCache.setAlwaysFireEventOnFileChanged(true); javaProjectFinder.addJavaProjectFinder(new MavenProjectFinder(mavenProjectCache)); - GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), false, null); + GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); gradleProjectCache.setAlwaysFireEventOnFileChanged(true); javaProjectFinder.addJavaProjectFinder(new GradleProjectFinder(gradleProjectCache)); @@ -157,11 +172,11 @@ public class BootLanguageServerParams { return (SimpleLanguageServer server) -> { // Initialize project finders, project caches and project observers CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder(); - MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), false, null); + MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); mavenProjectCache.setAlwaysFireEventOnFileChanged(true); javaProjectFinder.addJavaProjectFinder(new MavenProjectFinder(mavenProjectCache)); - GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), false, null); + GradleProjectCache gradleProjectCache = new GradleProjectCache(server, GradleCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe)); gradleProjectCache.setAlwaysFireEventOnFileChanged(true); javaProjectFinder.addJavaProjectFinder(new GradleProjectFinder(gradleProjectCache)); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/RawJavadoc.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/InitializableJavaProjectsService.java similarity index 50% rename from headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/RawJavadoc.java rename to headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/InitializableJavaProjectsService.java index 6ddb2752b..bc34babfd 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/javadoc/RawJavadoc.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/InitializableJavaProjectsService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * 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 @@ -8,27 +8,12 @@ * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ +package org.springframework.ide.vscode.boot.jdt.ls; -package org.springframework.ide.vscode.commons.javadoc; +import reactor.core.Disposable; -import org.springframework.ide.vscode.commons.util.Renderable; - -public class RawJavadoc implements IJavadoc { +public interface InitializableJavaProjectsService extends JavaProjectsService { - private String rawContent; - - public RawJavadoc(String rawContent) { - this.rawContent = rawContent; - } - - @Override - public String raw() { - return rawContent; - } - - @Override - public Renderable getRenderable() { - throw new UnsupportedOperationException("Not yet implemented"); - } + Disposable initialize() throws Exception; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsService.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsService.java index 7eb1e5c8a..5063d71a8 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsService.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsService.java @@ -11,7 +11,8 @@ package org.springframework.ide.vscode.boot.jdt.ls; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.java.JavadocService; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; -public interface JavaProjectsService extends JavaProjectFinder, ProjectObserver { +public interface JavaProjectsService extends JavaProjectFinder, ProjectObserver, JavadocService { } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java new file mode 100644 index 000000000..7b24149d8 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * 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.boot.jdt.ls; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.commons.java.IJavaProject; +import org.springframework.ide.vscode.commons.java.IJavadocProvider; +import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.util.Assert; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + +import reactor.core.Disposable; + +public class JavaProjectsServiceWithFallback implements JavaProjectsService { + + private Logger log = LoggerFactory.getLogger(JavaProjectsServiceWithFallback.class); + + final private CompletableFuture initialized = new CompletableFuture(); + + final private SimpleLanguageServer server; + private Supplier fallback; + final private InitializableJavaProjectsService main; + + public JavaProjectsServiceWithFallback(SimpleLanguageServer server, InitializableJavaProjectsService main, Supplier fallback) { + Assert.isNotNull(fallback); + this.main = main; + this.fallback = Suppliers.memoize(fallback); + this.server = server; + CompletableFuture disposable = new CompletableFuture(); + this.server.onInitialized(() -> { + try { + disposable.complete(main.initialize()); + initialized.complete(null); + } catch (Throwable e) { + log.info("Fallback classpath provider will be enabled"); + disposable.complete(()-> {}); + initialized.completeExceptionally(e); + } + }); + this.server.onShutdown(() -> + disposable.thenAccept(Disposable::dispose).join() + ); + } + + @Override + public Optional find(TextDocumentIdentifier doc) { + if (initialized.isDone()) { + if (initialized.isCompletedExceptionally()) { + return fallback.get().find(doc); + } else { + return main.find(doc); + } + } else { + log.debug("find => NOT INITIALIZED YET"); + } + log.debug("NOT FOUND {} ", doc.getUri()); + return Optional.empty(); + } + + @Override + public void addListener(Listener listener) { + initialized.handle((success, failed) -> { + if (failed!=null) { + fallback.get().addListener(listener); + } else { + main.addListener(listener); + } + return null; + }); + } + + @Override + public void removeListener(Listener listener) { + initialized.handle((success, failed) -> { + if (failed!=null) { + fallback.get().removeListener(listener); + } else { + main.removeListener(listener); + } + return null; + }); + } + + @Override + public IJavadocProvider javadocProvider(String projectUri, CPE classpathEntry) { + if (initialized.isDone()) { + if (initialized.isCompletedExceptionally()) { + return fallback.get().javadocProvider(projectUri, classpathEntry); + } else { + return main.javadocProvider(projectUri, classpathEntry); + } + } else { + log.debug("javadoc => NOT INITIALIZED YET"); + } + return IJavadocProvider.NULL; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java index ed1618537..8d7d3dcf7 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JdtLsProjectCache.java @@ -21,101 +21,33 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ide.vscode.commons.jandex.JandexIndex.JavadocProviderFactory; import org.springframework.ide.vscode.commons.java.ClasspathData; 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.javadoc.JdtLsJavadocProvider; -import org.springframework.ide.vscode.commons.languageserver.JavadocParams; import org.springframework.ide.vscode.commons.languageserver.jdt.ls.Classpath.CPE; import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListener; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; -import org.springframework.ide.vscode.commons.util.Assert; 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; -import com.google.common.base.Suppliers; - import reactor.core.Disposable; -public class JdtLsProjectCache implements JavaProjectsService { +public class JdtLsProjectCache implements InitializableJavaProjectsService { - private CompletableFuture initialized = new CompletableFuture(); - private SimpleLanguageServer server; private Map table = new HashMap(); private Logger log = LoggerFactory.getLogger(JdtLsProjectCache.class); private List listeners = new ArrayList<>(); - private final Supplier fallback; - - public JdtLsProjectCache(SimpleLanguageServer server, Supplier fallback) { - Assert.isNotNull(fallback); - this.fallback = Suppliers.memoize(fallback); + public JdtLsProjectCache(SimpleLanguageServer server) { this.server = server; - CompletableFuture disposable = new CompletableFuture(); - this.server.onInitialized(() -> { - try { - disposable.complete(server.addClasspathListener(new ClasspathListener() { - @Override - public void changed(Event event) { - log.debug("claspath event received {}", event); - initialized.thenRun(() -> { - //log.info("initialized.thenRun block entered"); - try { - synchronized (table) { - String uri = UriUtil.normalize(event.projectUri); - log.debug("uri = {}", uri); - if (event.deleted) { - log.debug("event.deleted = true"); - JavaProject deleted = table.remove(uri); - if (deleted!=null) { - log.debug("removed from table = true"); - notifyDelete(deleted); - } else { - log.warn("Deleted project not removed because uri {} not found in {}", uri, table.keySet()); - } - } else { - log.debug("deleted = false"); - JdtLsJavadocProvider javadocProvider = new JdtLsJavadocProvider(server.getClient(), uri); - JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()), classpathResource -> javadocProvider); - JavaProject oldProject = table.put(uri, newProject); - if (oldProject != null) { - notifyChanged(newProject); - } else { - notifyCreated(newProject); - } - } - } - } catch (Exception e) { - log.error("", e); - } - }); - } - })); - initialized.complete(null); - } catch (Throwable e) { - if (isNoJdtError(e)) { - log.info("JDT Language Server not available. Fallback classpath provider will be used instead."); - } else if (isOldJdt(e)) { - log.info("JDT Lanuage Server too old. Fallback classpath provider will be used instead."); - } else { - log.error("Unexpected error registering classpath listener with JDT. Fallback classpath provider will be used instead.", e); - } - disposable.complete(()-> {}); - initialized.completeExceptionally(e); - } - }); - this.server.onShutdown(() -> - disposable.thenAccept(Disposable::dispose).join() - ); } private FileObserver getFileObserver() { @@ -132,30 +64,16 @@ public class JdtLsProjectCache implements JavaProjectsService { @Override public void addListener(Listener listener) { - initialized.handle((success, failed) -> { - if (failed!=null) { - fallback.get().addListener(listener); - } else { - synchronized (listeners) { - listeners.add(listener); - } - } - return null; - }); + synchronized (listeners) { + listeners.add(listener); + } } @Override public void removeListener(Listener listener) { - initialized.handle((success, failed) -> { - if (failed!=null) { - fallback.get().removeListener(listener); - } else { - synchronized (listeners) { - listeners.remove(listener); - } - } - return null; - }); + synchronized (listeners) { + listeners.remove(listener); + } } private void notifyCreated(JavaProject newProject) { @@ -215,28 +133,72 @@ public class JdtLsProjectCache implements JavaProjectsService { public Optional find(TextDocumentIdentifier doc) { String uri = UriUtil.normalize(doc.getUri()); log.debug("find {} ", uri); - if (initialized.isDone()) { - if (initialized.isCompletedExceptionally()) { - log.debug("find {} delegating to fallback", uri); - Optional result = fallback.get().find(doc); - log.debug("find => {}", result); - return result; - } - - synchronized (table) { - for (Entry e : table.entrySet()) { - String projectUri = e.getKey(); - log.debug("projectUri = '{}'", projectUri); - if (UriUtil.contains(projectUri, uri) ) { - log.debug("found {} for {}", e.getValue(), uri); - return Optional.of(e.getValue()); - } + synchronized (table) { + for (Entry e : table.entrySet()) { + String projectUri = e.getKey(); + log.debug("projectUri = '{}'", projectUri); + if (UriUtil.contains(projectUri, uri)) { + log.debug("found {} for {}", e.getValue(), uri); + return Optional.of(e.getValue()); } } - } else { - log.debug("find => NOT INITIALIZED YET"); } - log.debug("NOT FOUND {} ", uri); return Optional.empty(); } + + @Override + public IJavadocProvider javadocProvider(String projectUri, CPE classpathEntry) { + return new JdtLsJavadocProvider(server.getClient(), projectUri); + } + + @Override + public Disposable initialize() throws Exception { + try { + return server.addClasspathListener(new ClasspathListener() { + @Override + public void changed(Event event) { + log.debug("claspath event received {}", event); + server.onInitialized(() -> { + //log.info("initialized.thenRun block entered"); + try { + synchronized (table) { + String uri = UriUtil.normalize(event.projectUri); + log.debug("uri = {}", uri); + if (event.deleted) { + log.debug("event.deleted = true"); + JavaProject deleted = table.remove(uri); + if (deleted!=null) { + log.debug("removed from table = true"); + notifyDelete(deleted); + } else { + log.warn("Deleted project not removed because uri {} not found in {}", uri, table.keySet()); + } + } else { + log.debug("deleted = false"); + JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()), JdtLsProjectCache.this); + JavaProject oldProject = table.put(uri, newProject); + if (oldProject != null) { + notifyChanged(newProject); + } else { + notifyCreated(newProject); + } + } + } + } catch (Exception e) { + log.error("", e); + } + }); + } + }); + } catch (Throwable t) { + if (isNoJdtError(t)) { + log.info("JDT Language Server not available. Fallback classpath provider will be used instead."); + } else if (isOldJdt(t)) { + log.info("JDT Lanuage Server too old. Fallback classpath provider will be used instead."); + } else { + log.error("Unexpected error registering classpath listener with JDT. Fallback classpath provider will be used instead.", t); + } + throw t; + } + } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java index 3b048f37b..7852fdd9b 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/VSCodeSourceLinksTest.java @@ -21,11 +21,11 @@ import java.util.Optional; import org.junit.Test; import org.springframework.ide.vscode.boot.java.links.VSCodeSourceLinks; +import org.springframework.ide.vscode.commons.javadoc.JavaDocProviders; 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; @@ -45,8 +45,10 @@ 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 MavenJavaProject.create(new BasicFileObserver(), MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); - } + return MavenJavaProject.create(new BasicFileObserver(), MavenCore.getDefault(), + testProjectPath.resolve(MavenCore.POM_XML).toFile(), + (uri, cpe) -> JavaDocProviders.createFor(cpe)); + } }); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java index 7d93071e1..88012b7af 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 Pivotal, Inc. + * Copyright (c) 2016, 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 @@ -22,6 +22,7 @@ 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.LegacyJavaProject; +import org.springframework.ide.vscode.commons.javadoc.JavaDocProviders; 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; @@ -89,7 +90,8 @@ public class ProjectsHarness { } public static final IJavaProject dummyProject() throws URISyntaxException { - return new LegacyJavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), null, new DelegatingCachedClasspath(() -> null, null)); + return new LegacyJavaProject(new BasicFileObserver(), new URI("file:///someplace/nonexistent"), null, + new DelegatingCachedClasspath(() -> null, null), (uri, cpe) -> JavaDocProviders.createFor(cpe)); } private ProjectsHarness(FileObserver fileObserver) { @@ -111,7 +113,8 @@ public class ProjectsHarness { switch (type) { case MAVEN: MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute(); - return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile()); + return MavenJavaProject.create(fileObserver, MavenCore.getDefault(), + testProjectPath.resolve(MavenCore.POM_XML).toFile(), (uri, cpe) -> JavaDocProviders.createFor(cpe)); default: throw new IllegalStateException("Bug!!! Missing case"); }