Skip to content

ADFA-3604: Re-enable R8 shrinking with keep rules for kotlin-analysis-api - #1596

Merged
davidschachterADFA merged 4 commits into
stagefrom
chore/ADFA-3604-analyze-dex-code-bloat
Jul 30, 2026
Merged

ADFA-3604: Re-enable R8 shrinking with keep rules for kotlin-analysis-api#1596
davidschachterADFA merged 4 commits into
stagefrom
chore/ADFA-3604-analyze-dex-code-bloat

Conversation

@davidschachterADFA

@davidschachterADFA davidschachterADFA commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • ADFA-3604 asked us to investigate why classes*.dex exceeds 108 MB. The single biggest contributor turned out to be the bundled Kotlin Analysis API jar (used for in-editor Kotlin code intelligence): 43,951 classes / ~18.4 MB, ~42% of all dex bytecode.
  • R8 shrinking is already wired on for :app release (isMinifyEnabled = isAppModule), but app/proguard-rules.pro had a blanket -dontshrink added in ADFA-996 after shrinking broke release-build project init — neutering shrinking entirely ever since.
  • This PR removes -dontshrink and adds targeted -keep rules to subprojects/kotlin-analysis-api/consumer-rules.pro for every class the jar loads reflectively via IntelliJ plugin XML descriptors (Core.xml, CoreImpl.xml, JavaPsiPlugin.xml, analysis-api/*.xml) and META-INF/services ServiceLoader entries — the paths R8 can't trace from bytecode reachability alone.

Trial results

Local release build (:app:assembleV8Release), before vs after:

Before After
Dex files 16 4
Total size 119.4 MB 28.8 MB
Total classes 104,033 24,853
org.jetbrains.kotlin.* (analysis API) 43,951 classes / 18.4 MB 4,818 classes / 2.28 MB

Spot-checked R8's usage.txt and the output dex directly: MainActivity, OnboardingActivity, CrashHandlerActivity, and the Kotlin LSP classes are all still present. The com.itsaky.androidide.* entries R8 removed are unused synthetic R$/BuildConfig classes and dead private members, not core app code.

Risk

ADFA-996's prior shrink attempt failed at runtime (release-build project init), not at build time — static analysis and a build-succeeds check don't rule that out here. No ARM device was available to install and exercise the shrunk APK before opening this PR, particularly Kotlin autocomplete/diagnostics (the exact feature the new keep rules protect).

Test plan

  • Install a release build from this branch on a physical ARM device
  • Verify app launches and onboarding/main flow works
  • Open a Kotlin file and verify autocomplete and diagnostics work (go-to-definition is not implemented for Kotlin files in this codebase yet -- see PR comment)
  • Confirm no crashes during project init/sync

🤖 Generated with Claude Code

…-api

Removes the blanket -dontshrink added in ADFA-996, which neutered R8
shrinking entirely after it broke release-build project init. Adds
targeted keep rules for every class the bundled kotlin-analysis-api jar
loads reflectively via IntelliJ plugin XML descriptors and
ServiceLoader entries, since those are the paths R8 can't trace from
bytecode reachability alone.

Cuts release dex from 119.4 MB / 104,033 classes to 28.8 MB / 24,853
classes in a trial build. Not yet verified on a physical device.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

R8 shrinking is re-enabled for the application, while consumer rules preserve Kotlin analysis and IntelliJ classes instantiated through plugin descriptors and ServiceLoader.

Changes

R8 preservation configuration

Layer / File(s) Summary
Kotlin analysis consumer keep rules
subprojects/kotlin-analysis-api/consumer-rules.pro
Documents and adds generated keep rules for IntelliJ, Kotlin analysis API, FIR, decompiler, and UAST classes loaded reflectively or through ServiceLoader.
Application shrinking enablement
app/proguard-rules.pro
Removes the global -dontshrink directive so R8 can shrink unused classes.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

Suggested reviewers: hal-eisen-adfa

Poem

I’m a little rabbit guarding the keep,
While R8 trims classes in its sleep.
Plugin names sparkle, services stay bright,
Kotlin analysis hops through the night.
Shrink on, keep safe—what a fine feat! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: re-enabling R8 shrinking with targeted keep rules for kotlin-analysis-api.
Description check ✅ Passed The description is directly related to the changeset and accurately explains the shrink/keep-rule changes and rationale.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/ADFA-3604-analyze-dex-code-bloat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
subprojects/kotlin-analysis-api/consumer-rules.pro (1)

9-360: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the maintenance/refresh process for this keep-rule list.

This file replaces a blanket -dontshrink with ~350 hand-enumerated FQCN keep rules. That's the right tradeoff for size, but it's brittle against future upgrades of the bundled Kotlin Analysis API / IntelliJ platform jars: if a class referenced here is renamed or removed upstream, R8 will typically just drop the now-unresolvable keep rule (or warn) rather than fail the build, so breakage would only surface at runtime via ServiceConfigurationError/ClassNotFoundException — exactly the kind of regression the PR flags as still needing physical-device validation.

Consider adding a short note (here or in the ticket) on how this list was derived (e.g., scanning META-INF/services/* and plugin XML descriptors) and how to regenerate/diff it on future dependency bumps, so staleness is caught deliberately rather than discovered in the field.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@subprojects/kotlin-analysis-api/consumer-rules.pro` around lines 9 - 360,
Document how the hand-maintained keep-rule list was generated, including
scanning META-INF/services entries and plugin XML descriptors, and describe the
steps to regenerate and diff it after Kotlin Analysis API or IntelliJ platform
dependency upgrades. Add this maintenance note near the keep rules or in the
associated tracking documentation, referencing the enumerated FQCN rules as the
maintained artifact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@subprojects/kotlin-analysis-api/consumer-rules.pro`:
- Around line 9-360: Document how the hand-maintained keep-rule list was
generated, including scanning META-INF/services entries and plugin XML
descriptors, and describe the steps to regenerate and diff it after Kotlin
Analysis API or IntelliJ platform dependency upgrades. Add this maintenance note
near the keep rules or in the associated tracking documentation, referencing the
enumerated FQCN rules as the maintained artifact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b2ba7a8-0354-4e65-9b01-6a35a8ec8d9c

📥 Commits

Reviewing files that changed from the base of the PR and between 2e606b7 and 8e63ad8.

📒 Files selected for processing (2)
  • app/proguard-rules.pro
  • subprojects/kotlin-analysis-api/consumer-rules.pro
💤 Files with no reviewable changes (1)
  • app/proguard-rules.pro

Review feedback on #1596: the 352-entry keep-rule list had no documented
provenance. Adds the exact extraction/parsing steps used to generate it
and how to regenerate and diff it after a Kotlin Analysis API or
IntelliJ platform dependency bump.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidschachterADFA

Copy link
Copy Markdown
Collaborator Author

On-device verification (debug build, chore/ADFA-3604-analyze-dex-code-bloat, Samsung Galaxy Note20 Ultra / SM-N986U, arm64-v8a):

  • Built and installed :app:assembleV8Debug, launched cleanly, no crashes.
  • Created a new Kotlin project from the "Empty Activity" template — KotlinLanguageServer: Kotlin project initialized logged with no ClassNotFoundException/NoClassDefFoundError anywhere in the analysis pipeline.
  • Opened MainActivity.kt: Kotlin syntax highlighting rendered correctly.
  • Diagnostics engine ran live and surfaced an inline error tooltip.
  • Triggered autocomplete (identifier.) — popup correctly showed real member suggestions (equals, hashCode) resolved through the Kotlin analysis API, confirming the completion pipeline survives R8 shrinking with the new keep rules.

This was a debug build rather than release, so it doesn't fully replace the release-build device test already noted in the PR description, but it's a second independent confirmation that the kotlin-analysis-api keep rules hold up for project init, diagnostics, and completion. Go-to-definition check still to follow.

@davidschachterADFA

Copy link
Copy Markdown
Collaborator Author

Follow-up on the go-to-definition item: reopened the same test project (debug build) and long-pressed a resolved symbol (Bundle in an import) to bring up the code-actions menu. For this Kotlin file it only offered Comment line / Uncomment line / Organize imports / Surround with try/catch / Implement members — no "Go to definition".

Checked why: GoToDefinitionAction (lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/common/GoToDefinitionAction.kt) extends BaseJavaCodeAction and is only registered in the Java LSP's action menu. The Kotlin LSP's action set (lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/actions/) has AddImportAction, ImplementMembersAction, NullSafetyAction, OrganizeImportsAction, SurroundWithTryCatchAction — no go-to-definition action. The backend capability does exist (KotlinLanguageServer.findDefinition() is implemented and IDEEditor.findDefinition() calls through to it), but no UI action wires it up for Kotlin files.

So this is a pre-existing gap in the product (Kotlin go-to-definition was never hooked up to the editor UI), not something this PR's R8/keep-rule changes affect either way — there's no existing behavior here for the keep rules to have broken. Updated the test-plan checkbox to reflect that autocomplete and diagnostics were verified for Kotlin, and noted go-to-definition separately rather than leave it looking untested or falsely checked.

@davidschachterADFA

davidschachterADFA commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

Filed ADFA-4923 to track the missing Kotlin go-to-definition action.

@davidschachterADFA
davidschachterADFA merged commit 3262149 into stage Jul 30, 2026
4 checks passed
@davidschachterADFA
davidschachterADFA deleted the chore/ADFA-3604-analyze-dex-code-bloat branch July 30, 2026 02:10
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.

2 participants