Skip to content

Value class params in expandable sentence#160

Merged
paul-brooks merged 2 commits into
kensa-dev:masterfrom
michaelomichael:value-class-params-in-expandable-sentence
Jul 8, 2026
Merged

Value class params in expandable sentence#160
paul-brooks merged 2 commits into
kensa-dev:masterfrom
michaelomichael:value-class-params-in-expandable-sentence

Conversation

@michaelomichael

Copy link
Copy Markdown
Contributor

Kensa fails to find methods annotated with @ExpandableSentence when one or more of their parameters is a Kotlin value class:

Kensa was unable to parse this test. This usually means the test contains syntax that the parser does not yet handle.
Please copy the details below (together with some example code) and report them at https://github.com/kensa-dev/kensa/issues so we can fix it.
--- Error ---
Did not find expandable method [someAction] in class [com.example.ExpandableSentenceTest]
--- End ---

Very simple example that can trigger the problem:

@JvmInline
value class Foo(val value: String)

val myValueClassInstance = Foo("test")

@ExpandableSentence
fun someAction(param: Foo): Action<ActionContext> = {
    println("Do something with ${param.value}")
}

@Test
fun exampleTest() {
    whenever(someAction(myValueClassInstance))
    then(someStateCollector()) { }
}

The test output renders normally if you remove the @ExpandableSentence annotation, or change the parameter from Foo to String.

The issue is that the Kotlin compiler will append a hash to the method name so that the JVM can distinguish between e.g. fun someAction(param:Foo) and someAction(param:String) - the former's signature will appear to the JVM as void someAction-abc123(String param) - so we have to jump through a few hoops to get back to the original method name and parameter types.

I've made changes to CompilerPluginHookFunctions and MethodParser, and made sure to keep more generic fallback methods, but let me know if you think there's a better approach.

@paul-brooks

Copy link
Copy Markdown
Contributor

Thanks Michael, good find. Parser fix and tests look good.

Turns out @RenderedValue suffers the same problem and still does after this change (value class returns get mangled too, not just params). The lookup in RenderedValueInvocationContext compares the mangled JVM name against the source name and quietly records nothing.

Poking at that revealed something better though: deriveMethod only exists to get back the method name, and the plugin already knows the name at compile time and passes it in. So the hooks can just record by name and skip reflection entirely.

Going to merge this and put that on top as a follow-up, your parser change survives as is. Cheers.

@paul-brooks paul-brooks merged commit 770ebf7 into kensa-dev:master Jul 8, 2026
1 check passed
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