diff --git a/README.md b/README.md index 5543f429..5de23652 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ buildscript { Stand-alone examples are available for each of gradle's supported languages. * [Groovy](https://github.com/google/protobuf-gradle-plugin/tree/master/examples/exampleProject) ___(Default)___ * Run `../../gradlew build` under the example directory to test it out. - * [Kotlin (experimental)](https://github.com/google/protobuf-gradle-plugin/tree/master/examples/exampleKotlinDslProject) - * Run `./gradlew build` under the Kotlin example directory to test it out. This example is set up with Gradle 4.10, the minimum required version. + * [Kotlin](https://github.com/google/protobuf-gradle-plugin/tree/master/examples/exampleKotlinDslProject) ___(Experimental)___ + * Run `./gradlew build` under the Kotlin example directory to test it out. This example is set up with Gradle 5.0, the minimum required version. Directories that start with `testProject` can also serve as usage diff --git a/build.gradle b/build.gradle index 71fd9a5c..76b3bcf1 100644 --- a/build.gradle +++ b/build.gradle @@ -86,6 +86,8 @@ dependencies { } testCompile 'commons-io:commons-io:2.5' + // This kotlin version needs to be compatible with the + // android plugin being used in the test runtime. testProjectRuntime "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0" // Add android plugin to the test classpath, so that we can jump into class definitions, diff --git a/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt b/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt index 38c4ff12..12e96719 100644 --- a/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt +++ b/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt @@ -4,13 +4,53 @@ 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 @@ -18,47 +58,116 @@ fun SourceSet.proto(action: ProtobufSourceDirectorySet.() -> Unit) { ?.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.() -> Unit) { +fun ProtobufConfigurator.plugins(action: NamedDomainObjectContainerScope.() -> Unit) { plugins(closureOf> { - closure(NamedDomainObjectContainerScope.of(this)) + NamedDomainObjectContainerScope.of(this).action() }) } -fun NamedDomainObjectContainerScope.id(id: String, closure: (T.() -> Unit)? = null) { - closure?.let { create(id, closureOf(it)) } - ?: create(id) -} - -fun NamedDomainObjectContainerScope.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(configuration: NamedDomainObjectContainerScope.()->Unit) { +fun GenerateProtoTask.builtins(action: NamedDomainObjectContainerScope.()->Unit) { builtins(closureOf> { - configuration(NamedDomainObjectContainerScope.of(this)) + NamedDomainObjectContainerScope.of(this).action() }) } -fun GenerateProtoTask.plugins(configuration: NamedDomainObjectContainerScope.()-> Unit) { +fun GenerateProtoTask.plugins(action: NamedDomainObjectContainerScope.()-> Unit) { plugins(closureOf> { - configuration(NamedDomainObjectContainerScope.of(this)) + NamedDomainObjectContainerScope.of(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 NamedDomainObjectContainerScope.id(id: String, action: (T.() -> Unit)? = null) { + 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 NamedDomainObjectContainerScope.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. */