[KeepAnno] Enable more tests for native interpretation

This adds support for class names, access flags, annotations and fields.

Bug: b/323816623
Change-Id: I50e4557b2f6dce58cc09046084ca50c0cdf41ba5
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
index ccac25a..0d7e1b2 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
@@ -239,22 +239,32 @@
         return;
       }
       KeepClassItemPattern classPattern = schema.classes.get(classIndex);
-      if (!classPattern.getClassNamePattern().isExact()) {
-        throw new Unimplemented();
+      if (classPattern.getClassNamePattern().isExact()) {
+        DexType type =
+            appInfo
+                .dexItemFactory()
+                .createType(classPattern.getClassNamePattern().getExactDescriptor());
+        DexProgramClass clazz = DexProgramClass.asProgramClassOrNull(appInfo.definitionFor(type));
+        if (clazz == null) {
+          // No valid match, so the rule is discarded. This should likely be a diagnostics info.
+          return;
+        }
+        if (!predicates.matchesClass(clazz, classPattern)) {
+          // Invalid match for this class.
+          return;
+        }
+        continueWithClass(classIndex, clazz);
+      } else {
+        // TODO(b/323816623): This repeated iteration on all classes must be avoided.
+        for (DexProgramClass clazz : appInfo.classes()) {
+          if (predicates.matchesClass(clazz, classPattern)) {
+            continueWithClass(classIndex, clazz);
+          }
+        }
       }
-      DexType type =
-          appInfo
-              .dexItemFactory()
-              .createType(classPattern.getClassNamePattern().getExactDescriptor());
-      DexProgramClass clazz = DexProgramClass.asProgramClassOrNull(appInfo.definitionFor(type));
-      if (clazz == null) {
-        // No valid match, so the rule is discarded. This should likely be a diagnostics info.
-        return;
-      }
-      if (!predicates.matchesClass(clazz, classPattern)) {
-        // Invalid match for this class.
-        return;
-      }
+    }
+
+    private void continueWithClass(int classIndex, DexProgramClass clazz) {
       assignment.setClass(classIndex, clazz);
       IntList classMemberIndexList = schema.classMembers.get(classIndex);
       findMatchingMember(0, classMemberIndexList, clazz, classIndex + 1);
@@ -270,48 +280,55 @@
         findMatchingClass(nextClassIndex);
         return;
       }
-      int nextMemberInHolderIndex = memberInHolderIndex + 1;
       int memberIndex = memberIndexTranslation.getInt(memberInHolderIndex);
       KeepMemberItemPattern memberItemPattern = schema.members.get(memberIndex);
