Add a -neverreprocessclassinitializer directive for testing

Change-Id: I90dbbb4f6c274a9d1c181a784acaa512fb739032
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 7e9ed91..5b1f672 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -473,13 +473,21 @@
           configurationBuilder.addRule(rule);
           return true;
         }
+        if (acceptString("neverreprocessclassinitializer")) {
+          configurationBuilder.addRule(
+              parseReprocessClassInitializerRule(
+                  ReprocessClassInitializerRule.Type.NEVER, optionStart));
+          return true;
+        }
         if (acceptString("neverreprocessmethod")) {
           configurationBuilder.addRule(
               parseReprocessMethodRule(ReprocessMethodRule.Type.NEVER, optionStart));
           return true;
         }
         if (acceptString("reprocessclassinitializer")) {
-          configurationBuilder.addRule(parseReprocessClassInitializerRule(optionStart));
+          configurationBuilder.addRule(
+              parseReprocessClassInitializerRule(
+                  ReprocessClassInitializerRule.Type.ALWAYS, optionStart));
           return true;
         }
         if (acceptString("reprocessmethod")) {
@@ -822,10 +830,11 @@
       return keepRuleBuilder.build();
     }
 
-    private ReprocessClassInitializerRule parseReprocessClassInitializerRule(Position start)
+    private ReprocessClassInitializerRule parseReprocessClassInitializerRule(
+        ReprocessClassInitializerRule.Type type, Position start)
         throws ProguardRuleParserException {
       ReprocessClassInitializerRule.Builder builder =
-          ReprocessClassInitializerRule.builder().setOrigin(origin).setStart(start);
+          ReprocessClassInitializerRule.builder().setOrigin(origin).setStart(start).setType(type);
       parseClassSpec(builder, false);
       Position end = getPosition();
       builder.setSource(getSourceSnippet(contents, start, end));
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
index 41aa9c5..d59c63e 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
@@ -65,6 +65,14 @@
     return null;
   }
 
+  public boolean isReprocessClassInitializerRule() {
+    return false;
+  }
+
+  public ReprocessClassInitializerRule asReprocessClassInitializerRule() {
+    return null;
+  }
+
   public boolean isReprocessMethodRule() {
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/ReprocessClassInitializerRule.java b/src/main/java/com/android/tools/r8/shaking/ReprocessClassInitializerRule.java
index fa7d352..58e03d9 100644
--- a/src/main/java/com/android/tools/r8/shaking/ReprocessClassInitializerRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ReprocessClassInitializerRule.java
@@ -3,19 +3,32 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
+import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.Position;
 import java.util.List;
 
 public class ReprocessClassInitializerRule extends ProguardConfigurationRule {
 
+  public enum Type {
+    ALWAYS,
+    NEVER
+  }
+
   public static class Builder
       extends ProguardConfigurationRule.Builder<ReprocessClassInitializerRule, Builder> {
 
+    private Type type;
+
     private Builder() {
       super();
     }
 
+    public Builder setType(Type type) {
+      this.type = type;
+      return this;
+    }
+
     @Override
     public Builder self() {
       return this;
@@ -36,10 +49,13 @@
           inheritanceAnnotation,
           inheritanceClassName,
           inheritanceIsExtends,
-          memberRules);
+          memberRules,
+          type);
     }
   }
 
+  private final Type type;
+
   private ReprocessClassInitializerRule(
       Origin origin,
       Position position,
@@ -53,7 +69,8 @@
       ProguardTypeMatcher inheritanceAnnotation,
       ProguardTypeMatcher inheritanceClassName,
       boolean inheritanceIsExtends,
-      List<ProguardMemberRule> memberRules) {
+      List<ProguardMemberRule> memberRules,
+      Type type) {
     super(
         origin,
         position,
@@ -68,14 +85,36 @@
         inheritanceClassName,
         inheritanceIsExtends,
         memberRules);
+    this.type = type;
   }
 
   public static Builder builder() {
     return new Builder();
   }
 
+  public Type getType() {
+    return type;
+  }
+
+  @Override
+  public boolean isReprocessClassInitializerRule() {
+    return true;
+  }
+
+  @Override
+  public ReprocessClassInitializerRule asReprocessClassInitializerRule() {
+    return this;
+  }
+
   @Override
   String typeString() {
-    return "reprocessclassinitializer";
+    switch (type) {
+      case ALWAYS:
+        return "reprocessclassinitializer";
+      case NEVER:
+        return "neverreprocessclassinitializer";
+      default:
+        throw new Unreachable();
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index a0576b6..369bcd9 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -3,6 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
+import static com.android.tools.r8.shaking.ReprocessClassInitializerRule.Type.ALWAYS;
+import static com.android.tools.r8.shaking.ReprocessClassInitializerRule.Type.NEVER;
+
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
@@ -1219,7 +1222,16 @@
     } else if (context instanceof ReprocessClassInitializerRule) {
       DexProgramClass clazz = item.asProgramClass();
       if (clazz != null && clazz.hasClassInitializer()) {
-        reprocess.add(clazz.getClassInitializer().method);
+        switch (context.asReprocessClassInitializerRule().getType()) {
+          case ALWAYS:
+            reprocess.add(clazz.getClassInitializer().method);
+            break;
+          case NEVER:
+            neverReprocess.add(clazz.getClassInitializer().method);
+            break;
+          default:
+            throw new Unreachable();
+        }
         context.markAsUsed();
       }
     } else if (context.isReprocessMethodRule()) {
diff --git a/src/test/java/com/android/tools/r8/NeverReprocessClassInitializer.java b/src/test/java/com/android/tools/r8/NeverReprocessClassInitializer.java
new file mode 100644
index 0000000..d0fbd19
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/NeverReprocessClassInitializer.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, 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 java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+public @interface NeverReprocessClassInitializer {}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 569c222..e28b4eb 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -53,6 +53,7 @@
   private boolean enableMemberValuePropagationAnnotations = false;
   private boolean enableMergeAnnotations = false;
   private boolean enableNeverClassInliningAnnotations = false;
+  private boolean enableNeverReprocessClassInitializerAnnotations = false;
   private boolean enableNeverReprocessMethodAnnotations = false;
   private boolean enableReprocessClassInitializerAnnotations = false;
   private boolean enableReprocessMethodAnnotations = false;
@@ -72,6 +73,7 @@
         || enableMemberValuePropagationAnnotations
         || enableMergeAnnotations
         || enableNeverClassInliningAnnotations
+        || enableNeverReprocessClassInitializerAnnotations
         || enableNeverReprocessMethodAnnotations
         || enableReprocessClassInitializerAnnotations
         || enableReprocessMethodAnnotations
@@ -407,6 +409,16 @@
     return self();
   }
 
+  public T enableNeverReprocessClassInitializerAnnotations() {
+    if (!enableNeverReprocessClassInitializerAnnotations) {
+      enableNeverReprocessClassInitializerAnnotations = true;
+      addInternalKeepRules(
+          "-neverreprocessclassinitializer @com.android.tools.r8.NeverReprocessClassInitializer"
+              + " class *");
+    }
+    return self();
+  }
+
   public T enableReprocessMethodAnnotations() {
     if (!enableReprocessMethodAnnotations) {
       enableReprocessMethodAnnotations = true;