[Gradle] Implement KotlinExtensionPoint to allow extensible designs inside the KotlinGradlePlugin
KT-61634
This commit is contained in:
committed by
Space Team
parent
e78331cd5c
commit
30665c3e02
@@ -896,6 +896,11 @@ public abstract interface class org/jetbrains/kotlin/gradle/plugin/KotlinExecuti
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/plugin/KotlinExecution$ExecutionSource {
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/plugin/KotlinExtensionPoint {
|
||||
public abstract fun get (Lorg/gradle/api/Project;)Ljava/util/List;
|
||||
public abstract fun register (Lorg/gradle/api/Project;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract interface class org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin {
|
||||
}
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||
|
||||
/**
|
||||
* ### Extension Point for the Kotlin Gradle Plugin
|
||||
*
|
||||
* Note: Not stable for implementation: Custom implementations of this interface will not be supported by the Kotlin Gradle Plugin!
|
||||
*
|
||||
* #### Motivation
|
||||
* This [KotlinExtensionPoint] will be used to 'generically' extend parts of the Kotlin Gradle Plugin (internally and externally).
|
||||
* General Kotlin Gradle Plugin code will call into this 'semantically' structured extension points to load logic
|
||||
* Such extension points are to be used for public as well as for internal extension points.
|
||||
*
|
||||
* ### Usage
|
||||
* #### Declaring an Extension Point (internal in Kotlin Gradle Plugin)
|
||||
* Extension Points are to be declared on companion objects on the corresponding interface
|
||||
* ```kotlin
|
||||
* interface MyKotlinGradlePluginExtension {
|
||||
* fun foo(project: Project)
|
||||
*
|
||||
* companion object {
|
||||
* val extensionPoint = KotlinExtensionPoint<MyKotlinGradlePluginExtension>()
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* #### Registering an Extension Point
|
||||
* Extension Points are scoped by [Project] and should be registered as early as possible
|
||||
* ```kotlin
|
||||
* class MyPlugin: Plugin<Project> {
|
||||
* fun apply(project: Project) {
|
||||
* MyKotlinGradlePluginExtension.extensionPoint.register(project, MyKotlinGradlePluginExtensionImpl())
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* #### Kotlin Gradle Plugin Entry Point:
|
||||
* Extensions registered by the Kotlin Gradle Plugin directly will use the
|
||||
* [org.jetbrains.kotlin.gradle.plugin.registerKotlinPluginExtensions] entry point.
|
||||
*/
|
||||
@ExperimentalKotlinGradlePluginApi
|
||||
interface KotlinExtensionPoint<T> {
|
||||
/**
|
||||
* @return all currently registered extension points.
|
||||
* The returned list is *not* live and just represents the current snapshot.
|
||||
*/
|
||||
operator fun get(project: Project): List<T>
|
||||
|
||||
/**
|
||||
* @param project The current [project] to register an extension. The extension will only be visible to this particular [project]
|
||||
* @param extension The implementation of the extension to register. If registered twice, it will be returned twice when
|
||||
* the extensions are queried (no de-duplication)
|
||||
*/
|
||||
fun register(project: Project, extension: T)
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.utils.storedProjectProperty
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
|
||||
/**
|
||||
* Creates a new [KotlinExtensionPoint]
|
||||
* See [KotlinExtensionPoint] documentation for the intended usage!
|
||||
*/
|
||||
internal fun <T> KotlinExtensionPoint(): KotlinExtensionPoint<T> {
|
||||
@OptIn(UnsafeApi::class)
|
||||
return KotlinExtensionPointInternal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Only intended implementation of [KotlinExtensionPoint]!
|
||||
* Visible for tests to allow test utils to overwrite certain extension points
|
||||
*/
|
||||
@UnsafeApi("Visible for tests only")
|
||||
internal class KotlinExtensionPointInternal<T> : KotlinExtensionPoint<T> {
|
||||
|
||||
private val Project.registeredExtensions by storedProjectProperty<MutableList<T>> { mutableListOf() }
|
||||
|
||||
override fun get(project: Project): List<T> {
|
||||
return project.registeredExtensions.toList()
|
||||
}
|
||||
|
||||
override fun register(project: Project, extension: T) {
|
||||
project.registeredExtensions.add(extension)
|
||||
}
|
||||
|
||||
fun set(project: Project, extensions: List<T>) {
|
||||
project.registeredExtensions.clear()
|
||||
project.registeredExtensions.addAll(extensions)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* Active Extensions (using the [KotlinExtensionPoint] infrastructure) will be registered here by the Kotlin Gradle Plugin.
|
||||
*/
|
||||
internal fun Project.registerKotlinPluginExtensions() {
|
||||
// No extensions available yet.
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("FunctionName")
|
||||
|
||||
package org.jetbrains.kotlin.gradle.unitTests
|
||||
|
||||
import org.jetbrains.kotlin.gradle.util.buildProject
|
||||
import org.jetbrains.kotlin.gradle.util.set
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinExtensionPoint
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class KotlinExtensionPointTest {
|
||||
|
||||
@Test
|
||||
fun `test - simple extension point`() {
|
||||
val extensionPoint = KotlinExtensionPoint<String>()
|
||||
val projectA = buildProject()
|
||||
val projectB = buildProject()
|
||||
|
||||
extensionPoint.register(projectA, "a")
|
||||
extensionPoint.register(projectB, "b")
|
||||
|
||||
assertEquals(listOf("a"), extensionPoint[projectA])
|
||||
assertEquals(listOf("b"), extensionPoint[projectB])
|
||||
|
||||
extensionPoint.register(projectA, "a2")
|
||||
assertEquals(listOf("a", "a2"), extensionPoint[projectA])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - overwrite`() {
|
||||
val extensionPoint = KotlinExtensionPoint<Int>()
|
||||
val project = buildProject()
|
||||
|
||||
extensionPoint.register(project, 0)
|
||||
extensionPoint.register(project, 1)
|
||||
assertEquals(listOf(0, 1), extensionPoint[project])
|
||||
|
||||
extensionPoint.set(project, listOf(2, 3))
|
||||
assertEquals(listOf(2, 3), extensionPoint[project])
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.util
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinExtensionPoint
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinExtensionPointInternal
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
|
||||
/**
|
||||
* Completely overwrites the currently registered extensions on this [KotlinExtensionPoint] in this project.
|
||||
*/
|
||||
@OptIn(UnsafeApi::class)
|
||||
fun <T> KotlinExtensionPoint<T>.set(project: Project, extensions: List<T>) {
|
||||
(this as KotlinExtensionPointInternal<T>)
|
||||
set(project, extensions)
|
||||
}
|
||||
Reference in New Issue
Block a user