From 7e43e28509c36e47e4dc587af793f5168faa5956 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 4 Aug 2022 14:56:37 -0400 Subject: [PATCH] Ensure Rewrite java parser is cached where possible --- .../commons/rewrite/java/ORAstUtils.java | 12 ++- .../rewrite/RewriteCompilationUnitCache.java | 74 ++++++++++++------- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/ORAstUtils.java b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/ORAstUtils.java index f5ab8e47d..32fb87cb7 100644 --- a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/ORAstUtils.java +++ b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/java/ORAstUtils.java @@ -30,6 +30,7 @@ import org.openrewrite.TreeVisitor; import org.openrewrite.internal.RecipeIntrospectionUtils; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaParsingException; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.UpdateSourcePositions; import org.openrewrite.java.tree.J; @@ -219,7 +220,7 @@ public class ORAstUtils { // } public static List parse(JavaParser parser, Iterable sourceFiles) { - InMemoryExecutionContext ctx = new InMemoryExecutionContext(e -> log.error("", e)); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing); // ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true); List cus = parser.parse(sourceFiles, null, ctx); List results = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus); @@ -227,12 +228,19 @@ public class ORAstUtils { } public static List parseInputs(JavaParser parser, Iterable inputs) { - InMemoryExecutionContext ctx = new InMemoryExecutionContext(e -> log.error("", e)); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing); // ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true); List cus = parser.parseInputs(inputs, null, ctx); List results = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus); return results.stream().map(r -> r.getAfter() == null ? r.getBefore() : r.getAfter()).map(CompilationUnit.class::cast).collect(Collectors.toList()); } + + private static void logExceptionWhileParsing(Throwable t) { + if (!(t instanceof JavaParsingException || t instanceof StringIndexOutOfBoundsException)) { + // Do not log parse exceptions. Can be too many while user is typing code + log.error("", t); + } + } public static J.EnumValueSet getEnumValues(J.ClassDeclaration classDecl) { return classDecl.getBody().getStatements().stream() diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteCompilationUnitCache.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteCompilationUnitCache.java index 4a9185039..db28b4024 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteCompilationUnitCache.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteCompilationUnitCache.java @@ -48,6 +48,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.UncheckedExecutionException; import reactor.core.Disposable; @@ -180,10 +181,14 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis uriToCu.invalidate(uri); Optional project = projectFinder.find(new TextDocumentIdentifier(uriStr)); if (project.isPresent()) { - JavaParser parser = javaParsers.getIfPresent(project.get()); - if (parser != null) { - parser.reset(); - } + + //TODO There seems to be an issue with java parser #reset() call. After resetting it + // still complains that it needs to be reset +// JavaParser parser = javaParsers.getIfPresent(project.get()); +// if (parser != null) { +// parser.reset(); +// } + javaParsers.invalidate(project.get()); } } } @@ -217,33 +222,50 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis try { if (project != null) { synchronized (URI_TO_CU_LOCK) { - return uriToCu.get(uri, () -> { - logger.debug("Parsing CU {}", uri); - JavaParser javaParser = /*loadJavaParser(project)*/createJavaParser(project); - Input input = new Input(Paths.get(uri), () -> { + try { + return uriToCu.get(uri, () -> { + boolean newParser = javaParsers.getIfPresent(project) == null; try { - return new ByteArrayInputStream(fetchContent(uri).getBytes()); + logger.debug("Parsing CU {}", uri); + JavaParser javaParser = loadJavaParser(project); + Input input = new Input(Paths.get(uri), () -> { + try { + return new ByteArrayInputStream(fetchContent(uri).getBytes()); + } catch (Exception e) { + throw new IllegalStateException("Unexpected error fetching document content"); + } + }); + + List cus = ORAstUtils.parseInputs(javaParser, List.of(input)); + + CompilationUnit cu = cus.get(0); + + if (cu != null) { + projectToDocs.get(project, () -> new HashSet<>()).add(uri); + return cu; + } else { + throw new IllegalStateException("Failed to parse Java source"); + } } catch (Exception e) { - throw new IllegalStateException("Unexpected error fetching document content"); + if (newParser) { + javaParsers.invalidate(project); + } + throw e; } - }); - - CompilationUnit cu = null; - try { - List cus = ORAstUtils.parseInputs(javaParser, List.of(input)); - - cu = cus.get(0); - - if (cu != null) { - projectToDocs.get(project, () -> new HashSet<>()).add(uri); - } - } catch (Exception e) { - // ignore rewrite parse errors + }); + } catch (UncheckedExecutionException e1) { + if (e1.getCause() instanceof IllegalStateException) { + logger.error("", e1); + } else { + // ignore errors from rewrite parser. There could be many parser exceptions due to + // user incrementally typing code's text } - - return cu; - }); + return null; + } catch (Exception e) { + logger.error("", e); + return null; + } } } } catch (Exception e) {