Merge "Make dex segment type names UpperCamelCase."
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 8560de3..3bcf6e7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -164,4 +164,16 @@
public boolean hasClassInitializer() {
return getClassInitializer() != null;
}
+
+ public boolean hasNonTrivialClassInitializer() {
+ DexEncodedMethod clinit = getClassInitializer();
+ if (clinit == null || clinit.getCode() == null) {
+ return false;
+ }
+ if (clinit.getCode().isDexCode()) {
+ return !clinit.getCode().asDexCode().isEmptyVoidMethod();
+ }
+ // For non-dex code we don't try to check the code.
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index f48e7db..9327fb0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.ReturnVoid;
import com.android.tools.r8.code.SwitchPayload;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
@@ -135,6 +136,10 @@
return false;
}
+ boolean isEmptyVoidMethod() {
+ return instructions.length == 1 && instructions[0] instanceof ReturnVoid;
+ }
+
@Override
public IRCode buildIR(DexEncodedMethod encodedMethod, InternalOptions options) {
DexSourceCode source = new DexSourceCode(this, encodedMethod);
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index dd29e8d2..ec21ff0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -83,6 +83,8 @@
public DexString getClassMethodName = createString("getClass");
public DexString ordinalMethodName = createString("ordinal");
+ public final DexString desiredAssertionStatusMethodName = createString("desiredAssertionStatus");
+ public final DexString assertionsDisabled = createString("$assertionsDisabled");
public DexString stringDescriptor = createString("Ljava/lang/String;");
public DexString objectDescriptor = createString("Ljava/lang/Object;");
@@ -134,6 +136,7 @@
public ObjectMethods objectMethods = new ObjectMethods();
public LongMethods longMethods = new LongMethods();
public ThrowableMethods throwableMethods = new ThrowableMethods();
+ public ClassMethods classMethods = new ClassMethods();
public void clearSubtypeInformation() {
types.values().forEach(DexType::clearSubtypeInformation);
@@ -182,6 +185,17 @@
}
}
+ public class ClassMethods {
+
+ public DexMethod desiredAssertionStatus;
+
+ private ClassMethods() {
+ desiredAssertionStatus = createMethod(classDescriptor,
+ desiredAssertionStatusMethodName, booleanDescriptor, new DexString[]{});
+ }
+ }
+
+
public class StringBuildingMethods {
public DexMethod appendBoolean;
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index e70e8f0..25416d9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.naming.NamingLens;
import java.io.UTFDataFormatException;
@@ -246,7 +247,8 @@
// '<' SimpleName '>' should be valid. However, the art verifier only allows <init>
// and <clinit> which is reasonable.
if ((string.charAt(0) == '<') &&
- (string.equals("<init>") || string.equals("<clinit>"))) {
+ (string.equals(Constants.INSTANCE_INITIALIZER_NAME) ||
+ string.equals(Constants.CLASS_INITIALIZER_NAME))) {
return true;
}
for (int i = 0; i < string.length(); i++) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index 94f6507..d624990 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -21,7 +21,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
// Never remove argument instructions. That would change the signature of the method.
// TODO(ager): If we can tell that a method never uses an argument we might be able to
// rewrite the signature and call-sites.
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 5e1ff16..20ce7e8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -103,7 +103,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
// ArrayPut has side-effects on input values.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index 9b565a6..3a3626e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.utils.InternalOptions;
public class ConstClass extends ConstInstruction {
@@ -57,6 +58,16 @@
}
@Override
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
+ // A const-class instruction can be dead code only if the resulting program is known to contain
+ // the class mentioned.
+ // The simple conservative check is for the holder of the method.
+ // TODO(sgjesse): It might be beneficial to check for program classes in the super hierarchy or
+ // interfaces implemented.
+ return code.method.method.holder == clazz;
+ }
+
+ @Override
public boolean isConstClass() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
index ee8a279..f1a6d02 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
@@ -50,7 +50,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index 28d6b2b..e7917c6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -61,7 +61,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 3ff0624..400c30a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -355,4 +355,12 @@
public Value createValue(MoveType moveType) {
return createValue(moveType, null);
}
+
+ public ConstNumber createTrue() {
+ return new ConstNumber(ConstType.INT, createValue(MoveType.SINGLE), 1);
+ }
+
+ public ConstNumber createFalse() {
+ return new ConstNumber(ConstType.INT, createValue(MoveType.SINGLE), 0);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 2e821cf..ae4fd67 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -252,7 +252,7 @@
}
/** Returns true is this instruction can be treated as dead code if its outputs are not used. */
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return !instructionInstanceCanThrow();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index 7b1c007..ec9c12f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -32,7 +32,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 3e63e50..2691eed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -57,7 +57,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
return !options.debug;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index b7d05e8..63a1a0e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -80,7 +80,7 @@
}
@Override
- public boolean canBeDeadCode(InternalOptions options) {
+ public boolean canBeDeadCode(IRCode code, InternalOptions options) {
// Side-effects its input values.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 27b1e18..f208d49 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -507,7 +507,7 @@
// currently active values.
active.add(this);
for (Instruction instruction : uniqueUsers()) {
- if (!instruction.canBeDeadCode(options)) {
+ if (!instruction.canBeDeadCode(null, options)) {
return false;
}
Value outValue = instruction.outValue();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 9d8cbcf..a5e2df7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -437,6 +437,9 @@
assert !options.debug;
codeRewriter.removeSwitchMaps(code);
}
+ if (options.disableAssertions) {
+ codeRewriter.disableAssertions(code);
+ }
if (options.inlineAccessors && inliner != null) {
// TODO(zerny): Should we support inlining in debug mode? b/62937285
assert !options.debug;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index f26cacd..faed53d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -680,6 +680,65 @@
assert code.isConsistentGraph();
}
+ // For supporting assert javac adds the static field $assertionsDisabled to all classes which
+ // have methods with assertions. This is used to support the Java VM -ea flag.
+ //
+ // The class:
+ //
+ // class A {
+ // void m() {
+ // assert xxx;
+ // }
+ // }
+ //
+ // Is compiled into:
+ //
+ // class A {
+ // static boolean $assertionsDisabled;
+ // static {
+ // $assertionsDisabled = A.class.desiredAssertionStatus();
+ // }
+ //
+ // // method with "assert xxx";
+ // void m() {
+ // if (!$assertionsDisabled) {
+ // if (xxx) {
+ // throw new AssertionError(...);
+ // }
+ // }
+ // }
+ // }
+ //
+ // With the rewriting below (and other rewritings) the resulting code is:
+ //
+ // class A {
+ // void m() {
+ // }
+ // }
+ //
+ public void disableAssertions(IRCode code) {
+ InstructionIterator iterator = code.instructionIterator();
+ while (iterator.hasNext()) {
+ Instruction current = iterator.next();
+ if (current.isInvokeMethod()) {
+ InvokeMethod invoke = current.asInvokeMethod();
+ if (invoke.getInvokedMethod() == dexItemFactory.classMethods.desiredAssertionStatus) {
+ iterator.replaceCurrentInstruction(code.createFalse());
+ }
+ } else if (current.isStaticPut()) {
+ StaticPut staticPut = current.asStaticPut();
+ if (staticPut.getField().name == dexItemFactory.assertionsDisabled) {
+ iterator.remove();
+ }
+ } else if (current.isStaticGet()) {
+ StaticGet staticGet = current.asStaticGet();
+ if (staticGet.getField().name == dexItemFactory.assertionsDisabled) {
+ iterator.replaceCurrentInstruction(code.createTrue());
+ }
+ }
+ }
+ }
+
private boolean canBeFolded(Instruction instruction) {
return (instruction.isBinop() && instruction.asBinop().canBeFolded()) ||
(instruction.isUnop() && instruction.asUnop().canBeFolded());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 0c60642..b252915 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -31,7 +31,7 @@
// Ignore marked blocks, as they are scheduled for removal.
continue;
}
- removeDeadInstructions(worklist, block, options);
+ removeDeadInstructions(worklist, code, block, options);
removeDeadPhis(worklist, block, options);
removeUnneededCatchHandlers(worklist, block, dominator);
}
@@ -96,7 +96,7 @@
}
private static void removeDeadInstructions(
- Queue<BasicBlock> worklist, BasicBlock block, InternalOptions options) {
+ Queue<BasicBlock> worklist, IRCode code, BasicBlock block, InternalOptions options) {
InstructionListIterator iterator = block.listIterator(block.getInstructions().size());
while (iterator.hasPrevious()) {
Instruction current = iterator.previous();
@@ -106,8 +106,8 @@
&& current.outValue().numberOfAllUsers() == 0) {
current.setOutValue(null);
}
- // Never remove instructions that can have side effects.
- if (!current.canBeDeadCode(options)) {
+ // Never remove instructions that can have side effects, except for const-class.
+ if (!current.canBeDeadCode(code, options)) {
continue;
}
Value outValue = current.outValue();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
index 03f9470..febef82 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
@@ -219,7 +219,7 @@
return true;
}
DexClass clazz = inliner.appInfo.definitionFor(targetHolder);
- return (clazz != null) && (!clazz.hasClassInitializer());
+ return (clazz != null) && (!clazz.hasNonTrivialClassInitializer());
}
private synchronized boolean isDoubleInliningTarget(DexEncodedMethod candidate) {
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index abdda65..b8fa85a 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -348,10 +348,11 @@
}
// We also need to add the corresponding <clinit> to the set of live methods, as otherwise
// static field initialization (and other class-load-time sideeffects) will not happen.
- DexEncodedMethod clinit = holder.getClassInitializer();
- if (clinit != null) {
+ if (holder.hasNonTrivialClassInitializer()) {
+ DexEncodedMethod clinit = holder.getClassInitializer();
markDirectStaticOrConstructorMethodAsLive(clinit, KeepReason.reachableFromLiveType(type));
}
+
// If this type has deferred annotations, we have to process those now, too.
Set<DexAnnotation> annotations = deferredAnnotations.remove(type);
if (annotations != null) {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 7b1cfe1..9a8fa82 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -74,6 +74,7 @@
public boolean allowAccessModification = true;
public boolean inlineAccessors = true;
public boolean removeSwitchMaps = true;
+ public boolean disableAssertions = true;
public final OutlineOptions outline = new OutlineOptions();
public boolean debugKeepRules = false;
public final AttributeRemovalOptions attributeRemoval = new AttributeRemovalOptions();
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 3f31686..e6134e7 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -87,6 +87,15 @@
/**
* Compile an application with R8.
*/
+ protected AndroidApp compileWithR8(Class... classes)
+ throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
+ R8Command command = ToolHelper.prepareR8CommandBuilder(readClasses(classes)).build();
+ return ToolHelper.runR8(command);
+ }
+
+ /**
+ * Compile an application with R8.
+ */
protected AndroidApp compileWithR8(List<Class> classes)
throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
R8Command command = ToolHelper.prepareR8CommandBuilder(readClasses(classes)).build();
@@ -122,6 +131,15 @@
/**
* Compile an application with R8 using the supplied proguard configuration.
*/
+ protected AndroidApp compileWithR8(
+ List<Class> classes, String proguardConfig, Consumer<InternalOptions> optionsConsumer)
+ throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
+ return compileWithR8(readClasses(classes), proguardConfig, optionsConsumer);
+ }
+
+ /**
+ * Compile an application with R8 using the supplied proguard configuration.
+ */
protected AndroidApp compileWithR8(List<Class> classes, Path proguardConfig)
throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
return compileWithR8(readClasses(classes), proguardConfig);
@@ -143,6 +161,15 @@
* Compile an application with R8 using the supplied proguard configuration.
*/
protected AndroidApp compileWithR8(
+ AndroidApp app, String proguardConfig, Consumer<InternalOptions> optionsConsumer)
+ throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
+ return compileWithR8(app, writeTextToTempFile(proguardConfig), optionsConsumer);
+ }
+
+ /**
+ * Compile an application with R8 using the supplied proguard configuration.
+ */
+ protected AndroidApp compileWithR8(
AndroidApp app, Path proguardConfig, Consumer<InternalOptions> optionsConsumer)
throws CompilationException, ProguardRuleParserException, ExecutionException, IOException {
R8Command command =
@@ -185,6 +212,22 @@
}
/**
+ * Run application on Art with the specified main class and provided arguments.
+ */
+ protected String runOnArt(AndroidApp app, Class mainClass, String... args) throws IOException {
+ Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
+ app.writeToZip(out, OutputMode.Indexed, true);
+ return ToolHelper.runArtNoVerificationErrors(
+ ImmutableList.of(out.toString()), mainClass.getCanonicalName(),
+ builder -> {
+ builder.appendArtOption("-ea");
+ for (String arg : args) {
+ builder.appendProgramArgument(arg);
+ }
+ });
+ }
+
+ /**
* Run a single class application on Java.
*/
protected String runOnJava(Class mainClass) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java b/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java
new file mode 100644
index 0000000..cc56790
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/ClassWithAssertions.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2017, 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.rewrite.assertions;
+
+public class ClassWithAssertions {
+ int x = 0;
+
+ ClassWithAssertions(int x) {
+ this.x = x;
+ }
+
+ boolean condition() {
+ return x == 1;
+ }
+
+ int getX() {
+ assert condition();
+ return x;
+ }
+
+ public static void main(String[] args) {
+ new ClassWithAssertions(Integer.parseInt(args[0])).getX();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
new file mode 100644
index 0000000..3c79bd3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/RemoveAssertionsTest.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2017, 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.rewrite.assertions;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.android.tools.r8.utils.DexInspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+public class RemoveAssertionsTest extends TestBase {
+
+ @Test
+ public void test() throws Exception {
+ // Run with R8, but avoid inlining to really validate that the methods "condition"
+ // and "<clinit>" are gone.
+ Class testClass = ClassWithAssertions.class;
+ AndroidApp app = compileWithR8(
+ ImmutableList.of(testClass),
+ keepMainProguardConfiguration(testClass, true, false),
+ options -> options.inlineAccessors = false);
+ DexInspector x = new DexInspector(app);
+
+ ClassSubject clazz = x.clazz(ClassWithAssertions.class);
+ assertTrue(clazz.isPresent());
+ MethodSubject conditionMethod =
+ clazz.method(new MethodSignature("condition", "boolean", new String[]{}));
+ assertTrue(!conditionMethod.isPresent());
+ MethodSubject clinit =
+ clazz.method(new MethodSignature(Constants.CLASS_INITIALIZER_NAME, "void", new String[]{}));
+ assertTrue(!clinit.isPresent());
+ }
+}