Hello all, is there a public API to add custom Kot...
# community-support
m
Hello all, is there a public API to add custom Kotlin DSL accessors directly accessible from
build.gradle.kts
— like how
kotlin-dsl
generates accessors for extensions?
v
Just add an extension?
Or what is the actual use-case you are after?
m
Adding an extension is not enough. I’m not sure what the official motivations behind kotlin-dsl’s accessories generation are, but I think my goals are pretty similar — adding a bit of sugar to ease the pain of Gradle scripting. To give some context, here’s what my current build.gradle.kts looks like:
Copy code
kotlin

import komogen.gradle.plugin.flagset.FlagSet
import komogen.gradle.plugin.generics.Generics
import komogen.gradle.plugin.ionum.IonspinBignum
import komogen.gradle.plugin.kodate.KotlinxDateTime
import komogen.gradle.plugin.koser.KotlinxSerialization
import komogen.gradle.plugin.patternizer.Patternizer
import komogen.gradle.plugin.sqlite.SqliteLocal
import komogen.gradle.plugin.supabase.Supabase
import komogen.gradle.plugin.supabase.SupabaseClient
import komogen.gradle.schematizer.postgres.PostgresSchematizer

plugins {
  alias(libs.plugins.kotlin.multiplatform)
  alias(libs.plugins.komogen)
  alias(libs.plugins.komogen.plugin.flagset)
  alias(libs.plugins.komogen.plugin.generics)
  alias(libs.plugins.komogen.plugin.ionspin.bignum)
  alias(libs.plugins.komogen.plugin.kotlinx.datetime)
  alias(libs.plugins.komogen.plugin.kotlinx.serialization)
  alias(libs.plugins.komogen.plugin.patternizer)
  alias(libs.plugins.komogen.plugin.sqlite)
  alias(libs.plugins.komogen.plugin.supabase)
  alias(libs.plugins.komogen.schematizer.postgres)
}

komogen {
  basePackageName = "com.example"
  sensitiveConfigDirectory = gradle.gradleUserHomeDir.resolve("komogen")

  repositoryManager {
    name = "ExampleRepositoryManager"
    environment = Client
    dataSource = local<SqliteLocal>() hybridWith cloud<SupabaseClient>()
  }

  schematizers {
    register<PostgresSchematizer>()
  }

  generatorPlugins {
    register<FlagSet>()
    register<Generics>()
    register<IonspinBignum>()
    register<KotlinxDateTime>()
    register<KotlinxSerialization>()
    register<Patternizer>()
    register<Supabase>()
  }

  ionspinBignum {
    serializationKotlinx = true
  }

  kotlinxSerialization {
    serializationFormat = Json
  }

  supabase {
    runtime = true
    clientFactoryFunction.enabled = true
  }
}
Now, to explain a bit more — I’m currently developing the Komogen plugin, which provides the main
komogen {}
DSL. Child plugins can self-register when the main Komogen plugin is applied, extending the main DSL with their own sub-DSLs. This all works nicely thanks to
kotlin-dsl
and Gradle’s extension mechanism. But I want to go a step further. As you can see, there’s a
generatorPlugins {}
block that uses a custom ExtensiblePolymorphicDomainObjectContainer to handle plugins dynamically (since the main plugin doesn’t know about child plugins). The problem? Users still have to manually import classes from the child plugin sources, which I’d really like to avoid. So my goal is to generate type-safe extensions for each applied child plugin — functions that would be available only inside the
generatorPlugins {}
block, without requiring any imports from the user’s build script. That’s where I’ve hit some limitations with ExtensionContainer and
kotlin-dsl
. I don’t see why only
kotlin-dsl
should be able to do that kind of magic. 😄 I also want to improve the
repositoryManager {}
block in a similar way — removing the need for imports and ideally getting rid of the
local<T>()
and
cloud<T>()
API in favor of something cleaner. All of this would be possible if I can figure out a way to inject generated code directly into the build script classpath.
v
You cannot, not in a clean way.
🙏 1
An unclean way would be to put your classes into one of the packages which are auto-imported like
org.gradle.kotlin.dsl
. But that would mean you have classes in that package in your plugin and I personally majorly dislike that as it is not Gradle code.
I recommend and also as user prefer to import the 3rd party classes I use in a Kotlin DSL buildscript
Also, don't just focus on Kotlin DSL, there is also Groovy DSL (and who knows what other DSLs in the future). By sticking to common conventions you stay compatible and comforable for all consumers. 🤷‍♂️
m
I prefer not tu use any kind of unclean approaches like hard-coding or putting code in a root package. But yes, you may be right, and I'll go with your recommendation and try to follow the common conventions (is there a detailed and official page or article about them ?) For now, and since my initial need was purely optional, I'll stick with my current approach and not forget about imports in the docs snippets. Thank you for your answers and your time @Vampire
v
is there a detailed and official page or article about them?
I don't think so
1