Adopt Rewrite changes around JavaSourceSet

This commit is contained in:
aboyko
2023-04-17 12:39:43 -04:00
parent a6fcbd5326
commit 2cc2617516
4 changed files with 100 additions and 19 deletions

View File

@@ -24,15 +24,21 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.openrewrite.Tree;
import org.openrewrite.Parser.Input;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.utils.DocumentContentProvider;
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;
@@ -65,6 +71,8 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
private final Cache<URI, Set<URI>> projectToDocs;
private final Cache<URI, JavaParser> javaParsers;
private final Cache<URI, List<JavaType.FullyQualified>> sourceSetClasspath;
public RewriteCompilationUnitCache(JavaProjectFinder projectFinder, SimpleLanguageServer server, ProjectObserver projectObserver) {
// this.projectFinder = projectFinder;
this.projectObserver = projectObserver;
@@ -100,7 +108,17 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
.build();
this.projectToDocs = CacheBuilder.newBuilder().build();
this.javaParsers = CacheBuilder.newBuilder().build();
this.javaParsers = CacheBuilder.newBuilder()
.removalListener(new RemovalListener<URI, JavaParser>() {
@Override
public void onRemoval(RemovalNotification<URI, JavaParser> notification) {
sourceSetClasspath.invalidate(notification.getKey());
}
})
.build();
this.sourceSetClasspath = CacheBuilder.newBuilder().build();
this.documentService = server == null ? null : server.getTextDocumentService();
@@ -222,14 +240,13 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
}
private CompilationUnit doParse(IJavaProject project, URI uri) throws Exception {
boolean newParser = javaParsers.getIfPresent(project) == null;
JavaParser javaParser = null;;
boolean newParser = javaParsers.getIfPresent(project.getLocationUri()) == null;
JavaParser javaParser = null;
try {
logger.debug("Parsing CU {}", uri);
javaParser = loadJavaParser(project);
Path sourcePath = Paths.get(uri);
javaParser.setSourceSet(ORAstUtils.getSourceSetName(project, sourcePath));
Input input = new Input(sourcePath, () -> {
try {
@@ -241,6 +258,10 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser, List.of(input), null);
CompilationUnit cu = cus.get(0);
// Manually add source set
JavaSourceSet sourceSet = createSourceSet(project, ORAstUtils.getSourceSetName(project, sourcePath));
cu = cu.withMarkers(cu.getMarkers().computeByType(sourceSet, (original, updated) -> updated));
if (cu != null) {
projectToDocs.get(project.getLocationUri(), () -> new HashSet<>()).add(uri);
return cu;
@@ -259,6 +280,20 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
}
}
private JavaSourceSet createSourceSet(IJavaProject project, String name) {
List<FullyQualified> fqNames;
try {
fqNames = sourceSetClasspath.get(project.getLocationUri(), () -> {
List<Path> classpath = IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath()).collect(Collectors.toList());
return JavaSourceSet.build("", classpath, null, false).getClasspath();
});
} catch (ExecutionException e) {
logger.error("", e);
fqNames = Collections.emptyList();
}
return new JavaSourceSet(Tree.randomId(), name, fqNames);
}
/**
* Does not need to be via callback - kept the same in order to keep the same API to replace JDT with Rewrite in distant future
*/

View File

@@ -28,7 +28,9 @@ import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.Tree;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.marker.Marker;
@@ -157,11 +159,16 @@ public class RewriteReconciler implements JavaReconciler {
}
}
JavaParser javaParser = ORAstUtils.createJavaParser(project);
javaParser.setSourceSet(MavenProjectParser.MAIN);
allProblems.putAll(doReconcile(project, mainSources, javaParser, incrementProgress));
javaParser.setSourceSet(MavenProjectParser.TEST);
allProblems.putAll(doReconcile(project, testSources, javaParser, incrementProgress));
List<Path> classpath = IClasspathUtil.getAllBinaryRoots(project.getClasspath()).stream().map(f -> f.toPath()).collect(Collectors.toList());
JavaParser javaParser = ORAstUtils.createJavaParser(() -> JavaParser.fromJavaVersion().classpath(classpath));
// Pass in source sets created from classpath. (Perhaps it is a good idea to have separate classpath and parsers for test and main, TBD)
// Perhaps it is even better to create empty classpath java source sets as reconcile step seem to only need name of the java source set
// Usually java source set classpath is required to figure out how to organize imports for sources
JavaSourceSet mainJavaSourceSet = JavaSourceSet.build(MavenProjectParser.MAIN, classpath, null, false);
JavaSourceSet testJavaSourceSet = new JavaSourceSet(Tree.randomId(), MavenProjectParser.TEST, mainJavaSourceSet.getClasspath());
allProblems.putAll(doReconcile(project, mainSources, javaParser, mainJavaSourceSet, incrementProgress));
allProblems.putAll(doReconcile(project, testSources, javaParser, testJavaSourceSet, incrementProgress));
long end = System.currentTimeMillis();
log.info("reconciling project (OpenRewrite): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
@@ -242,7 +249,7 @@ public class RewriteReconciler implements JavaReconciler {
private static final int BATCH = 50;
// Parse in batches and share the parser
private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser, Runnable incrementProgress) {
private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser, JavaSourceSet javaSourceSet, Runnable incrementProgress) {
Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
if (javaParser != null && config.isRewriteReconcileEnabled()) {
try {
@@ -259,6 +266,8 @@ public class RewriteReconciler implements JavaReconciler {
return new ByteArrayInputStream(d.get().getBytes());
})).collect(Collectors.toList()), source -> incrementProgress.run());
cus = ListUtils.map(cus, cu -> cu.withMarkers(cu.getMarkers().computeByType(javaSourceSet, (original, updated) -> updated)));
/*
* If exception occurs during parsing inputs the list of inputs would become shorter than the list of corresponding documents
*/