1

Background:

I'm working on a small code generator. I would like to avoid the usual problem of no code hints before the code is actually generated. To solve this I created a general generic dummy method of the sort I intend to generate.

inline fun <R: Any> Any.into(block: MorphBuilder<R>.() -> Unit): MorphBuilder<R> {
    throw IllegalStateException("Didn't generate extension method")
}

This would provide the hints in the ide. After the actual specific methods would be generated

class FooMorphBuilder(
    var a: String?,
    var b: Double?,
    var c: Int?,
    var d: Float?,
    var e: List<String>?
) : MorphBuilder<Foo> {
    override fun morph(): Foo = Foo(a!!, b!!, c!!, d!!, e!!)
}

inline fun <Foo> Boo.into(block: FooMorphBuilder.() -> Unit): FooMorphBuilder =
        FooMorphBuilder(this.a, this.b, this.c, this.d, this.e)

they should be used.

Problem:

Unfortunately this causes the following error.

 Overload resolution ambiguity: 
public inline fun <Foo> Boo.into(block: FooMorphBuilder.() -> Unit): FooMorphBuilder defined in com.example.morph
public inline fun <R : Any> Any.into(block: MorphBuilder<com.example.morph.Foo>.() -> Unit): MorphBuilder<com.example.morph.Foo> defined in com.example.morph

I was hoping the compiler would choose the most specific implementation, but this doesn't seem to be the case.

Is there a way to disambiguate between those signatures?

Lukasz
  • 2,257
  • 3
  • 26
  • 44
  • 1
    The short answer is probably no... however, one approach I could think of is: if your generated code lives in a separate library module, you could put your dummy method in a separate module as well (let's call it `DummyModule` and `GenModule`). Set up `DummyModule` as a `compileOnly` dependency, and `GenModule` as a `runtimeOnly` dependency. That way, only the dummy method is used at compile time, but at runtime the real generated method would be used. – Kevin Coppock Feb 25 '19 at 22:48
  • 1
    The downside to that being, if a builder failed to be generated, you'd just crash at runtime rather than failing to compile. – Kevin Coppock Feb 25 '19 at 22:52
  • 1
    You could do your code generation as a plugin to the kotlin compiler. https://speakerdeck.com/kevinmost/writing-your-first-kotlin-compiler-plugin Or you could generate the code before you compile the code that uses the generated code. If you generate code based on other code, then you'll need to split your code into before-generation and after-generation code. – Erwin Bolwidt Feb 26 '19 at 11:11
  • 1
    @kcoppock I'll have a look at that when I get home, looks promising. Thanks :) I'm aware of the downside in your second comment, but I think I would still prefer it. Especially since I could give some useful error messages in my dummy method, like where you probably forgot to add an annotation. – Lukasz Feb 26 '19 at 15:09
  • @ErwinBolwidt Unfortunately I don't know anything about compiler plugins, and I'm not sure it's currently worth it, to invest the time, to learn about it. This is only a tiny side project I do for fun. I do generate the code before I compile it. It is an annotation processor, so that's a given. I just wanted the nicety of getting some code completion, and no squiggly lines before I build it. Anyways thanks :) – Lukasz Feb 26 '19 at 15:15

0 Answers0