Resolve getDisplayName also when inherited or returning non-null String - #136
Conversation
previewIndexDisplayName was always null unless the provider declared getDisplayName(index: Int): String? directly on the concrete class: - declaredMemberFunctions excludes inherited members, so an interface default or superclass implementation was never found - the matcher only accepted a nullable String? return, so a provider narrowing the return type to String never matched Look the function up via memberFunctions (kotlin-reflect returns the most-derived override) and accept a non-null String return as well. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe ChangesgetDisplayName resolution fix
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Mapper as ComposablePreviewWithPreviewParameterMapper
participant Reflection as KotlinReflect
participant Provider as ProviderInstance
Mapper->>Reflection: providerInstance::class.memberFunctions
Reflection-->>Mapper: getDisplayName(Int) candidates (String or String?)
Mapper->>Provider: call getDisplayName(index)
Provider-->>Mapper: display name value (inherited or non-nullable)
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@zaburen Looks very good! |
|
@sergio-sastre My team and I greatly appreciate you and your amazing tool! |
Fixes #135
What
getDisplayNameFunction(): look the function up viamemberFunctionsinstead ofdeclaredMemberFunctions, so implementations inherited from an interface default or an abstract superclass are found. kotlin-reflect returns the most-derived override and the function iscalled on the provider instance, so dispatch stays correct.Stringreturn type as well asString?(legal covariant overrides of AndroidX'sgetDisplayName(index: Int): String?).Tests
AndroidStringProviderWithDisplayName: declared non-null return, interface-default inherited, abstract-superclass inherited — each with its own preview group.AndroidComposablePreviewParameterDisplayNameTest: scans the fixture package and assertspreviewIndexDisplayNamefor all four shapes. Written before the fix: the three new cases failed withexpected:<[Jim, Jens]> but was:<[null, null]>; the control (declared nullable) passed — and it keeps guarding the same-name decoy overload (getDisplayName(index: Int?)returning"WRONG").Jim/Jensdisplay names.:tests:testApi(468 tests),:tests:testSourceSets,paparazziPreviewsRuntime/SourceSet -Pverify=true,roborazziPreviewsRuntime/SourceSet -Pverify=true,metalavaCheckCompatibilityfor all 5 modules (no public API change). No existing golden changes.Behavior note
getDisplayNamestart resolving names — consumers who relied on the index fallback for such providers will see index → name screenshot-ID changes when they upgrade.PreviewParameterProvider.getDisplayName(defaultnull) now matches for every provider; it returnsnull, so previews without a real implementation keep today's index fallback unchanged.Repro
https://github.com/zaburen/composable-preview-scanner-displayname-repro — fails 3/4 against 0.9.0; its
-Pfixedmode swaps in the patched scanner from this branch and passes 4/4.Summary by CodeRabbit
Bug Fixes
Tests