Skip to content
This repository has been archived by the owner on Aug 19, 2020. It is now read-only.

Provide convenient configuration of nested project extensions and conventions #457

Closed
bamboo opened this issue Aug 10, 2017 · 9 comments
Closed

Comments

@bamboo
Copy link
Member

bamboo commented Aug 10, 2017

Although a relatively uncommon pattern, project extensions can themselves be extended.

The Kotlin DSL should provide accessors for all nested extensions found at project schema computation time.

Related forum post: https://discuss.gradle.org/t/make-a-gradle-plugin-compatible-with-kotlin-dsl/23657/3

@eskatos
Copy link
Member

eskatos commented Sep 29, 2017

@JLLeitschuh
Copy link
Contributor

The Junit 5 plugin used to do this too before I opened a PR to fix it.
There needs to be a way to make sure that the compiler doesn't complain or blow up about having duplicate extensions if the plugin author has added these helper methods themself.

Example:
https://github.com/junit-team/junit5/blob/master/junit-platform-gradle-plugin/src/main/groovy/org/junit/platform/gradle/plugin/JUnitPlatformExtension.groovy#L100-L102

class JUnitPlatformExtension {
	void selectors(Action<SelectorsExtension> closure) {
		closure.execute(getProperty(JUnitPlatformPlugin.SELECTORS_EXTENSION_NAME) as SelectorsExtension)
	}
}

And how the extensions are added:
https://github.com/junit-team/junit5/blob/master/junit-platform-gradle-plugin/src/main/groovy/org/junit/platform/gradle/plugin/JUnitPlatformPlugin.groovy#L41

@NikolayMetchev
Copy link

Is there a workaround for this? Is there ANY way to get the nested extensions? i am trying to use the Jaxb plugin which nests the xjc extensions inside the jaxb extensions (https://github.com/jacobono/gradle-jaxb-plugin). How would I customize the xjc extensions?

@NikolayMetchev
Copy link

NikolayMetchev commented Oct 20, 2017

I have managed to figure out the workaround for the Jaxb case but it is a complete hack. If someone has a better workaround let me know.

Add this method to the script:

fun JaxbExtension.xjc(configure: XjcExtension.() -> Unit) {
  val convention: DefaultConvention = this::class.members.find { m -> m.name == "getConvention" }?.call(this) as DefaultConvention
  configure.invoke(convention.getByName("xjc") as XjcExtension)
}

Which will then allow you to customize Jaxb as expected:

jaxb {
  xjc {
    destinationDir = "src/generated/java"
  }
  xsdDir = projectDir.resolve("src").resolve("xsd").relativeTo(rootDir).toString()
}

@bamboo
Copy link
Member Author

bamboo commented Oct 20, 2017

Hi @NikolayMetchev,

A simpler workaround would be to cast the outer extension to ExtensionAware and extract the inner extension explicitly as in the following (working) example:

import org.gradle.jacobo.plugins.extension.XjcExtension

plugins {
    id("com.github.jacobono.jaxb") version "1.3.5"
}

jaxb {

    val jaxbExtensions = (this as ExtensionAware).extensions

    val xjc: XjcExtension by jaxbExtensions
    xjc.apply {
        destinationDir = "src/generated/java"
    }

    xsdDir = projectDir.resolve("src").resolve("xsd").relativeTo(rootDir).toString()
}

@NikolayMetchev
Copy link

Thanks @bamboo that is a much better workaround.

@bamboo bamboo modified the milestones: 1.0.0, 0.13.0 Nov 2, 2017
@bamboo bamboo modified the milestones: 0.13.0, 0.14.0 Nov 14, 2017
@eskatos eskatos self-assigned this Nov 29, 2017
@bamboo bamboo modified the milestones: 0.14.0, 0.15.0 Dec 1, 2017
@bamboo bamboo modified the milestones: 0.15.0, 1.0.0 Jan 8, 2018
@bamboo bamboo changed the title Accessors for nested project extensions Accessors for nested project extensions and conventions Jan 18, 2018
@eskatos eskatos changed the title Accessors for nested project extensions and conventions Provide convenient configuration of nested project extensions and conventions Jan 18, 2018
@eskatos eskatos modified the milestones: 1.0.0, 0.17.x Mar 25, 2018
@xeruf
Copy link

xeruf commented Mar 25, 2018

I think a first step would be to atleast have an extension function as a simple workaround within kotlin-dsl, maybe something like this:

fun <T : Any> Any.extensionAware(clazz: KClass<T>, action: T.() -> Unit) = (this as ExtensionAware).extensions.configure(clazz.java, action)

@JLLeitschuh
Copy link
Contributor

@Xerus2000 Slight improvement upon your code here:

inline fun <reified T : Any> Any.extensionAware(action: T.() -> Unit) =
    (this as ExtensionAware).extensions.configure(T.java, action)

@eskatos
Copy link
Member

eskatos commented Apr 25, 2018

Closing as delivered

@eskatos eskatos closed this as completed Apr 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants