Prune signature attribute if not kept and not in fullmode

Bug: 170077516
Change-Id: I9c892f2624b2db5e494fc1f20865fdbeafad6775
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 46e4629..fc6cb56 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 import java.util.IdentityHashMap;
@@ -27,6 +28,7 @@
 public class AnnotationRemover {
 
   private final AppView<AppInfoWithLiveness> appView;
+  private final InternalOptions options;
   private final Set<DexAnnotation> annotationsToRetain;
   private final Set<DexType> classesToRetainInnerClassAttributeFor;
   private final ProguardKeepAttributes keep;
@@ -38,6 +40,7 @@
       Set<DexAnnotation> annotationsToRetain,
       Set<DexType> removedClasses) {
     this.appView = appView;
+    this.options = appView.options();
     this.annotationsToRetain = annotationsToRetain;
     this.classesToRetainInnerClassAttributeFor = classesToRetainInnerClassAttributeFor;
     this.keep = appView.options().getProguardConfiguration().getKeepAttributes();
@@ -187,25 +190,31 @@
       stripAttributes(clazz);
       clazz.setAnnotations(
           clazz.annotations().rewrite(annotation -> rewriteAnnotation(clazz, annotation)));
-      clazz.forEachMethod(this::processMethod);
-      clazz.forEachField(this::processField);
+      clazz.forEachMethod(method -> processMethod(method, clazz));
+      clazz.forEachField(field -> processField(field, clazz));
     }
   }
 
