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;