+      Consumer<ProgramDefinition> continueWithMember =
+          m ->
+              continueWithMember(
+                  m, memberIndex, memberInHolderIndex + 1, memberIndexTranslation, nextClassIndex);
       memberItemPattern
           .getMemberPattern()
           .match(
-              generalMember -> {
-                if (!holder.hasMethodsOrFields()) {
+              generalMemberPattern -> {
+                if (!holder.hasMethodsOrFields() && generalMemberPattern.isAllMembers()) {
                   // The empty class can only match the "all member" pattern but with no assignment.
-                  if (generalMember.isAllMembers()) {
-                    assignment.setEmptyMemberMatch(memberIndex);
-                    findMatchingMember(
-                        nextMemberInHolderIndex, memberIndexTranslation, holder, nextClassIndex);
-                  }
-                  return;
+                  continueWithMember.accept(holder);
+                } else {
+                  holder.forEachProgramMember(
+                      m -> {
+                        if (predicates.matchesGeneralMember(
+                            m.getDefinition(), generalMemberPattern)) {
+                          continueWithMember.accept(m);
+                        }
+                      });
                 }
-                if (!generalMember.isAllMembers()) {
-                  throw new Unimplemented();
-                }
-                holder.forEachProgramMember(
-                    f -> {
-                      assignment.setMember(memberIndex, f);
-                      findMatchingMember(
-                          nextMemberInHolderIndex, memberIndexTranslation, holder, nextClassIndex);
-                    });
               },
-              fieldMember -> {
-                throw new Unimplemented();
-              },
-              methodMember -> {
-                holder.forEachProgramMethod(
-                    m -> {
-                      if (predicates.matchesMethod(methodMember, m)) {
-                        assignment.setMember(memberIndex, m);
-                        findMatchingMember(
-                            nextMemberInHolderIndex,
-                            memberIndexTranslation,
-                            holder,
-                            nextClassIndex);
-                      }
-                    });
-              });
+              fieldPattern ->
+                  holder.forEachProgramFieldMatching(
+                      f -> predicates.matchesField(f, fieldPattern), continueWithMember),
+              methodPattern ->
+                  holder.forEachProgramMethodMatching(
+                      m -> predicates.matchesMethod(m, methodPattern), continueWithMember));
+    }
+
+    private void continueWithMember(
+        ProgramDefinition definition,
+        int memberIndex,
+        int nextMemberInHolderIndex,
+        IntList memberIndexTranslation,
+        int nextClassIndex) {
+      if (definition.isProgramMember()) {
+        assignment.setMember(memberIndex, definition.asProgramMember());
+      } else {
+        assert definition.isProgramClass();
+        assert !definition.asProgramClass().hasMethodsOrFields();
+        assignment.setEmptyMemberMatch(memberIndex);
+      }
+      findMatchingMember(
+          nextMemberInHolderIndex,
+          memberIndexTranslation,
+          definition.getContextClass(),
+          nextClassIndex);
     }
   }
 
@@ -336,24 +353,6 @@
       this.edge = edge;
       edge.getPreconditions().forEach(this::addPrecondition);
       edge.getConsequences().forEachTarget(this::addConsequence);
