arrow-kt / arrow-meta

Functional companion to Kotlin's Compiler
https://meta.arrow-kt.io
Apache License 2.0
396 stars 42 forks source link

[BUG] KtParameter of a constructor cannot be transformed #871

Open vnermolaev opened 3 years ago

vnermolaev commented 3 years ago

A CliPlugin targeting constructor parameters of data classes fails to apply any transformation on such parameters. Such transformations include equivalent transformations too. A use-case for such functionality is adding an additional annotation to the fields defined in the class constructor, e.g.,

data class TestMe(val s: String)

to transform to

data class TestMe(val s: @ASCII String)

where ASCII is an appropriately defined annotation.

To reproduce Define a simple

val Meta.ConstructorParameterAnnotator: CliPlugin
    get() = "Constructor Parameter Annotator" {
        meta(
            parameter(this, match = {
                /**
                 * Returns true if this parameter is a val/var parameter of a constructor.
                 */        
                hasValOrVar()
            }) { ktParameter ->
                // Fails!
                Transform.replace(
                     replacing = ktParameter,
                     newDeclaration = ktParameter.scope()
                )
            }
        )
    }

Invocation of such a plugin leads to an exception java.lang.IllegalStateException: Unrecognized expression type from VALUE_PARAMETER

The exception points to at arrow.meta.internal.kastree.ast.psi.Converter.convertExpr(Converter.kt:385) which contain a when expression which does not handle KtParameter.

Expected behavior The parameter is expected to be replaced with the new declaration.

Environment (please complete the following information):

I have not found any workaround so far, e.g., by converting the respective text representation into (just for example) an expression: ktParameter.text.expression.

vnermolaev commented 3 years ago

For those facing a similar problem, I ended up matching the full class and then process parameters of the constructor and do the full class reconstruction with the altered contructor.