Skip to content

refactor(snapshot): Remove MergeClassesTask, scan classpath in-place#1121

Merged
runningcode merged 1 commit intono/snapshot-metadata-pluginfrom
no/merge-classes-into-export
Mar 26, 2026
Merged

refactor(snapshot): Remove MergeClassesTask, scan classpath in-place#1121
runningcode merged 1 commit intono/snapshot-metadata-pluginfrom
no/merge-classes-into-export

Conversation

@romtsn
Copy link
Copy Markdown
Member

@romtsn romtsn commented Mar 25, 2026

Summary

  • Eliminates MergeClassesTask by scanning classes directly from their source locations (directories and JARs) instead of merging them into an intermediate directory first
  • Moves classpath resolution into ExportPreviewMetadataTask.register() and adds a forEachClassEntry() helper that iterates both loose .class files and JAR entries in-place
  • No intermediate merged-classes directory is written to disk anymore

Test plan

  • Existing ExportPreviewMetadataTaskTest tests pass
  • spotlessCheck passes
  • compileKotlin succeeds

🤖 Generated with Claude Code

Instead of merging all classes into an intermediate directory,
ExportPreviewMetadataTask now scans directories and JARs directly
from the classpath.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Internal Changes 🔧

  • (snapshot) Remove MergeClassesTask, scan classpath in-place by romtsn in #1121
  • Pin GitHub Actions to full-length commit SHAs by joshuarli in #1116

🤖 This preview updates automatically when you update the PR.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Unused android parameter in register method
    • Removed the unused BaseExtension parameter and import, and updated the caller accordingly.

Create PR

Or push these changes by commenting:

@cursor push d17fed0e0a
Preview (d17fed0e0a)
diff --git a/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/ExportPreviewMetadataTask.kt b/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/ExportPreviewMetadataTask.kt
--- a/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/ExportPreviewMetadataTask.kt
+++ b/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/ExportPreviewMetadataTask.kt
@@ -1,6 +1,5 @@
 package io.sentry.android.gradle.snapshot.metadata
 
-import com.android.build.gradle.BaseExtension
 import groovy.json.JsonOutput
 import java.util.zip.ZipInputStream
 import org.gradle.api.DefaultTask
@@ -155,7 +154,6 @@
     fun register(
       project: Project,
       extension: SentrySnapshotMetadataExtension,
-      android: BaseExtension,
     ): TaskProvider<ExportPreviewMetadataTask> {
       return project.tasks.register(
         "exportPreviewMetadata",

diff --git a/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/SentrySnapshotMetadataPlugin.kt b/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/SentrySnapshotMetadataPlugin.kt
--- a/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/SentrySnapshotMetadataPlugin.kt
+++ b/plugin-build/src/main/kotlin/io/sentry/android/gradle/snapshot/metadata/SentrySnapshotMetadataPlugin.kt
@@ -1,6 +1,5 @@
 package io.sentry.android.gradle.snapshot.metadata
 
-import com.android.build.gradle.BaseExtension
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 
@@ -15,8 +14,7 @@
       )
 
     fun wireWithAndroid() {
-      val android = project.extensions.getByType(BaseExtension::class.java)
-      ExportPreviewMetadataTask.register(project, extension, android)
+      ExportPreviewMetadataTask.register(project, extension)
     }
 
     project.pluginManager.withPlugin("com.android.library") { wireWithAndroid() }

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

project: Project,
extension: SentrySnapshotMetadataExtension,
mergeTask: TaskProvider<MergeClassesTask>,
android: BaseExtension,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unused android parameter in register method

Low Severity

The android: BaseExtension parameter in register() is never referenced in the method body. The classpath resolution uses project.configurations and project.tasks directly, making the parameter dead code. Its corresponding import com.android.build.gradle.BaseExtension is also unused by the task class itself. The caller in SentrySnapshotMetadataPlugin still fetches and passes it needlessly.

Additional Locations (1)
Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@runningcode runningcode left a comment

Choose a reason for hiding this comment

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

this works! thank you for the performance improvement!

@runningcode runningcode merged commit 975231b into no/snapshot-metadata-plugin Mar 26, 2026
19 of 20 checks passed
@runningcode runningcode deleted the no/merge-classes-into-export branch March 26, 2026 08:44
runningcode added a commit that referenced this pull request Mar 26, 2026
* feat(snapshot): Add io.sentry.android.snapshot.metadata plugin

Add a standalone Gradle plugin that exports Compose @Preview metadata
to a JSON file using ASM bytecode scanning. This plugin can be applied
independently without Paparazzi — it only requires an Android plugin
and compiled Kotlin classes.

New plugin components:
- PreviewScanner: ASM-based bytecode scanner for @Preview annotations
- ExportPreviewMetadataTask: Cacheable task that scans compiled classes
  and writes preview-metadata.json
- SentrySnapshotMetadataPlugin: Plugin entry point (requires
  com.android.library or com.android.application)
- SentrySnapshotMetadataExtension: Configuration extension with
  includePrivatePreviews and packageTrees properties

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: Apply spotless formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(snapshot): Fix package prefix matching and reduce bytecode parsing

Fix matchesPackage to require a path separator after the prefix,
preventing com.example from matching com.exampleextended. Combine
source file extraction into the existing PreviewClassVisitor to
eliminate a redundant bytecode parse per class file. Add tests for
JAR scanning, private preview filtering, prefix collisions, and
multi-package scanning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(snapshot): Add MultiPreview, custom annotations, and MergeClasses support

Add full multipreview annotation support to the snapshot metadata plugin,
bringing it to parity with emerge-android's scanning capabilities:

- Two-pass custom annotation discovery with nested annotation support
- @Preview.Container for repeatable @Preview annotations
- Built-in multipreview expansion (PreviewLightDark, PreviewFontScale,
  PreviewScreenSizes, PreviewDynamicColors, and 5 Wear OS previews)
- @PreviewParameter extraction (provider class, limit, index, param name)
- group and wallpaper @Preview fields
- MergeClassesTask to explode JARs into a single directory before scanning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(snapshot): Extract constants to PreviewConstants.kt

Move annotation descriptors, device specs, UI mode constants, and
builtinMultipreviewConfigs() out of PreviewScanner.kt into a dedicated
PreviewConstants.kt file for better organization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(snapshot): Remove namespace and package filtering

Emerge-android doesn't have package filtering — the scope is controlled
entirely by what MergeClasses puts into the directory. Remove
scanPackages, namespace, packageTrees, matchesPackage, and
scannedPackages to match that approach.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(snapshot): Remove MergeClassesTask, scan classpath in-place (#1121)

Instead of merging all classes into an intermediate directory,
ExportPreviewMetadataTask now scans directories and JARs directly
from the classpath.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(snapshot): Fix builtin multipreview metadata to match Compose source

- Capitalize PreviewLightDark names to "Light"/"Dark" matching the
  actual @Preview annotations in Compose
- Swap Blue/Green wallpaper values in PreviewDynamicColors to match
  Wallpapers.GREEN_DOMINATED_EXAMPLE=1 and BLUE_DOMINATED_EXAMPLE=2
- Only register classes with non-empty previewConfigs in
  FindCustomPreviewClassVisitor to avoid polluting the map

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
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