-  private void processMethod(DexEncodedMethod method) {
+  private void processMethod(DexEncodedMethod method, DexProgramClass clazz) {
     method.setAnnotations(
         method.annotations().rewrite(annotation -> rewriteAnnotation(method, annotation)));
     method.parameterAnnotationsList =
         method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
-    if (!keep.signature) {
+    if (appView
+        .getKeepInfo()
+        .getMethodInfo(method, clazz)
+        .isAllowSignatureAttributeRemovalAllowed(options)) {
       method.clearGenericSignature();
     }
   }
 
-  private void processField(DexEncodedField field) {
+  private void processField(DexEncodedField field, DexProgramClass clazz) {
     field.setAnnotations(
         field.annotations().rewrite(annotation -> rewriteAnnotation(field, annotation)));
-    if (!keep.signature) {
+    if (appView
+        .getKeepInfo()
+        .getFieldInfo(field, clazz)
+        .isAllowSignatureAttributeRemovalAllowed(options)) {
       field.clearGenericSignature();
     }
   }
@@ -321,8 +330,10 @@
       clazz.clearEnclosingMethodAttribute();
       clazz.clearInnerClasses();
     }
-    // TODO(b/170077516): Prune attributes.
-    if (!keep.signature) {
+    if (appView
+        .getKeepInfo()
+        .getClassInfo(clazz)
+        .isAllowSignatureAttributeRemovalAllowed(options)) {
       clazz.clearClassSignature();
     }
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/gson.cfg b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/gson.cfg
index da7bcba..e7560e1f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/gson.cfg
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/gson.cfg
@@ -14,11 +14,11 @@
 -dontwarn sun.misc.Unsafe
 
 # Application classes that will be serialized/deserialized over Gson
--keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClasses$Data { <fields>; }
--keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClasses$NullableConcurrentHashMap
--keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClasses$NullableHashMap
--keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClasses$NullableMap
--keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClasses$NullableConcurrentMap
+-keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClass$Data { <fields>; }
+-keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClass$NullableConcurrentHashMap
+-keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClass$NullableHashMap
+-keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClass$NullableMap
+-keep class com.android.tools.r8.desugar.desugaredlibrary.gson.AllMapsTestClass$NullableConcurrentMap
 -keep class com.android.tools.r8.desugar.desugaredlibrary.gson.OptionalTestClass$Data { <fields>; }
 
 # Prevent R8 from stripping interface information from TypeAdapter, TypeAdapterFactory,
@@ -28,6 +28,9 @@
 -keep class * implements com.google.gson.JsonSerializer
 -keep class * implements com.google.gson.JsonDeserializer
 
+# Prevent R8 from removing the generic signature of TypeToken
+-keep,allowobfuscation class * extends com.google.gson.reflect.TypeToken
+
 # Prevent R8 from leaving Data object members always null
 -keepclassmembers,allowobfuscation class * {
   @com.google.gson.annotations.SerializedName <fields>;
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
index 6ababf1..d56503c 100644
--- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
+++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -63,7 +63,7 @@
   @Test
   public void test() throws Exception {
     R8TestCompileResult compileResult =
-        testForR8(parameters.getBackend())
+        testForR8Compat(parameters.getBackend())
             .addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class)
             .addKeepMainRule(Main.class)
             .addKeepAttributes(
diff --git a/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java b/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
index e945182..65445a7 100644
--- a/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
@@ -85,6 +85,7 @@
         .addKeepAttributes(ProguardKeepAttributes.SIGNATURE)
         .addKeepAttributes(ProguardKeepAttributes.INNER_CLASSES)
         .addKeepAttributes(ProguardKeepAttributes.ENCLOSING_METHOD)
+        .addKeepAllClassesRuleWithAllowObfuscation()
         .addKeepMainRule(Main.class)
         .addProgramClasses(Main.class)
         .addProgramClassesAndInnerClasses(A.class, B.class, CY.class, CYY.class)
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/ClassSignaturesTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/ClassSignaturesTest.java
deleted file mode 100644
index 7ca532d..0000000
--- a/src/test/java/com/android/tools/r8/shaking/attributes/ClassSignaturesTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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.shaking.attributes;
-
-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-
-import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.shaking.ProguardKeepAttributes;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.Iterator;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class ClassSignaturesTest extends TestBase {
-
-  private final TestParameters parameters;
-  private final String EXPECTED = "Hello World!";
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimesAndApiLevels().build();
-  }
-
-  public ClassSignaturesTest(TestParameters parameters) {
-    this.parameters = parameters;
-  }
-
-  @Test
-  public void testRuntime() throws Exception {
-    testForRuntime(parameters)
-        .addProgramClasses(A.class, Main.class)
-        .run(parameters.getRuntime(), Main.class)
-        .assertSuccessWithOutputLines(EXPECTED)
-        .inspect(this::inspect);
-  }
-
-  @Test
-  public void testR8() throws Exception {
-    testForR8(parameters.getBackend())
-        .addProgramClasses(A.class, Main.class)
-        .addKeepMainRule(Main.class)
-        .setMinApi(parameters.getApiLevel())
-        .enableNeverClassInliningAnnotations()
-        .enableInliningAnnotations()
-        .addKeepAttributes(
-            ProguardKeepAttributes.SIGNATURE,
-            ProguardKeepAttributes.INNER_CLASSES,
-            ProguardKeepAttributes.ENCLOSING_METHOD)
-        .run(parameters.getRuntime(), Main.class)
-        .assertSuccessWithOutputLines(EXPECTED)
-        .inspect(this::inspect);
-  }
-
-  private void inspect(CodeInspector inspector) {
-    ClassSubject aClass = inspector.clazz(A.class);
-    assertThat(aClass, isPresent());
-    assertEquals(
-        "Ljava/lang/Object;Ljava/lang/Iterable<"
-            + "Lcom/android/tools/r8/shaking/attributes/ClassSignaturesTest$Main;>;",
-        aClass.getFinalSignatureAttribute());
-  }
-
-  @NeverClassInline
-  public static class A implements Iterable<Main> {
-
-    @Override
-    @NeverInline
-    public Iterator<Main> iterator() {
-      throw new RuntimeException("FooBar");
-    }
-  }
-
-  public static class Main {
-
-    public static void main(String[] args) {
-      try {
-        new A().iterator();
-      } catch (RuntimeException e) {
-        if (!e.getMessage().contains("FooBar")) {
-          throw e;
-        }
-        System.out.println("Hello World!");
-      }
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
index b441e6b..05f9731 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepSignatureTest.java
@@ -56,8 +56,7 @@
 
   @Test
   public void testKeptClassFieldAndMethodFull() throws Exception {
-    // TODO(b/170077516): The below should pass in false.
-    runTest(testForR8(parameters.getBackend()), true);
+    runTest(testForR8(parameters.getBackend()), false);
   }
 
   @Test