https://kotlinlang.org logo
Title
a

araqnid

03/07/2018, 4:51 PM
you need to refer to extension classes/convention classes more explicitly in Kotlin DSL, they don't magically appear as extension properties on the project
f

Florian Wiesner

03/07/2018, 4:51 PM
do you know any good reference?
a

araqnid

03/07/2018, 4:52 PM
e.g.
the<JavaPluginConvention>().sourceCompatibility = JavaVersion.VERSION_1_8
a good reference, no, I had to figure this out by noodling around
f

Florian Wiesner

03/07/2018, 4:54 PM
ok, let me give it a try 🙂
a

araqnid

03/07/2018, 4:54 PM
there is a "withConvention" extension function intended to be used on any object that implements hasConvention (e.g. source sets etc, not just projects)
which I used like this:
val SourceSet.scala: SourceDirectorySet
    get() = withConvention(ScalaSourceSet::class) { scala }
f

Florian Wiesner

03/07/2018, 4:54 PM
well, I’m working with extensions, not conventions
a

araqnid

03/07/2018, 4:55 PM
I got the impression they were mixed together
f

Florian Wiesner

03/07/2018, 4:55 PM
conventions are the older concept
and are replaced by extensions over tome
time
which is why I’m implementing an extension
a

araqnid

03/07/2018, 4:56 PM
the DSL plugin typically uses "extension" to mean Kotlin extension functions, though
c

Czar

03/07/2018, 4:57 PM
Just use
plugins {}
block instead of
buildscript {}
, that will generate proper DSL for you, e.g.
plugins {
	java
}
java {
	sourceCompatibility = VERSION_1_8
	targetCompatibility = VERSION_1_8
}
f

Florian Wiesner

03/07/2018, 4:57 PM
ha - seems there is a problem with the test runner…
a

araqnid

03/07/2018, 4:58 PM
there is an
ExtensionContainerExtensions.kt
in the DSL plugin to allow you to write
extensions["xxx"]
etc
ah, right, so things like
reporting
are project extensions
f

Florian Wiesner

03/07/2018, 4:59 PM
weird one:
plugins {
     id("info.florian-wiesner.magicdraw")
}
it is found
but…
the<florianwiesner.gradle.magicdraw.MagicDrawExtension>()
leads to an unresolved reference
will dig deeper - thanks @araqnid
a

araqnid

03/07/2018, 5:04 PM
is your extension registered with a name? if so, as Alexander said, it should have been added to the generated glue so you can just refer to it by name
you can also just call
extensions.findByType(ReportingExtension::class.java)
which that should be sugar for
f

Florian Wiesner

03/07/2018, 5:04 PM
well, I have a plugin descriptor under META-INF
and I currently try gettings things work under Gradle’s test kit
using Spek as my test framework
my dynamic test script uses the
plugins{}
DSL
and I see the plugin to get loaded
a

araqnid

03/07/2018, 5:07 PM
don't you have to call something from the plugin method to register the project extension?
f

Florian Wiesner

03/07/2018, 5:07 PM
class MagicDrawGradlePlugin : Plugin<Project> {
    private lateinit var project: Project

    override fun apply(project: Project?) {
        if (project == null) throw GradleException("project must not be null")
        this.project = project
        val extension = addExtension<MagicDrawExtension>("magicdraw", project.objects)

        val verifyMagicDrawTask = project.tasks.create("verifyMagicDraw", VerifyMagicDrawTask::class.java)
        verifyMagicDrawTask.installDir = extension.installDir as String? ?: ""
    }

    private inline fun <reified T> addExtension(name: String, vararg args: Any): T = project.extensions.create(name, T::class.java, *args)

}
let me make a snippet
a

araqnid

03/07/2018, 5:08 PM
right, so it's registered as
magicdraw
so you should be able to write
magicdraw { ... }
in the build script, and the glue should have made a Project.magicdraw extension property
f

Florian Wiesner

03/07/2018, 5:08 PM
magicdraw{...}
is there
but the installDir property is not recognized
a

araqnid

03/07/2018, 5:09 PM
that's a property of the task or the extension or both?
f

Florian Wiesner

03/07/2018, 5:10 PM
both
a

araqnid

03/07/2018, 5:10 PM
are you running the test from IntelliJ or Gradle command-line? I had trouble running this kind of test from IntelliJ
f

Florian Wiesner

03/07/2018, 5:10 PM
in the apply function I copy the property value over to the newly created task
a

