Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

[![Kotlin Experimental](https://kotl.in/badges/experimental.svg)](https://kotlinlang.org/docs/components-stability.html)
[![Official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0--2.2.10-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0--2.2.20-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![GitHub License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)

[//]: # ([![TeamCity build](https://img.shields.io/teamcity/build/s/Build_kRPC_All.svg?server=http%3A%2F%2Fkrpc.teamcity.com)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Build_kRPC_All&guest=1))
Expand Down Expand Up @@ -102,7 +102,7 @@ To ensure that all IDE features of our compiler plugin work properly on IntelliJ
We support all stable Kotlin versions starting from 2.0.0:
- 2.0.0, 2.0.10, 2.0.20, 2.0.21
- 2.1.0, 2.1.10, 2.1.20, 2.1.21
- 2.2.0, 2.2.10
- 2.2.0, 2.2.10, 2.2.20

For a full compatibility checklist,
see [Versions](https://kotlin.github.io/kotlinx-rpc/versions.html).
Expand Down Expand Up @@ -134,8 +134,8 @@ that will set up code generation in a project.
Example of a setup in a project's `build.gradle.kts`:
```kotlin
plugins {
kotlin("multiplatform") version "2.2.10"
kotlin("plugin.serialization") version "2.2.10"
kotlin("multiplatform") version "2.2.20"
kotlin("plugin.serialization") version "2.2.20"
id("org.jetbrains.kotlinx.rpc.plugin") version "0.9.1"
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@

package kotlinx.rpc.codegen

import kotlinx.rpc.codegen.extension.RpcIrExtension
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter

@OptIn(ExperimentalCompilerApi::class)
class RpcCommandLineProcessor : CommandLineProcessor {
override val pluginId = "kotlinx-rpc"
override val pluginId = PLUGIN_ID

override val pluginOptions = listOf(
RpcFirCliOptions.ANNOTATION_TYPE_SAFETY,
Expand All @@ -37,20 +33,3 @@ class RpcCommandLineProcessor : CommandLineProcessor {
}
}
}

@OptIn(ExperimentalCompilerApi::class)
class RpcCompilerPlugin : CompilerPluginRegistrar() {
override val supportsK2: Boolean = true

override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
registerRpcExtensions(configuration)
}
}

@OptIn(ExperimentalCompilerApi::class)
fun CompilerPluginRegistrar.ExtensionStorage.registerRpcExtensions(configuration: CompilerConfiguration) {
VersionSpecificApi.INSTANCE = VersionSpecificApiImpl

IrGenerationExtension.registerExtension(RpcIrExtension(configuration))
FirExtensionRegistrarAdapter.registerExtension(FirRpcExtensionRegistrar(configuration))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.codegen

const val PLUGIN_ID = "org.jetbrains.kotlinx.rpc"
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.codegen

import kotlinx.rpc.codegen.extension.RpcIrExtension
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter

@OptIn(ExperimentalCompilerApi::class)
fun CompilerPluginRegistrar.ExtensionStorage.registerRpcExtensions(configuration: CompilerConfiguration) {
VersionSpecificApi.INSTANCE = VersionSpecificApiImpl

IrGenerationExtension.registerExtension(RpcIrExtension(configuration))
FirExtensionRegistrarAdapter.registerExtension(FirRpcExtensionRegistrar(configuration))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.codegen

import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration

@OptIn(ExperimentalCompilerApi::class)
class RpcCompilerPlugin : CompilerPluginRegistrar() {
override val supportsK2: Boolean = true

//##csm RpcCompilerPlugin.pluginId
//##csm specific=[2.0.0...2.2.99]
//##csm /specific
//##csm default
override val pluginId: String = PLUGIN_ID
//##csm /default
//##csm /RpcCompilerPlugin.pluginId

override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
registerRpcExtensions(configuration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class FirRpcServiceGenerator(
* Generates [owner]'s service stub.
* Scrapes the functions from the [owner] to generate method classes.
*/
private fun generateRpcServiceStubClass(owner: FirClassSymbol<*>): FirRegularClassSymbol? {
private fun generateRpcServiceStubClass(owner: FirClassSymbol<*>): FirRegularClassSymbol {
return createNestedClass(owner, RpcNames.SERVICE_STUB_NAME, RpcGeneratedStubKey(owner.name)) {
visibility = Visibilities.Public
modality = Modality.FINAL
Expand Down
3 changes: 0 additions & 3 deletions compiler-plugin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ org.gradle.configuration-cache=true
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true

# https://youtrack.jetbrains.com/issue/KT-78504
kotlin.js.yarn=false

# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin
kotlinx.rpc.plugin.internalDevelopment=true

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/kotlinx-rpc/topics/versions.topic
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<list>
<li>2.0.0, 2.0.10, 2.0.20, 2.0.21</li>
<li>2.1.0, 2.1.10, 2.1.20, 2.1.21</li>
<li>2.2.0, 2.2.10</li>
<li>2.2.0, 2.2.10, 2.2.20</li>
</list>
<p>
Our code generation will support these versions (See more on <a anchor="code-generation-artifacts">code
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/kotlinx-rpc/v.list
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@

<!-- Library versions -->
<var name="kotlinx-rpc-version" value="0.9.1"/>
<var name="kotlin-version" value="2.2.10"/>
<var name="kotlin-version" value="2.2.20"/>
</vars>
3 changes: 0 additions & 3 deletions dokka-plugin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ org.gradle.configuration-cache=true
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true

# https://youtrack.jetbrains.com/issue/KT-78504
kotlin.js.yarn=false

# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin
kotlinx.rpc.plugin.internalDevelopment=true

Expand Down
31 changes: 31 additions & 0 deletions dowload_kotlin_master.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

#
# Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
#

set -e

if [[ -z $BUILD_SERVER_TOKEN ]]; then
BUILD_SERVER_TOKEN=$(cat "$HOME"/.gradle/gradle.properties | sed -En 's/buildserver.token=(.*)/\1/p')

if [[ -z $BUILD_SERVER_TOKEN ]]; then
echo "No BUILD_SERVER_TOKEN token present"
exit 1
fi;
fi;

# Artifacts from https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_Artifacts
response=$(curl -f "https://teamcity.jetbrains.com/app/rest/builds?locator=count:1,buildType:Kotlin_KotlinPublic_Artifacts,status:SUCCESS,state:finished" --request GET --header "Authorization: Bearer $BUILD_SERVER_TOKEN")

buildId=$(echo "$response" | sed -En 's/.*build id="([0-9]+)".*/\1/p')
echo "Build id: $buildId"

version=$(echo "$response" | sed -En 's/.*number="([0-9a-zA-Z\.-]+)".*/\1/p')
echo "Build Kotlin version: $version"

curl -f "https://teamcity.jetbrains.com/app/rest/builds/id:$buildId/artifacts/content/maven.zip" --request GET --header "Authorization: Bearer $BUILD_SERVER_TOKEN" --output maven.zip

unzip maven.zip -d lib-kotlin

rm maven.zip
120 changes: 24 additions & 96 deletions gradle-conventions/src/main/kotlin/util/tasks/npm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,31 @@ package util.tasks

import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.Exec
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnvSpec
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.BaseNpmExtension
import org.jetbrains.kotlin.gradle.targets.js.npm.LockFileMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmExtension
import org.jetbrains.kotlin.gradle.targets.wasm.nodejs.WasmNodeJsEnvSpec
import org.jetbrains.kotlin.gradle.targets.wasm.nodejs.WasmNodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.wasm.nodejs.WasmNodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.wasm.npm.WasmNpmExtension
import org.jetbrains.kotlin.gradle.targets.web.nodejs.BaseNodeJsEnvSpec
import org.jetbrains.kotlin.gradle.targets.web.nodejs.BaseNodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.web.nodejs.CommonNodeJsRootPlugin
import org.gradle.kotlin.dsl.assign
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootEnvSpec
import org.jetbrains.kotlin.gradle.targets.wasm.yarn.WasmYarnPlugin
import org.jetbrains.kotlin.gradle.targets.wasm.yarn.WasmYarnRootEnvSpec
import org.jetbrains.kotlin.gradle.targets.web.yarn.BaseYarnRootEnvSpec
import org.jetbrains.kotlin.gradle.targets.web.yarn.CommonYarnPlugin
import util.other.optionalProperty
import util.other.spacePassword
import util.other.useProxyRepositories
import java.io.File

const val PUPPETEER_BROWSERS_DIR = ".puppeteer"

private inline fun <
reified Plugin : CommonNodeJsRootPlugin,
reified Spec : BaseNodeJsEnvSpec,
reified RootExtension : BaseNodeJsRootExtension,
reified Plugin : CommonYarnPlugin,
reified Spec : BaseYarnRootEnvSpec,
> Project.registerCustomNpmTasks(
target: String,
useProxy: Boolean,
) {
val capitalizedTarget = target.replaceFirstChar { it.titlecase() }
val login = tasks.register("execute${capitalizedTarget}NpmLogin") {
tasks.register("execute${capitalizedTarget}NpmLogin") {
if (!useProxyRepositories) {
return@register
}
Expand Down Expand Up @@ -91,100 +81,38 @@ private inline fun <
if (useProxy) {
downloadBaseUrl = "https://packages.jetbrains.team/files/p/krpc/build-deps/"
}

val nodeExecutable = executable

extensions.configure<RootExtension> {
/**
* Long story short:
* We can use Yarn because of this: https://youtrack.jetbrains.com/issue/KT-78504
* So: `kotlin.js.yarn=false`
*
* When we use `npm` instead, it runs `npm install` task.
* That should install `puppeteer` package, which should run its script `install.mjs`.
* That script installs browsers for tests.
*
* If we pass `--ignore-scripts` to npm, the script won't be executed.
* KGP does it by default.
* So we set `ignoreScripts = false`.
* We set it for `NpmExtension` and `WasmNpmExtension` in `NodeJsRootPlugin` and `WasmNodeJsRootPlugin`
* respectively (and not their common supertype because it will not work)
*
* And this approach worked for Yarn.
* Script was executed, browsers were installed.
*
* For some reason, for `npm` it didn't work.
* Even with a proper flag (which I checked with a --debug flag).
*
* So we need to run the script manually AFTER `kotlinNpmInstall` (or `kotlinWasmNpmInstall`).
* But also, BEFORE every other action that comes after `kotlinNpmInstall` (or `kotlinWasmNpmInstall`),
* as otherwise there will be race in parallel tasks execution.
*
* Hence, all shenanigans.
*/
val puppeteerInstall = tasks.register<Exec>("puppeteerInstall$capitalizedTarget") {
commandLine(nodeExecutable.get(), "build/$target/node_modules/puppeteer/install.mjs")
workingDir = rootProject.projectDir

// keep in sync with <ROOT>/.puppeteer.cjs
outputs.dir(rootProject.projectDir.resolve(PUPPETEER_BROWSERS_DIR).resolve("browsers"))
}

npmInstallTaskProvider.configure {
dependsOn(login)
finalizedBy(puppeteerInstall)
}

tasks.matching { task ->
task.dependsOn.any { dependency ->
when (dependency) {
is Task -> dependency == npmInstallTaskProvider.get()
is TaskProvider<*> -> dependency == npmInstallTaskProvider
is String -> dependency == npmInstallTaskProvider.name
else -> false
}
}
}.configureEach {
dependsOn(puppeteerInstall)
}
}
}
}
}

@Suppress("UnusedReceiverParameter")
fun BaseNpmExtension.configureNpmExtension(useProxy: Boolean, kotlinMasterBuild: Boolean) {
// todo it still doesn't work for an unknown reason, see 'puppeteerInstall*' tasks above
fun BaseYarnRootEnvSpec.configureNpmExtension(useProxy: Boolean, kotlinMasterBuild: Boolean) {
ignoreScripts = false // if true - puppeteer won't install browsers

packageLockMismatchReport = if (useProxy && !kotlinMasterBuild) {
LockFileMismatchReport.FAIL
yarnLockMismatchReport = if (useProxy && !kotlinMasterBuild) {
YarnLockMismatchReport.FAIL
} else {
LockFileMismatchReport.WARNING
YarnLockMismatchReport.WARNING
}
}

fun Project.configureNpm() {
val kotlinMasterBuild by optionalProperty()
val useProxy = useProxyRepositories

registerCustomNpmTasks<NodeJsRootPlugin, NodeJsEnvSpec, NodeJsRootExtension>("js", useProxy)
registerCustomNpmTasks<WasmNodeJsRootPlugin, WasmNodeJsEnvSpec, WasmNodeJsRootExtension>("wasm", useProxy)
registerCustomNpmTasks<YarnPlugin, YarnRootEnvSpec>("js", useProxy)
registerCustomNpmTasks<WasmYarnPlugin, WasmYarnRootEnvSpec>("wasm", useProxy)

// necessary for CI js tests
rootProject.plugins.withType<NodeJsRootPlugin> {
rootProject.extensions.configure<NpmExtension> {
rootProject.plugins.withType<YarnPlugin> {
rootProject.extensions.configure<YarnRootEnvSpec> {
configureNpmExtension(useProxy, kotlinMasterBuild)
}
}

rootProject.plugins.withType<WasmNodeJsRootPlugin> {
rootProject.extensions.configure<WasmNpmExtension> {
rootProject.plugins.withType<WasmYarnPlugin> {
rootProject.extensions.configure<WasmYarnRootEnvSpec> {
configureNpmExtension(useProxy, kotlinMasterBuild)
}
}

tasks.named<Delete>("clean") {
delete(project.layout.projectDirectory.dir(PUPPETEER_BROWSERS_DIR))
}
}
3 changes: 0 additions & 3 deletions gradle-plugin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ org.gradle.configuration-cache=true
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true

# https://youtrack.jetbrains.com/issue/KT-78504
kotlin.js.yarn=false

# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin
kotlinx.rpc.plugin.internalDevelopment=true

Expand Down
4 changes: 2 additions & 2 deletions gradle-plugin/src/main/kotlin/kotlinx/rpc/RpcPluginConst.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc
Expand All @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources

internal object RpcPluginConst {
const val GROUP_ID = "org.jetbrains.kotlinx"
const val PLUGIN_ID = "kotlinx-rpc"
const val PLUGIN_ID = "org.jetbrains.kotlinx.rpc"
const val COMPILER_PLUGIN_ARTIFACT_ID = "kotlinx-rpc-compiler-plugin"

const val INTERNAL_DEVELOPMENT_PROPERTY = "kotlinx.rpc.plugin.internalDevelopment"
Expand Down
Loading