| // 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; | |
| import com.android.tools.r8.keepanno.annotations.KeepForApi; | |
| import com.android.tools.r8.references.MethodReference; | |
| import com.android.tools.r8.utils.Reporter; | |
| import com.android.tools.r8.utils.internal.BooleanUtils; | |
| @KeepForApi | |
| public class AssertionsConfiguration { | |
| enum AssertionTransformation { | |
| ENABLE, | |
| DISABLE, | |
| PASSTHROUGH | |
| } | |
| public enum AssertionTransformationScope { | |
| ALL, | |
| PACKAGE, | |
| CLASS | |
| } | |
| private final AssertionTransformation transformation; | |
| private final MethodReference assertionHandler; | |
| private final AssertionTransformationScope scope; | |
| private final String value; | |
| AssertionsConfiguration( | |
| AssertionTransformation transformation, | |
| MethodReference assertionHandler, | |
| AssertionTransformationScope scope, | |
| String value) { | |
| this.transformation = transformation; | |
| this.assertionHandler = assertionHandler; | |
| this.scope = scope; | |
| this.value = value; | |
| assert BooleanUtils.xor(transformation != null, assertionHandler != null); | |
| } | |
| public boolean isCompileTimeEnabled() { | |
| return transformation == AssertionTransformation.ENABLE; | |
| } | |
| public boolean isCompileTimeDisabled() { | |
| return transformation == AssertionTransformation.DISABLE; | |
| } | |
| public boolean isPassthrough() { | |
| return transformation == AssertionTransformation.PASSTHROUGH; | |
| } | |
| public boolean isAssertionHandler() { | |
| return assertionHandler != null; | |
| } | |
| public MethodReference getAssertionHandler() { | |
| return assertionHandler; | |
| } | |
| public AssertionTransformationScope getScope() { | |
| return scope; | |
| } | |
| public String getValue() { | |
| return value; | |
| } | |
| static AssertionsConfiguration.Builder builder(Reporter reporter) { | |
| return new AssertionsConfiguration.Builder(reporter); | |
| } | |
| /** | |
| * Builder for constructing a <code>{@link AssertionsConfiguration}</code>. | |
| * | |
| * <p>A builder is obtained by calling {@link | |
| * BaseCompilerCommand.Builder#addAssertionsConfiguration}. | |
| */ | |
| @KeepForApi | |
| public static class Builder { | |
| Reporter reporter; | |
| private AssertionTransformation transformation; | |
| private MethodReference assertionHandler; | |
| private AssertionTransformationScope scope; | |
| private String value; | |
| private Builder(Reporter reporter) { | |
| this.reporter = reporter; | |
| } | |
| private AssertionsConfiguration.Builder setTransformation( | |
| AssertionTransformation transformation) { | |
| this.transformation = transformation; | |
| this.assertionHandler = null; | |
| return this; | |
| } | |
| /** | |
| * Unconditionally enable javac generated assertion code in all packages and classes. This | |
| * corresponds to passing <code>-enableassertions</code> or <code>-ea</code> to the java CLI. | |
| */ | |
| public AssertionsConfiguration.Builder setCompileTimeEnable() { | |
| setTransformation(AssertionTransformation.ENABLE); | |
| return this; | |
| } | |
| /** | |
| * Disable the javac generated assertion code in all packages and classes. This corresponds to | |
| * passing <code>-disableassertions</code> or <code>-da</code> to the java CLI. | |
| */ | |
| public AssertionsConfiguration.Builder setCompileTimeDisable() { | |
| setTransformation(AssertionTransformation.DISABLE); | |
| return this; | |
| } | |
| /** Passthrough of the javac generated assertion code in all packages and classes. */ | |
| public AssertionsConfiguration.Builder setPassthrough() { | |
| setTransformation(AssertionTransformation.PASSTHROUGH); | |
| return this; | |
| } | |
| /** | |
| * Rewrite the throwing of <code>java.lang.AssertionError</code> to call the supplied method | |
| * <code>assertionHandler</code>. The method must be a reference to a static method taking one | |
| * argument. The type of the argument should be <code>java.lang.Throwable</code> as kotlinc will | |
| * generate code where the assertion error is thrown as <code>java.lang.Throwable</code>. If all | |
| * code is generated by javac then the type of the argument can be <code> | |
| * java.lang.AssertionError</code>. After the assertion handler as been called, the code | |
| * continues as if assertions where disabled. | |
| */ | |
| public AssertionsConfiguration.Builder setAssertionHandler(MethodReference assertionHandler) { | |
| this.transformation = null; | |
| this.assertionHandler = assertionHandler; | |
| return this; | |
| } | |
| public AssertionsConfiguration.Builder setScopeAll() { | |
| this.scope = AssertionTransformationScope.ALL; | |
| this.value = null; | |
| return this; | |
| } | |
| /** | |
| * Apply the specified transformation in package <code>packageName</code> and all subpackages. | |
| * If <code>packageName</code> is the empty string, this specifies that the transformation is | |
| * applied ion the unnamed package. | |
| * | |
| * <p>If the transformation is 'enable' this corresponds to passing <code> | |
| * -enableassertions:packageName...</code> or <code>-ea:packageName...</code> to the java CLI. | |
| * | |
| * <p>If the transformation is 'disable' this corresponds to passing <code> | |
| * -disableassertions:packageName...</code> or <code>-da:packageName...</code> to the java CLI. | |
| */ | |
| public AssertionsConfiguration.Builder setScopePackage(String packageName) { | |
| this.scope = AssertionTransformationScope.PACKAGE; | |
| this.value = packageName; | |
| return this; | |
| } | |
| /** | |
| * Apply the specified transformation in class <code>className</code>. | |
| * | |
| * <p>If the transformation is 'enable' this corresponds to passing <code> | |
| * -enableassertions:className</code> or <code>-ea:className...</code> to the java CLI. | |
| * | |
| * <p>If the transformation is 'disable' this corresponds to passing <code> | |
| * -disableassertions:className</code> or <code>-da:className</code> to the java CLI. | |
| */ | |
| public AssertionsConfiguration.Builder setScopeClass(String className) { | |
| this.scope = AssertionTransformationScope.CLASS; | |
| this.value = className; | |
| return this; | |
| } | |
| /** Build and return the {@link AssertionsConfiguration}. */ | |
| @SuppressWarnings("InlineMeSuggester") | |
| public AssertionsConfiguration build() { | |
| if (transformation == null && assertionHandler == null) { | |
| reporter.error( | |
| "No transformation or assertion handler specified for building AssertionConfiguration"); | |
| } | |
| if (scope == null) { | |
| reporter.error("No scope specified for building AssertionConfiguration"); | |
| } | |
| if (scope == AssertionTransformationScope.PACKAGE && value == null) { | |
| reporter.error("No package name specified for building AssertionConfiguration"); | |
| } | |
| if (scope == AssertionTransformationScope.CLASS && value == null) { | |
| reporter.error("No class name specified for building AssertionConfiguration"); | |
| } | |
| return new AssertionsConfiguration(transformation, assertionHandler, scope, value); | |
| } | |
| /** | |
| * Static helper to build an <code>AssertionConfiguration</code> which unconditionally enables | |
| * javac generated assertion code in all packages and classes. To be used like this: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| * | |
| * which is a shorthand for: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration( | |
| * builder -> builder.setCompileTimeEnable().setScopeAll().build()) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| */ | |
| public static AssertionsConfiguration compileTimeEnableAllAssertions( | |
| AssertionsConfiguration.Builder builder) { | |
| return builder.setCompileTimeEnable().setScopeAll().build(); | |
| } | |
| /** | |
| * @deprecated As of version 3.3, replaced by {@link #compileTimeEnableAllAssertions(Builder)} | |
| */ | |
| @Deprecated | |
| @SuppressWarnings("InlineMeSuggester") | |
| public static AssertionsConfiguration enableAllAssertions( | |
| AssertionsConfiguration.Builder builder) { | |
| return compileTimeEnableAllAssertions(builder); | |
| } | |
| /** | |
| * Static helper to build an <code>AssertionConfiguration</code> which unconditionally disables | |
| * javac generated assertion code in all packages and classes. To be used like this: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration( | |
| * AssertionsConfiguration.Builder::compileTimeDisableAllAssertions) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| * | |
| * which is a shorthand for: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration( | |
| * builder -> builder.setCompileTimeDisabled().setScopeAll().build()) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| */ | |
| public static AssertionsConfiguration compileTimeDisableAllAssertions( | |
| AssertionsConfiguration.Builder builder) { | |
| return builder.setCompileTimeDisable().setScopeAll().build(); | |
| } | |
| /** | |
| * Static helper to build an <code>AssertionConfiguration</code> which will passthrough javac | |
| * generated assertion code in all packages and classes. To be used like this: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| * | |
| * which is a shorthand for: | |
| * | |
| * <pre> | |
| * D8Command command = D8Command.builder() | |
| * .addAssertionsConfiguration(builder -> builder.setPassthrough().setScopeAll().build()) | |
| * ... | |
| * .build(); | |
| * </pre> | |
| */ | |
| public static AssertionsConfiguration passthroughAllAssertions( | |
| AssertionsConfiguration.Builder builder) { | |
| return builder.setPassthrough().setScopeAll().build(); | |
| } | |
| } | |
| } |