This message was deleted.
# plugin-development
s
This message was deleted.
j
As a workaround, I haven’t this issue but I am adding the Kotlin dependency to the
implementation
configuration. Does your plugin do something with any KGP API?
j
Out of the
KotlinCompile
class I just read the
kotlinOptions
property to get:
Copy code
kotlinOptions.jvmTarget
kotlinOptions.apiVersion
kotlinOptions.languageVersion
The problem is that I’ll have to explicitly specify Kotlin version. OTOH, I’m already locked to the version I use for building the plugin…
j
But only in the project plugin, right? the settings one does nothing with them.
j
Correct, those are accessed only in the project plugin to feed the VerifyPluginConfiguration task with the user configuration and test against required setup
j
I have seen both plugins are in the same project, so the settings one has all those dependencies which can be unnecessary and maybe that can be the problem. I don’t know why this is happening but as a quick try, you can move the settings plugin to its own Gradle project without any dependency.
j
That's barely possible as Settings and Project plugins share logic.
e
if you use Groovy (or
.withGroovyBuilder { }
in the Kotlin DSL), you can interact with types that aren't in your classpath (stringly-typed via reflection)
🙌 1
t
Reading this thread, it looks like you don't need the Kotlin Plugin as a runtime dependency: declare it as
compileOnly
. …either that or change your plugin to apply the Kotlin plugin (with the version you're depending on) and remove the explicit application from the build script.
(note: you could also probably remove the
version "1.9.10"
from the build script so it uses the version brought in by your plugin)
v
@Thomas Broyer you read it exactly the wrong way around. He does have
compileOnly
, that's why the Kotlin plugin is not together with his plugin in the settings class loader and why his plugin classes cannot access the Kotlin classes which are on the build scritp class loader which is a child.
👍 1
@Jakub Chrzanowski I would have suggested the same as Javi, splitting the settings and the project plugin into separate artifacts, so that the project plugin can be on the build script class loader while the settings plugin is on the settings class loader. Is it the shared code that needs to access the Kotlin stuff, or only the project stuff? If the latter, then either put the shared stuff in the settings plugin project as the project plugin project will be able to access it, or create a third project with the shared stuff that the other two then depend on.
You probably then should also have some check that the versions of project and settings plugin match, by being able to get the version from the shared code and additionally from the project plugin code, verifying that both match.
Another way would of course be the
withGroovyBuilder
@ephemient suggested, or plain old reflection.
j
check that the versions of project and settings plugin match
As I think he is talking about the IntelliJ Gradle plugin, I think the Kotlin version should be defined by the user, so I am not sure if that can be a problem to get the same version in both plugins.
If I am checking the correct plugin:
Copy code
abstract class IntelliJPlatformSettingsPlugin @Inject constructor(
    private val objects: ObjectFactory,
    private val providers: ProviderFactory,
) : Plugin<Settings> {

    override fun apply(settings: Settings) {
        settings.dependencyResolutionManagement.repositories.applyIntelliJPlatformSettings(objects, providers)
    }
}
Copy code
interface IntelliJPlatformRepositorySettings {

    val useCacheRedirector: Property<Boolean>
}

internal fun RepositoryHandler.applyIntelliJPlatformSettings(objects: ObjectFactory, providers: ProviderFactory) {
    val settings = objects.newInstance(IntelliJPlatformRepositorySettings::class)

    settings.useCacheRedirector.convention(BuildFeature.USE_CACHE_REDIRECTOR.getValue(providers))

    (this as ExtensionAware).extensions.add(Extensions.INTELLIJ_PLATFORM_REPOSITORY_SETTINGS, settings)
}
It looks like you can create a shared module to put that interface and/or the utility function, splitting the plugins into two projects. Obviously, it will be a bit annoying but I think it is the cleanest way.
v
As I think he is talking about the IntelliJ Gradle plugin, I think the Kotlin version should be defined by the user, so I am not sure if that can be a problem to get the same version in both plugins.
I'm not talking about the Kotlin version. I'm talking about the versions of his project plugin and his settings plugin. If he splits them into two like you and me suggested, it would be possible to apply different versions of the two plugins, and this should most likely be prevented.
j
Ah, you are totally right on that.
j
The
MySettingsPlugin
is supposed to let you only add custom repositories to
dependencyResolutionManagement
— no more logic should be involved there. Same repositories are supposed to be added in the
Project
-level configuration with
repositories {}
block. Both use now the same code which is implemented using
ExtensionAware
— because of that, I’d like to avoid splitting project into two parts. In the snippet @Javi shared (yes, it’s all about IntelliJ Platform Gradle Plugin 2.0), I was still using Kotlin extension functions. As for now — thanks to
ExtensionAware
approach, I dropped this
IntelliJPlatformRepositorySettings
magic as all required objects are `@Inject`ed now properly. This refactoring revealed that
KotlinCompile
is actually called on the
Settings
-level, which became a blocker. Any tricks to import Kotlin dependency or reflections aren’t something I’d like to rely on. Also to don’t bring anything to the project (especially as crucial as Kotlin) without user’s knowledge. They still should be able to build the plugin with no Kotlin involved. I like the
withGroovyBuilder
approach, even though it relies on Groovy magic — but for such a small tasks it fits perfectly — and I was able to successfully implement it with no more exceptions on the
Settings
-level. Thanks so much, folks!
v
Using
withGroovyBuilder
is actually also just using reflection with added Groovy syntactic sugar. 🙂 So whatever feels better for you. :-)
j
Oh snap 😂