diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcIrContext.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcIrContext.kt index fa5c429b0..31c723653 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcIrContext.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcIrContext.kt @@ -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.codegen.extension @@ -176,6 +176,10 @@ internal class RpcIrContext( rpcClient.namedFunction("call") } + val rpcClientCallServerStreaming by lazy { + rpcClient.namedFunction("callServerStreaming") + } + val provideStubContext by lazy { rpcClient.namedFunction("provideStubContext") } diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcStubGenerator.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcStubGenerator.kt index 158788c12..661245317 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcStubGenerator.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcStubGenerator.kt @@ -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.codegen.extension @@ -530,7 +530,7 @@ internal class RpcStubGenerator( returnType = method.function.returnType modality = Modality.OPEN - isSuspend = true + isSuspend = method.function.isSuspend }.apply { val functionThisReceiver = vsApi { stubClassThisReceiver.copyToVS(this@apply, origin = IrDeclarationOrigin.DEFINED) @@ -550,6 +550,20 @@ internal class RpcStubGenerator( overriddenSymbols = listOf(method.function.symbol) body = irBuilder(symbol).irBlockBody { + if (method.function.isNonSuspendingWithFlowReturn()) { + +irReturn( + irRpcMethodClientCall( + method = method, + functionThisReceiver = functionThisReceiver, + isMethodObject = isMethodObject, + methodClass = methodClass, + arguments = arguments, + ) + ) + + return@irBlockBody + } + +irReturn( irCall( callee = ctx.functions.scopedClientCall, @@ -742,8 +756,14 @@ internal class RpcStubGenerator( methodClass: IrClass, arguments: List, ): IrCall { + val callee = if (method.function.isNonSuspendingWithFlowReturn()) { + ctx.functions.rpcClientCallServerStreaming.symbol + } else { + ctx.functions.rpcClientCall.symbol + } + val call = irCall( - callee = ctx.functions.rpcClientCall.symbol, + callee = callee, type = method.function.returnType, typeArgumentsCount = 1, ).apply { @@ -1218,13 +1238,15 @@ internal class RpcStubGenerator( * ), * ... * ), + * isNonSuspendFunction = !function.isSuspend, * ) *``` * * Where: * - `` - the name of the method (field) * - `` - a method class for a method and `FieldDataObject` for fields - * - `` - the return type for the method and the field type for a field + * - `` - the return type for the method and the field type for a field. + * For a non-suspending flow the return type is its element type * - `` - an invokator, previously generated by [generateInvokators] * - `` - if a method, its k-th parameter name * - `` - if a method, its k-th parameter type @@ -1253,7 +1275,16 @@ internal class RpcStubGenerator( putValueArgument(1, irRpcTypeCall(dataType)) val returnType = when (callable) { - is ServiceDeclaration.Method -> callable.function.returnType + is ServiceDeclaration.Method -> when { + callable.function.isNonSuspendingWithFlowReturn() -> { + (callable.function.returnType as IrSimpleType).arguments.single().typeOrFail + } + + else -> { + callable.function.returnType + } + } + is ServiceDeclaration.FlowField -> callable.property.getterOrFail.returnType } @@ -1321,9 +1352,14 @@ internal class RpcStubGenerator( } putValueArgument(4, arrayOfCall) + putValueArgument(5, booleanConst(callable is ServiceDeclaration.Method && !callable.function.isSuspend)) } } + private fun IrSimpleFunction.isNonSuspendingWithFlowReturn(): Boolean { + return returnType.classOrNull == ctx.flow && !isSuspend + } + /** * Accessor function for the `callableMap` property * Defined in `RpcServiceDescriptor` @@ -1525,7 +1561,7 @@ internal class RpcStubGenerator( } /** - * IR call of the `RpcType(KType, Array)` function + * IR call of the `RpcType(KType)` function */ private fun irRpcTypeCall(type: IrType): IrConstructorCallImpl { return vsApi { @@ -1644,6 +1680,13 @@ internal class RpcStubGenerator( value = value, ) + private fun booleanConst(value: Boolean) = IrConstImpl.boolean( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + type = ctx.irBuiltIns.booleanType, + value = value, + ) + private fun vsApi(body: VersionSpecificApi.() -> T): T { return ctx.versionSpecificApi.body() } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/StrictMode.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/StrictMode.kt index b401f3ad3..bec06d161 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/StrictMode.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/StrictMode.kt @@ -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.codegen @@ -52,8 +52,8 @@ fun CompilerConfiguration.strictModeAggregator(): StrictModeAggregator { stateFlow = get(StrictModeConfigurationKeys.STATE_FLOW, StrictMode.WARNING), sharedFlow = get(StrictModeConfigurationKeys.SHARED_FLOW, StrictMode.WARNING), nestedFlow = get(StrictModeConfigurationKeys.NESTED_FLOW, StrictMode.WARNING), - streamScopedFunctions = get(StrictModeConfigurationKeys.STREAM_SCOPED_FUNCTIONS, StrictMode.NONE), - suspendingServerStreaming = get(StrictModeConfigurationKeys.SUSPENDING_SERVER_STREAMING, StrictMode.NONE), + streamScopedFunctions = get(StrictModeConfigurationKeys.STREAM_SCOPED_FUNCTIONS, StrictMode.WARNING), + suspendingServerStreaming = get(StrictModeConfigurationKeys.SUSPENDING_SERVER_STREAMING, StrictMode.WARNING), notTopLevelServerFlow = get(StrictModeConfigurationKeys.NOT_TOP_LEVEL_SERVER_FLOW, StrictMode.WARNING), fields = get(StrictModeConfigurationKeys.FIELDS, StrictMode.WARNING), ) diff --git a/core/api/core.api b/core/api/core.api index 15add4b48..6623d8438 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -32,9 +32,14 @@ public final class kotlinx/rpc/RpcCall { public abstract interface class kotlinx/rpc/RpcClient : kotlinx/coroutines/CoroutineScope { public abstract fun call (Lkotlinx/rpc/RpcCall;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun callAsync (Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/Deferred; + public abstract fun callServerStreaming (Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow; public abstract fun provideStubContext (J)Lkotlin/coroutines/CoroutineContext; } +public final class kotlinx/rpc/RpcClient$DefaultImpls { + public static fun callServerStreaming (Lkotlinx/rpc/RpcClient;Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow; +} + public abstract interface annotation class kotlinx/rpc/RpcEagerField : java/lang/annotation/Annotation { } @@ -59,12 +64,13 @@ public abstract interface annotation class kotlinx/rpc/annotations/Rpc : java/la } public final class kotlinx/rpc/descriptor/RpcCallable { - public fun (Ljava/lang/String;Lkotlinx/rpc/descriptor/RpcType;Lkotlinx/rpc/descriptor/RpcType;Lkotlinx/rpc/descriptor/RpcInvokator;[Lkotlinx/rpc/descriptor/RpcParameter;)V + public fun (Ljava/lang/String;Lkotlinx/rpc/descriptor/RpcType;Lkotlinx/rpc/descriptor/RpcType;Lkotlinx/rpc/descriptor/RpcInvokator;[Lkotlinx/rpc/descriptor/RpcParameter;Z)V public final fun getDataType ()Lkotlinx/rpc/descriptor/RpcType; public final fun getInvokator ()Lkotlinx/rpc/descriptor/RpcInvokator; public final fun getName ()Ljava/lang/String; public final fun getParameters ()[Lkotlinx/rpc/descriptor/RpcParameter; public final fun getReturnType ()Lkotlinx/rpc/descriptor/RpcType; + public final fun isNonSuspendFunction ()Z } public abstract interface class kotlinx/rpc/descriptor/RpcInvokator { diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt index 019d66418..e1630a573 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt @@ -6,6 +6,7 @@ package kotlinx.rpc import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred +import kotlinx.coroutines.flow.Flow import kotlin.coroutines.CoroutineContext @Deprecated("Use RpcClient instead", ReplaceWith("RpcClient"), level = DeprecationLevel.ERROR) @@ -36,8 +37,25 @@ public interface RpcClient : CoroutineScope { * that is needed to route it properly to the server. * @return actual result of the call, for example, data from the server */ + @Deprecated( + "This method was primarily used for fields in RPC services, which are now deprecated. " + + "See https://kotlin.github.io/kotlinx-rpc/strict-mode.html fields guide for more information" + ) public fun callAsync(serviceScope: CoroutineScope, call: RpcCall): Deferred + /** + * This method is used by generated clients to perform a call to the server + * that returns a streaming flow. + * + * @param T type of the result + * @param call an object that contains all required information about the called method, + * that is needed to route it properly to the server. + * @return the actual result of the call, for example, data from the server + */ + public fun callServerStreaming(call: RpcCall): Flow { + error("Non-suspending server streaming is not supported by this client") + } + /** * Provides child [CoroutineContext] for a new [RemoteService] service stub. * diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt b/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt index c361a4921..4a2b138e4 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt @@ -62,6 +62,7 @@ public class RpcCallable<@Rpc T : Any>( public val returnType: RpcType, public val invokator: RpcInvokator, public val parameters: Array, + public val isNonSuspendFunction: Boolean, ) @ExperimentalRpcApi diff --git a/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt b/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt index eaf6dbf37..03f67af3b 100644 --- a/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt +++ b/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt @@ -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. */ @file:Suppress("unused") @@ -64,16 +64,16 @@ open class RpcStrictModeExtension @Inject constructor(objects: ObjectFactory) { val nestedFlow: Property = objects.strictModeProperty() /** - * WIP: https://youtrack.jetbrains.com/issue/KRPC-133 - * Will be enabled later, when an alternative is ready. + * StreamScoped functions are deprecated. */ - private val streamScopedFunctions: Property = objects.strictModeProperty(RpcStrictMode.NONE) + val streamScopedFunctions: Property = objects.strictModeProperty() /** - * WIP: https://youtrack.jetbrains.com/issue/KRPC-133 - * Will be enabled later, when an alternative is ready. + * Suspending functions with server-streaming are deprecated in RPC. + * + * Consider returning a Flow in a non-suspending function. */ - private val suspendingServerStreaming: Property = objects.strictModeProperty(RpcStrictMode.NONE) + val suspendingServerStreaming: Property = objects.strictModeProperty() /** * Not top-level flows in the return value are deprecated in RPC for streaming. diff --git a/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt b/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt index 9f3d38522..d75dc0a5d 100644 --- a/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt +++ b/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt @@ -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. */ @file:Suppress("detekt.ClassNaming", "ClassName") @@ -36,12 +36,11 @@ class CompilerPluginCli : KotlinCompilerPluginSupportPlugin by compilerPlugin({ SubpluginOption("strict-stateFlow", strict.stateFlow.get().toCompilerArg()), SubpluginOption("strict-sharedFlow", strict.sharedFlow.get().toCompilerArg()), SubpluginOption("strict-nested-flow", strict.nestedFlow.get().toCompilerArg()), - // WIP: https://youtrack.jetbrains.com/issue/KRPC-133 -// SubpluginOption("strict-stream-scope", strict.streamScopedFunctions.get().toCompilerArg()), -// SubpluginOption( -// "strict-suspending-server-streaming", -// strict.suspendingServerStreaming.get().toCompilerArg() -// ), + SubpluginOption("strict-stream-scope", strict.streamScopedFunctions.get().toCompilerArg()), + SubpluginOption( + "strict-suspending-server-streaming", + strict.suspendingServerStreaming.get().toCompilerArg() + ), SubpluginOption("strict-not-top-level-server-flow", strict.notTopLevelServerFlow.get().toCompilerArg()), SubpluginOption("strict-fields", strict.fields.get().toCompilerArg()), @OptIn(RpcDangerousApi::class) diff --git a/krpc/krpc-client/api/krpc-client.api b/krpc/krpc-client/api/krpc-client.api index c4e9ddcc8..f93f0a4ad 100644 --- a/krpc/krpc-client/api/krpc-client.api +++ b/krpc/krpc-client/api/krpc-client.api @@ -2,6 +2,7 @@ public abstract class kotlinx/rpc/krpc/client/KrpcClient : kotlinx/rpc/krpc/inte public fun (Lkotlinx/rpc/krpc/KrpcConfig$Client;Lkotlinx/rpc/krpc/KrpcTransport;)V public final fun call (Lkotlinx/rpc/RpcCall;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun callAsync (Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/Deferred; + public fun callServerStreaming (Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow; protected final fun getConfig ()Lkotlinx/rpc/krpc/KrpcConfig$Client; public synthetic fun getConfig ()Lkotlinx/rpc/krpc/KrpcConfig; public final fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; diff --git a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/KrpcClient.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/KrpcClient.kt index 28816c4df..665b35d98 100644 --- a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/KrpcClient.kt +++ b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/KrpcClient.kt @@ -1,13 +1,18 @@ /* - * 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.krpc.client import kotlinx.atomicfu.atomic import kotlinx.coroutines.* +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.ClosedReceiveChannelException +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import kotlinx.rpc.RpcCall import kotlinx.rpc.RpcClient +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.descriptor.RpcCallable import kotlinx.rpc.internal.serviceScopeOrNull import kotlinx.rpc.internal.utils.InternalRpcApi @@ -140,6 +145,10 @@ public abstract class KrpcClient( } } + @Deprecated( + "This method was primarily used for fields in RPC services, which are now deprecated. " + + "See https://kotlin.github.io/kotlinx-rpc/strict-mode.html fields guide for more information" + ) override fun callAsync( serviceScope: CoroutineScope, call: RpcCall, @@ -305,6 +314,109 @@ public abstract class KrpcClient( connector.sendMessage(firstMessage) } + private val nonSuspendingSerialFormat = config.serialFormatInitializer.build() + + @Suppress("detekt.CyclomaticComplexMethod") + override fun callServerStreaming(call: RpcCall): Flow { + return flow { + awaitHandshakeCompletion() + + val id = callCounter.incrementAndGet() + val callable = call.descriptor.getCallable(call.callableName) + ?: error("Unexpected callable '${call.callableName}' for ${call.descriptor.fqName} service") + + val dataTypeString = callable.dataType.toString() + + val callId = "$connectionId:$dataTypeString:$id" + + val channel = Channel() + + val request = serializeRequest( + callId = callId, + call = call, + callable = callable, + serialFormat = nonSuspendingSerialFormat, + pluginParams = mapOf(KrpcPluginKey.NON_SUSPENDING_SERVER_FLOW_MARKER to ""), + ) + + connector.sendMessage(request) + + try { + connector.subscribeToCallResponse(call.descriptor.fqName, callId) { message -> + handleServerStreamingMessage(message, channel, callable, call, callId) + } + + while (true) { + val element = channel.receiveCatching() + if (element.isClosed) { + val ex = element.exceptionOrNull() ?: break + throw ex + } + + if (!element.isFailure) { + emit(element.getOrThrow()) + } + } + } catch (e: CancellationException) { + // sendCancellation is not suspending, so no need for NonCancellable + sendCancellation(CancellationType.REQUEST, call.serviceId.toString(), callId) + + throw e + } + } + } + + private suspend fun handleServerStreamingMessage( + message: KrpcCallMessage, + channel: Channel, + callable: RpcCallable, + call: RpcCall, + callId: String, + ) { + when (message) { + is KrpcCallMessage.CallData -> { + error("Unexpected message") + } + + is KrpcCallMessage.CallException -> { + val cause = runCatching { + message.cause.deserialize() + } + + val result = if (cause.isFailure) { + cause.exceptionOrNull()!! + } else { + cause.getOrNull()!! + } + + channel.close(result) + } + + is KrpcCallMessage.CallSuccess, is KrpcCallMessage.StreamMessage -> { + val value = runCatching { + val serializerResult = nonSuspendingSerialFormat.serializersModule + .rpcSerializerForType(callable.returnType) + + decodeMessageData(nonSuspendingSerialFormat, serializerResult, message) + } + + @Suppress("UNCHECKED_CAST") + channel.send(value.getOrNull() as T) + } + + is KrpcCallMessage.StreamFinished -> { + connector.unsubscribeFromMessages(call.descriptor.fqName, callId) + channel.close() + } + + is KrpcCallMessage.StreamCancel -> { + connector.unsubscribeFromMessages(call.descriptor.fqName, callId) + val cause = message.cause.deserialize() + channel.close(cause) + } + } + } + private suspend fun handleMessage( message: KrpcCallMessage, streamContext: LazyKrpcStreamContext, @@ -385,6 +497,7 @@ public abstract class KrpcClient( call: RpcCall, callable: RpcCallable<*>, serialFormat: SerialFormat, + pluginParams: Map = emptyMap(), ): KrpcCallMessage { val serializerData = serialFormat.serializersModule.rpcSerializerForType(callable.dataType) return when (serialFormat) { @@ -398,6 +511,7 @@ public abstract class KrpcClient( data = stringValue, connectionId = connectionId, serviceId = call.serviceId, + pluginParams = pluginParams, ) } @@ -411,6 +525,7 @@ public abstract class KrpcClient( data = binaryValue, connectionId = connectionId, serviceId = call.serviceId, + pluginParams = pluginParams, ) } diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPlugin.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPlugin.kt index e39e3ef77..134fc27bb 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPlugin.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPlugin.kt @@ -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.krpc.internal @@ -50,6 +50,11 @@ public enum class KrpcPlugin( * This feature adds support for proper service/request cancellation over the network. */ CANCELLATION(2, KrpcVersion.V_0_1_0_BETA), + + /** + * This feature adds support for proper service/request cancellation over the network. + */ + NON_SUSPENDING_SERVER_FLOWS(3, KrpcVersion.V_0_6_0), ; @InternalRpcApi diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPluginKey.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPluginKey.kt index 703995ba6..4cd9b7258 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPluginKey.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcPluginKey.kt @@ -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.krpc.internal @@ -45,6 +45,11 @@ public enum class KrpcPluginKey(override val uniqueIndex: Int, private val assoc * Represents a service id that is unique to a current connection. */ CLIENT_SERVICE_ID(4, KrpcPlugin.CANCELLATION), + + /** + * Marks a request as a one doesn't suspend and returns a flow. + */ + NON_SUSPENDING_SERVER_FLOW_MARKER(5, KrpcPlugin.NON_SUSPENDING_SERVER_FLOWS), ; init { diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcVersion.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcVersion.kt index 71e5f7ffb..7b8a3009a 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcVersion.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcVersion.kt @@ -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.krpc.internal @@ -12,4 +12,9 @@ internal enum class KrpcVersion { * Version 0.1.0 */ V_0_1_0_BETA, + + /** + * Version 0.6.0 + */ + V_0_6_0, } diff --git a/krpc/krpc-ktor/krpc-ktor-client/api/krpc-ktor-client.api b/krpc/krpc-ktor/krpc-ktor-client/api/krpc-ktor-client.api index 2cc3957bd..64a0821c4 100644 --- a/krpc/krpc-ktor/krpc-ktor-client/api/krpc-ktor-client.api +++ b/krpc/krpc-ktor/krpc-ktor-client/api/krpc-ktor-client.api @@ -20,3 +20,7 @@ public abstract interface class kotlinx/rpc/krpc/ktor/client/KtorRpcClient : kot public abstract fun getWebSocketSession ()Lio/ktor/websocket/WebSocketSession; } +public final class kotlinx/rpc/krpc/ktor/client/KtorRpcClient$DefaultImpls { + public static fun callServerStreaming (Lkotlinx/rpc/krpc/ktor/client/KtorRpcClient;Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow; +} + diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerService.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerService.kt index 684e547c0..320329d04 100644 --- a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerService.kt +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerService.kt @@ -1,10 +1,11 @@ /* - * 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.krpc.server.internal import kotlinx.coroutines.* +import kotlinx.coroutines.flow.Flow import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.descriptor.RpcInvokator import kotlinx.rpc.descriptor.RpcServiceDescriptor @@ -16,6 +17,8 @@ import kotlinx.rpc.krpc.internal.logging.CommonLogger import kotlinx.rpc.krpc.streamScopeOrNull import kotlinx.rpc.krpc.withServerStreamScope import kotlinx.serialization.BinaryFormat +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialFormat import kotlinx.serialization.StringFormat import kotlin.coroutines.CoroutineContext @@ -152,7 +155,19 @@ internal class KrpcServerService<@Rpc T : Any>( var failure: Throwable? = null val requestJob = launch(start = CoroutineStart.LAZY) { - val result = try { + try { + val markedNonSuspending = callData.pluginParams.orEmpty() + .contains(KrpcPluginKey.NON_SUSPENDING_SERVER_FLOW_MARKER) + + if (callable.isNonSuspendFunction && !markedNonSuspending) { + @Suppress("detekt.MaxLineLength") + error( + "Server flow returned from non-suspend function but marked so by a client: ${descriptor.fqName}::$callableName." + + "Probable cause is outdated client version, that does not support non-suspending flows, " + + "but calls the function with the same name. Change the function name or update the client." + ) + } + val value = when (val invokator = callable.invokator) { is RpcInvokator.Method -> { callScoped(callId) { @@ -167,32 +182,18 @@ internal class KrpcServerService<@Rpc T : Any>( val returnType = callable.returnType val returnSerializer = serialFormat.serializersModule.rpcSerializerForType(returnType) - when (serialFormat) { - is StringFormat -> { - val stringValue = serialFormat.encodeToString(returnSerializer, value) - KrpcCallMessage.CallSuccessString( - callId = callData.callId, - serviceType = descriptor.fqName, - data = stringValue, - connectionId = callData.connectionId, - serviceId = callData.serviceId, - ) - } - is BinaryFormat -> { - val binaryValue = serialFormat.encodeToByteArray(returnSerializer, value) - KrpcCallMessage.CallSuccessBinary( - callId = callData.callId, - serviceType = descriptor.fqName, - data = binaryValue, - connectionId = callData.connectionId, - serviceId = callData.serviceId, + if (callable.isNonSuspendFunction) { + if (value !is Flow<*>) { + error( + "Return value of non-suspend function must be a non nullable flow, " + + "but was: ${value?.let { it::class.simpleName }}" ) } - else -> { - unsupportedSerialFormatError(serialFormat) - } + sendFlowMessages(serialFormat, returnSerializer, value, callData) + } else { + sendMessages(serialFormat, returnSerializer, value, callData) } } catch (cause: CancellationException) { throw cause @@ -206,11 +207,9 @@ internal class KrpcServerService<@Rpc T : Any>( cause = serializedCause, connectionId = callData.connectionId, serviceId = callData.serviceId, - ) + ).also { sender.sendMessage(it) } } - sender.sendMessage(result) - if (failure == null) { streamContext.valueOrNull?.apply { launchIf({ incomingHotFlowsAvailable }) { @@ -233,6 +232,110 @@ internal class KrpcServerService<@Rpc T : Any>( requestJob.start() } + private suspend fun sendMessages( + serialFormat: SerialFormat, + returnSerializer: KSerializer, + value: Any?, + callData: KrpcCallMessage.CallData, + ) { + val result = when (serialFormat) { + is StringFormat -> { + val stringValue = serialFormat.encodeToString(returnSerializer, value) + KrpcCallMessage.CallSuccessString( + callId = callData.callId, + serviceType = descriptor.fqName, + data = stringValue, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + ) + } + + is BinaryFormat -> { + val binaryValue = serialFormat.encodeToByteArray(returnSerializer, value) + KrpcCallMessage.CallSuccessBinary( + callId = callData.callId, + serviceType = descriptor.fqName, + data = binaryValue, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + ) + } + + else -> { + unsupportedSerialFormatError(serialFormat) + } + } + + sender.sendMessage(result) + } + + private suspend fun sendFlowMessages( + serialFormat: SerialFormat, + returnSerializer: KSerializer, + flow: Flow, + callData: KrpcCallMessage.CallData, + ) { + try { + flow.collect { value -> + val result = when (serialFormat) { + is StringFormat -> { + val stringValue = serialFormat.encodeToString(returnSerializer, value) + KrpcCallMessage.StreamMessageString( + callId = callData.callId, + serviceType = descriptor.fqName, + data = stringValue, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + streamId = SINGLE_STREAM_ID, + ) + } + + is BinaryFormat -> { + val binaryValue = serialFormat.encodeToByteArray(returnSerializer, value) + KrpcCallMessage.StreamMessageBinary( + callId = callData.callId, + serviceType = descriptor.fqName, + data = binaryValue, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + streamId = SINGLE_STREAM_ID, + ) + } + + else -> { + unsupportedSerialFormatError(serialFormat) + } + } + + connector.sendMessage(result) + } + + connector.sendMessage( + KrpcCallMessage.StreamFinished( + callId = callData.callId, + serviceType = descriptor.fqName, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + streamId = SINGLE_STREAM_ID, + ) + ) + } catch (cause: CancellationException) { + throw cause + } catch (@Suppress("detekt.TooGenericExceptionCaught") cause: Throwable) { + val serializedCause = serializeException(cause) + connector.sendMessage( + KrpcCallMessage.StreamCancel( + callId = callData.callId, + serviceType = descriptor.fqName, + connectionId = callData.connectionId, + serviceId = callData.serviceId, + streamId = SINGLE_STREAM_ID, + cause = serializedCause, + ) + ) + } + } + suspend fun cancelRequest( callId: String, message: String? = null, @@ -253,9 +356,15 @@ internal class KrpcServerService<@Rpc T : Any>( ) ) } + + companion object { + // streams in non-suspend server functions are unique in each call, so no separate is in needed + // this one is provided as a way to interact with the old code around streams + private const val SINGLE_STREAM_ID = "1" + } } -private class RpcRequest(val handlerJob: Job, val streamContext: LazyKrpcStreamContext) { +internal class RpcRequest(val handlerJob: Job, val streamContext: LazyKrpcStreamContext) { suspend fun cancelAndClose( callId: String, message: String? = null, diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt index 33817e2e9..b4d31f729 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt @@ -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.krpc.test @@ -17,6 +17,9 @@ import java.time.LocalDateTime @Suppress("detekt.TooManyFunctions") @Rpc interface KrpcTestService : RemoteService { + fun nonSuspendFlow(): Flow + fun nonSuspendFlowErrorOnEmit(): Flow + fun nonSuspendFlowErrorOnReturn(): Flow suspend fun empty() suspend fun returnType(): String suspend fun simpleWithParams(name: String): String diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt index 7cf2f785f..8f72e4056 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt @@ -21,6 +21,25 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : const val SHARED_FLOW_REPLAY = 5 } + override fun nonSuspendFlow(): Flow { + return flow { + repeat(10) { + delay(100) + emit(it) + } + } + } + + override fun nonSuspendFlowErrorOnEmit(): Flow { + return flow { + error("nonSuspendFlowErrorOnEmit") + } + } + + override fun nonSuspendFlowErrorOnReturn(): Flow { + error("nonSuspendFlowErrorOnReturn") + } + @Suppress("detekt.EmptyFunctionBlock") override suspend fun empty() {} diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt index 1970a3234..c1c51759b 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt @@ -121,6 +121,32 @@ abstract class KrpcTransportTestBase { @JvmField val globalTimeout: Timeout = Timeout.seconds(30) + @Test + fun nonSuspend() { + runBlocking { + assertEquals(List(10) { it }, client.nonSuspendFlow().toList()) + } + } + + @Test + fun nonSuspendErrorOnEmit() { + runBlocking { + val flow = client.nonSuspendFlowErrorOnReturn() + assertFailsWith { + flow.toList() + } + } + } + + @Test + fun nonSuspendErrorOnReturn() { + runBlocking { + assertFailsWith { + client.nonSuspendFlowErrorOnReturn().toList() + } + } + } + @Test fun empty() { backend.cancel() diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt index 314510f88..a46c1548f 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt @@ -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.krpc.test.api.util @@ -103,6 +103,7 @@ private fun writeTmp( Please, review and commit: ${goldFileLine(goldPath)} Temp file: file://${file.absolutePath} + Reason: $reason Run 'moveToGold' Gradle task to update gold files. """.trimIndent() } diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt index dcd83bb7c..5bed4e894 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt @@ -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.krpc.test.cancellation @@ -41,6 +41,8 @@ interface CancellationService : RemoteService { suspend fun closedStreamScopeCallback() suspend fun closedStreamScopeCallbackWithStream(): Flow + + fun nonSuspendable(): Flow } class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : CancellationService { @@ -169,6 +171,31 @@ class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : } } } + + var nonSuspendableSecond = false + val nonSuspendableFinished = CompletableDeferred() + + override fun nonSuspendable(): Flow { + return flow { + try { + repeat(2) { + if (it == 1) { + nonSuspendableSecond = true + } + + emit(it) + + if (it == 0) { + fence.await() + } + } + } catch (e: CancellationException) { + nonSuspendableFinished.complete(Unit) + + throw e + } + } + } } fun resumableFlow(fence: Deferred, onEmit: (Int) -> Unit = {}): Flow = flow { diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt index ca1d9b6ec..ab393d5d9 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt @@ -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.krpc.test.cancellation @@ -671,6 +671,61 @@ class CancellationTest { stopAllAndJoin() } + @Test + fun testCancellingNonSuspendable() = runCancellationTest { + val flow = service.nonSuspendable() + val firstDone = CompletableDeferred() + val requestJob = launch { + flow.collect { + if (it == 0) { + firstDone.complete(Unit) + } + } + } + + firstDone.await() + requestJob.cancel("Cancelled by test") + requestJob.join() + serverInstance().nonSuspendableFinished.await() + + assertEquals(false, serverInstance().nonSuspendableSecond) + + checkAlive() + stopAllAndJoin() + } + + @Test + fun testGCNonSuspendable() = runCancellationTest { + val firstDone = CompletableDeferred() + val latch = CompletableDeferred() + val requestJob = processFlowAndLeaveUnusedForGC(firstDone, latch) + + firstDone.await() + System.gc() // hint GC to collect the flow + serverInstance().nonSuspendableFinished.await() + + assertEquals(false, serverInstance().nonSuspendableSecond) + latch.complete(Unit) + requestJob.join() + + checkAlive() + stopAllAndJoin() + } + + private fun CancellationToolkit.processFlowAndLeaveUnusedForGC( + firstDone: CompletableDeferred, + latch: CompletableDeferred + ): Job { + val flow = service.nonSuspendable() + val requestJob = launch { + flow.first() + firstDone.complete(Unit) + latch.await() + } + + return requestJob + } + private fun CancellationToolkit.checkAlive( serviceAlive: Boolean = true, clientAlive: Boolean = true, diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallData.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallData.gold new file mode 100644 index 000000000..d4581352a --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallData.gold @@ -0,0 +1,18 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.CallData [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallData] + - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType + - Nullable + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType + - callableName: kotlin.String + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + + org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallDataBinary + org.jetbrains.krpc.RPCMessage.CallData + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallDataString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataBinary.gold new file mode 100644 index 000000000..b0edd5b46 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataBinary.gold @@ -0,0 +1,15 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallDataBinary] + - callId: kotlin.String + - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType + - Nullable + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType + - method: kotlin.String + - Declared name: callableName + - connectionId: kotlin.Long + - Nullable + - data: kotlin.ByteArray + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataString.gold new file mode 100644 index 000000000..b9ba5971b --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallDataString.gold @@ -0,0 +1,15 @@ +org.jetbrains.krpc.RPCMessage.CallData [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallDataString] + - callId: kotlin.String + - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType + - Nullable + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType + - method: kotlin.String + - Declared name: callableName + - connectionId: kotlin.Long + - Nullable + - data: kotlin.String + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallException.gold new file mode 100644 index 000000000..3b7dfc0e7 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallException.gold @@ -0,0 +1,11 @@ +org.jetbrains.krpc.RPCMessage.CallException [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallException] + - callId: kotlin.String + - cause: org.jetbrains.krpc.SerializedException + - Declared name: kotlinx.rpc.krpc.internal.SerializedException + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallResult.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallResult.gold new file mode 100644 index 000000000..2e7672b9e --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallResult.gold @@ -0,0 +1,14 @@ +org.jetbrains.krpc.RPCMessage.CallResult [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallResult] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + + org.jetbrains.krpc.RPCMessage.CallException + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallException + org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccess \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccess.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccess.gold new file mode 100644 index 000000000..f34c74a72 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccess.gold @@ -0,0 +1,14 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccess] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + + org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessBinary + org.jetbrains.krpc.RPCMessage.CallSuccess + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessBinary.gold new file mode 100644 index 000000000..e8cd58905 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessBinary.gold @@ -0,0 +1,10 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessBinary] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - data: kotlin.ByteArray + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessString.gold new file mode 100644 index 000000000..34c961851 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallSuccessString.gold @@ -0,0 +1,10 @@ +org.jetbrains.krpc.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessString] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - data: kotlin.String + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallType.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallType.gold new file mode 100644 index 000000000..84b5971b3 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/CallType.gold @@ -0,0 +1,3 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.CallType [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType] + Method + Field \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Failure.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Failure.gold new file mode 100644 index 000000000..f01da216f --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Failure.gold @@ -0,0 +1,8 @@ +org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Failure [Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Failure] + - connectionId: kotlin.Long + - Nullable + - errorMessage: kotlin.String + - failedMessage: org.jetbrains.krpc.internal.transport.RPCMessage + - Nullable + - Declared name: kotlinx.rpc.krpc.internal.KrpcMessage + - pluginParams: kotlin.collections.Map \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Handshake.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Handshake.gold new file mode 100644 index 000000000..2f5e2be80 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/Handshake.gold @@ -0,0 +1,5 @@ +org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake [Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Handshake] + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - supportedPlugins: kotlin.collections.Set \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcCallMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcCallMessage.gold new file mode 100644 index 000000000..0273b93a3 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcCallMessage.gold @@ -0,0 +1,20 @@ +org.jetbrains.krpc.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage] + - callId: kotlin.String + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + + org.jetbrains.krpc.internal.transport.RPCMessage.CallData + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallData + org.jetbrains.krpc.RPCMessage.CallResult + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallResult + org.jetbrains.krpc.RPCMessage.StreamCancel + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamCancel + org.jetbrains.krpc.RPCMessage.StreamFinished + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamFinished + org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessage \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcGenericMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcGenericMessage.gold new file mode 100644 index 000000000..b27a3f009 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcGenericMessage.gold @@ -0,0 +1,5 @@ +org.jetbrains.krpc.internal.transport.RPCGenericMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcGenericMessage] + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcMessage.gold new file mode 100644 index 000000000..6924a1c42 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcMessage.gold @@ -0,0 +1,12 @@ +org.jetbrains.krpc.internal.transport.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcMessage] + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + + org.jetbrains.krpc.RPCMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage + org.jetbrains.krpc.internal.transport.RPCGenericMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcGenericMessage + org.jetbrains.krpc.internal.transport.RPCProtocolMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPlugin.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPlugin.gold new file mode 100644 index 000000000..d46db17a9 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPlugin.gold @@ -0,0 +1,5 @@ +kotlinx.rpc.krpc.internal.KrpcPlugin + UNKNOWN + HANDSHAKE + CANCELLATION + NON_SUSPENDING_SERVER_FLOWS \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPluginKey.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPluginKey.gold new file mode 100644 index 000000000..137d218c5 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcPluginKey.gold @@ -0,0 +1,7 @@ +kotlinx.rpc.krpc.internal.KrpcPluginKey + UNKNOWN + GENERIC_MESSAGE_TYPE + CANCELLATION_TYPE + CANCELLATION_ID + CLIENT_SERVICE_ID + NON_SUSPENDING_SERVER_FLOW_MARKER \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcProtocolMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcProtocolMessage.gold new file mode 100644 index 000000000..7e80aac18 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/KrpcProtocolMessage.gold @@ -0,0 +1,9 @@ +org.jetbrains.krpc.internal.transport.RPCProtocolMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage] + - pluginParams: kotlin.collections.Map + - connectionId: kotlin.Long + - Nullable + + org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Failure + - Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Failure + org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake + - Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Handshake \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/SerializedException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/SerializedException.gold new file mode 100644 index 000000000..427993cbb --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/SerializedException.gold @@ -0,0 +1,8 @@ +org.jetbrains.krpc.SerializedException [Declared name: kotlinx.rpc.krpc.internal.SerializedException] + - cause: org.jetbrains.krpc.SerializedException + - Nullable + - Declared name: kotlinx.rpc.krpc.internal.SerializedException + - className: kotlin.String + - message: kotlin.String + - stacktrace: kotlin.collections.List + - toStringMessage: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StackElement.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StackElement.gold new file mode 100644 index 000000000..d67b95977 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StackElement.gold @@ -0,0 +1,6 @@ +org.jetbrains.krpc.StackElement [Declared name: kotlinx.rpc.krpc.internal.StackElement] + - clazz: kotlin.String + - fileName: kotlin.String + - Nullable + - lineNumber: kotlin.Int + - method: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamCancel.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamCancel.gold new file mode 100644 index 000000000..8e6bd5e5e --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamCancel.gold @@ -0,0 +1,13 @@ +org.jetbrains.krpc.RPCMessage.StreamCancel [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamCancel] + - callId: kotlin.String + - cause: org.jetbrains.krpc.SerializedException + - Declared name: kotlinx.rpc.krpc.internal.SerializedException + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + - flowId: kotlin.String + - Declared name: streamId \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamFinished.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamFinished.gold new file mode 100644 index 000000000..a260d7d75 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamFinished.gold @@ -0,0 +1,11 @@ +org.jetbrains.krpc.RPCMessage.StreamFinished [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamFinished] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + - flowId: kotlin.String + - Declared name: streamId \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessage.gold new file mode 100644 index 000000000..e07485913 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessage.gold @@ -0,0 +1,15 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessage] + - streamId: kotlin.String + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + + org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageBinary + org.jetbrains.krpc.RPCMessage.StreamMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageBinary.gold new file mode 100644 index 000000000..6da67510f --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageBinary.gold @@ -0,0 +1,12 @@ +org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageBinary] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - data: kotlin.ByteArray + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + - flowId: kotlin.String + - Declared name: streamId \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageString.gold new file mode 100644 index 000000000..3316fc14e --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_6_0/StreamMessageString.gold @@ -0,0 +1,12 @@ +org.jetbrains.krpc.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageString] + - callId: kotlin.String + - connectionId: kotlin.Long + - Nullable + - data: kotlin.String + - pluginParams: kotlin.collections.Map + - Nullable + - serviceId: kotlin.Long + - Nullable + - serviceType: kotlin.String + - flowId: kotlin.String + - Declared name: streamId \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPlugin.gold b/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPlugin.gold index c913726f7..7733354c7 100644 --- a/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPlugin.gold +++ b/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPlugin.gold @@ -1,3 +1,4 @@ UNKNOWN - 0 HANDSHAKE - 1 -CANCELLATION - 2 \ No newline at end of file +CANCELLATION - 2 +NON_SUSPENDING_SERVER_FLOWS - 3 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPluginKey.gold b/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPluginKey.gold index 1558b9479..edc818e2f 100644 --- a/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPluginKey.gold +++ b/krpc/krpc-test/src/jvmTest/resources/indexed_enum_dumps/KrpcPluginKey.gold @@ -2,4 +2,5 @@ UNKNOWN - 0 GENERIC_MESSAGE_TYPE - 1 CANCELLATION_TYPE - 2 CANCELLATION_ID - 3 -CLIENT_SERVICE_ID - 4 \ No newline at end of file +CLIENT_SERVICE_ID - 4 +NON_SUSPENDING_SERVER_FLOW_MARKER - 5 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/callException_json.gold new file mode 100644 index 000000000..138b31556 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/callException_json.gold @@ -0,0 +1,10 @@ +[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765]} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765]} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765],"connectionId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765],"connectionId":1} +[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}","connectionId":1,"serviceId":1} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}","connectionId":1,"serviceId":1} +[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"CANCELLATION_ACK","-32765":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1"}} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"CANCELLATION_ACK","-32765":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`callException$rpcMethod`:1"}} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_json.gold new file mode 100644 index 000000000..0746c8b30 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_json.gold @@ -0,0 +1,10 @@ +[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765]} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765]} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765],"connectionId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765],"connectionId":1} +[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}","connectionId":1,"serviceId":1} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}","connectionId":1,"serviceId":1} +[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"CANCELLATION_ACK","-32765":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1"}} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"CANCELLATION_ACK","-32765":"1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1"}} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_protobuf.gold new file mode 100644 index 000000000..b043a1ae5 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_6_0/echo_protobuf.gold @@ -0,0 +1,18 @@ +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?!????????????????????????????????? +[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651221088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?!????????????????????????????????? +[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651221088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?#??????????????????????????????????? +[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651223088180feffffffffffff01088280feffffffffffff01088380feffffffffffff011001 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?#??????????????????????????????????? +[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651223088180feffffffffffff01088280feffffffffffff01088380feffffffffffff011001 +// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????W1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? +[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912a8010a57313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 +// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????W1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? +[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912a8010a57313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????W1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? +[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791297010a57313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????W1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? +[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791297010a57313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 +// decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage??????????????????cancellation???????????????CANCELLATION_ACK?d????????????W1:org.jetbrains.krpc.test.api.util.SamplingService.`$rpcServiceStub`.`echo$rpcMethod`:1 +[Server] [Send] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d65737361676512a0011219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b1264088380feffffffffffff011257313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a31 \ No newline at end of file diff --git a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.ir.txt b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.ir.txt index 7e7d517e3..7536f8fe3 100644 --- a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.ir.txt @@ -440,7 +440,7 @@ FILE fqName: fileName:/customParameterTypes.kt : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="test1" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="test1" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -459,11 +459,12 @@ FILE fqName: fileName:/customParameterTypes.kt type: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null : .TestData + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false CALL 'public final fun to (that: B of kotlin.to): kotlin.Pair declared in kotlin' type=kotlin.Pair.BoxService>> origin=null : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="test2" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="test2" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -482,6 +483,7 @@ FILE fqName: fileName:/customParameterTypes.kt type: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null : .TestData + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.collections.Map.BoxService>> correspondingProperty: PROPERTY name:callableMap visibility:private modality:FINAL [val] $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion diff --git a/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt b/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt index f74c0cdc5..b402c4130 100644 --- a/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt @@ -227,7 +227,7 @@ FILE fqName: fileName:/fields.kt : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="plainFlow" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="plainFlow" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -240,11 +240,12 @@ FILE fqName: fileName:/fields.kt $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion' type=.BoxService.$rpcServiceStub.Companion origin=null parameters: CALL 'public final fun emptyArray (): kotlin.Array declared in kotlin' type=kotlin.Array origin=null : kotlinx.rpc.descriptor.RpcParameter + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false CALL 'public final fun to (that: B of kotlin.to): kotlin.Pair declared in kotlin' type=kotlin.Pair.BoxService>> origin=null : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="sharedFlow" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="sharedFlow" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -257,11 +258,12 @@ FILE fqName: fileName:/fields.kt $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion' type=.BoxService.$rpcServiceStub.Companion origin=null parameters: CALL 'public final fun emptyArray (): kotlin.Array declared in kotlin' type=kotlin.Array origin=null : kotlinx.rpc.descriptor.RpcParameter + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false CALL 'public final fun to (that: B of kotlin.to): kotlin.Pair declared in kotlin' type=kotlin.Pair.BoxService>> origin=null : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="stateFlow" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="stateFlow" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -274,6 +276,7 @@ FILE fqName: fileName:/fields.kt $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion' type=.BoxService.$rpcServiceStub.Companion origin=null parameters: CALL 'public final fun emptyArray (): kotlin.Array declared in kotlin' type=kotlin.Array origin=null : kotlinx.rpc.descriptor.RpcParameter + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.collections.Map.BoxService>> correspondingProperty: PROPERTY name:callableMap visibility:private modality:FINAL [val] $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion diff --git a/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.ir.txt b/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.ir.txt index 0e4443b0e..58410c0f9 100644 --- a/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.ir.txt @@ -101,7 +101,7 @@ FILE fqName: fileName:/flowParameter.kt : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="stream" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="stream" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -120,6 +120,7 @@ FILE fqName: fileName:/flowParameter.kt type: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null : kotlinx.coroutines.flow.Flow + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.collections.Map.BoxService>> correspondingProperty: PROPERTY name:callableMap visibility:private modality:FINAL [val] $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion diff --git a/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.ir.txt b/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.ir.txt index 317a3dd9a..14f1a0c39 100644 --- a/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.ir.txt @@ -100,7 +100,7 @@ FILE fqName: fileName:/module_lib_multiModule.kt : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="simple" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="simple" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -113,6 +113,7 @@ FILE fqName: fileName:/module_lib_multiModule.kt $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion' type=.BoxService.$rpcServiceStub.Companion origin=null parameters: CALL 'public final fun emptyArray (): kotlin.Array declared in kotlin' type=kotlin.Array origin=null : kotlinx.rpc.descriptor.RpcParameter + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.collections.Map.BoxService>> correspondingProperty: PROPERTY name:callableMap visibility:private modality:FINAL [val] $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion diff --git a/tests/compiler-plugin-tests/src/testData/box/simple.fir.ir.txt b/tests/compiler-plugin-tests/src/testData/box/simple.fir.ir.txt index 4f526d57d..befa0d70e 100644 --- a/tests/compiler-plugin-tests/src/testData/box/simple.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/simple.fir.ir.txt @@ -99,7 +99,7 @@ FILE fqName: fileName:/simple.kt : kotlin.String : kotlinx.rpc.descriptor.RpcCallable<.BoxService> $receiver: CONST String type=kotlin.String value="simple" - that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null + that: CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, dataType: kotlinx.rpc.descriptor.RpcType, returnType: kotlinx.rpc.descriptor.RpcType, invokator: kotlinx.rpc.descriptor.RpcInvokator, parameters: kotlin.Array, isNonSuspendFunction: kotlin.Boolean) declared in kotlinx.rpc.descriptor.RpcCallable' type=kotlinx.rpc.descriptor.RpcCallable<.BoxService> origin=null : .BoxService name: CONST String type=kotlin.String value="simple" dataType: CONSTRUCTOR_CALL 'public constructor (kType: kotlin.reflect.KType) declared in kotlinx.rpc.descriptor.RpcType' type=kotlinx.rpc.descriptor.RpcType origin=null @@ -112,6 +112,7 @@ FILE fqName: fileName:/simple.kt $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion' type=.BoxService.$rpcServiceStub.Companion origin=null parameters: CALL 'public final fun emptyArray (): kotlin.Array declared in kotlin' type=kotlin.Array origin=null : kotlinx.rpc.descriptor.RpcParameter + isNonSuspendFunction: CONST Boolean type=kotlin.Boolean value=false FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.collections.Map.BoxService>> correspondingProperty: PROPERTY name:callableMap visibility:private modality:FINAL [val] $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt index 00e5f72b0..6fd3db61b 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt @@ -226,6 +226,10 @@ FILE: b.kt public abstract suspend fun clientNestedTrickyFlow(inner: R|Wrapper>>>|): R|kotlin/Unit| + public abstract fun nonSuspendNoFlow(): R|kotlin/Unit| + + public abstract fun nonSuspendNoFlowString(): R|kotlin/String| + public final class $rpcServiceStub : R|kotlin/Any| { @R|kotlinx/serialization/Serializable|() public final class state$rpcMethod : R|kotlin/Any| { @R|kotlinx/serialization/Contextual|() public final val flow: R|kotlinx/coroutines/flow/StateFlow| @@ -716,6 +720,24 @@ FILE: b.kt } + @R|kotlinx/serialization/Serializable|() public final object nonSuspendNoFlow$rpcMethod : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|MyService.$rpcServiceStub.nonSuspendNoFlow$rpcMethod| { + super() + } + + } + + @R|kotlinx/serialization/Serializable|() public final object nonSuspendNoFlowString$rpcMethod : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|MyService.$rpcServiceStub.nonSuspendNoFlowString$rpcMethod| { + super() + } + + } + public final companion object Companion : R|kotlin/Any| { } diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt index 0a853f940..0e879fd2f 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt @@ -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. */ // MODULE: none @@ -76,6 +76,8 @@ interface MyService { suspend fun clientInnerFlow(inner: InnerFlow) suspend fun clientNestedFlow(inner: Flow>) suspend fun clientNestedTrickyFlow(inner: Wrapper>>>) + fun nonSuspendNoFlow() + fun nonSuspendNoFlowString(): String } fun main(): Unit = runBlocking {