Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions wire-gradle-plugin/api/wire-gradle-plugin.api
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
public class com/squareup/wire/gradle/CustomOutput : com/squareup/wire/gradle/WireOutput {
public fun <init> ()V
public final fun getExcludes ()Ljava/util/List;
public final fun getExcludesProperty ()Lorg/gradle/api/provider/ListProperty;
public final fun getExclusive ()Z
public final fun getExclusiveProperty ()Lorg/gradle/api/provider/Property;
public final fun getIncludes ()Ljava/util/List;
public final fun getIncludesProperty ()Lorg/gradle/api/provider/ListProperty;
public final fun getOptions ()Ljava/util/Map;
public final fun getOptionsProperty ()Lorg/gradle/api/provider/MapProperty;
public final fun getSchemaHandlerFactory ()Lcom/squareup/wire/schema/SchemaHandler$Factory;
public final fun getSchemaHandlerFactoryClass ()Ljava/lang/String;
public final fun getSchemaHandlerFactoryClassProperty ()Lorg/gradle/api/provider/Property;
public final fun getSchemaHandlerFactoryProperty ()Lorg/gradle/api/provider/Property;
public final fun setExcludes (Ljava/util/List;)V
public final fun setExclusive (Z)V
public final fun setIncludes (Ljava/util/List;)V
Expand Down Expand Up @@ -160,7 +166,9 @@ public final class com/squareup/wire/gradle/WireExtension$ProtoRootSet {

public abstract class com/squareup/wire/gradle/WireOutput {
public fun <init> ()V
protected fun getObjectFactory ()Lorg/gradle/api/model/ObjectFactory;
public final fun getOut ()Ljava/lang/String;
public final fun getOutProperty ()Lorg/gradle/api/provider/Property;
public final fun setOut (Ljava/lang/String;)V
public abstract fun toTarget (Ljava/lang/String;)Lcom/squareup/wire/schema/Target;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,45 @@ import com.squareup.wire.schema.ProtoTarget
import com.squareup.wire.schema.SchemaHandler
import com.squareup.wire.schema.Target
import com.squareup.wire.schema.newSchemaHandler
import java.io.File
import javax.inject.Inject
import kotlin.LazyThreadSafetyMode.NONE
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider

/**
* Specifies Wire's outputs (expressed as a list of [Target] objects) using Gradle's DSL (expressed
* as destination directories and configuration options). This includes registering output
* directories with the project so they can be compiled after they are generated.
*/
abstract class WireOutput {
// Gradle decorates this getter for instances created with ObjectFactory.newInstance().
@get:Inject
protected open val objectFactory: ObjectFactory
get() = throw UnsupportedOperationException("Injected by Gradle")

val outProperty: Property<String> by lazy(NONE) {
objectFactory.property(String::class.java)
}

/** Set this to override the default output directory for this [WireOutput]. */
var out: String? = null
@Deprecated(
"Use outProperty to support Gradle lazy configuration",
ReplaceWith("outProperty"),
)
var out: String?
get() = outProperty.orNull
set(value) {
outProperty.set(value)
}

internal fun outputDirectory(
projectDir: File,
defaultOutputDirectory: Provider<String>,
): Provider<String> = outProperty.map { relativizeOutputDirectory(it, projectDir) }.orElse(defaultOutputDirectory)

/**
* Transforms this [WireOutput] into a [Target] for which Wire will generate code. The [Target]
Expand All @@ -43,6 +72,16 @@ abstract class WireOutput {
abstract fun toTarget(outputDirectory: String): Target
}

internal fun relativizeOutputDirectory(
outputDirectory: String,
projectDir: File,
): String {
val file = File(outputDirectory)
if (!file.isAbsolute) return outputDirectory
return runCatching { file.relativeTo(projectDir).path }
.getOrElse { outputDirectory }
}

open class JavaOutput @Inject constructor() : WireOutput() {
/** See [com.squareup.wire.schema.Target.includes] */
var includes: List<String>? = null
Expand Down Expand Up @@ -228,40 +267,114 @@ open class ProtoOutput @Inject constructor() : WireOutput() {
}

open class CustomOutput @Inject constructor() : WireOutput() {
val includesProperty: ListProperty<String> by lazy(NONE) {
objectFactory.listProperty(String::class.java)
}

val excludesProperty: ListProperty<String> by lazy(NONE) {
objectFactory.listProperty(String::class.java)
}

val exclusiveProperty: Property<Boolean> by lazy(NONE) {
objectFactory.property(Boolean::class.java).convention(true)
}

val optionsProperty: MapProperty<String, String> by lazy(NONE) {
objectFactory.mapProperty(String::class.java, String::class.java)
}

val schemaHandlerFactoryProperty: Property<SchemaHandler.Factory> by lazy(NONE) {
objectFactory.property(SchemaHandler.Factory::class.java)
}

val schemaHandlerFactoryClassProperty: Property<String> by lazy(NONE) {
objectFactory.property(String::class.java)
}

/** See [com.squareup.wire.schema.Target.includes] */
var includes: List<String>? = null
@Deprecated(
"Use includesProperty to support Gradle lazy configuration",
ReplaceWith("includesProperty"),
)
var includes: List<String>?
get() = includesProperty.orNull
set(value) {
includesProperty.set(value)
}

/** See [com.squareup.wire.schema.Target.excludes] */
var excludes: List<String>? = null
@Deprecated(
"Use excludesProperty to support Gradle lazy configuration",
ReplaceWith("excludesProperty"),
)
var excludes: List<String>?
get() = excludesProperty.orNull
set(value) {
excludesProperty.set(value)
}

/** See [com.squareup.wire.schema.Target.exclusive] */
var exclusive: Boolean = true
@Deprecated(
"Use exclusiveProperty to support Gradle lazy configuration",
ReplaceWith("exclusiveProperty"),
)
var exclusive: Boolean
get() = exclusiveProperty.orElse(true).get()
set(value) {
exclusiveProperty.set(value)
}

/**
* Black boxed payload which a caller can set for the custom [SchemaHandler.Factory] to receive.
*/
var options: Map<String, String>? = null
/** Black boxed payload which a caller can set for the custom [SchemaHandler.Factory] to receive. */
@Deprecated(
"Use optionsProperty to support Gradle lazy configuration",
ReplaceWith("optionsProperty"),
)
var options: Map<String, String>?
get() = optionsProperty.orNull
set(value) {
optionsProperty.set(value)
}

/** Assign the schema handler factory instance. */
var schemaHandlerFactory: SchemaHandler.Factory? = null
@Deprecated(
"Use schemaHandlerFactoryProperty to support Gradle lazy configuration",
ReplaceWith("schemaHandlerFactoryProperty"),
)
var schemaHandlerFactory: SchemaHandler.Factory?
get() = schemaHandlerFactoryProperty.orNull
set(value) {
schemaHandlerFactoryProperty.set(value)
}

/**
* Assign the schema handler factory by name. If you use a class name, that class must have a
* no-arguments constructor.
*/
var schemaHandlerFactoryClass: String? = null
@Deprecated(
"Use schemaHandlerFactoryClassProperty to support Gradle lazy configuration",
ReplaceWith("schemaHandlerFactoryClassProperty"),
)
var schemaHandlerFactoryClass: String?
get() = schemaHandlerFactoryClassProperty.orNull
set(value) {
schemaHandlerFactoryClassProperty.set(value)
}

override fun toTarget(outputDirectory: String): CustomTarget {
check((schemaHandlerFactory != null) || (schemaHandlerFactoryClass != null)) {
val configuredSchemaHandlerFactory = schemaHandlerFactoryProperty.orNull
val configuredSchemaHandlerFactoryClass = schemaHandlerFactoryClassProperty.orNull

check(configuredSchemaHandlerFactory != null || configuredSchemaHandlerFactoryClass != null) {
"schemaHandlerFactory or schemaHandlerFactoryClass required"
}

return CustomTarget(
includes = includes ?: listOf("*"),
excludes = excludes ?: listOf(),
exclusive = exclusive,
includes = includesProperty.orNull ?: listOf("*"),
excludes = excludesProperty.orNull ?: listOf(),
exclusive = exclusiveProperty.orElse(true).get(),
outDirectory = outputDirectory,
options = options ?: mapOf(),
schemaHandlerFactory = schemaHandlerFactory ?: newSchemaHandler(schemaHandlerFactoryClass!!),
options = optionsProperty.orNull ?: mapOf(),
schemaHandlerFactory = configuredSchemaHandlerFactory ?: newSchemaHandler(configuredSchemaHandlerFactoryClass!!),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import com.squareup.wire.gradle.internal.libraryProtoOutputPath
import com.squareup.wire.gradle.internal.protoProjectDependenciesJvmConfiguration
import com.squareup.wire.gradle.kotlin.WireSource
import com.squareup.wire.gradle.kotlin.forEachWireSource
import com.squareup.wire.schema.ProtoTarget
import com.squareup.wire.schema.newEventListenerFactory
import com.squareup.wire.wireVersion
import java.io.File
Expand Down Expand Up @@ -85,12 +84,12 @@ class WirePlugin : Plugin<Project> {
val existingProtoOutput = extension.outputs.get().filterIsInstance<ProtoOutput>().singleOrNull()
if (existingProtoOutput != null) {
// There exists a `proto {}` target already, we only set the output path if need be.
if (existingProtoOutput.out == null) {
existingProtoOutput.out = File(project.libraryProtoOutputPath()).path
if (!existingProtoOutput.outProperty.isPresent) {
existingProtoOutput.outProperty.set(File(project.libraryProtoOutputPath()).path)
}
} else {
extension.proto { protoOutput ->
protoOutput.out = File(project.libraryProtoOutputPath()).path
protoOutput.outProperty.set(File(project.libraryProtoOutputPath()).path)
}
}
}
Expand Down Expand Up @@ -134,6 +133,11 @@ class WirePlugin : Plugin<Project> {
source: WireSource,
) {
val outputs = extension.outputs.get()
val nonProtoOutputs = outputs.filterNot { it is ProtoOutput }
val projectDir = project.projectDir
val projectDirectory = project.layout.projectDirectory
val defaultOutputPath = relativizeOutputDirectory(source.outputDir(project).path, projectDir)
val defaultOutputDirectory = project.providers.provider { defaultOutputPath }

val protoSourceProtoRootSets = extension.protoSourceProtoRootSets.toMutableList()
val protoPathProtoRootSets = extension.protoPathProtoRootSets.toMutableList()
Expand All @@ -149,11 +153,13 @@ class WirePlugin : Plugin<Project> {
}
}

val targets = outputs.map {
it.toTarget(project.relativePath(it.out ?: source.outputDir(project)))
val targets = project.provider {
outputs.map { output ->
output.toTarget(output.outputDirectory(projectDir, defaultOutputDirectory).get())
}
}

val protoTarget = targets.filterIsInstance<ProtoTarget>().singleOrNull()
val protoOutput = outputs.filterIsInstance<ProtoOutput>().singleOrNull()

val taskName = "generate${source.name.replaceFirstChar { it.uppercase() }}Protos"
val task = project.tasks.register(taskName, WireTask::class.java) { task: WireTask ->
Expand All @@ -177,24 +183,23 @@ class WirePlugin : Plugin<Project> {
}
}

targets
// Emitted `.proto` files have a special treatment. Their root should be a resource, not
// a source. We exclude the `ProtoTarget` and we'll add its output to the resources
// below.
.filterNot { it is ProtoTarget }.forEach { target ->
val dir = project.objects.directoryProperty()
dir.set(
project.tasks.named(taskName).map {
project.layout.projectDirectory.dir(target.outDirectory)
},
)
task.outputDirectoriesList.add(dir)
}
nonProtoOutputs.forEach { output ->
val dir = project.objects.directoryProperty()
dir.set(
project.tasks.named(taskName).map {
projectDirectory.dir(output.outputDirectory(projectDir, defaultOutputDirectory).get())
},
)
task.outputDirectoriesList.add(dir)
}
task.protoSourceConfiguration.setFrom(project.configurations.getByName("protoSource"))
task.protoPathConfiguration.setFrom(project.configurations.getByName("protoPath"))
task.projectDependenciesJvmConfiguration.setFrom(project.configurations.getByName("protoProjectDependenciesJvm"))
if (protoTarget != null) {
task.protoLibraryOutput.set(project.file(protoTarget.outDirectory))
if (protoOutput != null) {
task.protoLibraryOutput.set(
protoOutput.outputDirectory(projectDir, defaultOutputDirectory)
.map { projectDirectory.dir(it) },
)
}
task.sourceInput.set(project.provider { protoSourceProtoRootSets.inputLocations })
task.protoInput.set(project.provider { protoPathProtoRootSets.inputLocations })
Expand All @@ -219,10 +224,10 @@ class WirePlugin : Plugin<Project> {
task.eventListenerFactories.set(factories)
}

source.registerGeneratedSources(project, task, targets)
source.registerGeneratedSources(project, task, nonProtoOutputs)

val protoOutputDirectory = task.map { it.protoLibraryOutput }
if (protoTarget != null) {
if (protoOutput != null) {
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
// Note that there are no source sets for some platforms such as native.
// TODO(Benoit) Probably should be checking for other names than `main`. As well, source
Expand Down
Loading
Loading