Skip to content

Commit

Permalink
Fix #255
Browse files Browse the repository at this point in the history
  • Loading branch information
ileasile committed Jul 7, 2021
1 parent 4e0d30a commit 7e43483
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 70 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ shadowJarVersion=7.0.0
kotlinxSerializationVersion=1.1.0
ktlintGradleVersion=10.0.0
ktlintVersion=0.40.0
publishPluginVersion=0.0.27-dev
publishPluginVersion=0.0.29-dev
junitVersion=5.7.1
slf4jVersion=1.7.30
logbackVersion=1.2.3
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
27 changes: 20 additions & 7 deletions jupyter-lib/kotlin-jupyter-api-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,21 @@ val saveVersion by tasks.registering {
}
}

tasks.processResources {
dependsOn(saveVersion)
}
tasks {
processResources {
dependsOn(saveVersion)
}

test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}

tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
register<Jar>("sourceJar") {
archiveClassifier.set("sources")
from(sourceSets.named("main").get().allSource)
}
}

Expand Down Expand Up @@ -90,6 +97,12 @@ pluginBundle {
}

publishing {
publications {
withType<MavenPublication> {
artifact(tasks["sourceJar"])
}
}

repositories {
(rootProject.findProperty("localPublicationsRepo") as? java.nio.file.Path)?.let {
maven {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package org.jetbrains.kotlinx.jupyter.api.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Copy
import org.gradle.kotlin.dsl.closureOf
import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.repositories
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
import org.jetbrains.kotlin.gradle.plugin.KaptExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlinx.jupyter.api.plugin.tasks.JupyterApiResourcesTask

Expand Down Expand Up @@ -41,37 +45,50 @@ class ApiGradlePlugin : Plugin<Project> {
}

val resourcesTaskName = "processJupyterApiResources"
fun registerResourceTask() {
register<JupyterApiResourcesTask>(resourcesTaskName) {
val kaptKotlinTask = findByName("kaptKotlin")
if (kaptKotlinTask != null) {
dependsOn(kaptKotlinTask)
kaptKotlinTask.dependsOn(cleanJupyterTask)
kaptKotlinTask.outputs.dir(jupyterBuildPath)
fun registerResourceTask(): JupyterApiResourcesTask {
findByName(resourcesTaskName) ?: register<JupyterApiResourcesTask>(resourcesTaskName)
return named<JupyterApiResourcesTask>(resourcesTaskName).get()
}

fun dependOnProcessingTask(processTaskName: String) {
val jupyterTask = registerResourceTask()
tasks.named<Copy>(processTaskName) {
dependsOn(resourcesTaskName)
from(jupyterTask.outputDir)
}
}

fun dependOnKapt(kaptTaskName: String) {
registerResourceTask()
tasks.whenObjectAdded {
val addedTask = this
if (addedTask.name == kaptTaskName) {
tasks.named(resourcesTaskName) {
dependsOn(addedTask)
addedTask.dependsOn(cleanJupyterTask)
addedTask.outputs.dir(jupyterBuildPath)
}
}
}
}

// apply configuration to JVM-only project
plugins.withId("org.jetbrains.kotlin.jvm") {
// Task should be registered after plugin is applied
registerResourceTask()
named("processResources") {
dependsOn(resourcesTaskName)
}
dependOnProcessingTask("processResources")
dependOnKapt("kaptKotlin")
}

// apply only to multiplatform plugin
plugins.withId("org.jetbrains.kotlin.multiplatform") {
// Task should be registered after plugin is applied
registerResourceTask()
extensions.findByType<KotlinMultiplatformExtension>()?.apply {
val jvmTargetName = targets.filterIsInstance<KotlinJvmTarget>().firstOrNull()?.name
?: error("Single JVM target not found in a multiplatform project")
named(jvmTargetName + "ProcessResources") {
dependsOn(resourcesTaskName)
}
targets.whenObjectAdded(
closureOf<KotlinTarget> {
if (this !is KotlinJvmTarget) return@closureOf
dependOnProcessingTask(this.name + "ProcessResources")
}
)
}
dependOnKapt("kaptKotlinJvm")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import com.google.gson.Gson
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.findByType
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlinx.jupyter.api.plugin.ApiGradlePlugin
import java.io.File

Expand All @@ -31,30 +26,7 @@ open class JupyterApiResourcesTask : DefaultTask() {
var libraryDefinitions: List<String> = emptyList()

@OutputDirectory
val outputDir: File

init {
val sourceSets = project.extensions.getByName("sourceSets") as SourceSetContainer
when {
project.plugins.findPlugin("org.jetbrains.kotlin.jvm") != null -> {
val mainSourceSet: SourceSet = sourceSets.named("main").get()
outputDir = mainSourceSet.output.resourcesDir?.resolve("META-INF/kotlin-jupyter-libraries")
?: throw IllegalStateException("No resources dir for main source set")
}
project.plugins.findPlugin("org.jetbrains.kotlin.multiplatform") != null -> {
val mppExtension = project.extensions.findByType<KotlinMultiplatformExtension>()
?: error("Kotlin MPP extension not found")
val jvmTargetName = mppExtension.targets.filterIsInstance<KotlinJvmTarget>().firstOrNull()?.name
?: error("Single JVM target not found in a multiplatform project")
// TODO properly resolve resource directory
outputDir = project.buildDir.resolve("processedResources/$jvmTargetName/main")
.resolve("META-INF/kotlin-jupyter-libraries")
}
else -> {
error("Kotlin plugin not found in the project")
}
}
}
val outputDir: File = project.buildDir.resolve("jupyterProcessedResources")

@TaskAction
fun createDescriptions() {
Expand All @@ -64,7 +36,9 @@ open class JupyterApiResourcesTask : DefaultTask() {
) + getScanResultFromAnnotations()
val json = Gson().toJson(resultObject)

val libFile = outputDir.resolve("libraries.json")
val jupyterDir = outputDir.resolve("META-INF/kotlin-jupyter-libraries")
val libFile = jupyterDir.resolve("libraries.json")
libFile.parentFile.mkdirs()
libFile.writeText(json)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ResourcesTaskTests {
val buildFile = projectDir.resolve("build.gradle")
val taskSetupIndented = taskSetup.prependIndent(" ".repeat(2))
val buildFileText = """
$PLUGINS_BLOCK
${pluginsBlock()}
tasks {
$JUPYTER_RESOURCES_TASK_NAME {
Expand All @@ -34,12 +34,15 @@ class ResourcesTaskTests {
buildFile.writeText(buildFileText)
}

private fun runResourcesTask(args: Array<String>? = null): BuildResult {
private fun runResourcesTask(args: Array<String>? = null, type: String = ""): BuildResult {
val arguments = args?.toMutableList() ?: mutableListOf(
"-Pkotlin.jupyter.add.api=false",
"-Pkotlin.jupyter.add.scanner=false"
"-Pkotlin.jupyter.add.scanner=false",
"--stacktrace",
"--info"
)
arguments.add(0, RESOURCES_TASK_NAME)
val taskName = RESOURCES_TASK_NAME.withPrefix(type)
arguments.add(0, taskName)

return GradleRunner.create()
.withProjectDir(projectDir)
Expand All @@ -49,8 +52,8 @@ class ResourcesTaskTests {
.build()
}

private fun assertLibrariesJsonContents(expected: LibrariesScanResult) {
val librariesJsonText = projectDir.resolve(BUILD_LIBRARIES_JSON_PATH).readText()
private fun assertLibrariesJsonContents(expected: LibrariesScanResult, type: String = "") {
val librariesJsonText = projectDir.resolve(buildLibrariesJsonPath(type)).readText()
val libraryInfo = Json.decodeFromString<LibrariesScanResult>(librariesJsonText)

assertEquals(expected, libraryInfo)
Expand Down Expand Up @@ -111,7 +114,7 @@ class ResourcesTaskTests {
val apiAnnotations = jarFile("api-annotations")
buildFile.writeText(
"""
$PLUGINS_BLOCK
${pluginsBlock()}
dependencies {
implementation(files("$apiJar"))
Expand Down Expand Up @@ -149,6 +152,89 @@ class ResourcesTaskTests {
)
}

@Test
fun `check annotations in MPP`() {
val version = ClassLoader.getSystemClassLoader().getResource("VERSION")?.readText().orEmpty()

val propertiesFile = projectDir.resolve("properties.gradle")
propertiesFile.writeText(
"""
kapt.verbose=true
""".trimIndent()
)

val buildFile = projectDir.resolve("build.gradle.kts")

fun jarFile(name: String): String {
return File("../$name/build/libs/$name-$version.jar").canonicalFile.absolutePath.replace("\\", "/")
}

val apiJar = jarFile("api")
val apiAnnotations = jarFile("api-annotations")
buildFile.writeText(
"""
plugins {
kotlin("multiplatform") version "$KOTLIN_VERSION"
id("org.jetbrains.kotlin.jupyter.api")
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
js(LEGACY) {
binaries.executable()
browser()
}
sourceSets {
val commonMain by getting
val commonTest by getting
val jvmMain by getting {
dependencies {
implementation(files("$apiJar"))
implementation(files("$apiAnnotations"))
}
dependencies.add("kapt", files("$apiAnnotations"))
}
val jvmTest by getting
val jsMain by getting
val jsTest by getting
}
}
""".trimIndent()
)

val srcDir = projectDir.resolve("src/jvmMain/kotlin")
srcDir.mkdirs()

val integrationKt = srcDir.resolve("pack").resolve("Integration.kt")
integrationKt.parentFile.mkdirs()
integrationKt.writeText(
"""
package pack
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.*
import org.jetbrains.kotlinx.jupyter.api.libraries.*
@JupyterLibrary
class Integration : JupyterIntegration({
import("org.my.lib.*")
})
""".trimIndent()
)
runResourcesTask(type = "jvm")

assertLibrariesJsonContents(
LibrariesScanResult(
producers = listOf("pack.Integration").map(::LibrariesProducerDeclaration)
),
"jvm"
)
}

@Test
fun `check extension`() {
val version = "0.8.3.202"
Expand All @@ -157,7 +243,7 @@ class ResourcesTaskTests {

buildFile.writeText(
"""
$PLUGINS_BLOCK
${pluginsBlock()}
kotlinJupyter {
addApiDependency("$version")
Expand Down Expand Up @@ -195,17 +281,27 @@ class ResourcesTaskTests {
}

companion object {
private const val KOTLIN_VERSION = "1.5.20"
private const val RESOURCES_TASK_NAME = "processResources"
private const val JUPYTER_RESOURCES_TASK_NAME = "processJupyterApiResources"

private const val MAIN_SOURCE_SET_BUILD_RESOURCES_PATH = "build/resources/main"
private const val BUILD_LIBRARIES_JSON_PATH = "$MAIN_SOURCE_SET_BUILD_RESOURCES_PATH/$KOTLIN_JUPYTER_RESOURCES_PATH/$KOTLIN_JUPYTER_LIBRARIES_FILE_NAME"
private fun mainSourceSetBuildResourcesPath(type: String = ""): String {
return if (type.isEmpty()) {
"build/resources/main"
} else {
"build/processedResources/$type/main"
}
}
private fun buildLibrariesJsonPath(type: String = "") = "${mainSourceSetBuildResourcesPath(type)}/$KOTLIN_JUPYTER_RESOURCES_PATH/$KOTLIN_JUPYTER_LIBRARIES_FILE_NAME"

private val PLUGINS_BLOCK = """
private fun pluginsBlock(ktPluginId: String = "jvm") = """
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.20'
id 'org.jetbrains.kotlin.$ktPluginId' version '$KOTLIN_VERSION'
id 'org.jetbrains.kotlin.jupyter.api'
}
""".trimIndent()

private fun String.withPrefix(prefix: String) =
if (prefix.isEmpty()) this else prefix + capitalize()
}
}

0 comments on commit 7e43483

Please sign in to comment.