Skip to content

Revised the ProGuard rules and added tests on R8 #3041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

shanshin
Copy link
Contributor

  • The warning message about unusual symbols in field type is eliminated.
  • Added correct rules for named companions
  • Changed code for the locating name companion by annotation. Since the list of nested classes is not saved by R8, static fields are analyzed
  • added tests on the rules using R8 in full mode and ProGuard compatibility mode

Fixes #3033

@shanshin shanshin requested a review from sandwwraith July 11, 2025 09:32
woainikk and others added 3 commits July 15, 2025 14:41
serializer(typeOf<SealedInterface>()).descriptor.toString()
)
}
assertSame<KSerializer<*>>(PlainSerializer, serializer(typeOf<PlainWithCustom>()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change related? I suggest extracting it to separate commit

Also change base branch to dev btw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fully related but I think we should add these changes somewhere

}

tasks.compileTestKotlin {
configureCompilation(true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to call function with explicit parameter name: configureCompilation(r8FullMode = true)

return R8CheckerImpl(parseR8Output(mapFile, usageFile))
}

interface R8Checker {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should do interface/Impl split in a 250-lines-long utils file for a small test

private fun <T : Any> Class<T>.findNamedCompanionByAnnotation(): Any? {
// search static field with type marked by kotlinx.serialization.internal.NamedCompanion - it's the companion
val field = declaredFields.firstOrNull { field ->
Modifier.isStatic(field.modifiers) && field.type.getAnnotation(NamedCompanion::class.java) != null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention in the comment that declaredClasses unavailable after R8


sourceSets {
// create the source set for storing sources and using dependency configuration
val common by creating
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

common name can be misleading because of the strong associations with MPP. Also, test/testCompatible names themselves are quite vague. WDYT of renaming everything to:

  • '(test)Shared'
  • 'testR8Full'
  • 'testPGCompatible'

Or something similar.

Also, you can just reuse regular main sourceset?

}
}
} else {
current.fields.put(name, FieldEntry(name, returnType, obfuscated))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is it different from fieldRegex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused branch

// process usage.txt
var currentUsageClass: ClassEntry? = null

usageFile.forEachLine { raw ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this file contains methods that were removed due to being unused, then it better be named unused.txt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same question :)
But it's common name for this files in Android.

val unusedClass = checker.findClass("kotlinx.serialization.r8.UnusedClass")
assertTrue(unusedClass.isShrunk)

ObfuscatedClass("World").used()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this line causes test to fail, so it's technically a test data. Maybe put this call to some top-level function in Model.kt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move this call to Model.kt it will be shrinked as only *Tests classes are alwayes kept. So I move it to separate method in R8Tests.

}



Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary blank lines

@@ -82,6 +82,9 @@ project(":benchmark").projectDir = file("./benchmark")
include(":guide")
project(":guide").projectDir = file("./guide")

include(":proguard-rules")
project(":proguard-rules").projectDir = file("./rules")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be named proguard-rules-test, because rules on their own are just a bunch of .pro files and do not need Gradle module

shanshin added 3 commits July 29, 2025 17:12
- The warning message about unusual symbols in field type is eliminated.
- Added correct rules for named companions
- Changed code for the locating name companion by annotation. Since the list of nested classes is not saved by R8, static fields are analyzed
- added tests on the rules using R8 in full mode and ProGuard compatibility mode

Fixes #3033
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New ProGuard implementation in #2983 causes R8 warning
5 participants