Skip to content

Commit 15f44f1

Browse files
committed
Improve properties handling
1 parent 6005439 commit 15f44f1

File tree

4 files changed

+167
-51
lines changed

4 files changed

+167
-51
lines changed

buildSrc/src/main/kotlin/net/kautler/Properties.kt

Lines changed: 132 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,149 @@
1717
package net.kautler
1818

1919
import org.gradle.api.Project
20+
import org.gradle.api.Task
2021
import kotlin.properties.ReadOnlyProperty
2122
import kotlin.reflect.KProperty
2223

23-
abstract class Property<out T>(
24-
private val project: Project,
25-
private var propertyName: String?,
26-
private val default: T
27-
) : ReadOnlyProperty<Any, T> {
24+
sealed class Property<out T> constructor(
25+
private val default: () -> T,
26+
private var propertyName: String,
27+
private var project: Project
28+
) : ReadOnlyProperty<Any?, T> {
2829
protected abstract fun doGetValue(project: Project, propertyName: String): T?
2930

30-
fun getValue() = doGetValue(project, propertyName!!) ?: default
31+
fun getValue() = doGetValue(project, propertyName) ?: default.invoke()
3132

32-
override fun getValue(thisRef: Any, property: KProperty<*>) = doGetValue(project, propertyName!!) ?: default
33+
override fun getValue(thisRef: Any?, property: KProperty<*>) = getValue()
3334

34-
operator fun provideDelegate(thisRef: Any, property: KProperty<*>) = this.apply {
35-
propertyName = propertyName ?: property.name
35+
companion object {
36+
fun boolean(
37+
default: () -> Boolean = { false },
38+
propertyName: String? = null,
39+
project: Project? = null
40+
) = PropertyDelegateProvider(
41+
default,
42+
propertyName,
43+
project,
44+
::BooleanProperty
45+
)
46+
47+
fun boolean(
48+
default: Boolean,
49+
propertyName: String? = null,
50+
project: Project? = null
51+
) = boolean({ default }, propertyName, project)
52+
53+
fun boolean(
54+
project: Project,
55+
propertyName: String,
56+
default: () -> Boolean = { false }
57+
): Property<Boolean> = BooleanProperty(default, propertyName, project)
58+
59+
fun boolean(
60+
project: Project,
61+
propertyName: String,
62+
default: Boolean
63+
) = boolean(project, propertyName) { default }
64+
65+
fun string(
66+
default: () -> String,
67+
propertyName: String? = null,
68+
project: Project? = null
69+
) = PropertyDelegateProvider(
70+
default,
71+
propertyName,
72+
project,
73+
::StringProperty
74+
)
75+
76+
fun string(
77+
default: String,
78+
propertyName: String? = null,
79+
project: Project? = null
80+
) = string({ default }, propertyName, project)
81+
82+
fun string(
83+
project: Project,
84+
propertyName: String,
85+
default: () -> String
86+
): Property<String> = StringProperty(default, propertyName, project)
87+
88+
fun string(
89+
project: Project,
90+
propertyName: String,
91+
default: String
92+
) = string(project, propertyName) { default }
93+
94+
fun optionalString(
95+
propertyName: String? = null,
96+
project: Project? = null
97+
) = PropertyDelegateProvider(
98+
{ null },
99+
propertyName,
100+
project,
101+
::OptionalStringProperty
102+
)
103+
104+
fun optionalString(
105+
project: Project,
106+
propertyName: String
107+
): Property<String?> = OptionalStringProperty(propertyName, project)
36108
}
37109
}
38110

39-
class StringProperty(
40-
project: Project,
41-
propertyName: String? = null,
42-
default: String? = null
43-
) : Property<String?>(project, propertyName, default) {
44-
override fun doGetValue(project: Project, propertyName: String) = findProperty(project, propertyName)
111+
class PropertyDelegateProvider<out T>(
112+
private val default: () -> T,
113+
private val propertyName: String? = null,
114+
private val project: Project? = null,
115+
private val delegateFactory: (() -> T, String, Project) -> Property<T>
116+
) {
117+
operator fun provideDelegate(thisRef: Project, property: KProperty<*>) =
118+
delegateFactory(default, propertyName ?: property.name, project ?: thisRef)
119+
120+
operator fun provideDelegate(thisRef: Task, property: KProperty<*>) =
121+
provideDelegate(thisRef.project, property)
122+
123+
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>) =
124+
project?.let {
125+
provideDelegate(it, property)
126+
} ?: error("Property '${property.name}' must be declared on 'Project' or 'Task', " +
127+
"or 'Project' must be given explicitly")
128+
}
129+
130+
private class OptionalStringProperty(
131+
default: () -> String?,
132+
propertyName: String,
133+
project: Project
134+
) : Property<String?>(default, propertyName, project) {
135+
constructor(propertyName: String, project: Project) : this({ null }, propertyName, project)
136+
137+
override fun doGetValue(project: Project, propertyName: String) =
138+
findProperty(project, propertyName)
45139
}
46140

47-
class BooleanProperty(
48-
project: Project,
49-
propertyName: String? = null,
50-
default: Boolean = false
51-
) : Property<Boolean>(project, propertyName, default) {
52-
override fun doGetValue(project: Project, propertyName: String) = findProperty(project, propertyName)?.toBoolean()
141+
private class StringProperty(
142+
default: () -> String,
143+
propertyName: String,
144+
project: Project
145+
) : Property<String>(default, propertyName, project) {
146+
override fun doGetValue(project: Project, propertyName: String) =
147+
findProperty(project, propertyName)
53148
}
54149

55-
private fun findProperty(project: Project, propertyName: String) = (
56-
project.findProperty("${project.rootProject.name}.$propertyName")
57-
?: project.findProperty(propertyName))
58-
as String?
150+
private class BooleanProperty(
151+
default: () -> Boolean = { false },
152+
propertyName: String,
153+
project: Project
154+
) : Property<Boolean>(default, propertyName, project) {
155+
override fun doGetValue(project: Project, propertyName: String) =
156+
findProperty(project, propertyName)?.toBoolean()
157+
}
158+
159+
private fun findProperty(project: Project, propertyName: String): String? {
160+
var result = project.findProperty("${project.rootProject.name}.$propertyName") as String?
161+
if (result.isNullOrBlank()) {
162+
result = project.findProperty(propertyName) as String?
163+
}
164+
return if (result.isNullOrBlank()) null else result
165+
}

buildSrc/src/main/kotlin/net/kautler/PropertyExtension.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,31 @@
1616

1717
package net.kautler
1818

19-
import org.gradle.api.provider.ListProperty
19+
import org.gradle.api.file.FileSystemLocation
20+
import org.gradle.api.file.FileSystemLocationProperty
21+
import org.gradle.api.provider.HasMultipleValues
22+
import org.gradle.api.provider.MapProperty
2023
import org.gradle.api.provider.Property
2124
import org.gradle.api.provider.Provider
22-
import org.gradle.api.provider.SetProperty
25+
import java.io.File
2326

2427
@Suppress("UnstableApiUsage")
2528
operator fun <T> Property<T>.invoke(value: T) = set(value)
2629

2730
@Suppress("UnstableApiUsage")
28-
operator fun <T> Property<T>.invoke(valueProvider: Provider<out T>) = set(valueProvider)
31+
operator fun <T> Property<T>.invoke(provider: Provider<out T>) = set(provider)
2932

3033
@Suppress("UnstableApiUsage")
31-
operator fun <T> ListProperty<T>.invoke(value: Iterable<T>) = set(value)
34+
operator fun <T> HasMultipleValues<T>.invoke(elements: Iterable<T>) = set(elements)
3235

3336
@Suppress("UnstableApiUsage")
34-
operator fun <T> ListProperty<T>.invoke(valueProvider: Provider<out Iterable<T>>) = set(valueProvider)
37+
operator fun <T> HasMultipleValues<T>.invoke(provider: Provider<out Iterable<T>>) = set(provider)
3538

3639
@Suppress("UnstableApiUsage")
37-
operator fun <T> SetProperty<T>.invoke(value: Iterable<T>) = set(value)
40+
operator fun <K, V> MapProperty<K, V>.invoke(entries: Map<K, V>) = set(entries)
3841

3942
@Suppress("UnstableApiUsage")
40-
operator fun <T> SetProperty<T>.invoke(valueProvider: Provider<out Iterable<T>>) = set(valueProvider)
43+
operator fun <K, V> MapProperty<K, V>.invoke(provider: Provider<out Map<K, V>>) = set(provider)
44+
45+
@Suppress("UnstableApiUsage")
46+
operator fun <T : FileSystemLocation> FileSystemLocationProperty<T>.invoke(file: File) = set(file)

buildSrc/src/main/kotlin/net/kautler/publishing.gradle.kts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ package net.kautler
1818

1919
import io.codearte.gradle.nexus.BaseStagingTask
2020
import io.codearte.gradle.nexus.GetStagingProfileTask
21+
import net.kautler.Property.Companion.boolean
22+
import net.kautler.Property.Companion.optionalString
2123
import net.researchgate.release.ReleasePlugin
2224
import org.ajoberstar.grgit.Grgit
2325
import org.kohsuke.github.GHIssueState.OPEN
@@ -48,27 +50,27 @@ plugins {
4850
}
4951

5052
val releaseVersion = !version.toString().endsWith("-SNAPSHOT")
51-
val useGpgAgent by BooleanProperty(project, "signing.useGpgAgent")
52-
val sonatypeUsername by StringProperty(project, "sonatype.username")
53-
val sonatypePassword by StringProperty(project, "sonatype.password")
54-
val sonatypeStagingProfileId by StringProperty(project, "sonatype.stagingProfileId")
55-
56-
extra["release.useAutomaticVersion"] = BooleanProperty(project, "release.useAutomaticVersion").getValue()
57-
extra["release.releaseVersion"] = StringProperty(project, "release.releaseVersion").getValue()
58-
extra["release.newVersion"] = StringProperty(project, "release.newVersion").getValue()
53+
val useGpgAgent by boolean(propertyName = "signing.useGpgAgent")
54+
val sonatypeUsername by optionalString("sonatype.username")
55+
val sonatypePassword by optionalString("sonatype.password")
56+
val sonatypeStagingProfileId by optionalString("sonatype.stagingProfileId")
57+
58+
extra["release.useAutomaticVersion"] = boolean(project, "release.useAutomaticVersion").getValue()
59+
extra["release.releaseVersion"] = optionalString(project, "release.releaseVersion").getValue()
60+
extra["release.newVersion"] = optionalString(project, "release.newVersion").getValue()
5961
if (useGpgAgent) {
60-
extra["signing.gnupg.executable"] = StringProperty(project, "signing.gnupg.executable").getValue()
61-
extra["signing.gnupg.useLegacyGpg"] = StringProperty(project, "signing.gnupg.useLegacyGpg").getValue()
62-
extra["signing.gnupg.homeDir"] = StringProperty(project, "signing.gnupg.homeDir").getValue()
63-
extra["signing.gnupg.optionsFile"] = StringProperty(project, "signing.gnupg.optionsFile").getValue()
64-
extra["signing.gnupg.keyName"] = StringProperty(project, "signing.gnupg.keyName").getValue()
65-
extra["signing.gnupg.passphrase"] = StringProperty(project, "signing.gnupg.passphrase").getValue()
62+
extra["signing.gnupg.executable"] = optionalString(project, "signing.gnupg.executable").getValue()
63+
extra["signing.gnupg.useLegacyGpg"] = optionalString(project, "signing.gnupg.useLegacyGpg").getValue()
64+
extra["signing.gnupg.homeDir"] = optionalString(project, "signing.gnupg.homeDir").getValue()
65+
extra["signing.gnupg.optionsFile"] = optionalString(project, "signing.gnupg.optionsFile").getValue()
66+
extra["signing.gnupg.keyName"] = optionalString(project, "signing.gnupg.keyName").getValue()
67+
extra["signing.gnupg.passphrase"] = optionalString(project, "signing.gnupg.passphrase").getValue()
6668
} else {
67-
extra["signing.secretKeyRingFile"] = StringProperty(project, "signing.secretKeyRingFile").getValue()
68-
extra["signing.password"] = StringProperty(project, "signing.password").getValue()
69-
extra["signing.keyId"] = StringProperty(project, "signing.keyId").getValue()
69+
extra["signing.secretKeyRingFile"] = optionalString(project, "signing.secretKeyRingFile").getValue()
70+
extra["signing.password"] = optionalString(project, "signing.password").getValue()
71+
extra["signing.keyId"] = optionalString(project, "signing.keyId").getValue()
7072
}
71-
extra["github.token"] = StringProperty(project, "github.token").getValue()
73+
extra["github.token"] = optionalString(project, "github.token").getValue()
7274

7375
tasks.withType<PublishToMavenRepository>().configureEach {
7476
doFirst("verify username and password are set") {

buildSrc/src/main/kotlin/net/kautler/spotbugs.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package net.kautler
1818

1919
import com.github.spotbugs.SpotBugsTask
20+
import net.kautler.Property.Companion.string
2021
import net.sf.saxon.TransformerFactoryImpl
2122
import org.gradle.api.tasks.PathSensitivity.NONE
2223
import javax.xml.transform.TransformerFactory
@@ -32,7 +33,7 @@ val versions: Map<String, String> by project
3233

3334
spotbugs {
3435
toolVersion = versions["spotbugs"] ?: error("spotbugs version is missing")
35-
reportLevel = StringProperty(project, "spotbugs.reportLevel", "low").getValue()
36+
reportLevel = string(project, "spotbugs.reportLevel", "low").getValue()
3637
@Suppress("UnstableApiUsage")
3738
excludeFilterConfig = resources.text.fromFile("config/spotbugs/spotbugs-exclude.xml")
3839
}

0 commit comments

Comments
 (0)