araqnid

03/07/2018, 5:10 PM
with it using old versions of the classes under test
f

Florian Wiesner

03/07/2018, 5:10 PM
I run it from gradle
a

araqnid

03/07/2018, 5:11 PM
you copy it from the project extension to the task at the time the plugin is applied? that sounds a bit fishy
f

Florian Wiesner

03/07/2018, 5:12 PM
I wonder whether the test framework
GradleRunner
supports Kotlin DSL
this is just a trial so far
and btw, that’s even done in the Gradle docs, when a task is auto-generated from the plugin
a

araqnid

03/07/2018, 5:13 PM
I suspect that if it didn't, you encounter problems much earlier
f

Florian Wiesner

03/07/2018, 5:13 PM
and I see a big issue
a

araqnid

03/07/2018, 5:13 PM
ah? hmm, I should really get more acquainted with those
f

Florian Wiesner

03/07/2018, 5:13 PM
well, how would you generate a default task definition without having the plugin code do so? 😉
a

araqnid

03/07/2018, 5:14 PM
so what happens when the build file changes the settings in the extension object?
f

Florian Wiesner

03/07/2018, 5:14 PM
anyway…
plugins{id()...)}
finds my plugin and loads it
but the script cannot find my classes
imports fail
so, I guess that the test runner only sees the proxies
but not the plugin classes
plugins{...}
might work because it is somewhat separated from the rest of the script
which is why
val fooVersion:String by extra
plugins {
  id("bar") version fooVersion
}
won’t work
a

araqnid

03/07/2018, 5:18 PM
yes, plugins{} has to be right at the top iirc
f

Florian Wiesner

03/07/2018, 5:19 PM
from a Gradle script perspective yes
it has to be the first element after
buildscript
a

araqnid

03/07/2018, 5:19 PM
well, using plugins{} should replace buildscript{} entirely
f

Florian Wiesner

03/07/2018, 5:19 PM
but Kotlin could of course to things ahead of the
plugins
block
tell that to the JUnit platform guys..
I will investigate and update this thread
a

araqnid

03/07/2018, 5:20 PM
kotlin-dsl aiui must grab the set of plugins, use that to generate the "glue" project class with all the extensions/conventions in and then compile the script with an instance of the glue project as receiver
(you can see the "glue" class if you ctrl+click on sth like "java" or "reporting" in a build.gradle.kts)
f

Florian Wiesner

03/07/2018, 5:21 PM
guess that’s option-B on my keyboard
but really, I assume there is breakage in the test runner
a

araqnid

03/07/2018, 5:22 PM
something like that
f

Florian Wiesner

03/07/2018, 5:22 PM
I will test publish the plugin to MavenLocal()
and then have a standalone project use it
a

araqnid

03/07/2018, 5:22 PM
I'm trying it here, but even explicitly requesting the extension I'm creating by name isn't working so ...
f

Florian Wiesner

03/07/2018, 5:23 PM
I have to leave for dinner. Will look into it tomorrow and update the thread
thanks so far!
a

araqnid

03/07/2018, 5:37 PM
hmph, yes, I can register a project extension and it seems to work when referenced entirely separately, but not when trying to use GradleRunner
the "glue" class is written to somewhere like
/tmp/.gradle-test-kit-shaslam/caches/4.5/gradle-kotlin-dsl-accessors
-- i tried just removing the caches, no change
but that generated class doesn't specify the type of my project extension, the extension property is type
Any
so it seems lined up with the problem you're seeing of not finding the classes in the build script?
it writes in a comment above the extension property that the named class is not available -- so it knows what the type should be, it just couldn't load it
/**
 * Configures the [webpack][com.timgroup.gradle.webpack.WebpackProjectExtension] project extension.
 *
 * `webpack` is not accessible in a type safe way because:
 * - `com.timgroup.gradle.webpack.WebpackProjectExtension` is not available
 */
fun Project.`webpack`(configure: Any.() -> Unit): Unit =
    extensions.configure("webpack", configure)
but publishing to mavenLocal, and pulling it into another project generates the glue class fine ¯\_(ツ)_/¯
same result with Gradle 4.6. There is also a #gradle btw 😉
f

Florian Wiesner

03/07/2018, 6:51 PM
ah thanks
m

mkobit

03/08/2018, 6:32 PM
saw the post in #gradle - this sounds similar to https://github.com/gradle/kotlin-dsl/issues/492