'How to keep class' members untouched if it contains a field with an annotation in proguard

How do I configure proguard/R8 to keep all the fields and methods of a class if the class contains an annotated field?

I have a class

public class MyDocument {
  @DocumentId
  private String foo;

  private String bar;

  public getFoo() { .. }
  public getBar() { .. }
}

I was able to make it not remove foo with

-keepclassmembers class * {
  @a.b.c.DocumentId <fields>;
  @a.b.c.DocumentId <methods>;
}

But it still removes getBar()

Is there any way to say "don't remove any methods or fields in a class if one of the fields in the same class contains the annotation?

The usecase here is that they are DTO classes used by firestore's toObject
I don't want to do the matching based on the name of the class since this rule will apply to many classes.



Solution 1:[1]

I just read about -keepclasseswithmembers, which would equate to an inferred @Keep based on the contents of the class:

-keepclasseswithmembers class * { 
  @a.b.c.DocumentId <fields>;
}

A more strict alternative that really boils down to the -keepclassmembers would be to annotate the DTOs with something r8 can detect (for example, an annotation with retention=runtime) and then just target that annotation in the rule:

-keepclassmembers @a.b.c.Dto class *

Solution 2:[2]

You should be able to use a conditional rule like this:

-if class * {
  @a.b.c.DocumentId *** *;
}
-keep class <1> {
  *;
}

Which says exactly that if a class has a field with the annotation, then keep all members of that class.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 karllindmark
Solution 2 aruh