-      ListUtils.forEachWithIndex(
-          members,
-          (member, memberIndex) -> {
-            member
-                .getClassReference()
-                .matchClassItemReference(
-                    bindingReference -> {
-                      int classIndex = symbolToKey.getInt(bindingReference);
-                      classMembers.get(classIndex).add(memberIndex);
-                    },
-                    classItemPattern -> {
-                      // The member declares its own inline class so link it directly.
-                      IntArrayList memberList = new IntArrayList();
-                      memberList.add(memberIndex);
-                      classes.add(classItemPattern);
-                      classMembers.add(memberList);
-                    });
-          });
     }
 
     public static boolean isClassKeyReference(int keyRef) {
@@ -393,14 +392,17 @@
 
     private int defineItemPattern(KeepItemPattern item) {
       if (item.isClassItemPattern()) {
-        int key = classes.size();
+        int classIndex = classes.size();
         classes.add(item.asClassItemPattern());
         classMembers.add(new IntArrayList());
-        return encodeClassKey(key);
+        return encodeClassKey(classIndex);
+      } else {
+        int classIndex = defineItemReference(item.asMemberItemPattern().getClassReference());
+        int memberIndex = members.size();
+        members.add(item.asMemberItemPattern());
+        classMembers.get(classIndex).add(memberIndex);
+        return encodeMemberKey(memberIndex);
       }
-      int key = members.size();
-      members.add(item.asMemberItemPattern());
-      return encodeMemberKey(key);
     }
 
     public void addPrecondition(KeepCondition condition) {
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcherPredicates.java b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcherPredicates.java
index 45e8385..364a17f 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcherPredicates.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcherPredicates.java
@@ -5,25 +5,38 @@
 package com.android.tools.r8.shaking.rules;
 
 import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.AccessFlags;
+import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
+import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.FieldAccessFlags;
 import com.android.tools.r8.graph.MethodAccessFlags;
-import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.keepanno.ast.AccessVisibility;
 import com.android.tools.r8.keepanno.ast.KeepArrayTypePattern;
 import com.android.tools.r8.keepanno.ast.KeepClassItemPattern;
+import com.android.tools.r8.keepanno.ast.KeepFieldAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepFieldPattern;
 import com.android.tools.r8.keepanno.ast.KeepInstanceOfPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberAccessPattern;
+import com.android.tools.r8.keepanno.ast.KeepMemberPattern;
 import com.android.tools.r8.keepanno.ast.KeepMethodAccessPattern;
 import com.android.tools.r8.keepanno.ast.KeepMethodParametersPattern;
 import com.android.tools.r8.keepanno.ast.KeepMethodPattern;
 import com.android.tools.r8.keepanno.ast.KeepMethodReturnTypePattern;
+import com.android.tools.r8.keepanno.ast.KeepPackagePattern;
 import com.android.tools.r8.keepanno.ast.KeepPrimitiveTypePattern;
 import com.android.tools.r8.keepanno.ast.KeepQualifiedClassNamePattern;
 import com.android.tools.r8.keepanno.ast.KeepStringPattern;
 import com.android.tools.r8.keepanno.ast.KeepTypePattern;
+import com.android.tools.r8.keepanno.ast.KeepUnqualfiedClassNamePattern;
+import com.android.tools.r8.keepanno.ast.ModifierPattern;
 import com.android.tools.r8.keepanno.ast.OptionalPattern;
 import java.util.List;
 
@@ -48,7 +61,25 @@
     if (pattern.isExact()) {
       return type.toDescriptorString().equals(pattern.getExactDescriptor());
     }
-    throw new Unimplemented();
+    return matchesPackage(type.getPackageName(), pattern.getPackagePattern())
+        && matchesSimpleName(type.getSimpleName(), pattern.getNamePattern());
+  }
+
+  private boolean matchesPackage(String packageName, KeepPackagePattern pattern) {
+    if (pattern.isAny()) {
+      return true;
+    }
+    if (pattern.isTop() && packageName.equals("")) {
+      return true;
+    }
+    return packageName.equals(pattern.getExactPackageAsString());
+  }
+
+  public boolean matchesSimpleName(String simpleName, KeepUnqualfiedClassNamePattern pattern) {
+    if (pattern.isAny()) {
+      return true;
+    }
+    return pattern.asExact().getExactNameAsString().equals(simpleName);
   }
 
   private boolean matchesInstanceOfPattern(
@@ -59,30 +90,109 @@
     throw new Unimplemented();
   }
 
-  public boolean matchesMethod(KeepMethodPattern methodPattern, ProgramMethod method) {
-    if (methodPattern.isAnyMethod()) {
+  public boolean matchesGeneralMember(DexEncodedMember<?, ?> member, KeepMemberPattern pattern) {
+    assert pattern.isGeneralMember();
+    if (pattern.isAllMembers()) {
       return true;
     }
-    return matchesName(method.getName(), methodPattern.getNamePattern().asStringPattern())
-        && matchesReturnType(method.getReturnType(), methodPattern.getReturnTypePattern())
-        && matchesParameters(method.getParameters(), methodPattern.getParametersPattern())
-        && matchesAnnotatedBy(method.getAnnotations(), methodPattern.getAnnotatedByPattern())
-        && matchesAccess(method.getAccessFlags(), methodPattern.getAccessPattern());
+    return matchesAnnotatedBy(member.annotations(), pattern.getAnnotatedByPattern())
+        && matchesGeneralMemberAccess(member.getAccessFlags(), pattern.getAccessPattern());
   }
 
-  public boolean matchesAccess(MethodAccessFlags access, KeepMethodAccessPattern pattern) {
+  public boolean matchesMethod(DexEncodedMethod method, KeepMethodPattern pattern) {
+    if (pattern.isAnyMethod()) {
+      return true;
+    }
+    return matchesName(method.getName(), pattern.getNamePattern().asStringPattern())
+        && matchesReturnType(method.getReturnType(), pattern.getReturnTypePattern())
+        && matchesParameters(method.getParameters(), pattern.getParametersPattern())
+        && matchesAnnotatedBy(method.annotations(), pattern.getAnnotatedByPattern())
+        && matchesMethodAccess(method.getAccessFlags(), pattern.getAccessPattern());
+  }
+
+  public boolean matchesField(DexEncodedField field, KeepFieldPattern pattern) {
+    if (pattern.isAnyField()) {
+      return true;
+    }
+    return matchesName(field.getName(), pattern.getNamePattern().asStringPattern())
+        && matchesType(field.getType(), pattern.getTypePattern().asType())
+        && matchesAnnotatedBy(field.annotations(), pattern.getAnnotatedByPattern())
+        && matchesFieldAccess(field.getAccessFlags(), pattern.getAccessPattern());
+  }
+
+  public boolean matchesGeneralMemberAccess(
+      AccessFlags<?> access, KeepMemberAccessPattern pattern) {
     if (pattern.isAny()) {
       return true;
     }
-    throw new Unimplemented();
+    if (!pattern.isAnyVisibility() && !pattern.isVisibilityAllowed(getAccessVisibility(access))) {
+      return false;
+    }
+    return matchesModifier(access.isStatic(), pattern.getStaticPattern())
+        && matchesModifier(access.isFinal(), pattern.getFinalPattern())
+        && matchesModifier(access.isSynthetic(), pattern.getSyntheticPattern());
+  }
+
+  public boolean matchesMethodAccess(MethodAccessFlags access, KeepMethodAccessPattern pattern) {
+    if (pattern.isAny()) {
+      return true;
+    }
+    return matchesGeneralMemberAccess(access, pattern)
+        && matchesModifier(access.isSynchronized(), pattern.getSynchronizedPattern())
+        && matchesModifier(access.isBridge(), pattern.getBridgePattern())
+        && matchesModifier(access.isNative(), pattern.getNativePattern())
+        && matchesModifier(access.isAbstract(), pattern.getAbstractPattern())
+        && matchesModifier(access.isStrict(), pattern.getStrictFpPattern());
+  }
+
+  public boolean matchesFieldAccess(FieldAccessFlags access, KeepFieldAccessPattern pattern) {
+    if (pattern.isAny()) {
+      return true;
+    }
+    return matchesGeneralMemberAccess(access, pattern)
+        && matchesModifier(access.isVolatile(), pattern.getVolatilePattern())
+        && matchesModifier(access.isTransient(), pattern.getTransientPattern());
+  }
+
+  private boolean matchesModifier(boolean value, ModifierPattern pattern) {
+    return pattern.isAny() || value == pattern.isOnlyPositive();
+  }
+
+  private AccessVisibility getAccessVisibility(AccessFlags<?> accessFlags) {
+    if (accessFlags.isPublic()) {
+      return AccessVisibility.PUBLIC;
+    }
+    if (accessFlags.isProtected()) {
+      return AccessVisibility.PROTECTED;
+    }
+    if (accessFlags.isPackagePrivate()) {
+      return AccessVisibility.PACKAGE_PRIVATE;
+    }
+    assert accessFlags.isPrivate();
+    return AccessVisibility.PRIVATE;
   }
 
   public boolean matchesAnnotatedBy(
       DexAnnotationSet annotations, OptionalPattern<KeepQualifiedClassNamePattern> pattern) {
     if (pattern.isAbsent()) {
+      // No pattern for annotations matches regardless of annotation content.
       return true;
     }
-    throw new Unimplemented();
+    if (annotations.isEmpty()) {
+      // Fast-path if pattern is present but no annotations.
+      return false;
+    }
+    KeepQualifiedClassNamePattern classNamePattern = pattern.get();
+    if (classNamePattern.isAny()) {
+      // Fast-path the "any" case.
+      return true;
+    }
+    for (DexAnnotation annotation : annotations.getAnnotations()) {
+      if (matchesClassName(annotation.getAnnotationType(), classNamePattern)) {
+        return true;
+      }
+    }
+    return false;
   }
 
   public boolean matchesParameters(DexTypeList parameters, KeepMethodParametersPattern pattern) {
diff --git a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternAnyRetentionTest.java b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternAnyRetentionTest.java
index 31de01d..2dd3af2 100644
--- a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternAnyRetentionTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternAnyRetentionTest.java
@@ -44,6 +44,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternClassRetentionTest.java b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternClassRetentionTest.java
index df1bee8..af205e6 100644
--- a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternClassRetentionTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternClassRetentionTest.java
@@ -45,6 +45,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternMultipleTest.java b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternMultipleTest.java
index feafc7f..af1e3b0 100644
--- a/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternMultipleTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/AnnotationPatternMultipleTest.java
@@ -46,6 +46,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/ArrayPatternsTest.java b/src/test/java/com/android/tools/r8/keepanno/ArrayPatternsTest.java
index 2f1f572..86bf2a5 100644
--- a/src/test/java/com/android/tools/r8/keepanno/ArrayPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/ArrayPatternsTest.java
@@ -41,6 +41,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByAnyAnnoPatternTest.java b/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByAnyAnnoPatternTest.java
index 7f3840f..5c7237a 100644
--- a/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByAnyAnnoPatternTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByAnyAnnoPatternTest.java
@@ -44,6 +44,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByPatternsTest.java b/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByPatternsTest.java
index 6d0f966..ea21a44 100644
--- a/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/ClassAnnotatedByPatternsTest.java
@@ -44,6 +44,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/FieldPatternsTest.java b/src/test/java/com/android/tools/r8/keepanno/FieldPatternsTest.java
index 669d945..61fb54c 100644
--- a/src/test/java/com/android/tools/r8/keepanno/FieldPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/FieldPatternsTest.java
@@ -38,6 +38,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepAccessVisibilityFlagsTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepAccessVisibilityFlagsTest.java
index a9dec7d..6e41cc0 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepAccessVisibilityFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepAccessVisibilityFlagsTest.java
@@ -82,6 +82,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .allowAccessModification()
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java b/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
index 1105bd3..5e34061 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepAnnoTestBuilder.java
@@ -113,8 +113,8 @@
     return applyIfPG(b -> b.addDontWarn(clazz));
   }
 
-  public final KeepAnnoTestBuilder allowUnusedProguardConfigurationRules() {
-    return applyIfR8Current(R8TestBuilder::allowUnusedProguardConfigurationRules);
+  public KeepAnnoTestBuilder allowUnusedProguardConfigurationRules() {
+    return this;
   }
 
   public final KeepAnnoTestBuilder allowAccessModification() {
@@ -170,6 +170,7 @@
     private List<Consumer<R8TestCompileResult>> compileResultConsumers = new ArrayList<>();
     private final boolean normalizeEdges;
     private final boolean extractRules;
+    private boolean enableNative = false;
 
     private R8NativeBuilder(KeepAnnoParameters params, TemporaryFolder temp) {
       super(params, temp);
@@ -189,10 +190,25 @@
     }
 
     @Override
+    public KeepAnnoTestBuilder allowUnusedProguardConfigurationRules() {
+      if (!enableNative) {
+        builder.allowUnusedProguardConfigurationRules();
+      }
+      return this;
+    }
+
+    @Override
     public KeepAnnoTestBuilder enableNativeInterpretation() {
       if (extractRules) {
         return this;
       }
+      enableNative = true;
+      // TODO(b/323816623): The compiler assumes that this is known prior to tracing.
+      //   We should update the compiler to always read annotations and only remove them after
+      //   initial tracing regardless of -keepattributes.
+      builder.addKeepRuntimeVisibleAnnotations();
+      builder.addKeepRuntimeInvisibleAnnotations();
+
       // This enables native interpretation of all keep annotations.
       builder.addOptionsModification(
           o -> {
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepBindingTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepBindingTest.java
index 464ee91..18bc3d5 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepBindingTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepBindingTest.java
@@ -37,6 +37,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepClassRules(A.class, B.class)
         .addKeepMainRule(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepClassApiTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepClassApiTest.java
index 4abe376..8e73b21 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepClassApiTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepClassApiTest.java
@@ -59,6 +59,7 @@
     assertTrue(parameters.isShrinker());
     Box<Path> lib = new Box<>();
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getLibraryClasses())
         .setExcludedOuterClass(getClass())
         .applyIfShrinker(b -> lib.set(b.compile().inspect(this::checkLibraryOutput).writeToZip()));
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepFieldValueApiTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepFieldValueApiTest.java
index 9ac84d1..f9cd926 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepFieldValueApiTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepFieldValueApiTest.java
@@ -58,6 +58,7 @@
     assertTrue(parameters.isShrinker());
     Box<Path> lib = new Box<>();
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getLibraryClasses())
         .setExcludedOuterClass(getClass())
         .applyIfShrinker(b -> lib.set(b.compile().inspect(this::checkLibraryOutput).writeToZip()));
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarAnyClassTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarAnyClassTest.java
index bf82204..76e7a94 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarAnyClassTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarAnyClassTest.java
@@ -35,6 +35,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarSameClassTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarSameClassTest.java
index 0a2e16b..6e287d6 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarSameClassTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepFooIfBarSameClassTest.java
@@ -39,6 +39,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepMembersAccessFlagsTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepMembersAccessFlagsTest.java
index fe8eacd..8d8b397 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepMembersAccessFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepMembersAccessFlagsTest.java
@@ -42,6 +42,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepMembersApiTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepMembersApiTest.java
index c6d3b7d..3ad549d 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepMembersApiTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepMembersApiTest.java
@@ -58,6 +58,7 @@
     assertTrue(parameters.isShrinker());
     Box<Path> lib = new Box<>();
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getLibraryClasses())
         .setExcludedOuterClass(getClass())
         .applyIfShrinker(b -> lib.set(b.compile().inspect(this::checkLibraryOutput).writeToZip()));
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepMethodsAccessFlagsTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepMethodsAccessFlagsTest.java
index 0de2eaf..9dec3d5 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepMethodsAccessFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepMethodsAccessFlagsTest.java
@@ -41,6 +41,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepMethodsEmptyAccessFlagsTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepMethodsEmptyAccessFlagsTest.java
index cac4ddb..e1db615 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepMethodsEmptyAccessFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepMethodsEmptyAccessFlagsTest.java
@@ -40,6 +40,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(TestClass.class)
         .setExcludedOuterClass(getClass())
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepStaticBindingTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepStaticBindingTest.java
index 1fbe385..dca36c5 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepStaticBindingTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepStaticBindingTest.java
@@ -36,6 +36,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByReflectionAnnotationTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByReflectionAnnotationTest.java
index 0bc2417..9190d30 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByReflectionAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByReflectionAnnotationTest.java
@@ -41,6 +41,7 @@
   public void test() throws Exception {
     Class<?> mainClass = TestClass.class;
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(mainClass)
         .setExcludedOuterClass(getClass())
@@ -53,6 +54,7 @@
   public void testNoRef() throws Exception {
     Class<?> mainClass = TestClassNoRef.class;
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .addKeepMainRule(mainClass)
         .allowUnusedProguardConfigurationRules()
diff --git a/src/test/java/com/android/tools/r8/keepanno/MembersAnnotatedByPatternsTest.java b/src/test/java/com/android/tools/r8/keepanno/MembersAnnotatedByPatternsTest.java
index 52850da..35c1494 100644
--- a/src/test/java/com/android/tools/r8/keepanno/MembersAnnotatedByPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/MembersAnnotatedByPatternsTest.java
@@ -47,6 +47,7 @@
   @Test
   public void test() throws Exception {
     testForKeepAnno(parameters)
+        .enableNativeInterpretation()
         .addProgramClasses(getInputClasses())
         .setExcludedOuterClass(getClass())
         .run(TestClass.class)