Skip to content

Commit b483ad4

Browse files
Add preview support to Gradle plugin
1 parent f80456d commit b483ad4

File tree

8 files changed

+153
-14
lines changed

8 files changed

+153
-14
lines changed

gradle-plugins/build.gradle.kts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,28 +48,36 @@ subprojects {
4848
}
4949

5050
afterEvaluate {
51-
mavenPublicationConfig?.let { mavenPublicationConfig ->
52-
configurePublication(mavenPublicationConfig)
51+
val publicationConfig = mavenPublicationConfig
52+
val gradlePluginConfig = gradlePluginConfig
5353

54-
gradlePluginConfig?.let { gradlePluginConfig ->
55-
configureGradlePlugin(mavenPublicationConfig, gradlePluginConfig)
54+
if (publicationConfig != null) {
55+
if (gradlePluginConfig != null) {
56+
// pluginMaven is a default publication created by java-gradle-plugin
57+
// https://github.com/gradle/gradle/issues/10384
58+
configureMavenPublication("pluginMaven", publicationConfig)
59+
configureGradlePlugin(publicationConfig, gradlePluginConfig)
60+
} else {
61+
configureMavenPublication("maven", publicationConfig) {
62+
from(components["java"])
63+
}
5664
}
5765
}
5866
}
5967
}
6068

61-
fun Project.configurePublication(
62-
publicationConfig: MavenPublicationConfigExtension
69+
fun Project.configureMavenPublication(
70+
publicationName: String,
71+
config: MavenPublicationConfigExtension,
72+
customize: MavenPublication.() -> Unit = {}
6373
) {
6474
// maven publication for plugin
6575
configureIfExists<PublishingExtension> {
66-
// pluginMaven is a default publication created by java-gradle-plugin
67-
// https://github.com/gradle/gradle/issues/10384
68-
publications.create<MavenPublication>("pluginMaven") {
69-
artifactId = publicationConfig.artifactId
76+
publications.create<MavenPublication>(publicationName) {
77+
artifactId = config.artifactId
7078
pom {
71-
name.set(publicationConfig.displayName)
72-
description.set(publicationConfig.description)
79+
name.set(config.displayName)
80+
description.set(config.description)
7381
url.set(BuildProperties.website)
7482
licenses {
7583
license {
@@ -78,6 +86,8 @@ fun Project.configurePublication(
7886
}
7987
}
8088
}
89+
90+
customize()
8191
}
8292
}
8393
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
plugins {
2+
kotlin("jvm")
3+
id("maven-publish")
4+
}
5+
6+
mavenPublicationConfig {
7+
displayName = "Compose Desktop Preview Runtime"
8+
description = "Runtime helpers for Compose Desktop Preview"
9+
artifactId = "compose-preview-runtime-desktop"
10+
}
11+
12+
dependencies {
13+
compileOnly("org.jetbrains.kotlin:kotlin-stdlib")
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.compose.desktop.preview.runtime
7+
8+
import kotlin.reflect.KProperty1
9+
10+
class ComposePreviewRunner {
11+
companion object {
12+
private const val PREVIEW_ANNOTATION_FQ_NAME = "androidx.compose.ui.tooling.desktop.preview.Preview"
13+
14+
@JvmStatic
15+
fun main(args: Array<String>) {
16+
val classLoader = ComposePreviewRunner::class.java.classLoader
17+
18+
val previewFqName = args[0]
19+
val previewClassFqName = previewFqName.substringBeforeLast(".")
20+
val previewMethodName = previewFqName.substringAfterLast(".")
21+
val previewClass = classLoader.loadClass(previewClassFqName)
22+
val previewMethod = previewClass.methods.find { it.name == previewMethodName }
23+
?: error("Could not find method '$previewMethodName' in class '${previewClass.canonicalName}'")
24+
25+
val content = previewMethod.invoke(previewClass)
26+
val previewAnnotation = previewMethod.annotations.find { it.annotationClass.qualifiedName == PREVIEW_ANNOTATION_FQ_NAME }
27+
?: error("Could not find '$PREVIEW_ANNOTATION_FQ_NAME' annotation on '$previewClassFqName#$previewMethodName'")
28+
val environmentKClassProperty = previewAnnotation.annotationClass.members.find { it is KProperty1<*, *> && it.name == "environment" }
29+
as KProperty1<Any, Class<*>>
30+
val environmentClass = environmentKClassProperty.get(previewAnnotation)
31+
val previewEnvironment = environmentClass
32+
.getDeclaredConstructor()
33+
.newInstance()
34+
val showMethod = previewEnvironment.javaClass
35+
.methods.find { it.name == "show" }
36+
?: error("Could not find 'show' in class '${environmentClass.canonicalName}'")
37+
showMethod.invoke(previewEnvironment, content)
38+
}
39+
}
40+
}

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.gradle.api.plugins.ExtensionAware
1515
import org.jetbrains.compose.desktop.DesktopExtension
1616
import org.jetbrains.compose.desktop.application.internal.configureApplicationImpl
1717
import org.jetbrains.compose.desktop.application.internal.currentTarget
18+
import org.jetbrains.compose.desktop.preview.internal.initializePreview
1819
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
1920
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2021

@@ -35,6 +36,8 @@ class ComposePlugin : Plugin<Project> {
3536
}
3637
}
3738

39+
project.initializePreview()
40+
3841
project.pluginManager.apply(ComposeCompilerKotlinSupportPlugin::class.java)
3942

4043
project.afterEvaluate {

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureApplication.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import org.jetbrains.compose.desktop.application.dsl.Application
1717
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
1818
import org.jetbrains.compose.desktop.application.internal.validation.validatePackageVersions
1919
import org.jetbrains.compose.desktop.application.tasks.*
20+
import org.jetbrains.compose.desktop.preview.internal.configureRunPreviewTask
21+
import org.jetbrains.compose.desktop.preview.tasks.AbstractRunComposePreviewTask
2022
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
2123
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
2224
import java.io.File
@@ -155,6 +157,10 @@ internal fun Project.configurePackagingTasks(apps: Collection<Application>) {
155157
val run = project.tasks.composeTask<JavaExec>(taskName("run", app)) {
156158
configureRunTask(app)
157159
}
160+
161+
val runPreview = project.tasks.composeTask<AbstractRunComposePreviewTask>("runComposeDesktopPreview") {
162+
configureRunPreviewTask(app)
163+
}
158164
}
159165
}
160166

@@ -327,7 +333,7 @@ private fun File.isZipOrJar() =
327333
name.endsWith(".jar", ignoreCase = true)
328334
|| name.endsWith(".zip", ignoreCase = true)
329335

330-
private fun Application.javaHomeOrDefault(): String =
336+
internal fun Application.javaHomeOrDefault(): String =
331337
javaHome ?: System.getProperty("java.home")
332338

333339
private inline fun <reified T : Task> TaskContainer.composeTask(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.jetbrains.compose.desktop.preview.internal
2+
3+
import org.gradle.api.Project
4+
import org.jetbrains.compose.composeVersion
5+
import org.jetbrains.compose.desktop.application.dsl.Application
6+
import org.jetbrains.compose.desktop.application.internal.javaHomeOrDefault
7+
import org.jetbrains.compose.desktop.application.internal.provider
8+
import org.jetbrains.compose.desktop.preview.tasks.AbstractRunComposePreviewTask
9+
10+
internal const val PREVIEW_RUNTIME_CLASSPATH_CONFIGURATION = "composeDesktopPreviewRuntimeClasspath"
11+
private val COMPOSE_PREVIEW_RUNTIME_DEPENDENCY = "org.jetbrains.compose:compose-preview-runtime-desktop:$composeVersion"
12+
13+
fun Project.initializePreview() {
14+
configurations.create(PREVIEW_RUNTIME_CLASSPATH_CONFIGURATION).defaultDependencies { deps ->
15+
deps.add(dependencies.create(COMPOSE_PREVIEW_RUNTIME_DEPENDENCY))
16+
}
17+
}
18+
19+
internal fun AbstractRunComposePreviewTask.configureRunPreviewTask(app: Application) {
20+
app._configurationSource?.let { configSource ->
21+
dependsOn(configSource.jarTaskName)
22+
classpath = configSource.runtimeClasspath(project)
23+
javaHome.set(provider { app.javaHomeOrDefault() })
24+
jvmArgs.set(provider { app.jvmArgs })
25+
}
26+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.jetbrains.compose.desktop.preview.tasks
2+
3+
import org.gradle.api.file.FileCollection
4+
import org.gradle.api.provider.ListProperty
5+
import org.gradle.api.provider.Property
6+
import org.gradle.api.tasks.*
7+
import org.jetbrains.compose.desktop.application.internal.javaExecutable
8+
import org.jetbrains.compose.desktop.application.internal.notNullProperty
9+
import org.jetbrains.compose.desktop.preview.internal.PREVIEW_RUNTIME_CLASSPATH_CONFIGURATION
10+
import org.jetbrains.compose.desktop.tasks.AbstractComposeDesktopTask
11+
12+
abstract class AbstractRunComposePreviewTask : AbstractComposeDesktopTask() {
13+
@get:InputFiles
14+
internal lateinit var classpath: FileCollection
15+
16+
@get:InputFiles
17+
internal val previewRuntimeClasspath: FileCollection
18+
get() = project.configurations.getByName(PREVIEW_RUNTIME_CLASSPATH_CONFIGURATION)
19+
20+
@get:Internal
21+
internal val javaHome: Property<String> = objects.notNullProperty<String>().apply {
22+
set(providers.systemProperty("java.home"))
23+
}
24+
25+
@get:Input
26+
@get:Optional
27+
internal val jvmArgs: ListProperty<String> = objects.listProperty(String::class.java)
28+
29+
@TaskAction
30+
fun run() {
31+
val target = project.findProperty("compose.desktop.preview.target") as String
32+
execOperations.javaexec { javaExec ->
33+
javaExec.executable = javaExecutable(javaHome.get())
34+
javaExec.main = "org.jetbrains.compose.desktop.preview.runtime.ComposePreviewRunner"
35+
javaExec.classpath = previewRuntimeClasspath + classpath
36+
javaExec.args = listOf(target)
37+
}
38+
}
39+
}

gradle-plugins/settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pluginManagement {
55
}
66
}
77

8-
include(":compose")
8+
include(":compose")
9+
include(":compose-preview-runtime")

0 commit comments

Comments
 (0)