All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.java.template.internal.TemplateCode Maven / Gradle / Ivy

There is a newer version: 1.17.1
Show newest version
/*
 * Copyright 2023 the original author or authors.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openrewrite.java.template.internal; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.Pretty; import java.io.IOException; import java.io.StringWriter; import java.io.UncheckedIOException; import java.io.Writer; import java.util.*; import static java.util.stream.Collectors.joining; public class TemplateCode { public static String process(T tree, List parameters, boolean asStatement, boolean fullyQualified) { StringWriter writer = new StringWriter(); TemplateCodePrinter printer = new TemplateCodePrinter(writer, parameters, fullyQualified); try { if (asStatement) { printer.printStat(tree); } else { printer.printExpr(tree); } StringBuilder builder = new StringBuilder("JavaTemplate\n"); builder .append(" .builder(\"") .append(writer.toString() .replace("\\", "\\\\") .replace("\"", "\\\"") .replaceAll("\\R", "\\\\n")) .append("\")"); if (!printer.imports.isEmpty()) { builder.append("\n .imports(").append(printer.imports.stream().map(i -> '"' + i + '"').collect(joining(", "))).append(")"); } if (!printer.staticImports.isEmpty()) { builder.append("\n .staticImports(").append(printer.staticImports.stream().map(i -> '"' + i + '"').collect(joining(", "))).append(")"); } List imports = ImportDetector.imports(tree); Set jarNames = ClasspathJarNameDetector.classpathFor(tree, imports); for (JCTree.JCVariableDecl parameter : parameters) { 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 https://github.com/openrewrite/rewrite-templating/issues/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()))"); } return builder.toString(); } catch (IOException e) { throw new RuntimeException(e); } } public static String indent(String code, int width) { char[] indent = new char[width]; Arrays.fill(indent, ' '); String replacement = "$1" + new String(indent); return code.replaceAll("(?m)(\\R)", replacement); } private static class TemplateCodePrinter extends Pretty { private static final String PRIMITIVE_ANNOTATION = "org.openrewrite.java.template.Primitive"; private final List declaredParameters; private final boolean fullyQualified; private final Set seenParameters = new HashSet<>(); private final TreeSet imports = new TreeSet<>(); private final TreeSet staticImports = new TreeSet<>(); public TemplateCodePrinter(Writer writer, List declaredParameters, boolean fullyQualified) { super(writer, true); this.declaredParameters = declaredParameters; this.fullyQualified = fullyQualified; } @Override public void visitMethodDef(JCTree.JCMethodDecl tree) { if ((Flags.GENERATEDCONSTR & tree.getModifiers().flags) == 0L) { super.visitMethodDef(tree); } } @Override public void visitIdent(JCIdent jcIdent) { try { Symbol sym = jcIdent.sym; Optional param = declaredParameters.stream().filter(p -> p.sym == sym).findFirst(); if (param.isPresent()) { print("#{" + sym.name); if (seenParameters.add(param.get())) { Type type = param.get().sym.type; String typeString; if (type instanceof Type.ArrayType) { print(":anyArray(" + ((Type.ArrayType) type).elemtype.toString() + ")"); } else { if (param.get().getModifiers().getAnnotations().stream() .anyMatch(a -> a.attribute.type.tsym.getQualifiedName().toString().equals(PRIMITIVE_ANNOTATION))) { typeString = getUnboxedPrimitive(type.toString()); } else { typeString = type.toString(); } print(":any(" + typeString + ")"); } } print("}"); } else if (sym != null) { print(sym); } else { print(jcIdent.name); } } catch (IOException e) { throw new UncheckedIOException(e); } } void print(Symbol sym) throws IOException { if (sym instanceof Symbol.ClassSymbol) { if (fullyQualified) { print(sym.packge().fullname.contentEquals("java.lang") ? sym.name : sym.getQualifiedName()); } else { print(sym.name); if (!sym.packge().fullname.contentEquals("java.lang")) { imports.add(sym.getQualifiedName().toString()); } } } else if (sym instanceof Symbol.VarSymbol) { if (fullyQualified) { if (sym.owner instanceof Symbol.ClassSymbol) { print(sym.owner); print('.'); } print(sym.name); } else { print(sym.name); if (!sym.packge().fullname.contentEquals("java.lang")) { staticImports.add(sym.owner.getQualifiedName() + "." + sym.name); } } } else if (sym instanceof Symbol.MethodSymbol) { if (fullyQualified) { print(sym.owner); print('.'); print(sym.name); } else { print(sym.name); if (!sym.packge().fullname.contentEquals("java.lang")) { staticImports.add(sym.owner.getQualifiedName() + "." + sym.name); } } } else if (sym instanceof Symbol.PackageSymbol) { print(sym.getQualifiedName()); } } private String getUnboxedPrimitive(String paramType) { switch (paramType) { case "java.lang.Boolean": return "boolean"; case "java.lang.Byte": return "byte"; case "java.lang.Character": return "char"; case "java.lang.Double": return "double"; case "java.lang.Float": return "float"; case "java.lang.Integer": return "int"; case "java.lang.Long": return "long"; case "java.lang.Short": return "short"; case "java.lang.Void": return "void"; } return paramType; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy