Using afterEvaluate
is almost always the wrong thing to do. In 98.7 % of the cases it is just symptom treatment like calling SwingUtilities.invokeLater
or Platform.runLater
to “fix” a GUI problem. It usually just shifts the problem to a later time where it is much harder to reproduce, much harder to debug, and much harder to fix. The main thing afterEvaluate
does is introducing timing problems, ordering problems, and race conditions. That’s why the Property
/ Provider
APIs were introduced, so that properties can lazily be wired together without the need to do delayed evaluation to give someone the chance to configure the value before you read it. What happens for example if someone sets the value in an afterEvaluate
that is evaluated after your afterEvaluate
? …
Your conclusions were right though.
There are a couple of ways to do it properly.
You could for example make the consumer not set this property but instead just apply the pure checkstyle plugin, then in your plugin you can have project.pluginManager.withPlugin("checkstyle") { /* configure checkstyle */
.
Or you can have multiple convention plugins and one of them if applied, applies and configures the checkstyle plugin without condition, as the condition is that the consumer applies it.
Or you can replace the addCheckStyle
property by an addCheckStyle
function that is then called by the consumer and do the checkstyle configuration within that function.
Btw. your extension can be much simpler unless you need to support ancient Gradle versions:
abstract class CodeStyleExtension {
abstract val addCheckStyle: Property<Boolean>
init {
addCheckStyle.convention(false)
}
}
Or if you follow good practices and configure defaults and wirings in the plugin, you can even have
interface CodeStyleExtension {
val addCheckStyle: Property<Boolean>
}
and then
project.extensions.create(
"myplugin",
CodeStyleExtension::class.java
).apply {
addCheckStyle.convention(false)
}
to create it.
Also, extensions.create
already returns the extension instance to you, so you don’t have to request the extension by type, unless you oversimplified the example.
And, Property
s should always be val
, not var
.
Their value might change, but the instance should never change.
And using val
also enables the assignment plugin in latest Gradle versions where you can use addCheckStyle = true
also in Kotlin DSL build scripts.