skiptools / skiptools/skip-ui

Non-public PreferenceKey implementations throw IllegalAccessException

Open
#243 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
330
Forks
76
Avg merge
3h 6m
Merged PRs (30d)
1

Description

When a custom preference key (as implemented in https://github.com/skiptools/skip-ui/pull/242) is not public, like in this example: https://github.com/skiptools/skip-ui/blob/783bb4c18382f6d75b899aa06cc8e694e6caa031/Tests/SkipUITests/SkipUITests.swift#L649-L659

accessing the preference fails in test cases with a reflection error:

testCustomEnvironmentValue$SkipUI_debugUnitTest java.lang.IllegalAccessException: class kotlin.reflect.jvm.internal.KClassImpl$Data cannot access a member of class skip.ui.EnvironmentValueTestKey with modifiers "public static final"
testCustomEnvironmentValue$SkipUI_debugUnitTest java.lang.IllegalAccessException: class kotlin.reflect.jvm.internal.KClassImpl$Data cannot access a member of class skip.ui.EnvironmentValueTestKey with modifiers "public static final"
java.lang.IllegalAccessException: class kotlin.reflect.jvm.internal.KClassImpl$Data cannot access a member of class skip.ui.EnvironmentValueTestKey with modifiers "public static final"
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:400)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.objectInstance_delegate$lambda$14(KClassImpl.kt:155)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.accessor$KClassImpl$Data$lambda7(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$$Lambda$7.invoke(Unknown Source)
	at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:125)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getObjectInstance(KClassImpl.kt:141)
	at kotlin.reflect.jvm.internal.KClassImpl.getObjectInstance(KClassImpl.kt:287)
	at kotlin.reflect.full.KClasses.getCompanionObjectInstance(KClasses.kt:55)
	at skip.ui.EnvironmentValues.valueCompositionLocal$lambda$5(EnvironmentValues.kt:141)
	at skip.ui.EnvironmentValues.compositionLocal$lambda$9(EnvironmentValues.kt:159)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:86)
	at androidx.compose.runtime.LazyValueHolder.getCurrent(ValueHolders.kt:46)
	at androidx.compose.runtime.LazyValueHolder.readValue(ValueHolders.kt:48)
	at androidx.compose.runtime.CompositionLocalMapKt.read(CompositionLocalMap.kt:88)
	at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2390)
	at skip.ui.EnvironmentValues.get(EnvironmentValues.kt:2377)
	at skip.ui.SkipUITestsKt.getTestValue(SkipUITests.kt:722)
	at skip.ui.SkipUITests$EnvironmentValueDefaultView.Evaluate(SkipUITests.kt:529)
	at skip.ui.ModifiedContent$Companion.Evaluate$SkipUI_debug(ModifiedContent.kt:293)
	at skip.ui.RenderModifier.Evaluate(ModifiedContent.kt:99)
	at skip.ui.ModifiedContent.Evaluate(ModifiedContent.kt:192)
	at skip.ui.View._ComposeContent(View.kt:3066)
	at skip.ui.ModifiedContent._ComposeContent(ModifiedContent.kt:168)
	at skip.ui.View.Compose(View.kt:3053)
	at skip.ui.ModifiedContent.Compose(ModifiedContent.kt:168)
	at skip.ui.SkipUITests.testCustomEnvironmentValue$lambda$29$lambda$28(SkipUITests.kt:502)
	at skip.ui.ComposeBuilder._ComposeContent(ComposeBuilder.kt:54)
	at skip.ui.ComposeBuilder.Compose(ComposeBuilder.kt:46)
	at skip.ui.View.Compose(View.kt:3033)
	at skip.ui.ComposeBuilder.Compose(ComposeBuilder.kt:11)
	at skip.ui.SkipUITests.testUI$lambda$0(SkipUITests.kt:192)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:431)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
	at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:216)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
	at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:140)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:139)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:384)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:139)
	at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:123)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
	at androidx.compose.runtime.internal.Utils_jvmKt.invokeComposable(Utils.jvm.kt:27)
	at androidx.compose.runtime.ComposerImpl.doCompose-aFTiNEg(Composer.kt:3694)
	at androidx.compose.runtime.ComposerImpl.composeContent--ZbOJvo$runtime_release(Composer.kt:3616)
	at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:792)
	at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1132)
	at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:677)
	at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:616)
	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:1959)
	at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:114)
	at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:168)
	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:2038)
	at android.view.View.dispatchAttachedToWindow(View.java:18347)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3397)
	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404)
	at android.view.ViewGroup.addViewInner(ViewGroup.java:5077)
	at android.view.ViewGroup.addView(ViewGroup.java:4865)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at org.robolectric.shadows.ShadowViewGroup$ViewGroupReflector$$Reflector27.addView(Unknown Source)
	at org.robolectric.shadows.ShadowViewGroup.lambda$addView$0(ShadowViewGroup.java:29)
	at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:33)
	at android.view.ViewGroup.addView(ViewGroup.java)
	at android.view.ViewGroup.addView(ViewGroup.java:4837)
	at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:451)
	at android.app.Activity.setContentView(Activity.java:2807)
	at androidx.activity.ComponentActivity.setContentView(ComponentActivity.kt:410)
	at androidx.activity.compose.ComponentActivityKt.setContent(ComponentActivity.kt:70)
	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl$setContent$3.invoke(ComposeUiTest.android.kt:549)
	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl$setContent$3.invoke(ComposeUiTest.android.kt:548)
	at androidx.compose.ui.test.AndroidSynchronization_androidKt.runOnUiThread(AndroidSynchronization.android.kt:35)
	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidTestOwner.runOnUiThread(ComposeUiTest.android.kt:599)
	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.runOnUiThread(ComposeUiTest.android.kt:463)
	at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.setContent(ComposeUiTest.android.kt:548)
	at androidx.compose.ui.test.junit4.AndroidComposeTestRule.setContent(AndroidComposeTestRule.android.kt:381)
	at skip.ui.SkipUITests.testUI$SkipUI_debugUnitTest(SkipUITests.kt:192)
	at skip.ui.SkipUITests.testCustomEnvironmentValue$SkipUI_debugUnitTest(SkipUITests.kt:499)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with EnvironmentValues.kt around the valueCompositionLocal and compositionLocal paths cited in the stack trace, then inspect testCustomEnvironmentValue and the non-public key example in Tests/SkipUITests/SkipUITests.swift. Reproduce the failing test and confirm it passes for a non-public custom preference key without the IllegalAccessException.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin, swift
Domain
frontend, mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.