Skip to content
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

Jetpack Compose previews crashes #250

Closed
dees91 opened this issue Oct 25, 2024 · 10 comments
Closed

Jetpack Compose previews crashes #250

dees91 opened this issue Oct 25, 2024 · 10 comments
Labels
core 🧬 Issue related to :core module enhancement 🚀 New feature or request
Milestone

Comments

@dees91
Copy link

dees91 commented Oct 25, 2024

Problem Description

Jetpack Compose preview throws an error when I create a preview using PreviewParameterProvider that utilizes a faker with a provider, such as address.

Faker Version Used

2.0.0-rc.6

Stacktrace

(observed in Android Studio logs ~/Library/Logs/Google/AndroidStudio2024.2/idea.log):

java.lang.NoSuchMethodException: Composable pl.deesoft.fakerpreview.GreetingPreviewProvider.$FailToLoadPreviewParameterProvider not found
	at androidx.compose.ui.tooling.ComposableInvoker.invokeComposable(ComposableInvoker.jvm.kt:216)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.android.kt:504)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1$composable$1.invoke(ComposeViewAdapter.android.kt:502)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.android.kt:539)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3$1.invoke(ComposeViewAdapter.android.kt:497)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.tooling.InspectableKt.Inspectable(Inspectable.android.kt:61)
	at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.android.kt:444)
	at androidx.compose.ui.tooling.ComposeViewAdapter$WrapPreview$1.invoke(ComposeViewAdapter.android.kt:443)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.tooling.ComposeViewAdapter.WrapPreview(ComposeViewAdapter.android.kt:438)
	at androidx.compose.ui.tooling.ComposeViewAdapter.access$WrapPreview(ComposeViewAdapter.android.kt:124)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.android.kt:497)
	at androidx.compose.ui.tooling.ComposeViewAdapter$init$3.invoke(ComposeViewAdapter.android.kt:494)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:428)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:186)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:139)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:138)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:138)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:123)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
	at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:90)
	at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3302)
	at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3235)
	at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:725)
	at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1071)
	at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:633)
	at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:619)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:123)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1289)
	at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:164)
	at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320)
	at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:121)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1364)
	at android.view.View.dispatchAttachedToWindow(View.java:21980)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
	at android.view.AttachInfo_Accessor.setAttachInfo(AttachInfo_Accessor.java:53)
	at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:372)
	at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:454)
	at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:120)
	at com.android.tools.rendering.RenderTask.createRenderSession(RenderTask.java:784)
	at com.android.tools.rendering.RenderTask.lambda$inflate$6(RenderTask.java:932)
	at com.android.tools.rendering.RenderExecutor$runAsyncActionWithTimeout$3.run(RenderExecutor.kt:204)
	at com.android.tools.rendering.RenderExecutor$PriorityRunnable.run(RenderExecutor.kt:321)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)

In the logs I also found:

java.util.NoSuchElementException: Faker provider 'Name' not found in io.github.serpro69.kfaker.Faker@8bf1fee or io.github.serpro69.kfaker.Faker@28d1533d
	at io.github.serpro69.kfaker.FakerService.getProvider(FakerService.kt:610)
	at io.github.serpro69.kfaker.FakerService.access$getProvider(FakerService.kt:34)
	at io.github.serpro69.kfaker.FakerService$resolveExpression$resolvedExpression$1.invoke(FakerService.kt:497)
	at io.github.serpro69.kfaker.FakerService$resolveExpression$resolvedExpression$1.invoke(FakerService.kt:492)
	at io.github.serpro69.kfaker.FakerService.findMatchesAndAppendTail(FakerService.kt:622)
	at io.github.serpro69.kfaker.FakerService.resolveExpression-goSy63c(FakerService.kt:492)
	at io.github.serpro69.kfaker.FakerService.resolve(FakerService.kt:414)
	at io.github.serpro69.kfaker.provider.YamlFakeDataProvider$returnOrResolveUnique$3.invoke(YamlFakeDataProvider.kt:227)
	at io.github.serpro69.kfaker.provider.YamlFakeDataProvider$returnOrResolveUnique$3.invoke(YamlFakeDataProvider.kt:221)
	at io.github.serpro69.kfaker.provider.AbstractFakeDataProvider.resolveUniqueValue(AbstractFakeDataProvider.kt:74)
	at io.github.serpro69.kfaker.provider.AbstractFakeDataProvider.resolveUniqueValue(AbstractFakeDataProvider.kt:59)
	at io.github.serpro69.kfaker.provider.YamlFakeDataProvider.returnOrResolveUnique(YamlFakeDataProvider.kt:221)
	at io.github.serpro69.kfaker.provider.YamlFakeDataProvider.returnOrResolveUnique$default(YamlFakeDataProvider.kt:216)
	at io.github.serpro69.kfaker.provider.YamlFakeDataProvider.resolve(YamlFakeDataProvider.kt:77)
	at io.github.serpro69.kfaker.provider.Address.streetAddress(Address.kt:50)

I've created sample reproduction: https://github.com/dees91/Faker-preview-issue

@serpro69
Copy link
Owner

serpro69 commented Oct 25, 2024

Hey @dees91 ,
Thanks for reporting the issue, and for the repro example!
I haven't worked with compose yet myself, and it's been quite awhile since I've dealt with android also 😬 but I will try to look into this and see if I can find the root cause.
If you do figure out the issue - don't hesitate to update with more details or contribute a fix.

Just out of curiosity, did you try latest stable version also, 1.6.0? Do you have the same problem there?

@dees91
Copy link
Author

dees91 commented Oct 25, 2024

Yes I have the same problem using version 1.6.0

@serpro69
Copy link
Owner

Could this https://issuetracker.google.com/issues/254315195 or https://issuetracker.google.com/issues/281014894 be somewhat related?
The first one has "fixed" status, but the second one does not. So could this be something that faker uses and compose doesn't support yet? 🤔

@serpro69
Copy link
Owner

A bit more updates: I've narrowed it down to code that uses reflection to call functions from other providers. E.g. in your example, faker.address.streetAddress() would actually call faker.name.* functionality.
So this must be something related to reflection? 🤔
If you try a function that doesn't need to resolve data from other providers, e.g. faker.name.name(), - it would work fine.

@serpro69 serpro69 added bug 🐞 Something isn't working core 🧬 Issue related to :core module labels Oct 25, 2024
@serpro69 serpro69 added this to the 2.0.0 milestone Oct 25, 2024
@dees91
Copy link
Author

dees91 commented Oct 25, 2024

If you try a function that doesn't need to resolve data from other providers, e.g. faker.name.name(), - it would work fine.

Yes, I confirm that faker.name.name() works 👍🏻 Can be a temporary solution for me, thanks

@serpro69
Copy link
Owner

Yes, I confirm that faker.name.name() works 👍🏻 Can be a temporary solution for me, thanks

No problem, glad at least some parts can be of use for now.
I'll try to debug further and see if I can at least come up with a workaround, if not an immediate fix. A bit challenging since whenever I startup intellij/android studio these days - my CPU temps go to a 100 😁

@serpro69
Copy link
Owner

So faker uses KProperty1<out T, *> for the above mentioned functionality (

this::class.declaredMemberProperties.firstOrNull { it.name == funcName.substringBefore(".") }?.let {
(it.getter.call(this) as YamlFakeDataProvider<*>)
.getFunctionName(funcName.substringAfter("."))
), and according to this comment in the issue I linked above, this will break preview in Android Studio.

I'm not sure what else we could do here but wait for the fix. Of course implementing #23 would also help here. But I'm not sure if I'll be able to tackle that one quick enough :/

@serpro69 serpro69 added help wanted 🆘 Extra attention is needed enhancement 🚀 New feature or request and removed bug 🐞 Something isn't working help wanted 🆘 Extra attention is needed labels Oct 26, 2024
serpro69 added a commit that referenced this issue Oct 28, 2024
Partially does what #23 wants. Over-engineering is evil...

There are still some parts in :core that user reflection, e.g. unique data generation bits. This PR doesn't attempt to address those.

At the very least, this should fix most issues with #250
@serpro69
Copy link
Owner

Hey @dees91 ,
I think I have a fix for it now. Would you mind testing out latest snapshot version - 2.1.0-SNAPSHOT? (I had to remove Android studio since I didn't have enough storage 😁 so can't test it anymore myself.)
If it works as expected - I'll make rc.7 with the fix.

Note that while regular functionality should work fine now, things like e.g. unique data generation might still produce same exceptions in compose preview because that part of faker still depends on reflection.

@dees91
Copy link
Author

dees91 commented Oct 28, 2024

it looks like the preview is being generated now 🎉
Screenshot 2024-10-28 at 09 52 02

But I can't build and run the app using 2.1.0-SNAPSHOT, I get this error:

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:checkDebugAarMetadata'.
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
   > Could not find org.jetbrains.kotlin:kotlin-reflect:.
     Required by:
         project :app > io.github.serpro69:kotlin-faker:2.1.0-SNAPSHOT:20241028.081202-24

I wonder if it's because it's a snapshot version? or did I connect something wrong? here's the commit: dees91/Faker-preview-issue@655ea7c

@serpro69
Copy link
Owner

serpro69 commented Oct 28, 2024

Thanks for the confirmation.

That error is weird. I can't see what changes could have caused this since rc.6
Kotlin version was bumped, and I started using a new shadow plugin, so those are probably the first things to look into.

So I guess you needed to explicitly add kotlin-reflect dependency to make it work?

I'll look into this in #253

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core 🧬 Issue related to :core module enhancement 🚀 New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants