Get a property of task? in Gradle kotlin - kotlin

I'm trying to convert my build.gradle file to build.gradle.kts.
I almost do that but only one problem left.
I don't have any idea how to convert code below.
Kotlin
import org.asciidoctor.gradle.AsciidoctorTask
...
apply(plugin = "org.asciidoctor.convert")
val snippetsDir = file("build/generated-snippets")
tasks.named<AsciidoctorTask>("asciidoctor") {
attributes(
mapOf(
"snippets" to snippetsDir
)
)
inputs.dir(snippetsDir)
dependsOn("test")
}
tasks.withType<BootJar> {
dependsOn("asciidoctor")
// This is the problem!
// from("${asciidoctor.outputDir}/html5") {
// into("static/docs")
// }
}
Please help me! Thanks :)

See Tasks documentation : you can access asciidoctor tasks using Kotlin delegated properties, and then access its properties like outputDir
tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> {
dependsOn("asciidoctor")
// This was the problem!
val asciidoctor by tasks.getting(AsciidoctorTask::class)
from("${asciidoctor.outputDir}/html5") {
into("static/docs")
}
}

Related

Calling PCEnhancerTask from Kotlin in Gradle

I need to call the OpenJPA PCEnhancerTask class from Kotlin instead of Groovy. The following code works just fine (based on a previous solution documented here):
def openJPAClosure = {
def entityFiles = sourceSets.main.output.classesDirs.asFileTree.matching {
include 'com/company/persist/*Entity.class'
}
println "Enhancing with OpenJPA:"
entityFiles.getFiles().each {
println it
}
ant.taskdef(
name : 'openjpac',
classpath : sourceSets.main.runtimeClasspath.asPath,
classname : 'org.apache.openjpa.ant.PCEnhancerTask'
)
ant.openjpac(
classpath: sourceSets.main.runtimeClasspath.asPath,
addDefaultConstructor: false,
enforcePropertyRestrictions: true) {
entityFiles.addToAntBuilder(ant, 'fileset', FileCollection.AntType.FileSet)
}
}
I was looking at the documentation on how to call Ant tasks from Gradle but I could not translate all the necessary steps using the GroovyBuilder. So instead I tough of calling the PCEnhancer directly:
fun openJPAEnrich() {
val entityFiles = sourceSets.main.get().output.classesDirs.asFileTree.matching {
include("com/company/persist/*Entity.class")
}
println("Enhancing with OpenJPA, the following files...")
entityFiles.getFiles().forEach() {
println(it)
}
org.apache.openjpa.ant.PCEnhancerTask.main(asList(entityFiles))
}
But it complains about not being able to find org.apache.openjpa in the classpath (but is it listed as a compilation dependency)
My questions are:
What is the correct way to translate the original Groovy construct to Kotlin using groovyBuilder
If is not possible, how you can correctly call PCEnhancer from Kotlin in Gradle?
So I ended making it work with a custom JavaExec Gradle task:
tasks.create<JavaExec>("openJPAEnrich") {
val entityFiles = sourceSets.main.get().output.classesDirs.asFileTree.matching {
include("com/company/persist/*Entity.class")
}
println("Enhancing with OpenJPA, the following files...")
entityFiles.files.forEach() {
println(it)
}
classpath = sourceSets.main.get().runtimeClasspath
main = "org.apache.openjpa.enhance.PCEnhancer"
args(listOf("-enforcePropertyRestrictions", "true", "-addDefaultConstructor", "false"))
entityFiles.forEach { classFile -> args?.add(classFile.toString())}
}
I was tempted to build my own custom Gradle task but for this felt overkill.
Thanks.
--Jose

Unresolved reference: grgit

This is my world server land plug-in, and I don't know much about gradle and kotlin.(Know some front-end, but every line is like a mountain)
I encountered a problem when compiling. It seems that I lack something called grgit.
How to solve this problem?
Or you can try to compile this project. If you succeed, don't forget to tell me your method. Thank you very much!
import java.time.format.DateTimeFormatter
dependencies {
// Expected everywhere.
compileOnlyApi(libs.checkerqual)
// Minecraft expectations
compileOnlyApi(libs.guava)
compileOnlyApi(libs.gson)
// Platform expectations
compileOnlyApi(libs.snakeyaml)
// Adventure
api(libs.adventure)
api(libs.minimessage)
// Guice
api(libs.guice) {
exclude(group = "com.google.guava")
}
api(libs.guiceassistedinject) {
exclude("com.google.inject", "guice")
}
compileOnlyApi(libs.findbugs)
// Plugins
compileOnlyApi(libs.worldeditCore) {
exclude(group = "bukkit-classloader-check")
exclude(group = "mockito-core")
exclude(group = "dummypermscompat")
}
testImplementation(libs.worldeditCore)
compileOnlyApi(libs.fastasyncworldeditCore) { isTransitive = false }
testImplementation(libs.fastasyncworldeditCore) { isTransitive = false }
// Logging
compileOnlyApi(libs.log4j)
// Other libraries
api(libs.prtree)
api(libs.aopalliance)
api(libs.pipeline) {
exclude(group = "com.google.guava")
}
api(libs.arkitektonika)
api(libs.paster)
}
tasks.processResources {
filesMatching("plugin.properties") {
expand(
"version" to project.version.toString(),
"commit" to rootProject.grgit.head().abbreviatedId, // The error points here
"date" to rootProject.grgit.head().dateTime.format(DateTimeFormatter.ofPattern("yy.MM.dd")) // The error points here
)
}
}
Problems arising
Address of this project: https://github.com/IntellectualSites/PlotSquared
Thanks again!
First, you need to declare the grgit variable before using it, that's why you're getting the error.
Add plugin for grgit in the plugins{} block:
id("org.ajoberstar.grgit") version "4.0.2"
Import Grgit like this:
import org.ajoberstar.grgit.Grgit
Then, declare the variable grgit like this:
val grgit = Grgit.open(mapOf("currentDir" to project.rootDir))

How to configure a plugin with custom sourceSet extension in Kotlin DSL

I could use a helping hand converting victor trellos simple sourceSet extension to Kotlin DSL, I seem a bit lost.
Victor Trello has an extension on SourceSet named svg
project.extensions.create('victor', VictorPluginExtension)
// Add 'svg' as a source set extension
project.android.sourceSets.all { sourceSet ->
SourceDirectorySet sds = project.objects.sourceDirectorySet(sourceSet.name, "${sourceSet.name} svgs")
sourceSet.extensions.add('svg', sds)
}
This is how it is configured in Groovy:
// build.gradle:
android {
// Variant 1 with individual setup
sourceSets {
main {
svg.srcDir 'src/main/svg'
}
}
// Variant 2 handling all at once
sourceSets.all { sourceSet ->
svg.srcDir "src/${sourceSet.name}/svg"
}
}
// Plugin configuration of class com.trello.victor.VictorPluginExtension
victor {
svgDpi = 72
generateVectorDrawables = true
}
What would this look like in Kotlin DSL?
Here's the Victor Trello Gradle Plugin source
I notice that the Victor plugin extends SourceSet, and project.sourceSet has type SourceSet (from gradle) which contains an extensions, whereas AndroidSourceSet does not contain the .extensions. Also I can seem to get a gradle SourceSet from the AndroidSourceSet
This might be the right way to do the plugin configuration, though I cannot test it without the srcDir (I'll remove this from the question if its wrong, to avoid confusion for future readers).
// build.gradle.kts:
configure<com.trello.victor.VictorPluginExtension> {
svgDpi = 72
generateVectorDrawables = true
}
I found the solution with the help of several people (Google + Gradle forums). Hopefully this can help others with other plugins.
The solution had three parts to solve,
Configure a plugin with the configure()
Access Groovy extensions
Iterate sourceSets.all in kotlin (which is obvious if your not unlucky enough to start with sourceSets.all { sourceSet -> })
Here's the source
val Any.extensions get() = (this as org.gradle.api.plugins.ExtensionAware).extensions
android {
sourceSets {
// Variant 1 with individual setup
named("main") {
val a: com.android.build.api.dsl.AndroidSourceSet = this
java.srcDir("src/sharedTest/java")
}
}
// Variant 2 handling all at once
sourceSets.all {
val svgSourceSet = this.extensions["svg"] as SourceDirectorySet
svgSourceSet.srcDir("src/${name}/svg")
}
}
configure<com.trello.victor.VictorPluginExtension> {
// Any assets defined in relative terms needs a base DPI specified
svgDpi = 72
// Do not generate these densities for SVG assets
excludeDensities = listOf("ldpi", "xxxhdpi")
// Set this to "true" if you want to generate Android vectors instead of PNGs
generateVectorDrawables = false
}

How to register AndroidLintInspectionBase in IntellijIdea Plugin

I'm creating a costum Android Lint Inspection and I need to register the inspection, to be run. Where do I need to register it?
I've already tried to register the inspection which provides the inspection inside plugin.xml file.
The actual inspection:
class HardcodedDimensionsInspection : AndroidLintInspectionBase("Hardcoded dimensions", HardcodedDimensDetector.ISSUE) {
override fun getShortName(): String {
return "AndroidLintHardcodedDimension"
}
}
The entry in plugin.xml file
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<!-- <inspectionToolProvider implementation="JavaInspectionProvider"/>-->
<globalInspection shortName="AndroidLintHardcodedDimension" displayName="Hardcoded dimensions"
enabledByDefault="true" level="WARNING"
implementationClass="HardcodedDimensionsInspection"/>
</extensions>
The actual detector
class HardcodedDimensDetector : LayoutDetector() {
override fun getApplicableAttributes(): Collection<String>? {
return Arrays.asList(
// Layouts
ATTR_TEXT
)
}
override fun appliesTo(folderType: ResourceFolderType): Boolean {
return (folderType == ResourceFolderType.LAYOUT ||
folderType == ResourceFolderType.MENU ||
folderType == ResourceFolderType.XML)
}
override fun visitAttribute(context: XmlContext, attribute: Attr) {
val value = attribute.value
}
companion object {
/** The main issue discovered by this detector */
#JvmField
val ISSUE = Issue.create(
id = "HardcodedDimension",
briefDescription = "Hardcoded dimens",
explanation = """
Brief
""",
category = Category.I18N,
priority = 5,
severity = Severity.ERROR,
implementation = Implementation(
HardcodedDimensDetector::class.java,
Scope.RESOURCE_FILE_SCOPE
)
)
}
}
I've expected to hit the breakpoints in any of the functions for Detector but the code is never called. Seems like my detector is not registered. Can you please point me to the missing part, is there a class where I should register my Detector?
Thank you.
The link to the full project: https://github.com/magicbytes/Android-Lint-Inspection
I don't see anything obvious wrong from these snippets. Could you please post on our forum and link to the full sources of your plugin? Thanks. https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development
I have a workaround for now, not sure it's the official way to do it. Android Lint has a registry with all the Issue classes (built-in), the class is called LintIdeIssueRegistry. When it runs the Android Lint, it's looking in this registry for Issue processors. Since the list is hardcoded, we need to inject ours in the list. I'm using the following code for that:
val registry = LintIdeIssueRegistry()
val issue = registry.getIssue(HardcodedDimensDetector.ISSUE.id)
if (issue == null) {
val list = registry.issues as MutableList<Issue>
list.add(HardcodedDimensDetector.ISSUE)
}
Hopefully in future we will have a method called addIssue inside the LintIdeIssueRegistry.

Creating an IntelliJ Module Programmatically

I'm trying to make a proper project, like the one setup when you go through the Kotlin wizard or something, but I can't figure it out.
class SpigotKtWizard : ModuleBuilder() {
override fun setupRootModel(modifiableRootModel: ModifiableRootModel?) {}
override fun getModuleType(): ModuleType<*> {
return SpigotKtModuleType.instance
}
override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider): Array<ModuleWizardStep> {
return arrayOf(BuildOptionsStep())
}
override fun createProject(name: String?, path: String?): Project? {
val project = super.createProject(name, path) ?: return null
val d = project.baseDir.createChildData(this, "Test")
File(d.path).writeText("Testing boyyyy")
return project
}
}
This is what I have currently, and I'm getting this:
But other projects (and specifically, the same design I'm trying to achieve), look more like this:
Is there a page in the docs that I missed?
In pic 2 you're displaying a "project" instead of a "module", see the offical doc.
You may want to implement a DirectoryProjectGeneratorBase<YourSettingsBean> and register a (as an example you may refer to this file my julia plugin) directoryProjectGenerator in plugin.xml.
In your implementation of generateProject, you can create files, set files as source root/test root/excluded root by using:
ApplicationManager.getApplication().runWriteAction {
val modifiableModel: ModifiableRootModel = ModifiableModelsProvider.SERVICE.getInstance().getModuleModifiableModel(module)
module.rootManager.modifiableModel.apply {
inheritSdk()
contentEntries.firstOrNull()?.apply {
addExcludeFolder(findOrCreate(baseDir, "out", module))
addSourceFolder(findOrCreate(baseDir, "src", module), false)
}
commit()
}
ModifiableModelsProvider.SERVICE.getInstance().commitModuleModifiableModel(modifiableModel)
}
This should be missing in the doc, BTW. So it's not your fault. But I recommend you to take a look at the existing plugin projects (like the julia plugin mentioned above, the mathemetica plugin or the covscript plugin), which are extremely helpful for new comers.