-
Notifications
You must be signed in to change notification settings - Fork 274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update to stable kotlin dsl #275
Changes from all commits
d6c505d
99c344a
1ec2c22
9d1da25
6fe9209
6028363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.google.protobuf.gradle; | ||
|
||
import kotlin.Unit; | ||
import kotlin.jvm.functions.Function1; | ||
import org.gradle.api.NamedDomainObjectContainer; | ||
import org.gradle.kotlin.dsl.NamedDomainObjectContainerExtensionsKt; | ||
import org.gradle.kotlin.dsl.NamedDomainObjectContainerScope; | ||
|
||
public class KtDslCompatibilityUtils { | ||
|
||
/** | ||
* This method is used to delegate the NamedDomainObjectContainer configuration to | ||
* to which ever kotlin-dsl ext implementation is available on the classpath. | ||
* | ||
* Since NamedDomainObjectContainerExtensionsKt.invoke is an inline extension function, our | ||
* usages in 'ProtobufConfiguratorExts.kt' would use the byte code for which ever kotlin-dsl | ||
* version we compiled against. This caused issues with providing compatibility with | ||
* kotlin-dsl 1.0.0-rc3 and 1.0.4 (Stable). | ||
* | ||
* Since the kotlin compiler creates a static implementations of all extensions, we can create a | ||
* delegating utility function that ensures we are not inline-ing our kotlin-dsl compilation | ||
* target byte code. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I still don't understand why this additional layer of indirection would prevent the problem. Doesn't this method inline the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In-lining can only be performed by the Kotlin compiler, and this is file is compiled via the java compiler. The method is resolvable from java due to Kotlins interop features. Since inline methods dont exist in java, Kotlin will create a static implementation of the method for usage from java sources. This work around solves the compatibility issue because the method contract didnt change between ktdsl versions, only its implementation. |
||
* | ||
* @param container Container to apply the scope configuration | ||
* @param block A kotlin lambda to apply to the NamedDomainObjectContainerScope | ||
* @return A NamedDomainObjectContainer with the block lambda applied to is NamedDomainObjectContainerScope | ||
*/ | ||
static <T> NamedDomainObjectContainer<T> configureNamedDomainObjectContainer( | ||
NamedDomainObjectContainer<T> container, | ||
Function1<? super NamedDomainObjectContainerScope<T>, Unit> block){ | ||
|
||
return NamedDomainObjectContainerExtensionsKt.invoke(container, block); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,61 +4,170 @@ import org.gradle.api.NamedDomainObjectContainer | |
import org.gradle.api.Project | ||
import org.gradle.api.plugins.ExtensionAware | ||
import org.gradle.api.tasks.SourceSet | ||
import org.gradle.kotlin.dsl.* | ||
|
||
import org.gradle.kotlin.dsl.NamedDomainObjectContainerScope | ||
import org.gradle.kotlin.dsl.closureOf | ||
import org.gradle.kotlin.dsl.get | ||
|
||
/** | ||
* Applies the supplied action to the project's instance of [ProtobufConfigurator]. | ||
* | ||
* @since 0.8.7 | ||
* @usage | ||
* ``` | ||
* protobuf { | ||
* ... | ||
* generatedFilesBaseDir = files(...) | ||
* } | ||
* ``` | ||
* | ||
* @receiver [Project] The project for which the plugin configuration will be applied | ||
* @param action A configuration lambda to apply on a receiver of type [ProtobufConfigurator] | ||
* | ||
* @return [Unit] | ||
*/ | ||
fun Project.protobuf(action: ProtobufConfigurator.()->Unit) { | ||
project.convention.getPlugin(ProtobufConvention::class.java).protobuf.apply(action) | ||
} | ||
|
||
/** | ||
* Applies the supplied action to the [ProtobufSourceDirectorySet] extension on | ||
* a receiver of type [SourceSet] | ||
* | ||
* @since 0.8.7 | ||
* @usage | ||
* ``` | ||
* sourceSets { | ||
* create("sample") { | ||
* proto { | ||
* srcDir("src/sample/protobuf") | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* @receiver [SourceSet] The source set for which the [ProtobufSourceDirectorySet] extension | ||
* will be configured | ||
* | ||
* @param action A configuration lambda to apply on a receiver of type [ProtobufSourceDirectorySet] | ||
* @return [Unit] | ||
*/ | ||
fun SourceSet.proto(action: ProtobufSourceDirectorySet.() -> Unit) { | ||
(this as? ExtensionAware) | ||
?.extensions | ||
?.getByType(ProtobufSourceDirectorySet::class.java) | ||
?.apply(action) | ||
} | ||
|
||
fun ProtobufConfigurator.protoc(closure: ExecutableLocator.() -> Unit) { | ||
protoc(closureOf(closure)) | ||
/** | ||
* Uses the supplied action to configure the [ExecutableLocator] for protoc. | ||
* | ||
* @since 0.8.7 | ||
* @usage | ||
* ``` | ||
* protobuf { | ||
* protoc { | ||
* artifact = "com.google.protobuf:protoc:3.6.1" | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* @receiver [ProtobufConfigurator] The protobuf plugin configuration instance | ||
* for the project. | ||
* | ||
* @param action A lambda with receiver of type [ExecutableLocator] used | ||
* for configuring the locator for protoc | ||
* | ||
* @return [Unit] | ||
*/ | ||
fun ProtobufConfigurator.protoc(action: ExecutableLocator.() -> Unit) { | ||
protoc(closureOf(action)) | ||
} | ||
|
||
fun ProtobufConfigurator.plugins(closure: NamedDomainObjectContainerScope<ExecutableLocator>.() -> Unit) { | ||
fun ProtobufConfigurator.plugins(action: NamedDomainObjectContainerScope<ExecutableLocator>.() -> Unit) { | ||
plugins(closureOf<NamedDomainObjectContainer<ExecutableLocator>> { | ||
this(closure) | ||
KtDslCompatibilityUtils.configureNamedDomainObjectContainer<ExecutableLocator>(this, action) | ||
}) | ||
} | ||
|
||
fun <T : Any> NamedDomainObjectContainerScope<T>.id(id: String, closure: (T.() -> Unit)? = null) { | ||
closure?.let { create(id, closureOf(it)) } | ||
?: create(id) | ||
} | ||
|
||
fun <T : Any> NamedDomainObjectContainerScope<T>.remove(id: String) { | ||
remove(this[id]) | ||
} | ||
|
||
fun ProtobufConfigurator.generateProtoTasks(closure: ProtobufConfigurator.GenerateProtoTaskCollection.()->Unit) { | ||
generateProtoTasks(closureOf(closure)) | ||
fun ProtobufConfigurator.generateProtoTasks(action: ProtobufConfigurator.GenerateProtoTaskCollection.()->Unit) { | ||
generateProtoTasks(closureOf(action)) | ||
} | ||
|
||
fun GenerateProtoTask.builtins(closure: NamedDomainObjectContainerScope<GenerateProtoTask.PluginOptions>.()->Unit) { | ||
fun GenerateProtoTask.builtins(action: NamedDomainObjectContainerScope<GenerateProtoTask.PluginOptions>.()->Unit) { | ||
builtins(closureOf<NamedDomainObjectContainer<GenerateProtoTask.PluginOptions>> { | ||
this(closure) | ||
KtDslCompatibilityUtils.configureNamedDomainObjectContainer<GenerateProtoTask.PluginOptions>(this, action) | ||
}) | ||
} | ||
|
||
fun GenerateProtoTask.plugins(closure: NamedDomainObjectContainerScope<GenerateProtoTask.PluginOptions>.()-> Unit) { | ||
fun GenerateProtoTask.plugins(action: NamedDomainObjectContainerScope<GenerateProtoTask.PluginOptions>.()-> Unit) { | ||
plugins(closureOf<NamedDomainObjectContainer<GenerateProtoTask.PluginOptions>> { | ||
this(closure) | ||
KtDslCompatibilityUtils.configureNamedDomainObjectContainer<GenerateProtoTask.PluginOptions>(this, action) | ||
}) | ||
} | ||
|
||
/** | ||
* An extension for creating and configuring the elements of an instance of [NamedDomainObjectContainer]. | ||
* | ||
* @since 0.8.7 | ||
* @usage | ||
* ``` | ||
* protobuf { | ||
* plugins { | ||
* id("grpc") { | ||
* artifact = "io.grpc:protoc-gen-grpc-java:1.15.1" | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* @receiver [NamedDomainObjectContainerScope] The scope of the [NamedDomainObjectContainer] | ||
* on which to create or configure an element. | ||
* | ||
* @param id The string id of the element to create or configure. | ||
* @param action An optional action that will be applied to the element instance. | ||
* | ||
* @return [Unit] | ||
*/ | ||
fun <T : Any> NamedDomainObjectContainerScope<T>.id(id: String, action: (T.() -> Unit)? = null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two methods arent new. I just moved them down in the file and documented their usage |
||
action?.let { create(id, closureOf(it)) } | ||
?: create(id) | ||
} | ||
|
||
|
||
/** | ||
* An extension for removing an element by id on an instance of [NamedDomainObjectContainer]. | ||
* | ||
* @since 0.8.7 | ||
* @usage | ||
* ``` | ||
* protobuf { | ||
* generateProtoTasks { | ||
* ofSourceSet("main").forEach { | ||
* it.builtins { | ||
* remove("java") | ||
* } | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* @receiver [NamedDomainObjectContainerScope] The scope of the [NamedDomainObjectContainer] | ||
* on which to remove an element. | ||
* | ||
* @param id The string id of the element to remove. | ||
* | ||
* @return [Unit] | ||
*/ | ||
fun <T : Any> NamedDomainObjectContainerScope<T>.remove(id: String) { | ||
remove(this[id]) | ||
} | ||
|
||
/** | ||
* The method generatorProtoTasks applies the supplied closure to the | ||
* instance of [ProtobufConfigurator.GenerateProtoTaskCollection]. | ||
* | ||
* Since [ProtobufConfigurator.JavaGenerateProtoTaskCollection] and [ProtobufConfigurator.AndroidGenerateProtoTaskCollection] | ||
* each have unique methods, and only one instance in allocated per project, we need a way to statically resolve the | ||
* each have unique methods, and only one instance is allocated per project, we need a way to statically resolve the | ||
* available methods. This is a necessity since Kotlin does not have any dynamic method resolution capabilities. | ||
*/ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,7 +100,7 @@ tasks { | |
from(sourceSet.output) | ||
|
||
val compileTaskName = sourceSet.getCompileTaskName("java") | ||
dependsOn(tasks.getByName(compileTaskName)) | ||
dependsOn(project.tasks.getByName(compileTaskName)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An additional extension was added to the task container in 1.0.3. So in order to deal with ambiguity in method resolution I had to explicitly qualify the |
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bumping this dependency version is what was causing the failures in the ci. The test runtime kotlin version needs to be compatible with the older version of the android plugin. I didnt need to update it in the first place so its fine being set to
1.2.0