Conversation
| builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))"); | ||
| // builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))"); | ||
| builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "); | ||
| builder.append(jarNames.stream().map(jarName -> '"' + jarName + '"').collect(joining(", "))); |
There was a problem hiding this comment.
jarNames is constructed from ClasspathJarNameDetector. Do we need to check if the resulting list is correct and complete, including dependencies from type tables?
| if ((matcher = JavaTemplate | ||
| .builder("String.format(\"\\\"%s\\\"\", com.sun.tools.javac.util.Convert.quote(#{value:any(java.lang.String)}))") | ||
| .javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath())) | ||
| .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "tools")) |
There was a problem hiding this comment.
How do we "know" that tools is in fact on the classpath or in a type table?
How do we handle situations where the names listed do not match the class path/typetables?
|
There are several tests for |
src/main/java/org/openrewrite/java/template/internal/TemplateCode.java
Outdated
Show resolved
Hide resolved
diff --git c/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java i/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java index a9a22d2..58f1dea 100644 --- c/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java +++ i/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java @@ -68,12 +68,9 @@ public class TemplateCode { jarNames.addAll(ClasspathJarNameDetector.classpathFor(parameter, ImportDetector.imports(parameter))); } if (!jarNames.isEmpty()) { - // It might be preferable to enumerate exactly the needed dependencies rather than the full classpath - // But this is expedient - // See #86 - // String classpath = jarNames.stream().map(jarName -> '"' + jarName + '"').sorted().collect(joining(", ")); - // builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpath(").append(classpath).append("))"); - builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpath(JavaParser.runtimeClasspath()))"); + builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "); + builder.append(jarNames.stream().map(jarName -> '"' + jarName + '"').collect(joining(", "))); + builder.append("))\n "); } return builder.toString(); } catch (IOException e) {
diff --git c/src/main/java/org/openrewrite/java/template/internal/ClasspathJarNameDetector.java i/src/main/java/org/openrewrite/java/template/internal/ClasspathJarNameDetector.java index ab59a8a..8a4b126 100644 --- c/src/main/java/org/openrewrite/java/template/internal/ClasspathJarNameDetector.java +++ i/src/main/java/org/openrewrite/java/template/internal/ClasspathJarNameDetector.java @@ -19,6 +19,7 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.TreeScanner; +import org.jspecify.annotations.Nullable; import javax.tools.JavaFileObject; import java.util.LinkedHashSet; @@ -38,7 +39,7 @@ public class ClasspathJarNameDetector { public static Set<String> classpathFor(JCTree input, List<Symbol> imports) { Set<String> jarNames = new LinkedHashSet<String>() { @OverRide - public boolean add(String s) { + public boolean add(@nullable String s) { return s != null && super.add(s); } }; @@ -64,7 +65,7 @@ public class ClasspathJarNameDetector { } - private static String jarNameFor(Symbol anImport) { + private static @nullable String jarNameFor(Symbol anImport) { Symbol.ClassSymbol enclClass = anImport instanceof Symbol.ClassSymbol ? (Symbol.ClassSymbol) anImport : anImport.enclClass(); while (enclClass.enclClass() != null && enclClass.enclClass() != enclClass) { enclClass = enclClass.enclClass(); diff --git c/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java i/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java index 58f1dea..337a65a 100644 --- c/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java +++ i/src/main/java/org/openrewrite/java/template/internal/TemplateCode.java @@ -68,9 +68,11 @@ public class TemplateCode { jarNames.addAll(ClasspathJarNameDetector.classpathFor(parameter, ImportDetector.imports(parameter))); } if (!jarNames.isEmpty()) { - builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "); - builder.append(jarNames.stream().map(jarName -> '"' + jarName + '"').collect(joining(", "))); - builder.append("))\n "); + String joinedJarNames = jarNames.stream().collect(joining(", ", "\"", "\"")); + builder.append("\n .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, ") + .append(joinedJarNames) + .append("))\n "); + } return builder.toString(); } catch (IOException e) {
643ef43 to
fc56e32
Compare
classpathFromResource in Refaster templates
classpathFromResource in Refaster templatesclasspathFromResources in recipes generated for Refaster rules
src/main/java/org/openrewrite/java/template/processor/TemplateDescriptor.java
Outdated
Show resolved
Hide resolved
|
If I understand this PR correctly, then it just assumes that whatever dependencies are referenced via types in the Refaster template are also present in the jars / type tables of the recipe artifact's resources. I think this seems reasonable. We should however also make an effort to check that any of the types which are directly referenced by the referenced classes are also loaded. So if we for example reference a |
src/main/java/org/openrewrite/java/template/processor/TemplateProcessor.java
Outdated
Show resolved
Hide resolved
| if (numberOfArguments < 3 || 4 < numberOfArguments) { | ||
| return; | ||
| } | ||
| boolean classpathFromResources = numberOfArguments == 4; |
There was a problem hiding this comment.
From the usage site of Semantics you can pass in an initial ExecutionContext where possible to determine if classpathFromResources should be used. This is preferable over a annotation processor option here, as not all usage sites have access to an ExecutionContext, as seen here:
https://github.com/openrewrite/rewrite-apache/blob/df33d276534aaaea4c2f2f93ad681954084e09b2/src/main/java/org/openrewrite/apache/commons/lang/IsNotEmptyToJdk.java#L74-L77
It's also not necessary to pass in an ExecutionContext for every type of use, as seen here for the standard JDK class:
https://github.com/openrewrite/rewrite-migrate-java/blob/6b98403236ad24c7d949750cd1c7af5fb94eebd8/src/main/java/org/openrewrite/java/migrate/UseJavaUtilBase64.java#L126-L127
| JavaTemplate.Builder logger = Semantics.expression(ctx, this, "logger", (String s) -> LoggerFactory.getLogger(s)); | ||
| JavaTemplate.Builder info = Semantics.statement(ctx, this, "info", (Logger l, String s) -> l.info(s)); |
There was a problem hiding this comment.
This shows intended use when you do want to pass in an ExecutionContext.
…untimeclasspath-in-remaster-templates
What's changed?
Changed implementation in TemplateCode when generating refaster recipes to use classPathFromResource
What's your motivation?
Ensures Refaster template based recipes are able to match and use external types when running outside of build plugins.