| // Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8.ir.desugar.backports; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.TestBase; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestParametersCollection; |
| import com.android.tools.r8.TestRuntime.CfVm; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.ProcessResult; |
| import com.android.tools.r8.cf.CfCodePrinter; |
| import com.android.tools.r8.graph.ClassKind; |
| import com.android.tools.r8.graph.DexEncodedMethod; |
| import com.android.tools.r8.graph.JarApplicationReader; |
| import com.android.tools.r8.graph.JarClassFileReader; |
| import com.android.tools.r8.origin.Origin; |
| import com.android.tools.r8.utils.FileUtils; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.android.tools.r8.utils.StringUtils; |
| import com.google.common.collect.ImmutableList; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.PrintStream; |
| import java.nio.charset.StandardCharsets; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.List; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| // Class to generate and validate CfCode for backport methods. |
| @RunWith(Parameterized.class) |
| public class GenerateBackportMethods extends TestBase { |
| |
| static final Path javaExecutable = Paths.get(ToolHelper.getJavaExecutable(CfVm.JDK9)); |
| static final Path googleFormatDir = Paths.get(ToolHelper.THIRD_PARTY_DIR, "google-java-format"); |
| static final Path googleFormatJar = |
| googleFormatDir.resolve("google-java-format-1.7-all-deps.jar"); |
| static final Path backportMethodsFile = |
| Paths.get( |
| ToolHelper.SOURCE_DIR, |
| "com", |
| "android", |
| "tools", |
| "r8", |
| "ir", |
| "desugar", |
| "backports", |
| "BackportedMethods.java"); |
| |
| static final String header = |
| StringUtils.lines( |
| "// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file", |
| "// for details. All rights reserved. Use of this source code is governed by a", |
| "// BSD-style license that can be found in the LICENSE file.", |
| "", |
| "// ***********************************************************************************", |
| "// GENERATED FILE. DO NOT EDIT! Changes should be made to GenerateBackportMethods.java", |
| "// ***********************************************************************************", |
| "", |
| "package com.android.tools.r8.ir.desugar.backports;"); |
| |
| static final List<Class<?>> methodTemplateClasses = |
| ImmutableList.of( |
| BooleanMethods.class, |
| ByteMethods.class, |
| CharacterMethods.class, |
| CloseResourceMethod.class, |
| CollectionMethods.class, |
| CollectionsMethods.class, |
| DoubleMethods.class, |
| FloatMethods.class, |
| IntegerMethods.class, |
| LongMethods.class, |
| MathMethods.class, |
| ObjectsMethods.class, |
| OptionalMethods.class, |
| ShortMethods.class, |
| StringMethods.class); |
| |
| final TestParameters parameters; |
| |
| @Parameters(name = "{0}") |
| public static TestParametersCollection data() { |
| return getTestParameters().withNoneRuntime().build(); |
| } |
| |
| public GenerateBackportMethods(TestParameters parameters) { |
| this.parameters = parameters; |
| } |
| |
| @Test |
| public void test() throws Exception { |
| ArrayList<Class<?>> sorted = new ArrayList<>(methodTemplateClasses); |
| sorted.sort(Comparator.comparing(Class::getTypeName)); |
| assertEquals("Classes should be listed in sorted order", sorted, methodTemplateClasses); |
| assertEquals( |
| FileUtils.readTextFile(backportMethodsFile, StandardCharsets.UTF_8), |
| generateBackportMethods()); |
| } |
| |
| // Running this method will regenerate / overwrite the content of the backport methods. |
| public static void main(String[] args) throws Exception { |
| FileUtils.writeToFile(backportMethodsFile, null, generateBackportMethods().getBytes()); |
| } |
| |
| private static String generateBackportMethods() throws IOException { |
| InternalOptions options = new InternalOptions(); |
| CfCodePrinter codePrinter = new CfCodePrinter(); |
| JarClassFileReader reader = |
| new JarClassFileReader( |
| new JarApplicationReader(options), |
| clazz -> { |
| for (DexEncodedMethod method : clazz.allMethodsSorted()) { |
| if (method.isInitializer()) { |
| continue; |
| } |
| String methodName = |
| method.method.holder.getName() + "_" + method.method.name.toString(); |
| codePrinter.visitMethod(methodName, method.getCode().asCfCode()); |
| } |
| }); |
| for (Class<?> clazz : methodTemplateClasses) { |
| try (InputStream stream = Files.newInputStream(ToolHelper.getClassFileForTestClass(clazz))) { |
| reader.read(Origin.unknown(), ClassKind.PROGRAM, stream); |
| } |
| } |
| |
| Path outfile = Paths.get(ToolHelper.BUILD_DIR, "backports.java"); |
| try (PrintStream printer = new PrintStream(Files.newOutputStream(outfile))) { |
| printer.println(header); |
| codePrinter.getImports().forEach(i -> printer.println("import " + i + ";")); |
| printer.println("public final class BackportedMethods {\n"); |
| codePrinter.getMethods().forEach(printer::println); |
| printer.println("}"); |
| } |
| |
| ProcessBuilder builder = |
| new ProcessBuilder( |
| ImmutableList.of( |
| javaExecutable.toString(), |
| "-jar", |
| googleFormatJar.toString(), |
| outfile.toAbsolutePath().toString())); |
| String commandString = String.join(" ", builder.command()); |
| System.out.println(commandString); |
| Process process = builder.start(); |
| ProcessResult result = ToolHelper.drainProcessOutputStreams(process, commandString); |
| if (result.exitCode != 0) { |
| throw new IllegalStateException(result.toString()); |
| } |
| String content = result.stdout; |
| if (!StringUtils.LINE_SEPARATOR.equals("\n")) { |
| return content.replace(StringUtils.LINE_SEPARATOR, "\n"); |
| } |
| return content; |
| } |
| } |