0

We're writing an internal DSL in Kotlin. Then we use it from our Java code. We see that the objects defined in the DSL are not yet available. Hence the question: Why is the package property not initialized?

Simplified the situation is thus:

val myObject = dsl {
    ...
}

And the DSL:

class Dsl() {
    companion object {
        val stored = mutableListOf<Dsl>()

        fun add(added: Dsl) {
            stored += added
        }
    }
}

fun dsl(init: Dsl.() -> Unit) {
    val dsl = Dsl()
    dsl.init()
    Dsl.add(dsl) // Intentional side effect to simplify DSL definition
}

Using the DSL from Java:

public class ExpectMyObject {
    @Test
    public void testMyObjectLoaded() {
        Assert.assertEquals(1, Dsl.Companion.getStored().size)
    }
}

I expected the package property to be initialized when starting the JVM. But the test fails. What am I overlooking?

Michiel Leegwater
  • 1,172
  • 4
  • 11
  • 27

1 Answers1

2

You need to refer to something defined in same the file as val myObject, directly or indirectly, from your test. Otherwise its generated class won't get loaded. E.g.

@Test
public void testMyObjectLoaded() {
    your.package.FileNameKt.getMyObject();
    Assert.assertEquals(1, Dsl.Companion.getStored().size);
}
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Hmmm. That limits the usability of the DSL. I think it means I will use some reflection to discover the classes and make sure they're loaded. Thanks for explaining what happens. – Michiel Leegwater Jul 31 '19 at 08:50
  • Reflection was not the tool for the job. Instead I've used the ServiceLoader. Yes, that required wrapping the DSL in a new class that implements an interfase. So sad.... – Michiel Leegwater Jul 31 '19 at 10:11