Skip to content

Replace Kotlin reflection with Java reflection in Setter DSL for Mocking#736

Merged
elihart merged 6 commits intomainfrom
eli-fix_kotlin_reflect_in_set_dls
Feb 7, 2026
Merged

Replace Kotlin reflection with Java reflection in Setter DSL for Mocking#736
elihart merged 6 commits intomainfrom
eli-fix_kotlin_reflect_in_set_dls

Conversation

@elihart
Copy link
Copy Markdown
Contributor

@elihart elihart commented Feb 5, 2026

Jetpack Compose UI previews fail in Android Studio with Kotlin 2.3+ because layoutlib has a shaded kotlin-reflect that lacks K2 MetadataExtensions. This causes crashes when DataClassSetDsl calls KClass.isData or memberProperties.

Changes:

  • Add DataClassJavaReflection.kt with Java reflection utilities:
    • isData: duck-type data class detection via copy$default/componentN methods
    • callCopy(): invoke copy$default with bitmask pattern for default params
    • getPropertyValue(): access properties via getters or field reflection
  • Update DataClassSetDsl to use Java reflection instead of Kotlin reflection
  • Add tests covering core utilities and DSL integration
  • Add publishing.gradle for custom Artifactory repository publishing

…mpatibility

Jetpack Compose UI previews fail in Android Studio with Kotlin 2.3+ because
layoutlib has a shaded kotlin-reflect that lacks K2 MetadataExtensions.
This causes crashes when DataClassSetDsl calls KClass.isData or memberProperties.

Changes:
- Add DataClassJavaReflection.kt with Java reflection utilities:
  - isData: duck-type data class detection via copy$default/componentN methods
  - callCopy(): invoke copy$default with bitmask pattern for default params
  - getPropertyValue(): access properties via getters or field reflection
- Update DataClassSetDsl to use Java reflection instead of Kotlin reflection
- Add 25 tests covering core utilities and DSL integration

JDK 22 compatibility:
- Update Robolectric 4.10.3 -> 4.16.1 (older ASM can't read JDK 22 class files)
- Add test AndroidManifest.xml files with tools:overrideLibrary to allow
  Robolectric's minSdk 21 test deps while keeping library minSdk at 16

Also includes:
- Add publishing.gradle for custom Artifactory repository publishing
The buildPropertyIndexMap function was iterating through all fields
(including body properties with backing fields) and matching them to
componentN methods. When a body property had the same type and value
as a constructor property (e.g., multiple Boolean = false fields),
the body property could incorrectly "steal" the component slot.

The fix iterates through componentN methods first (only constructor
params have these), then finds the matching field for each. This ensures
body properties don't get mapped since they lack componentN methods.

Added tests for data classes with body properties to prevent regression.

Version bump: 3.1.0-airbnb4 -> 3.1.0-airbnb5
Value-based field matching fails when R8 reorders fields and multiple
fields share the same type and runtime value (e.g., Boolean body
property becoming true after a prior callCopy sets a constructor
parameter to true). This caused crashes in mock builders that call
callCopy sequentially.

Replace with two strategies:
1. Primary: Parse data class toString() output for parameter names in
   constructor order (names are string literals that survive R8)
2. Fallback: Mutation-probe disambiguation — temporarily change each
   candidate field's value to identify which one backs the componentN
   method

Version bump: 3.1.0-airbnb5 -> 3.1.0-airbnb6
@elihart elihart merged commit 195e9ed into main Feb 7, 2026
1 of 2 checks passed
@elihart elihart deleted the eli-fix_kotlin_reflect_in_set_dls branch February 7, 2026 00:07
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.

1 participant