From 7fa9ef5689b97f9ef14174192091e89c5f7f2122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Wed, 26 Jul 2023 14:57:38 +0200 Subject: [PATCH 1/7] Update ProGuard default shrinking rules to correctly deal with classes without a no-args constructor --- gson/src/main/resources/META-INF/proguard/gson.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gson/src/main/resources/META-INF/proguard/gson.pro b/gson/src/main/resources/META-INF/proguard/gson.pro index 59d3bb441d..d35b7b14bf 100644 --- a/gson/src/main/resources/META-INF/proguard/gson.pro +++ b/gson/src/main/resources/META-INF/proguard/gson.pro @@ -65,6 +65,6 @@ # See also https://github.com/google/gson/pull/2420#discussion_r1241813541 for a more detailed explanation -if class * -keepclasseswithmembers,allowobfuscation,allowoptimization class <1> { - (); + (...); @com.google.gson.annotations.SerializedName ; } From f60e17d48f8ea44fc95b655bd0ed6d639dee031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Thu, 27 Jul 2023 14:50:44 +0200 Subject: [PATCH 2/7] Update test after changing default shrinking rules --- shrinker-test/common.pro | 48 +++++++++++++++++++ shrinker-test/proguard.pro | 48 ++----------------- shrinker-test/r8.pro | 4 +- .../com/example/DefaultConstructorMain.java | 2 +- 4 files changed, 55 insertions(+), 47 deletions(-) create mode 100644 shrinker-test/common.pro diff --git a/shrinker-test/common.pro b/shrinker-test/common.pro new file mode 100644 index 0000000000..3e8a812041 --- /dev/null +++ b/shrinker-test/common.pro @@ -0,0 +1,48 @@ +### Common rules for ProGuard and R8 +### Should only contains rules needed specifically for the integration test; +### any general rules which are relevant for all users should not be here but in `META-INF/proguard` of Gson + +-allowaccessmodification + +# On Windows mixed case class names might cause problems +-dontusemixedcaseclassnames + +# Ignore notes about duplicate JDK classes +-dontnote module-info,jdk.internal.** + + +# Keep test entrypoints +-keep class com.example.Main { + public static void runTests(...); +} +-keep class com.example.DefaultConstructorMain { + public static java.lang.String runTest(); + public static java.lang.String runTestNoJdkUnsafe(); + public static java.lang.String runTestNoDefaultConstructor(); +} + + +### Test data setup + +# Keep fields without annotations which should be preserved +-keepclassmembers class com.example.ClassWithNamedFields { + !transient ; +} + +-keepclassmembernames class com.example.ClassWithExposeAnnotation { + ; +} +-keepclassmembernames class com.example.ClassWithJsonAdapterAnnotation { + ** f; +} +-keepclassmembernames class com.example.ClassWithVersionAnnotations { + ; +} + + +-keepclassmembernames class com.example.DefaultConstructorMain$TestClass { + ; +} +-keepclassmembernames class com.example.DefaultConstructorMain$TestClassNotAbstract { + ; +} diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index 3e8a812041..9e56e03fb4 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -1,48 +1,8 @@ -### Common rules for ProGuard and R8 -### Should only contains rules needed specifically for the integration test; -### any general rules which are relevant for all users should not be here but in `META-INF/proguard` of Gson +# Include common rules +-include common.pro --allowaccessmodification +### ProGuard specific rules -# On Windows mixed case class names might cause problems --dontusemixedcaseclassnames - -# Ignore notes about duplicate JDK classes --dontnote module-info,jdk.internal.** - - -# Keep test entrypoints --keep class com.example.Main { - public static void runTests(...); -} --keep class com.example.DefaultConstructorMain { - public static java.lang.String runTest(); - public static java.lang.String runTestNoJdkUnsafe(); - public static java.lang.String runTestNoDefaultConstructor(); -} - - -### Test data setup - -# Keep fields without annotations which should be preserved --keepclassmembers class com.example.ClassWithNamedFields { - !transient ; -} - --keepclassmembernames class com.example.ClassWithExposeAnnotation { - ; -} --keepclassmembernames class com.example.ClassWithJsonAdapterAnnotation { - ** f; -} --keepclassmembernames class com.example.ClassWithVersionAnnotations { - ; -} - - --keepclassmembernames class com.example.DefaultConstructorMain$TestClass { - ; -} --keepclassmembernames class com.example.DefaultConstructorMain$TestClassNotAbstract { +-keep class com.example.DefaultConstructorMain$TestClassWithoutDefaultConstructor { ; } diff --git a/shrinker-test/r8.pro b/shrinker-test/r8.pro index 392f0f0d9c..bd5bc0b5d1 100644 --- a/shrinker-test/r8.pro +++ b/shrinker-test/r8.pro @@ -1,5 +1,5 @@ -# Extend the ProGuard rules --include proguard.pro +# Include common rules +-include common.pro ### The following rules are needed for R8 in "full mode", which performs more aggressive optimizations than ProGuard ### See https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#r8-full-mode diff --git a/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java b/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java index 4f0152f7d1..5c61788864 100644 --- a/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java +++ b/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java @@ -20,7 +20,7 @@ static class TestClassNotAbstract { // making class abstract); other constructors are ignored to suggest to user adding default // constructor instead of implicitly relying on JDK Unsafe static class TestClassWithoutDefaultConstructor { - @SerializedName("s") + // No @SerializedName annotation to avoid matching the consumer rules from gson.pro. public String s; public TestClassWithoutDefaultConstructor(String s) { From eea08d09e8ddce9ff54a2e80ada3ae7f640b9989 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 5 Aug 2023 14:26:26 +0200 Subject: [PATCH 3/7] Adjust shrinker tests --- .../main/resources/META-INF/proguard/gson.pro | 5 ++-- shrinker-test/common.pro | 10 +------ shrinker-test/proguard.pro | 11 +++++++- shrinker-test/r8.pro | 6 ++--- .../example/ClassWithDefaultConstructor.java | 4 +++ .../ClassWithoutDefaultConstructor.java | 17 ++++++++++++ .../src/main/java/com/example/Main.java | 11 ++++++++ ...torMain.java => NoSerializedNameMain.java} | 20 +++++++------- .../java/com/google/gson/it/ShrinkingIT.java | 26 ++++++++++++------- 9 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 shrinker-test/src/main/java/com/example/ClassWithoutDefaultConstructor.java rename shrinker-test/src/main/java/com/example/{DefaultConstructorMain.java => NoSerializedNameMain.java} (58%) diff --git a/gson/src/main/resources/META-INF/proguard/gson.pro b/gson/src/main/resources/META-INF/proguard/gson.pro index d35b7b14bf..262878c27a 100644 --- a/gson/src/main/resources/META-INF/proguard/gson.pro +++ b/gson/src/main/resources/META-INF/proguard/gson.pro @@ -59,8 +59,9 @@ (); } -# If a class is used in some way by the application, and has fields annotated with @SerializedName -# and a no-args constructor, keep those fields and the constructor +# If a class is used in some way by the application and has fields annotated with @SerializedName, +# keep those fields and the constructors of the class +# For convenience this also matches classes without no-args constructor, in which case Gson uses JDK Unsafe # Based on https://issuetracker.google.com/issues/150189783#comment11 # See also https://github.com/google/gson/pull/2420#discussion_r1241813541 for a more detailed explanation -if class * diff --git a/shrinker-test/common.pro b/shrinker-test/common.pro index 3e8a812041..ab45d2039a 100644 --- a/shrinker-test/common.pro +++ b/shrinker-test/common.pro @@ -15,7 +15,7 @@ -keep class com.example.Main { public static void runTests(...); } --keep class com.example.DefaultConstructorMain { +-keep class com.example.NoSerializedNameMain { public static java.lang.String runTest(); public static java.lang.String runTestNoJdkUnsafe(); public static java.lang.String runTestNoDefaultConstructor(); @@ -38,11 +38,3 @@ -keepclassmembernames class com.example.ClassWithVersionAnnotations { ; } - - --keepclassmembernames class com.example.DefaultConstructorMain$TestClass { - ; -} --keepclassmembernames class com.example.DefaultConstructorMain$TestClassNotAbstract { - ; -} diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index 9e56e03fb4..ee96073372 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -3,6 +3,15 @@ ### ProGuard specific rules --keep class com.example.DefaultConstructorMain$TestClassWithoutDefaultConstructor { +# Unlike R8, ProGuard does not perform aggressive optimization which makes classes abstract, +# therefore for ProGuard can successfully perform deserialization, and for that need to +# preserve the field names +-keepclassmembernames class com.example.NoSerializedNameMain$TestClass { + ; +} +-keepclassmembernames class com.example.NoSerializedNameMain$TestClassNotAbstract { + ; +} +-keepclassmembernames class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor { ; } diff --git a/shrinker-test/r8.pro b/shrinker-test/r8.pro index bd5bc0b5d1..01b8c84ee2 100644 --- a/shrinker-test/r8.pro +++ b/shrinker-test/r8.pro @@ -10,11 +10,11 @@ -keep,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification class com.example.GenericClasses$GenericUsingGenericClass # Don't obfuscate class name, to check it in exception message --keep,allowshrinking,allowoptimization class com.example.DefaultConstructorMain$TestClass --keep,allowshrinking,allowoptimization class com.example.DefaultConstructorMain$TestClassWithoutDefaultConstructor +-keep,allowshrinking,allowoptimization class com.example.NoSerializedNameMain$TestClass +-keep,allowshrinking,allowoptimization class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor # This rule has the side-effect that R8 still removes the no-args constructor, but does not make the class abstract --keep class com.example.DefaultConstructorMain$TestClassNotAbstract { +-keep class com.example.NoSerializedNameMain$TestClassNotAbstract { @com.google.gson.annotations.SerializedName ; } diff --git a/shrinker-test/src/main/java/com/example/ClassWithDefaultConstructor.java b/shrinker-test/src/main/java/com/example/ClassWithDefaultConstructor.java index 6296237f66..6cff119011 100644 --- a/shrinker-test/src/main/java/com/example/ClassWithDefaultConstructor.java +++ b/shrinker-test/src/main/java/com/example/ClassWithDefaultConstructor.java @@ -2,6 +2,10 @@ import com.google.gson.annotations.SerializedName; +/** + * Class with no-args default constructor and with field annotated with + * {@link SerializedName}. + */ public class ClassWithDefaultConstructor { @SerializedName("myField") public int i; diff --git a/shrinker-test/src/main/java/com/example/ClassWithoutDefaultConstructor.java b/shrinker-test/src/main/java/com/example/ClassWithoutDefaultConstructor.java new file mode 100644 index 0000000000..2af573677a --- /dev/null +++ b/shrinker-test/src/main/java/com/example/ClassWithoutDefaultConstructor.java @@ -0,0 +1,17 @@ +package com.example; + +import com.google.gson.annotations.SerializedName; + +/** + * Class without no-args default constructor, but with field annotated with + * {@link SerializedName}. + */ +public class ClassWithoutDefaultConstructor { + @SerializedName("myField") + public int i; + + // Specify explicit constructor with args to remove implicit no-args default constructor + public ClassWithoutDefaultConstructor(int i) { + this.i = i; + } +} diff --git a/shrinker-test/src/main/java/com/example/Main.java b/shrinker-test/src/main/java/com/example/Main.java index 55bbb6377d..488bc03b82 100644 --- a/shrinker-test/src/main/java/com/example/Main.java +++ b/shrinker-test/src/main/java/com/example/Main.java @@ -32,6 +32,7 @@ public static void runTests(BiConsumer outputConsumer) { testNamedFields(outputConsumer); testSerializedName(outputConsumer); + testNoDefaultConstructor(outputConsumer); testNoJdkUnsafe(outputConsumer); testEnum(outputConsumer); @@ -89,6 +90,16 @@ private static void testSerializedName(BiConsumer outputConsumer }); } + private static void testNoDefaultConstructor(BiConsumer outputConsumer) { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + TestExecutor.run(outputConsumer, "Write: No default constructor", () -> toJson(gson, new ClassWithoutDefaultConstructor(2))); + // This most likely relies on JDK Unsafe (unless the shrinker rewrites the constructor in some way) + TestExecutor.run(outputConsumer, "Read: No default constructor", () -> { + ClassWithoutDefaultConstructor deserialized = fromJson(gson, "{\"myField\": 3}", ClassWithoutDefaultConstructor.class); + return Integer.toString(deserialized.i); + }); + } + private static void testNoJdkUnsafe(BiConsumer outputConsumer) { Gson gson = new GsonBuilder().disableJdkUnsafe().create(); TestExecutor.run(outputConsumer, "Read: No JDK Unsafe; initial constructor value", () -> { diff --git a/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java b/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java similarity index 58% rename from shrinker-test/src/main/java/com/example/DefaultConstructorMain.java rename to shrinker-test/src/main/java/com/example/NoSerializedNameMain.java index 5c61788864..cd70af34a7 100644 --- a/shrinker-test/src/main/java/com/example/DefaultConstructorMain.java +++ b/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java @@ -4,32 +4,32 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; -public class DefaultConstructorMain { +/** + * Covers cases of classes which don't use {@code @SerializedName} on their fields, and are + * therefore not matched by the default {@code gson.pro} rules. + */ +public class NoSerializedNameMain { static class TestClass { public String s; } - // R8 rule for this class still removes no-args constructor, but doesn't make class abstract + // R8 test rule in r8.pro for this class still removes no-args constructor, but doesn't make class abstract static class TestClassNotAbstract { public String s; } - // Current Gson ProGuard rules only keep default constructor (and only then prevent R8 from - // making class abstract); other constructors are ignored to suggest to user adding default - // constructor instead of implicitly relying on JDK Unsafe static class TestClassWithoutDefaultConstructor { - // No @SerializedName annotation to avoid matching the consumer rules from gson.pro. public String s; + // Specify explicit constructor with args to remove implicit no-args default constructor public TestClassWithoutDefaultConstructor(String s) { this.s = s; } } /** - * Main entrypoint, called by {@code ShrinkingIT.testDefaultConstructor()}. + * Main entrypoint, called by {@code ShrinkingIT.testNoSerializedName_DefaultConstructor()}. */ public static String runTest() { TestClass deserialized = new Gson().fromJson("{\"s\":\"value\"}", same(TestClass.class)); @@ -37,7 +37,7 @@ public static String runTest() { } /** - * Main entrypoint, called by {@code ShrinkingIT.testDefaultConstructorNoJdkUnsafe()}. + * Main entrypoint, called by {@code ShrinkingIT.testNoSerializedName_DefaultConstructorNoJdkUnsafe()}. */ public static String runTestNoJdkUnsafe() { Gson gson = new GsonBuilder().disableJdkUnsafe().create(); @@ -46,7 +46,7 @@ public static String runTestNoJdkUnsafe() { } /** - * Main entrypoint, called by {@code ShrinkingIT.testNoDefaultConstructor()}. + * Main entrypoint, called by {@code ShrinkingIT.testNoSerializedName_NoDefaultConstructor()}. */ public static String runTestNoDefaultConstructor() { TestClassWithoutDefaultConstructor deserialized = new Gson().fromJson("{\"s\":\"value\"}", same(TestClassWithoutDefaultConstructor.class)); diff --git a/shrinker-test/src/test/java/com/google/gson/it/ShrinkingIT.java b/shrinker-test/src/test/java/com/google/gson/it/ShrinkingIT.java index 3304570197..d9d8d56cfb 100644 --- a/shrinker-test/src/test/java/com/google/gson/it/ShrinkingIT.java +++ b/shrinker-test/src/test/java/com/google/gson/it/ShrinkingIT.java @@ -127,6 +127,14 @@ public void test() throws Exception { "Read: SerializedName", "3", "===", + "Write: No default constructor", + "{", + " \"myField\": 2", + "}", + "===", + "Read: No default constructor", + "3", + "===", "Read: No JDK Unsafe; initial constructor value", "-3", "===", @@ -181,8 +189,8 @@ public void test() throws Exception { } @Test - public void testDefaultConstructor() throws Exception { - runTest("com.example.DefaultConstructorMain", c -> { + public void testNoSerializedName_DefaultConstructor() throws Exception { + runTest("com.example.NoSerializedNameMain", c -> { Method m = c.getMethod("runTest"); if (jarToTest.equals(PROGUARD_RESULT_PATH)) { @@ -193,7 +201,7 @@ public void testDefaultConstructor() throws Exception { Exception e = assertThrows(InvocationTargetException.class, () -> m.invoke(null)); assertThat(e).hasCauseThat().hasMessageThat().isEqualTo( "Abstract classes can't be instantiated! Adjust the R8 configuration or register an InstanceCreator" - + " or a TypeAdapter for this type. Class name: com.example.DefaultConstructorMain$TestClass" + + " or a TypeAdapter for this type. Class name: com.example.NoSerializedNameMain$TestClass" + "\nSee https://github.com/google/gson/blob/main/Troubleshooting.md#r8-abstract-class" ); } @@ -201,8 +209,8 @@ public void testDefaultConstructor() throws Exception { } @Test - public void testDefaultConstructorNoJdkUnsafe() throws Exception { - runTest("com.example.DefaultConstructorMain", c -> { + public void testNoSerializedName_DefaultConstructorNoJdkUnsafe() throws Exception { + runTest("com.example.NoSerializedNameMain", c -> { Method m = c.getMethod("runTestNoJdkUnsafe"); if (jarToTest.equals(PROGUARD_RESULT_PATH)) { @@ -212,7 +220,7 @@ public void testDefaultConstructorNoJdkUnsafe() throws Exception { // R8 performs more aggressive optimizations Exception e = assertThrows(InvocationTargetException.class, () -> m.invoke(null)); assertThat(e).hasCauseThat().hasMessageThat().isEqualTo( - "Unable to create instance of class com.example.DefaultConstructorMain$TestClassNotAbstract;" + "Unable to create instance of class com.example.NoSerializedNameMain$TestClassNotAbstract;" + " usage of JDK Unsafe is disabled. Registering an InstanceCreator or a TypeAdapter for this type," + " adding a no-args constructor, or enabling usage of JDK Unsafe may fix this problem. Or adjust" + " your R8 configuration to keep the no-args constructor of the class." @@ -222,8 +230,8 @@ public void testDefaultConstructorNoJdkUnsafe() throws Exception { } @Test - public void testNoDefaultConstructor() throws Exception { - runTest("com.example.DefaultConstructorMain", c -> { + public void testNoSerializedName_NoDefaultConstructor() throws Exception { + runTest("com.example.NoSerializedNameMain", c -> { Method m = c.getMethod("runTestNoDefaultConstructor"); if (jarToTest.equals(PROGUARD_RESULT_PATH)) { @@ -234,7 +242,7 @@ public void testNoDefaultConstructor() throws Exception { Exception e = assertThrows(InvocationTargetException.class, () -> m.invoke(null)); assertThat(e).hasCauseThat().hasMessageThat().isEqualTo( "Abstract classes can't be instantiated! Adjust the R8 configuration or register an InstanceCreator" - + " or a TypeAdapter for this type. Class name: com.example.DefaultConstructorMain$TestClassWithoutDefaultConstructor" + + " or a TypeAdapter for this type. Class name: com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor" + "\nSee https://github.com/google/gson/blob/main/Troubleshooting.md#r8-abstract-class" ); } From c34126bb2827099d32dacfd1fd29d77e7276fb62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Thu, 10 Aug 2023 13:27:32 +0200 Subject: [PATCH 4/7] Update rules --- .../main/resources/META-INF/proguard/gson.pro | 28 +++++++++---------- shrinker-test/proguard.pro | 3 ++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/gson/src/main/resources/META-INF/proguard/gson.pro b/gson/src/main/resources/META-INF/proguard/gson.pro index 262878c27a..e5aa2f1515 100644 --- a/gson/src/main/resources/META-INF/proguard/gson.pro +++ b/gson/src/main/resources/META-INF/proguard/gson.pro @@ -15,13 +15,13 @@ # Note: Cannot perform finer selection here to only cover Gson annotations, see also https://stackoverflow.com/q/47515093 -keepattributes RuntimeVisibleAnnotations,AnnotationDefault - ### The following rules are needed for R8 in "full mode" which only adheres to `-keepattribtues` if ### the corresponding class or field is matches by a `-keep` rule as well, see ### https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#r8-full-mode -# Keep class TypeToken (respectively its generic signature) --keep class com.google.gson.reflect.TypeToken { *; } +# Keep class TypeToken (respectively its generic signature) if present +-if class com.google.gson.reflect.TypeToken +-keep,allowobfuscation class com.google.gson.reflect.TypeToken # Keep any (anonymous) classes extending TypeToken -keep,allowobfuscation class * extends com.google.gson.reflect.TypeToken @@ -29,11 +29,6 @@ # Keep classes with @JsonAdapter annotation -keep,allowobfuscation,allowoptimization @com.google.gson.annotations.JsonAdapter class * -# Keep fields with @SerializedName annotation, but allow obfuscation of their names --keepclassmembers,allowobfuscation class * { - @com.google.gson.annotations.SerializedName ; -} - # Keep fields with any other Gson annotation # Also allow obfuscation, assuming that users will additionally use @SerializedName or # other means to preserve the field names @@ -59,13 +54,16 @@ (); } -# If a class is used in some way by the application and has fields annotated with @SerializedName, -# keep those fields and the constructors of the class -# For convenience this also matches classes without no-args constructor, in which case Gson uses JDK Unsafe -# Based on https://issuetracker.google.com/issues/150189783#comment11 -# See also https://github.com/google/gson/pull/2420#discussion_r1241813541 for a more detailed explanation +# Keep fields annotated with @SerializedName for classes which are present. +# If classes with fields annotated with @SerializedName have a no-args +# constructor keep that as well. -if class * --keepclasseswithmembers,allowobfuscation,allowoptimization class <1> { - (...); +-keepclasseswithmembers,allowobfuscation class <1> { @com.google.gson.annotations.SerializedName ; } +-if class * { + @com.google.gson.annotations.SerializedName ; +} +-keepclassmembers,allowobfuscation class <1> { + (); +} diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index ee96073372..987f4d377d 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -15,3 +15,6 @@ -keepclassmembernames class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor { ; } +#-keep class com.example.ClassWithSerializedName { +# (...); +#} From ac6e590953f558c0ea247b0e3bc077c9bd4f1e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Tue, 15 Aug 2023 10:53:35 +0200 Subject: [PATCH 5/7] Addressed review comments --- gson/src/main/resources/META-INF/proguard/gson.pro | 10 +++++++--- shrinker-test/common.pro | 2 ++ shrinker-test/proguard.pro | 6 ------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gson/src/main/resources/META-INF/proguard/gson.pro b/gson/src/main/resources/META-INF/proguard/gson.pro index e5aa2f1515..f9eb83e849 100644 --- a/gson/src/main/resources/META-INF/proguard/gson.pro +++ b/gson/src/main/resources/META-INF/proguard/gson.pro @@ -22,6 +22,7 @@ # Keep class TypeToken (respectively its generic signature) if present -if class com.google.gson.reflect.TypeToken -keep,allowobfuscation class com.google.gson.reflect.TypeToken +#-keep class com.google.gson.reflect.TypeToken { *; } # Keep any (anonymous) classes extending TypeToken -keep,allowobfuscation class * extends com.google.gson.reflect.TypeToken @@ -54,9 +55,12 @@ (); } -# Keep fields annotated with @SerializedName for classes which are present. +# Keep fields annotated with @SerializedName for classes which are referenced. # If classes with fields annotated with @SerializedName have a no-args -# constructor keep that as well. +# constructor keep that as well. Based on +# https://issuetracker.google.com/issues/150189783#comment11. +# See also https://github.com/google/gson/pull/2420#discussion_r1241813541 +# for a more detailed explanation. -if class * -keepclasseswithmembers,allowobfuscation class <1> { @com.google.gson.annotations.SerializedName ; @@ -64,6 +68,6 @@ -if class * { @com.google.gson.annotations.SerializedName ; } --keepclassmembers,allowobfuscation class <1> { +-keepclassmembers,allowobfuscation,allowoptimization class <1> { (); } diff --git a/shrinker-test/common.pro b/shrinker-test/common.pro index ab45d2039a..ec34c2eef9 100644 --- a/shrinker-test/common.pro +++ b/shrinker-test/common.pro @@ -38,3 +38,5 @@ -keepclassmembernames class com.example.ClassWithVersionAnnotations { ; } + +-dontobfuscate diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index 987f4d377d..c80942c121 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -12,9 +12,3 @@ -keepclassmembernames class com.example.NoSerializedNameMain$TestClassNotAbstract { ; } --keepclassmembernames class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor { - ; -} -#-keep class com.example.ClassWithSerializedName { -# (...); -#} From 8d14f1a8ef1d2f9c1237a6f48e917f0c4e391989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Mon, 21 Aug 2023 14:12:29 +0200 Subject: [PATCH 6/7] Addressed more review comments --- gson/src/main/resources/META-INF/proguard/gson.pro | 1 - shrinker-test/common.pro | 4 +--- shrinker-test/proguard.pro | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gson/src/main/resources/META-INF/proguard/gson.pro b/gson/src/main/resources/META-INF/proguard/gson.pro index f9eb83e849..8f5a69b30f 100644 --- a/gson/src/main/resources/META-INF/proguard/gson.pro +++ b/gson/src/main/resources/META-INF/proguard/gson.pro @@ -22,7 +22,6 @@ # Keep class TypeToken (respectively its generic signature) if present -if class com.google.gson.reflect.TypeToken -keep,allowobfuscation class com.google.gson.reflect.TypeToken -#-keep class com.google.gson.reflect.TypeToken { *; } # Keep any (anonymous) classes extending TypeToken -keep,allowobfuscation class * extends com.google.gson.reflect.TypeToken diff --git a/shrinker-test/common.pro b/shrinker-test/common.pro index ec34c2eef9..e4444aa3c4 100644 --- a/shrinker-test/common.pro +++ b/shrinker-test/common.pro @@ -37,6 +37,4 @@ } -keepclassmembernames class com.example.ClassWithVersionAnnotations { ; -} - --dontobfuscate +} \ No newline at end of file diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index c80942c121..9b872b5d3c 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -12,3 +12,6 @@ -keepclassmembernames class com.example.NoSerializedNameMain$TestClassNotAbstract { ; } +-keepclassmembernames class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor { + ; +} \ No newline at end of file From 743d5295df795da167a8e3185969160f65c64320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Mon, 21 Aug 2023 14:12:29 +0200 Subject: [PATCH 7/7] Addressed more review comments --- shrinker-test/common.pro | 2 +- shrinker-test/proguard.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shrinker-test/common.pro b/shrinker-test/common.pro index e4444aa3c4..ab45d2039a 100644 --- a/shrinker-test/common.pro +++ b/shrinker-test/common.pro @@ -37,4 +37,4 @@ } -keepclassmembernames class com.example.ClassWithVersionAnnotations { ; -} \ No newline at end of file +} diff --git a/shrinker-test/proguard.pro b/shrinker-test/proguard.pro index 9b872b5d3c..ee96073372 100644 --- a/shrinker-test/proguard.pro +++ b/shrinker-test/proguard.pro @@ -14,4 +14,4 @@ } -keepclassmembernames class com.example.NoSerializedNameMain$TestClassWithoutDefaultConstructor { ; -} \ No newline at end of file +}