From a50c09097a0d3f0357fcd0c3b28afd7c91a8e2d7 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Wed, 22 Nov 2017 14:20:31 -0500 Subject: [PATCH] PT #153100339 Don't cache CU unless there is a project for it --- .../boot/java/utils/CompilationUnitCache.java | 46 +++++++++--------- .../utils/test/CompilationUnitCacheTest.java | 47 +++++++++++++++++-- ...opertiesCompletionProposalsCalculator.java | 17 ++++--- .../commons/gradle/GradleProjectCache.java | 3 +- .../java/DelegatingCachedClasspath.java | 15 ++++-- .../commons/maven/java/MavenProjectCache.java | 3 +- .../commons/maven/MavenProjectCacheTest.java | 38 +++++++-------- 7 files changed, 108 insertions(+), 61 deletions(-) diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java index a3111cbc6..a35a14572 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java @@ -15,7 +15,6 @@ import java.nio.file.Path; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -31,7 +30,6 @@ 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; import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; -import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.text.TextDocument; @@ -87,18 +85,32 @@ public final class CompilationUnitCache { */ public T withCompilationUnit(TextDocument document, Function requestor) { URI uri = URI.create(document.getUri()); - readLock.lock(); - try { - CompilationUnit cu = uriToCu.get(uri, () -> parse(document)); - if (cu!=null) { - synchronized (cu.getAST()) { - return requestor.apply(cu); + IJavaProject project = projectFinder.find(document.getId()).orElse(null); + if (project != null) { + readLock.lock(); + try { + CompilationUnit cu = uriToCu.get(uri, () -> { + CompilationUnit cUnit = parse(document, project); + projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri())); + return cUnit; + }); + if (cu!=null) { + projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri())); + synchronized (cu.getAST()) { + return requestor.apply(cu); + } } + } catch (Exception e) { + Log.log(e); + } finally { + readLock.unlock(); + } + } else { + try { + return requestor.apply(parse(document, null)); + } catch (Exception e) { + Log.log(e); } - } catch (Exception e) { - Log.log(e); - } finally { - readLock.unlock(); } return requestor.apply(null); } @@ -137,16 +149,6 @@ public final class CompilationUnitCache { return cu; } - private CompilationUnit parse(TextDocument document) - throws Exception, BadLocationException { - IJavaProject project = projectFinder.find(document.getId()).orElse(null); - CompilationUnit cu = parse(document, project); - if (project != null) { - projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri())); - } - return cu; - } - private static String[] getClasspathEntries(TextDocument document, IJavaProject project) throws Exception { if (project == null) { return new String[0]; diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java index 367cfe26f..67d021f85 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java @@ -23,11 +23,12 @@ import java.nio.file.Paths; import org.eclipse.jdt.core.dom.CompilationUnit; import org.junit.Before; import org.junit.Test; -import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer; +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.maven.MavenCore; import org.springframework.ide.vscode.commons.util.text.LanguageId; import org.springframework.ide.vscode.commons.util.text.TextDocument; -import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness; import org.springframework.ide.vscode.project.harness.ProjectsHarness; @@ -39,7 +40,7 @@ import org.springframework.ide.vscode.project.harness.ProjectsHarness; */ public class CompilationUnitCacheTest { - private LanguageServerHarness harness; + private BootLanguageServerHarness harness; @Before public void setup() throws Exception { @@ -48,6 +49,14 @@ public class CompilationUnitCacheTest { @Test public void cu_cached() throws Exception { + harness = BootLanguageServerHarness.builder() + .mockDefaults().build(); + harness.useProject(new IJavaProject() { + @Override + public IClasspath getClasspath() { + return new DelegatingCachedClasspath<>(() -> null, null); + } + }); harness.intialize(null); TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" + @@ -62,12 +71,36 @@ public class CompilationUnitCacheTest { assertTrue(cu == cuAnother); } + @Test + public void cu_not_cached_without_project() throws Exception { + harness.intialize(null); + + TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" + + "\n" + + "public class SomeClass {\n" + + "\n" + + "}\n"); + CompilationUnit cu = getCompilationUnit(doc); + assertNotNull(cu); + + CompilationUnit cuAnother = getCompilationUnit(doc); + assertFalse(cu == cuAnother); + } + private CompilationUnit getCompilationUnit(TextDocument doc) { return harness.getServer().getCompilationUnitCache().withCompilationUnit(doc, cu -> cu); } @Test public void cu_cache_invalidated_by_doc_change() throws Exception { + harness = BootLanguageServerHarness.builder() + .mockDefaults().build(); + harness.useProject(new IJavaProject() { + @Override + public IClasspath getClasspath() { + return new DelegatingCachedClasspath<>(() -> null, null); + } + }); harness.intialize(null); TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" + @@ -91,6 +124,14 @@ public class CompilationUnitCacheTest { @Test public void cu_cache_invalidated_by_doc_close() throws Exception { + harness = BootLanguageServerHarness.builder() + .mockDefaults().build(); + harness.useProject(new IJavaProject() { + @Override + public IClasspath getClasspath() { + return new DelegatingCachedClasspath<>(() -> null, null); + } + }); harness.intialize(null); TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" + diff --git a/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java b/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java index 2b6ff9e5e..7ca069404 100644 --- a/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java +++ b/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java @@ -334,14 +334,19 @@ public class PropertiesCompletionProposalsCalculator { DocumentEdits docEdits; try { docEdits = LazyProposalApplier.from(() -> { - Type type = TypeParser.parse(match.data.getType()); - DocumentEdits edits = new DocumentEdits(doc); - edits.delete(offset-prefix.length(), offset); - edits.insert(offset, match.data.getId() + propertyCompletionPostfix(typeUtil, type)); - return edits; + try { + Type type = TypeParser.parse(match.data.getType()); + DocumentEdits edits = new DocumentEdits(doc); + edits.delete(offset-prefix.length(), offset); + edits.insert(offset, match.data.getId() + propertyCompletionPostfix(typeUtil, type)); + return edits; + } catch (Throwable t) { + Log.log(t); + return new DocumentEdits(doc); + } }); proposals.add(completionFactory.property(doc, docEdits, match, typeUtil)); - } catch (Exception e) { + } catch (Throwable e) { Log.log(e); } } 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 f494882c9..657a0cd66 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 @@ -51,8 +51,7 @@ public class GradleProjectCache extends AbstractFileToProjectCache implements IClasspath { public static final String CLASSPATH_DATA_CACHE_FILE = "classpath-data.json"; + private static final ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(), + Collections.emptySet(), null); private static final String OUTPUT_FOLDER_PROPERTY = "outputFolder"; private static final String CLASSPATH_RESOURCES_PROPERTY = "classpathResources"; @@ -238,15 +240,20 @@ public class DelegatingCachedClasspath implements IClasspa @Override public Flux allSubtypesOf(IType type) { - return cachedDelegate.get().allSubtypesOf(type); + T t = cachedDelegate.get(); + return t == null ? Flux.empty() : t.allSubtypesOf(type); } protected ClasspathData createClasspathData() throws Exception { T newDelegate = delegateCreator.call(); cachedDelegate.set(newDelegate); - LinkedHashSet classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries()); - return new ClasspathData(newDelegate.getName(), classpathEntries, - new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder()); + if (newDelegate == null) { + return EMPTY_CLASSPATH_DATA; + } else { + LinkedHashSet classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries()); + return new ClasspathData(newDelegate.getName(), classpathEntries, + new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder()); + } } } 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 2a237238b..19d451445 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 @@ -50,8 +50,7 @@ public class MavenProjectCache extends AbstractFileToProjectCache { while (!progressDone.get()) { @@ -195,7 +189,7 @@ public class MavenProjectCacheTest { }).get(10, TimeUnit.SECONDS); assertTrue(classpathCacheFile.exists()); - assertEquals(49, project.getClasspath().getClasspathEntries().size()); + assertEquals(48, project.getClasspath().getClasspathEntries().size()); progressDone.set(false); @@ -204,18 +198,7 @@ public class MavenProjectCacheTest { // Check loaded from cache file project = cache.project(pomFile); - assertEquals(49, project.getClasspath().getClasspathEntries().size()); - - // check async project update (no changes no project changed event) - CompletableFuture.runAsync(() -> { - while (!progressDone.get()) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }).get(10, TimeUnit.SECONDS); + assertEquals(48, project.getClasspath().getClasspathEntries().size()); } @Test @@ -243,8 +226,19 @@ public class MavenProjectCacheTest { MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder); MavenJavaProject project = cache.project(pomFile); - assertEquals(48, project.getClasspath().getClasspathEntries().size()); - + assertTrue(project.getClasspath().getClasspathEntries().isEmpty()); + + CompletableFuture.runAsync(() -> { + while (!progressDone.get()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }).get(10, TimeUnit.SECONDS); + progressDone.set(false); + verify(diagnosticService, never()).diagnosticEvent(any(ShowMessageException.class)); progressDone.set(false);