diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcDeclarationScanner.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcDeclarationScanner.kt index 3061edb0d..23a0492f0 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcDeclarationScanner.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RpcDeclarationScanner.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.dumpKotlinLike /** @@ -47,16 +46,10 @@ internal object RpcDeclarationScanner { return@memoryOptimizedMap null } - val symbol = declaration.getter!!.returnType.classOrNull - - val flowType = when (symbol) { - ctx.flow -> ServiceDeclaration.FlowField.Kind.Plain - ctx.sharedFlow -> ServiceDeclaration.FlowField.Kind.Shared - ctx.stateFlow -> ServiceDeclaration.FlowField.Kind.State - else -> return@memoryOptimizedMap unsupportedDeclaration(service, declaration, logger) - } - - ServiceDeclaration.FlowField(declaration, flowType) + error( + "Fields are not supported in @Rpc services, this error should be caught by frontend. " + + "Please report this issue to the kotlinx-rpc maintainers." + ) } is IrClass -> { @@ -80,8 +73,7 @@ internal object RpcDeclarationScanner { return ServiceDeclaration( service = service, stubClass = stubClassNotNull, - methods = declarations.filterIsInstance(), - fields = declarations.filterIsInstance(), + methods = declarations.filterNotNull(), ) } } @@ -89,7 +81,7 @@ internal object RpcDeclarationScanner { private fun unsupportedDeclaration(service: IrClass, declaration: IrDeclaration, logger: MessageCollector): Nothing? { logger.report( severity = CompilerMessageSeverity.LOGGING, - message = "Unsupported declaration in RemoteService interface ${service.name}: ${declaration.dumpKotlinLike()}", + message = "Unsupported declaration in @Rpc interface ${service.name}: ${declaration.dumpKotlinLike()}", ) return null 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 9ba01c84f..2c16f608c 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 @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.isVararg @@ -33,34 +32,10 @@ internal class RpcIrContext( irBuiltIns.arrayClass.typeWith(anyNullable, Variance.OUT_VARIANCE) } - val coroutineScope by lazy { - getIrClassSymbol("kotlinx.coroutines", "CoroutineScope") - } - - val coroutineContext by lazy { - getIrClassSymbol("kotlin.coroutines", "CoroutineContext") - } - val kTypeClass by lazy { getIrClassSymbol("kotlin.reflect", "KType") } - val lazy by lazy { - getIrClassSymbol("kotlin", "Lazy") - } - - val function0 by lazy { - getIrClassSymbol("kotlin", "Function0") - } - - val function1 by lazy { - getIrClassSymbol("kotlin", "Function1") - } - - val suspendFunction0 by lazy { - getIrClassSymbol("kotlin.coroutines", "SuspendFunction0") - } - val suspendFunction2 by lazy { getIrClassSymbol("kotlin.coroutines", "SuspendFunction2") } @@ -69,18 +44,6 @@ internal class RpcIrContext( getIrClassSymbol("kotlinx.coroutines.flow", "Flow") } - val sharedFlow by lazy { - getIrClassSymbol("kotlinx.coroutines.flow", "SharedFlow") - } - - val stateFlow by lazy { - getIrClassSymbol("kotlinx.coroutines.flow", "StateFlow") - } - - val kProperty1 by lazy { - getIrClassSymbol("kotlin.reflect", "KProperty1") - } - val pair by lazy { getIrClassSymbol("kotlin", "Pair") } @@ -97,10 +60,6 @@ internal class RpcIrContext( getRpcIrClassSymbol("WithServiceDescriptor", "internal") } - val rpcEagerFieldAnnotation by lazy { - getRpcIrClassSymbol("RpcEagerField") - } - val rpcServiceDescriptor by lazy { getRpcIrClassSymbol("RpcServiceDescriptor", "descriptor") } @@ -121,22 +80,10 @@ internal class RpcIrContext( rpcInvokator.subClass("Method") } - val rpcInvokatorField by lazy { - rpcInvokator.subClass("Field") - } - val rpcParameter by lazy { getRpcIrClassSymbol("RpcParameter", "descriptor") } - val rpcDeferredField by lazy { - getRpcIrClassSymbol("RpcDeferredField", "internal") - } - - val fieldDataObject by lazy { - getRpcIrClassSymbol("FieldDataObject", "internal") - } - val rpcMethodClass by lazy { getRpcIrClassSymbol("RpcMethodClass", "internal") } @@ -156,18 +103,6 @@ internal class RpcIrContext( val functions = Functions() inner class Functions { - val registerPlainFlowField by lazy { - namedFunction("kotlinx.rpc", "registerPlainFlowField") - } - - val registerSharedFlowField by lazy { - namedFunction("kotlinx.rpc", "registerSharedFlowField") - } - - val registerStateFlowField by lazy { - namedFunction("kotlinx.rpc", "registerStateFlowField") - } - val dataCast by lazy { namedFunction("kotlinx.rpc.internal", "rpcInternalDataCast") } @@ -180,10 +115,6 @@ internal class RpcIrContext( rpcClient.namedFunction("callServerStreaming") } - val provideStubContext by lazy { - rpcClient.namedFunction("provideStubContext") - } - val asArray by lazy { rpcMethodClass.namedFunction("asArray") } @@ -196,38 +127,6 @@ internal class RpcIrContext( namedFunction("kotlin", "emptyArray") } - val scopedClientCall by lazy { - namedFunction("kotlinx.rpc.internal", "scopedClientCall") - } - - val lazy by lazy { - namedFunction("kotlin", "lazy") { - vsApi { - it.owner.valueParametersVS().size == 1 - } - } - } - - val lazyGetValue by lazy { - namedFunction("kotlin", "getValue") { - vsApi { - it.owner.extensionReceiverParameterVS?.type?.classOrNull == this@RpcIrContext.lazy - } - } - } - - val listOf by lazy { - namedFunction("kotlin.collections", "listOf") { - vsApi { - it.owner.valueParametersVS().singleOrNull()?.isVararg ?: false - } - } - } - - val emptyList by lazy { - namedFunction("kotlin.collections", "emptyList") - } - val mapOf by lazy { namedFunction("kotlin.collections", "mapOf") { vsApi { @@ -266,10 +165,6 @@ internal class RpcIrContext( val properties = Properties() inner class Properties { - val rpcClientCoroutineContext by lazy { - rpcClient.namedProperty("coroutineContext") - } - val rpcServiceDescriptorFqName by lazy { rpcServiceDescriptor.namedProperty("fqName") } 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 fd46efe84..61a8c07a5 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 @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.util.OperatorNameConventions -import org.jetbrains.kotlin.utils.memoryOptimizedPlus import kotlin.properties.Delegates private object Stub { @@ -38,7 +37,6 @@ private object Stub { private object Descriptor { const val CALLABLE_MAP = "callableMap" const val FQ_NAME = "fqName" - const val GET_FIELDS = "getFields" const val GET_CALLABLE = "getCallable" const val CREATE_INSTANCE = "createInstance" } @@ -121,12 +119,6 @@ internal class RpcStubGenerator( stubIdProperty() clientProperty() - - coroutineContextProperty() - - declaration.fields.forEach { - rpcFlowField(it) - } } private var stubIdProperty: IrProperty by Delegates.notNull() @@ -196,307 +188,6 @@ internal class RpcStubGenerator( } } - private var coroutineContextProperty: IrProperty by Delegates.notNull() - - /** - * `coroutineContext` property from `RemoteService` interface - * - * ```kotlin - * final override val coroutineContext: CoroutineContext = __rpc_client.provideStubContext(__rpc_stub_id) - * ``` - */ - private fun IrClass.coroutineContextProperty() { - coroutineContextProperty = addProperty { - name = Name.identifier("coroutineContext") - visibility = DescriptorVisibilities.PUBLIC - modality = Modality.FINAL - }.apply { - overriddenSymbols = listOf(ctx.properties.rpcClientCoroutineContext) - - addBackingFieldUtil { - visibility = DescriptorVisibilities.PRIVATE - type = ctx.coroutineContext.defaultType - vsApi { isFinalVS = true } - }.apply { - val coroutineContextClass = ctx.coroutineContext.owner - - initializer = factory.createExpressionBody( - vsApi { - IrCallImplVS( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = coroutineContextClass.typeWith(), - symbol = ctx.functions.provideStubContext.symbol, - valueArgumentsCount = 1, - typeArgumentsCount = 0, - ) - }.apply { - arguments { - dispatchReceiver = irCallProperty(stubClass, clientProperty) - - values { - +irCallProperty(stubClass, stubIdProperty) - } - } - } - ) - } - - addDefaultGetter(this@coroutineContextProperty, ctx.irBuiltIns) { - val serviceCoroutineContext = declaration.service.getPropertyGetter("coroutineContext") - ?: error( - "RPC services expected to have \"coroutineContext\" property with getter: " + - declaration.service.dump() - ) - - overriddenSymbols = listOf(serviceCoroutineContext) - } - } - } - - /** - * RPC fields. - * Can be of two kinds: Lazy and Eager (defined by `@RpcEagerField` annotation) - * - * Lazy: - * ``` kotlin - * final override val : by lazy { - * client.registerFlowField( - * serviceScope = this, // CoroutineScope - * descriptor = Companion, - * fieldName = "", - * serviceId = __rpc_stub_id, - * ) - * } - * ``` - * - * - * Eager: - * ```kotlin - * final override val : = - * client.registerFlowField( - * serviceScope = this, // CoroutineScope - * descriptor = Companion, - * fieldName = "", - * serviceId = __rpc_stub_id, - * ) - * ``` - * - * Where: - * - `` - the name of the RPC field - * - `` - actual type of the field. Can be either Flot, SharedFlow or StateFlow - * - `` - [ServiceDeclaration.FlowField.Kind] - */ - @Suppress( - "detekt.NestedBlockDepth", - "detekt.LongMethod", - "detekt.CyclomaticComplexMethod", - ) - private fun IrClass.rpcFlowField(field: ServiceDeclaration.FlowField) { - val isLazy = !field.property.hasAnnotation(ctx.rpcEagerFieldAnnotation) - - val servicePropertyGetter = field.property.getterOrFail - - addProperty { - name = field.property.name - visibility = field.property.visibility - modality = Modality.FINAL - isDelegated = isLazy - }.apply { - val fieldProperty = this - - overriddenSymbols = listOf(field.property.symbol) - - val fieldType = servicePropertyGetter.returnType - - val fieldTypeParameter = (fieldType as IrSimpleType).arguments.single() - - val registerFunction = when (field.flowKind) { - ServiceDeclaration.FlowField.Kind.Plain -> ctx.functions.registerPlainFlowField - ServiceDeclaration.FlowField.Kind.Shared -> ctx.functions.registerSharedFlowField - ServiceDeclaration.FlowField.Kind.State -> ctx.functions.registerStateFlowField - } - - val registerCall = vsApi { - IrCallImplVS( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = fieldType, - symbol = registerFunction, - typeArgumentsCount = 1, - valueArgumentsCount = 4, - ) - }.apply { - arguments { - extensionReceiver = irCallProperty(stubClass, clientProperty) - - types { - +fieldTypeParameter.typeOrFail - } - - values { - +IrGetValueImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = ctx.coroutineScope.defaultType, - symbol = stubClassThisReceiver.symbol, - ) - - +irGetDescriptor() - - +stringConst(field.property.name.asString()) - - +irCallProperty(stubClass, stubIdProperty) - } - } - } - - if (!isLazy) { - addBackingFieldUtil { - type = fieldType - visibility = DescriptorVisibilities.PRIVATE - vsApi { isFinalVS = true } - }.apply { - initializer = factory.createExpressionBody(registerCall) - } - - addDefaultGetter(this@rpcFlowField, ctx.irBuiltIns) { - visibility = field.property.visibility - overriddenSymbols = listOf(servicePropertyGetter.symbol) - } - } else { - val lazyFieldType = ctx.lazy.typeWith(fieldType) - - val lazyField = addBackingFieldUtil { - origin = IrDeclarationOrigin.PROPERTY_DELEGATE - name = propertyDelegateName(this@apply.name) - visibility = DescriptorVisibilities.PRIVATE - type = lazyFieldType - vsApi { isFinalVS = true } - }.apply { - val propertyDelegate = this - - // initializer for Lazy delegate with lambda - // inside lambda - 'registerCall' expression is used - initializer = factory.createExpressionBody( - vsApi { - IrCallImplVS( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = lazyFieldType, - symbol = ctx.functions.lazy, - typeArgumentsCount = 1, - valueArgumentsCount = 1, - ) - }.apply { - val lambdaType = ctx.function0.typeWith(fieldType) - - val lambdaFunction = factory.buildFun { - origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA - name = SpecialNames.ANONYMOUS - visibility = DescriptorVisibilities.LOCAL - returnType = fieldType - }.apply { - parent = propertyDelegate - - body = irBuilder(symbol).irBlockBody { - +irReturn(registerCall) - } - } - - val lambda = IrFunctionExpressionImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = lambdaType, - origin = IrStatementOrigin.LAMBDA, - function = lambdaFunction, - ) - - arguments { - types { - +fieldType - } - - values { - +lambda - } - } - } - ) - } - - // Invocation of `operator fun getValue(thisRef: Any?, property: KProperty<*>): T` for delegates - addGetter { - origin = IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR - visibility = this@apply.visibility - returnType = fieldType - }.apply { - val propertyGetter = this - - overriddenSymbols = listOf(servicePropertyGetter.symbol) - - val getterThisReceiver = vsApi { - stubClassThisReceiver.copyToVS(propertyGetter, origin = IrDeclarationOrigin.DEFINED) - }.also { - vsApi { - dispatchReceiverParameterVS = it - } - } - - body = irBuilder(symbol).irBlockBody { - +irReturn( - irCall( - type = fieldType, - callee = ctx.functions.lazyGetValue, - typeArgumentsCount = 1, - ).apply { - arguments { - types { - +fieldType - } - - extensionReceiver = IrGetFieldImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - symbol = lazyField.symbol, - type = lazyFieldType, - receiver = IrGetValueImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = stubClass.defaultType, - symbol = getterThisReceiver.symbol, - ), - ) - - values { - +IrGetValueImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = stubClass.defaultType, - symbol = getterThisReceiver.symbol, - ) - - +IrPropertyReferenceImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = ctx.kProperty1.typeWith(stubClass.defaultType, fieldType), - symbol = fieldProperty.symbol, - typeArgumentsCount = 0, - field = null, - getter = propertyGetter.symbol, - setter = null, - origin = IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE, - ) - } - } - } - ) - } - } - } - } - } - private fun IrClass.generateMethods() { declaration.methods.forEach { generateRpcMethod(it) @@ -555,8 +246,6 @@ internal class RpcStubGenerator( } } - val declaredFunction = this - val arguments = method.arguments.memoryOptimizedMap { arg -> addValueParameter { name = arg.value.name @@ -581,63 +270,19 @@ internal class RpcStubGenerator( return@irBlockBody } - +irReturn( - irCall( - callee = ctx.functions.scopedClientCall, - type = method.function.returnType, - ).apply { - // suspend lambda - // it's type is not available at runtime, but in fact exists - val lambdaType = ctx.suspendFunction0.typeWith(method.function.returnType) - - val functionLambda = factory.buildFun { - origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA - name = SpecialNames.ANONYMOUS - visibility = DescriptorVisibilities.LOCAL - modality = Modality.FINAL - returnType = method.function.returnType - isSuspend = true - }.apply { - parent = declaredFunction - - body = irBuilder(symbol).irBlockBody { - val call = irRpcMethodClientCall( - method = method, - functionThisReceiver = functionThisReceiver, - isMethodObject = isMethodObject, - methodClass = methodClass, - arguments = arguments, - ) - - if (method.function.returnType == ctx.irBuiltIns.unitType) { - +call - } else { - +irReturn(call) - } - } - } - - val lambda = IrFunctionExpressionImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = lambdaType, - origin = IrStatementOrigin.LAMBDA, - function = functionLambda, - ) - - arguments { - types { - +method.function.returnType - } - - values { - +irGet(ctx.coroutineScope.defaultType, functionThisReceiver.symbol) - - +lambda - } - } - } + val call = irRpcMethodClientCall( + method = method, + functionThisReceiver = functionThisReceiver, + isMethodObject = isMethodObject, + methodClass = methodClass, + arguments = arguments, ) + + if (method.function.returnType == ctx.irBuiltIns.unitType) { + +call + } else { + +irReturn(call) + } } } } @@ -970,8 +615,6 @@ internal class RpcStubGenerator( generateGetCallableFunction() generateCreateInstanceFunction() - - generateGetFieldsFunction() } /** @@ -1008,7 +651,7 @@ internal class RpcStubGenerator( private val invokators = mutableMapOf() private fun IrClass.generateInvokators() { - (declaration.methods memoryOptimizedPlus declaration.fields).forEachIndexed { i, callable -> + declaration.methods.forEachIndexed { i, callable -> generateInvokator(i, callable) } } @@ -1055,12 +698,7 @@ internal class RpcStubGenerator( name = Name.identifier("${callable.name}Invokator") visibility = DescriptorVisibilities.PRIVATE }.apply { - val propertyTypeSymbol = when (callable) { - is ServiceDeclaration.Method -> ctx.rpcInvokatorMethod - is ServiceDeclaration.FlowField -> ctx.rpcInvokatorField - } - - val propertyType = propertyTypeSymbol.typeWith(declaration.serviceType) + val propertyType = ctx.rpcInvokatorMethod.typeWith(declaration.serviceType) addBackingFieldUtil { visibility = DescriptorVisibilities.PRIVATE @@ -1133,14 +771,6 @@ internal class RpcStubGenerator( } } } - - is ServiceDeclaration.FlowField -> { - irCall(callable.property.getterOrFail).apply { - arguments { - dispatchReceiver = irGet(serviceParameter) - } - } - } } +irReturn(call) @@ -1153,11 +783,6 @@ internal class RpcStubGenerator( ctx.anyNullable, // data ctx.anyNullable, // returnType ) - - is ServiceDeclaration.FlowField -> ctx.function1.typeWith( - declaration.serviceType, // service - ctx.anyNullable, // returnType - ) } val lambda = IrFunctionExpressionImpl( @@ -1220,7 +845,7 @@ internal class RpcStubGenerator( vsApi { isFinalVS = true } visibility = DescriptorVisibilities.PRIVATE }.apply { - val isEmpty = declaration.methods.isEmpty() && declaration.fields.isEmpty() + val isEmpty = declaration.methods.isEmpty() initializer = factory.createExpressionBody( vsApi { @@ -1248,7 +873,7 @@ internal class RpcStubGenerator( val varargType = ctx.irBuiltIns.arrayClass.typeWith(pairType, Variance.OUT_VARIANCE) - val callables = declaration.methods memoryOptimizedPlus declaration.fields + val callables = declaration.methods val vararg = IrVarargImpl( startOffset = UNDEFINED_OFFSET, @@ -1347,28 +972,22 @@ internal class RpcStubGenerator( val dataType = when (callable) { is ServiceDeclaration.Method -> methodClasses[i].defaultType - is ServiceDeclaration.FlowField -> ctx.fieldDataObject.defaultType } - val returnType = when (callable) { - is ServiceDeclaration.Method -> when { - callable.function.isNonSuspendingWithFlowReturn() -> { - (callable.function.returnType as IrSimpleType).arguments.single().typeOrFail - } - - else -> { - callable.function.returnType - } + val returnType = when { + callable.function.isNonSuspendingWithFlowReturn() -> { + (callable.function.returnType as IrSimpleType).arguments.single().typeOrFail } - is ServiceDeclaration.FlowField -> callable.property.getterOrFail.returnType + else -> { + callable.function.returnType + } } val invokator = invokators[callable.name] ?: error("Expected invokator for ${callable.name} in ${declaration.service.name}") - val parameters = (callable as? ServiceDeclaration.Method)?.arguments - ?: emptyList() + val parameters = callable.arguments val callee = if (parameters.isEmpty()) { ctx.functions.emptyArray @@ -1449,7 +1068,7 @@ internal class RpcStubGenerator( +arrayOfCall - +booleanConst(callable is ServiceDeclaration.Method && !callable.function.isSuspend) + +booleanConst(!callable.function.isSuspend) } } } @@ -1564,87 +1183,6 @@ internal class RpcStubGenerator( } } - /** - * Function for getting a list of all RPC fields in a given service as [RpcDeferredField<*>] - * - * ```kotlin - * final override fun getFields(service: MyService): List> { - * return listOf( // or emptyList() if no fields - * service., - * ... - * service., - * ) as List> - * } - * ``` - * - * Where: - * - `` - the k-th field of a given service - */ - private fun IrClass.generateGetFieldsFunction() { - val listType = ctx.irBuiltIns.listClass.typeWith(ctx.rpcDeferredField.starProjectedType) - - addFunction { - name = Name.identifier(Descriptor.GET_FIELDS) - visibility = DescriptorVisibilities.PUBLIC - modality = Modality.OPEN - - returnType = listType - }.apply { - overriddenSymbols = listOf(ctx.rpcServiceDescriptor.functionByName(Descriptor.GET_FIELDS)) - - vsApi { - dispatchReceiverParameterVS = stubCompanionObjectThisReceiver - .copyToVS(this@apply, origin = IrDeclarationOrigin.DEFINED) - } - - val service = addValueParameter { - name = Name.identifier("service") - type = declaration.serviceType - } - - body = irBuilder(symbol).irBlockBody { - val isEmpty = declaration.fields.isEmpty() - - val anyListType = ctx.irBuiltIns.listClass.typeWith(ctx.anyNullable) - - val listCall = irCall( - callee = if (isEmpty) ctx.functions.emptyList else ctx.functions.listOf, - type = anyListType, - ).apply listApply@{ - if (isEmpty) { - arguments { - types { +ctx.anyNullable } - } - - return@listApply - } - - val vararg = IrVarargImpl( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - type = ctx.arrayOfAnyNullable, - varargElementType = ctx.anyNullable, - elements = declaration.fields.memoryOptimizedMap { - irCallProperty(irGet(service), it.property) - } - ) - - arguments { - types { - +ctx.anyNullable - } - - values { - +vararg - } - } - } - - +irReturn(irAs(listCall, listType)) - } - } - } - // Associated object annotation works on JS, WASM, and Native platforms. // See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/find-associated-object.html private fun addAssociatedObjectAnnotationIfPossible() { diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/ServiceDeclaration.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/ServiceDeclaration.kt index 3c3dce74a..0af4fd2f6 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/ServiceDeclaration.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/ServiceDeclaration.kt @@ -16,7 +16,6 @@ class ServiceDeclaration( val service: IrClass, val stubClass: IrClass, val methods: List, - val fields: List, ) { val fqName = service.kotlinFqName.asString() @@ -37,15 +36,4 @@ class ServiceDeclaration( val type: IrType, ) } - - class FlowField( - val property: IrProperty, - val flowKind: Kind, - ) : Callable { - override val name: String = property.name.asString() - - enum class Kind { - Plain, Shared, State; - } - } } diff --git a/compiler-plugin/compiler-plugin-cli/src/main/latest/kotlinx/rpc/codegen/RpcCompilerPlugin.kt b/compiler-plugin/compiler-plugin-cli/src/main/latest/kotlinx/rpc/codegen/RpcCompilerPlugin.kt index 441f6794a..d450e67a3 100644 --- a/compiler-plugin/compiler-plugin-cli/src/main/latest/kotlinx/rpc/codegen/RpcCompilerPlugin.kt +++ b/compiler-plugin/compiler-plugin-cli/src/main/latest/kotlinx/rpc/codegen/RpcCompilerPlugin.kt @@ -18,13 +18,6 @@ class RpcCommandLineProcessor : CommandLineProcessor { override val pluginId = "kotlinx-rpc" override val pluginOptions = listOf( - StrictModeCliOptions.STATE_FLOW, - StrictModeCliOptions.SHARED_FLOW, - StrictModeCliOptions.NESTED_FLOW, - StrictModeCliOptions.STREAM_SCOPED_FUNCTIONS, - StrictModeCliOptions.SUSPENDING_SERVER_STREAMING, - StrictModeCliOptions.NOT_TOP_LEVEL_SERVER_FLOW, - StrictModeCliOptions.FIELDS, RpcFirCliOptions.ANNOTATION_TYPE_SAFETY, ) @@ -33,10 +26,6 @@ class RpcCommandLineProcessor : CommandLineProcessor { value: String, configuration: CompilerConfiguration, ) { - if (option.processAsStrictModeOption(value, configuration)) { - return - } - when (option) { RpcFirCliOptions.ANNOTATION_TYPE_SAFETY -> { @Suppress("NullableBooleanElvis") diff --git a/compiler-plugin/compiler-plugin-common/src/main/core/kotlinx/rpc/codegen/common/Names.kt b/compiler-plugin/compiler-plugin-common/src/main/core/kotlinx/rpc/codegen/common/Names.kt index c5da2bcaa..a60df0872 100644 --- a/compiler-plugin/compiler-plugin-common/src/main/core/kotlinx/rpc/codegen/common/Names.kt +++ b/compiler-plugin/compiler-plugin-common/src/main/core/kotlinx/rpc/codegen/common/Names.kt @@ -4,13 +4,11 @@ package kotlinx.rpc.codegen.common -import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name object RpcClassId { - val remoteServiceInterface = ClassId(FqName("kotlinx.rpc"), Name.identifier("RemoteService")) val rpcAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("Rpc")) val checkedTypeAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("CheckedTypeAnnotation")) @@ -22,16 +20,6 @@ object RpcClassId { val stateFlow = ClassId(FqName("kotlinx.coroutines.flow"), Name.identifier("StateFlow")) } -object RpcCallableId { - val streamScoped = CallableId(FqName("kotlinx.rpc.krpc"), Name.identifier("streamScoped")) - val withStreamScope = CallableId(FqName("kotlinx.rpc.krpc"), Name.identifier("withStreamScope")) - val StreamScope = CallableId(FqName("kotlinx.rpc.krpc"), Name.identifier("StreamScope")) - val invokeOnStreamScopeCompletion = CallableId( - FqName("kotlinx.rpc.krpc"), - Name.identifier("invokeOnStreamScopeCompletion"), - ) -} - object RpcNames { val SERVICE_STUB_NAME: Name = Name.identifier("\$rpcServiceStub") diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcAdditionalCheckers.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcAdditionalCheckers.kt index 2a8f38125..806540499 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcAdditionalCheckers.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcAdditionalCheckers.kt @@ -7,7 +7,6 @@ package kotlinx.rpc.codegen import kotlinx.rpc.codegen.checkers.FirCheckedAnnotationHelper import kotlinx.rpc.codegen.checkers.FirRpcDeclarationCheckers import kotlinx.rpc.codegen.checkers.FirRpcExpressionCheckers -import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcStrictModeDiagnostics import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers @@ -32,7 +31,6 @@ class FirRpcAdditionalCheckers( session = session, serializationIsPresent = serializationIsPresent, annotationTypeSafetyEnabled = configuration.get(RpcFirConfigurationKeys.ANNOTATION_TYPE_SAFETY, true), - modes = configuration.strictModeAggregator(), ) override val declarationCheckers: DeclarationCheckers = FirRpcDeclarationCheckers(ctx) @@ -43,10 +41,7 @@ class FirCheckersContext( private val session: FirSession, val serializationIsPresent: Boolean, val annotationTypeSafetyEnabled: Boolean, - modes: StrictModeAggregator, ) { - val strictModeDiagnostics = FirRpcStrictModeDiagnostics(modes) - val typeParametersCache = session.firCachesFactory.createCache { typeParameter: FirTypeParameterSymbol -> FirCheckedAnnotationHelper.checkedAnnotations(session, typeParameter) } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcExtensionRegistrar.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcExtensionRegistrar.kt index ae29208d0..0502bf622 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcExtensionRegistrar.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcExtensionRegistrar.kt @@ -30,7 +30,5 @@ class FirRpcExtensionRegistrar(private val configuration: CompilerConfiguration) } +CFactory { FirRpcAdditionalCheckers(it, serializationIsPresent, configuration) } - - +SFactory { FirRpcSupertypeGenerator(it, logger) } } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcSupertypeGeneratorAbstract.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcSupertypeGeneratorAbstract.kt deleted file mode 100644 index 268ce13a4..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcSupertypeGeneratorAbstract.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.common.RpcClassId -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.declarations.utils.isInterface -import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar -import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.name.ClassId - -abstract class FirRpcSupertypeGeneratorAbstract( - session: FirSession, - @Suppress("unused") private val logger: MessageCollector, -) : FirSupertypeGenerationExtension(session) { - override fun FirDeclarationPredicateRegistrar.registerPredicates() { - register(FirRpcPredicates.rpc) - } - - override fun needTransformSupertypes(declaration: FirClassLikeDeclaration): Boolean { - return session.predicateBasedProvider.matches( - predicate = FirRpcPredicates.rpc, - declaration = declaration, - ) && declaration is FirClass && declaration.isInterface - } - - protected fun computeAdditionalSupertypesAbstract( - resolvedSupertypes: List, - ): List { - if (resolvedSupertypes.any { it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) }) { - return emptyList() - } - - return listOf(RpcClassId.remoteServiceInterface) - } -} - diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcUtils.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcUtils.kt index 20869b4cc..54ed7fdea 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcUtils.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcUtils.kt @@ -4,7 +4,6 @@ package kotlinx.rpc.codegen -import kotlinx.rpc.codegen.common.RpcClassId import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId @@ -15,17 +14,11 @@ import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.name.ClassId -fun FirClassSymbol<*>.isRemoteService(session: FirSession): Boolean = resolvedSuperTypeRefs.any { - it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) -} - fun FirBasedSymbol<*>.rpcAnnotationSource( session: FirSession, predicate: DeclarationPredicate, @@ -53,14 +46,6 @@ fun List.rpcAnnotation(session: FirSession, predicate: Declaratio } } -fun FirClassSymbol<*>.remoteServiceSupertypeSource(session: FirSession): KtSourceElement? { - return remoteServiceSupertype(session)?.source -} - -fun FirClassSymbol<*>.remoteServiceSupertype(session: FirSession): FirResolvedTypeRef? { - return resolvedSuperTypeRefs.find { it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) } -} - @OptIn(SymbolInternals::class) internal fun FirTypeRef.doesMatchesClassId(session: FirSession, classId: ClassId): Boolean { return coneTypeSafe()?.fullyExpandedType(session)?.lookupTag?.classId == classId 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 deleted file mode 100644 index b8e4ca918..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/StrictMode.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.AbstractCliOption -import org.jetbrains.kotlin.compiler.plugin.CliOption -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.CompilerConfigurationKey -import kotlin.text.lowercase - -enum class StrictMode { - NONE, WARNING, ERROR; - - companion object { - fun fromCli(value: String): StrictMode? { - return when (value.lowercase()) { - "none" -> NONE - "warning" -> WARNING - "error" -> ERROR - else -> null - } - } - } -} - -data class StrictModeAggregator( - val stateFlow: StrictMode, - val sharedFlow: StrictMode, - val nestedFlow: StrictMode, - val streamScopedFunctions: StrictMode, - val suspendingServerStreaming: StrictMode, - val notTopLevelServerFlow: StrictMode, - val fields: StrictMode, -) - -object StrictModeConfigurationKeys { - val STATE_FLOW = CompilerConfigurationKey.create("state flow rpc mode") - val SHARED_FLOW = CompilerConfigurationKey.create("shared flow rpc mode") - val NESTED_FLOW = CompilerConfigurationKey.create("nested flow rpc mode") - val STREAM_SCOPED_FUNCTIONS = CompilerConfigurationKey.create("stream scoped rpc mode") - val SUSPENDING_SERVER_STREAMING = CompilerConfigurationKey.create( - "suspending server streaming rpc mode" - ) - val NOT_TOP_LEVEL_SERVER_FLOW = CompilerConfigurationKey.create("not top level server flow rpc mode") - val FIELDS = CompilerConfigurationKey.create("fields rpc mode") -} - -fun CompilerConfiguration.strictModeAggregator(): StrictModeAggregator { - return StrictModeAggregator( - stateFlow = get(StrictModeConfigurationKeys.STATE_FLOW, StrictMode.ERROR), - sharedFlow = get(StrictModeConfigurationKeys.SHARED_FLOW, StrictMode.ERROR), - nestedFlow = get(StrictModeConfigurationKeys.NESTED_FLOW, StrictMode.ERROR), - streamScopedFunctions = get(StrictModeConfigurationKeys.STREAM_SCOPED_FUNCTIONS, StrictMode.ERROR), - suspendingServerStreaming = get(StrictModeConfigurationKeys.SUSPENDING_SERVER_STREAMING, StrictMode.ERROR), - notTopLevelServerFlow = get(StrictModeConfigurationKeys.NOT_TOP_LEVEL_SERVER_FLOW, StrictMode.ERROR), - fields = get(StrictModeConfigurationKeys.FIELDS, StrictMode.ERROR), - ) -} - -object StrictModeCliOptions { - val STATE_FLOW = CliOption( - optionName = "strict-stateFlow", - valueDescription = VALUE_DESCRIPTION, - description = description("StateFlow"), - required = false, - allowMultipleOccurrences = false, - ) - - val SHARED_FLOW = CliOption( - optionName = "strict-sharedFlow", - valueDescription = VALUE_DESCRIPTION, - description = description("SharedFlow"), - required = false, - allowMultipleOccurrences = false, - ) - - val NESTED_FLOW = CliOption( - optionName = "strict-nested-flow", - valueDescription = VALUE_DESCRIPTION, - description = description("Nested flows"), - required = false, - allowMultipleOccurrences = false, - ) - - val STREAM_SCOPED_FUNCTIONS = CliOption( - optionName = "strict-stream-scope", - valueDescription = VALUE_DESCRIPTION, - description = description("Stream Scopes"), - required = false, - allowMultipleOccurrences = false, - ) - - val SUSPENDING_SERVER_STREAMING = CliOption( - optionName = "strict-suspending-server-streaming", - valueDescription = VALUE_DESCRIPTION, - description = description("suspending server streaming methods"), - required = false, - allowMultipleOccurrences = false, - ) - - val NOT_TOP_LEVEL_SERVER_FLOW = CliOption( - optionName = "strict-not-top-level-server-flow", - valueDescription = VALUE_DESCRIPTION, - description = description("not top-level server streaming declarations"), - required = false, - allowMultipleOccurrences = false, - ) - - val FIELDS = CliOption( - optionName = "strict-fields", - valueDescription = VALUE_DESCRIPTION, - description = description("fields"), - required = false, - allowMultipleOccurrences = false, - ) - - const val VALUE_DESCRIPTION = "none, warning or error" - - fun description(entity: String): String { - return "Diagnostic level for $entity in @Rpc services." - } - - val configurationMapper = mapOf( - STATE_FLOW to StrictModeConfigurationKeys.STATE_FLOW, - SHARED_FLOW to StrictModeConfigurationKeys.SHARED_FLOW, - NESTED_FLOW to StrictModeConfigurationKeys.NESTED_FLOW, - STREAM_SCOPED_FUNCTIONS to StrictModeConfigurationKeys.STREAM_SCOPED_FUNCTIONS, - SUSPENDING_SERVER_STREAMING to StrictModeConfigurationKeys.SUSPENDING_SERVER_STREAMING, - NOT_TOP_LEVEL_SERVER_FLOW to StrictModeConfigurationKeys.NOT_TOP_LEVEL_SERVER_FLOW, - FIELDS to StrictModeConfigurationKeys.FIELDS, - ) -} - -fun AbstractCliOption.processAsStrictModeOption(value: String, configuration: CompilerConfiguration): Boolean { - val key = StrictModeCliOptions.configurationMapper[this] ?: return false - val mode = StrictMode.fromCli(value) ?: return false - - configuration.put(key, mode) - return true -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt index edf1ca500..8049d18e6 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt @@ -8,8 +8,6 @@ import kotlinx.rpc.codegen.FirCheckersContext import kotlinx.rpc.codegen.FirRpcPredicates import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcDiagnostics import kotlinx.rpc.codegen.common.RpcClassId -import kotlinx.rpc.codegen.isRemoteService -import kotlinx.rpc.codegen.remoteServiceSupertypeSource import kotlinx.rpc.codegen.rpcAnnotation import kotlinx.rpc.codegen.rpcAnnotationSource import org.jetbrains.kotlin.descriptors.ClassKind @@ -51,14 +49,6 @@ object FirRpcAnnotationChecker { ) } - if (declaration.symbol.isRemoteService(context.session) && !rpcAnnotated) { - reporter.reportOn( - source = declaration.symbol.remoteServiceSupertypeSource(context.session), - factory = FirRpcDiagnostics.MISSING_RPC_ANNOTATION, - context = context, - ) - } - if (rpcAnnotated && !ctx.serializationIsPresent && isMetaAnnotated) { reporter.reportOn( source = declaration.symbol.rpcAnnotationSource( diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcCheckers.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcCheckers.kt index c29af0220..a31a73cff 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcCheckers.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcCheckers.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChec class FirRpcDeclarationCheckers(ctx: FirCheckersContext) : DeclarationCheckers() { override val regularClassCheckers: Set = setOfNotNull( FirRpcAnnotationCheckerVS(ctx), - if (ctx.serializationIsPresent) FirRpcStrictModeClassCheckerVS(ctx) else null, + if (ctx.serializationIsPresent) FirRpcStrictModeClassCheckerVS() else null, FirRpcServiceDeclarationCheckerVS(ctx), ) @@ -36,6 +36,5 @@ class FirRpcDeclarationCheckers(ctx: FirCheckersContext) : DeclarationCheckers() class FirRpcExpressionCheckers(ctx: FirCheckersContext) : ExpressionCheckers() { override val functionCallCheckers: Set = setOf( FirCheckedAnnotationFunctionCallCheckerVS(ctx), - FirRpcStrictModeExpressionCheckerVS(ctx), ) } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcStrictModeClassChecker.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcStrictModeClassChecker.kt index 5f6eaf1c6..5b0ba1dfd 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcStrictModeClassChecker.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcStrictModeClassChecker.kt @@ -4,10 +4,8 @@ package kotlinx.rpc.codegen.checkers -import kotlinx.rpc.codegen.FirCheckersContext import kotlinx.rpc.codegen.FirRpcPredicates import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcStrictModeDiagnostics -import kotlinx.rpc.codegen.common.RpcCallableId import kotlinx.rpc.codegen.common.RpcClassId import kotlinx.rpc.codegen.vsApi import org.jetbrains.kotlin.KtSourceElement @@ -19,9 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.extractArgumentsTypeRefAndSour import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.utils.isSuspend -import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider -import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.scopes.impl.toConeType import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol @@ -33,33 +29,8 @@ import org.jetbrains.kotlin.utils.memoryOptimizedPlus import org.jetbrains.kotlinx.serialization.compiler.fir.services.FirSerializablePropertiesProvider import org.jetbrains.kotlinx.serialization.compiler.fir.services.serializablePropertiesProvider -object FirRpcStrictModeExpressionChecker { - private val streamScopeFunctions = setOf( - RpcCallableId.StreamScope, - RpcCallableId.streamScoped, - RpcCallableId.withStreamScope, - RpcCallableId.invokeOnStreamScopeCompletion, - ) - - fun check( - ctx: FirCheckersContext, - expression: FirFunctionCall, - context: CheckerContext, - reporter: DiagnosticReporter, - ) { - expression.calleeReference.toResolvedCallableSymbol()?.let { symbol -> - if (symbol.callableId in streamScopeFunctions) { - ctx.strictModeDiagnostics.STREAM_SCOPE_FUNCTION_IN_RPC?.let { - reporter.reportOn(expression.calleeReference.source, it, context) - } - } - } - } -} - object FirRpcStrictModeClassChecker { fun check( - ctx: FirCheckersContext, declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter, @@ -72,13 +43,11 @@ object FirRpcStrictModeClassChecker { vsApi { declaration.declarationsVS(context.session) }.forEach { declaration -> when (declaration) { is FirPropertySymbol -> { - ctx.strictModeDiagnostics.FIELD_IN_RPC_SERVICE?.let { - reporter.reportOn(declaration.source, it, context) - } + reporter.reportOn(declaration.source, FirRpcStrictModeDiagnostics.FIELD_IN_RPC_SERVICE, context) } is FirNamedFunctionSymbol -> { - checkFunction(ctx, declaration, context, reporter, serializablePropertiesProvider) + checkFunction(declaration, context, reporter, serializablePropertiesProvider) } else -> {} @@ -87,14 +56,13 @@ object FirRpcStrictModeClassChecker { } private fun checkFunction( - ctx: FirCheckersContext, function: FirNamedFunctionSymbol, context: CheckerContext, reporter: DiagnosticReporter, serializablePropertiesProvider: FirSerializablePropertiesProvider, ) { fun reportOn(element: KtSourceElement?, checker: FirRpcStrictModeDiagnostics.() -> KtDiagnosticFactory0?) { - reporter.reportOn(element, ctx.strictModeDiagnostics.checker() ?: return, context) + reporter.reportOn(element, FirRpcStrictModeDiagnostics.checker() ?: return, context) } val returnClassSymbol = vsApi { diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt index adada6411..48cbb9bbd 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt @@ -6,7 +6,6 @@ package kotlinx.rpc.codegen.checkers.diagnostics -import kotlinx.rpc.codegen.StrictModeAggregator import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies import org.jetbrains.kotlin.diagnostics.error0 import org.jetbrains.kotlin.diagnostics.error1 @@ -26,7 +25,6 @@ import org.jetbrains.kotlin.psi.KtElement // ########################################################################### object FirRpcDiagnostics : RpcKtDiagnosticsContainer() { - val MISSING_RPC_ANNOTATION by error0() val MISSING_SERIALIZATION_MODULE by error0() val WRONG_RPC_ANNOTATION_TARGET by error1() val CHECKED_ANNOTATION_VIOLATION by error3>() @@ -40,17 +38,15 @@ object FirRpcDiagnostics : RpcKtDiagnosticsContainer() { } } -@Suppress("PropertyName", "detekt.VariableNaming") -class FirRpcStrictModeDiagnostics(val modes: StrictModeAggregator) : RpcKtDiagnosticsContainer() { - val STATE_FLOW_IN_RPC_SERVICE by modded0(modes.stateFlow) - val SHARED_FLOW_IN_RPC_SERVICE by modded0(modes.sharedFlow) - val NESTED_STREAMING_IN_RPC_SERVICE by modded0(modes.nestedFlow) - val STREAM_SCOPE_FUNCTION_IN_RPC by modded0(modes.streamScopedFunctions) - val SUSPENDING_SERVER_STREAMING_IN_RPC_SERVICE by modded0(modes.suspendingServerStreaming) - val NON_TOP_LEVEL_SERVER_STREAMING_IN_RPC_SERVICE by modded0(modes.notTopLevelServerFlow) - val FIELD_IN_RPC_SERVICE by modded0(modes.fields) +object FirRpcStrictModeDiagnostics : RpcKtDiagnosticsContainer() { + val STATE_FLOW_IN_RPC_SERVICE by error0() + val SHARED_FLOW_IN_RPC_SERVICE by error0() + val NESTED_STREAMING_IN_RPC_SERVICE by error0() + val SUSPENDING_SERVER_STREAMING_IN_RPC_SERVICE by error0() + val NON_TOP_LEVEL_SERVER_STREAMING_IN_RPC_SERVICE by error0() + val FIELD_IN_RPC_SERVICE by error0() override fun getRendererFactoryVs(): BaseDiagnosticRendererFactory { - return RpcStrictModeDiagnosticRendererFactory(this) + return RpcStrictModeDiagnosticRendererFactory } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt index 792fb24d5..56f83a855 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt @@ -4,21 +4,12 @@ package kotlinx.rpc.codegen.checkers.diagnostics -import kotlinx.rpc.codegen.StrictMode -import kotlinx.rpc.codegen.StrictModeAggregator import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.diagnostics.rendering.Renderer import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() { override val MAP by RpcKtDiagnosticFactoryToRendererMap("Rpc") { map -> - map.put( - factory = FirRpcDiagnostics.MISSING_RPC_ANNOTATION, - message = "Missing @Rpc annotation. " + - "All services children of kotlinx.rpc.RemoteService " + - "must be annotated with kotlinx.rpc.annotations.Rpc", - ) - map.put( factory = FirRpcDiagnostics.MISSING_SERIALIZATION_MODULE, message = "Missing kotlinx.serialization plugin in the module. " + @@ -78,68 +69,41 @@ private fun Int.indexPositionSpelled(): String { return "$padded$suffix" } -class RpcStrictModeDiagnosticRendererFactory( - private val diagnostics: FirRpcStrictModeDiagnostics, -) : BaseDiagnosticRendererFactory() { +object RpcStrictModeDiagnosticRendererFactory : BaseDiagnosticRendererFactory() { override val MAP by RpcKtDiagnosticFactoryToRendererMap("RpcStrictMode") { map -> - diagnostics.STATE_FLOW_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("StateFlow") { stateFlow }, - ) - } - - diagnostics.SHARED_FLOW_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("SharedFlow") { sharedFlow }, - ) - } - - diagnostics.NESTED_STREAMING_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("Nested streaming") { nestedFlow }, - ) - } - - diagnostics.STREAM_SCOPE_FUNCTION_IN_RPC?.let { - map.put( - factory = it, - message = message("Stream scope usage") { streamScopedFunctions }, - ) - } - - diagnostics.SUSPENDING_SERVER_STREAMING_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("Suspend function declaration with server streaming") { suspendingServerStreaming }, - ) - } - - diagnostics.NON_TOP_LEVEL_SERVER_STREAMING_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("Not top-level server-side streaming") { sharedFlow }, - ) - } - - diagnostics.FIELD_IN_RPC_SERVICE?.let { - map.put( - factory = it, - message = message("Field declaration") { fields }, - ) - } - } + map.put( + factory = FirRpcStrictModeDiagnostics.STATE_FLOW_IN_RPC_SERVICE, + message = message("StateFlow") + ) - private fun message(entityName: String, selector: StrictModeAggregator.() -> StrictMode): String { - val actionWord = when (diagnostics.modes.selector()) { - StrictMode.NONE -> "" - StrictMode.WARNING -> "deprecated" - StrictMode.ERROR -> "prohibited" - } + map.put( + factory = FirRpcStrictModeDiagnostics.SHARED_FLOW_IN_RPC_SERVICE, + message = message("SharedFlow"), + ) + + map.put( + factory = FirRpcStrictModeDiagnostics.NESTED_STREAMING_IN_RPC_SERVICE, + message = message("Nested streaming"), + ) + + map.put( + factory = FirRpcStrictModeDiagnostics.SUSPENDING_SERVER_STREAMING_IN_RPC_SERVICE, + message = message("Suspend function declaration with server streaming"), + ) + + map.put( + factory = FirRpcStrictModeDiagnostics.NON_TOP_LEVEL_SERVER_STREAMING_IN_RPC_SERVICE, + message = message("Not top-level server-side streaming"), + ) + + map.put( + factory = FirRpcStrictModeDiagnostics.FIELD_IN_RPC_SERVICE, + message = message("Field declaration"), + ) + } - return "$entityName is $actionWord in @Rpc services in strict mode. " + + private fun message(entityName: String): String { + return "$entityName is prohibited in @Rpc services in strict mode. " + "Support will be removed completely in the 0.8.0 release." } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt deleted file mode 100644 index 90269d1d8..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023-2024 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.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType - -class FirRpcSupertypeGenerator( - session: FirSession, - logger: MessageCollector, -) : FirRpcSupertypeGeneratorAbstract(session, logger) { - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List, - typeResolver: TypeResolveService, - ): List { - return computeAdditionalSupertypesAbstract(resolvedSupertypes).map { - it.constructClassLikeType(emptyArray(), isMarkedNullable = false) - } - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt index ca76f64c2..f6fcdbcad 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt @@ -65,16 +65,8 @@ class FirRpcServiceDeclarationCheckerVS( } } -class FirRpcStrictModeExpressionCheckerVS( - private val ctx: FirCheckersContext, -) : FirFunctionCallChecker(MppCheckerKind.Common) { - override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeExpressionChecker.check(ctx, expression, context, reporter) - } -} - -class FirRpcStrictModeClassCheckerVS(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) { +class FirRpcStrictModeClassCheckerVS : FirRegularClassChecker(MppCheckerKind.Common) { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeClassChecker.check(ctx, declaration, context, reporter) + FirRpcStrictModeClassChecker.check(declaration, context, reporter) } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt deleted file mode 100644 index 6f7b2e0e1..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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") - -package kotlinx.rpc.codegen.checkers.diagnostics - -import kotlinx.rpc.codegen.StrictMode -import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 -import org.jetbrains.kotlin.diagnostics.Severity -import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies -import org.jetbrains.kotlin.utils.DummyDelegate -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass -import kotlin.reflect.KProperty - -inline fun modded0(mode: StrictMode): DiagnosticFactory0DelegateProviderOnNull { - return DiagnosticFactory0DelegateProviderOnNull(mode, T::class) -} - -class DiagnosticFactory0DelegateProviderOnNull( - private val mode: StrictMode, - private val psiType: KClass<*>, -) { - operator fun provideDelegate( - @Suppress("unused") - thisRef: Any?, - prop: KProperty<*>, - ): ReadOnlyProperty { - val severity = when (mode) { - StrictMode.ERROR -> Severity.ERROR - StrictMode.WARNING -> Severity.WARNING - StrictMode.NONE -> null - } ?: return DummyDelegate(null) - - return DummyDelegate( - KtDiagnosticFactory0( - name = prop.name, - severity = severity, - defaultPositioningStrategy = SourceElementPositioningStrategies.DEFAULT, - psiType = psiType, - ), - ) - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt deleted file mode 100644 index 04b2667fc..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2023-2024 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.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType - -class FirRpcSupertypeGenerator( - session: FirSession, - logger: MessageCollector, -) : FirRpcSupertypeGeneratorAbstract(session, logger) { - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List, - typeResolver: TypeResolveService, - ): List { - return computeAdditionalSupertypesAbstract(resolvedSupertypes).map { - vsApi { - it.constructClassLikeType(emptyArray(), isNullable = false).toFirResolvedTypeRefVS() - } - } - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt index ca76f64c2..f6fcdbcad 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt @@ -65,16 +65,8 @@ class FirRpcServiceDeclarationCheckerVS( } } -class FirRpcStrictModeExpressionCheckerVS( - private val ctx: FirCheckersContext, -) : FirFunctionCallChecker(MppCheckerKind.Common) { - override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeExpressionChecker.check(ctx, expression, context, reporter) - } -} - -class FirRpcStrictModeClassCheckerVS(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) { +class FirRpcStrictModeClassCheckerVS : FirRegularClassChecker(MppCheckerKind.Common) { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeClassChecker.check(ctx, declaration, context, reporter) + FirRpcStrictModeClassChecker.check(declaration, context, reporter) } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt deleted file mode 100644 index 6f7b2e0e1..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_10/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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") - -package kotlinx.rpc.codegen.checkers.diagnostics - -import kotlinx.rpc.codegen.StrictMode -import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 -import org.jetbrains.kotlin.diagnostics.Severity -import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies -import org.jetbrains.kotlin.utils.DummyDelegate -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass -import kotlin.reflect.KProperty - -inline fun modded0(mode: StrictMode): DiagnosticFactory0DelegateProviderOnNull { - return DiagnosticFactory0DelegateProviderOnNull(mode, T::class) -} - -class DiagnosticFactory0DelegateProviderOnNull( - private val mode: StrictMode, - private val psiType: KClass<*>, -) { - operator fun provideDelegate( - @Suppress("unused") - thisRef: Any?, - prop: KProperty<*>, - ): ReadOnlyProperty { - val severity = when (mode) { - StrictMode.ERROR -> Severity.ERROR - StrictMode.WARNING -> Severity.WARNING - StrictMode.NONE -> null - } ?: return DummyDelegate(null) - - return DummyDelegate( - KtDiagnosticFactory0( - name = prop.name, - severity = severity, - defaultPositioningStrategy = SourceElementPositioningStrategies.DEFAULT, - psiType = psiType, - ), - ) - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt deleted file mode 100644 index 04b2667fc..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2023-2024 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.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType - -class FirRpcSupertypeGenerator( - session: FirSession, - logger: MessageCollector, -) : FirRpcSupertypeGeneratorAbstract(session, logger) { - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List, - typeResolver: TypeResolveService, - ): List { - return computeAdditionalSupertypesAbstract(resolvedSupertypes).map { - vsApi { - it.constructClassLikeType(emptyArray(), isNullable = false).toFirResolvedTypeRefVS() - } - } - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt index ca76f64c2..f6fcdbcad 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt @@ -65,16 +65,8 @@ class FirRpcServiceDeclarationCheckerVS( } } -class FirRpcStrictModeExpressionCheckerVS( - private val ctx: FirCheckersContext, -) : FirFunctionCallChecker(MppCheckerKind.Common) { - override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeExpressionChecker.check(ctx, expression, context, reporter) - } -} - -class FirRpcStrictModeClassCheckerVS(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) { +class FirRpcStrictModeClassCheckerVS : FirRegularClassChecker(MppCheckerKind.Common) { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { - FirRpcStrictModeClassChecker.check(ctx, declaration, context, reporter) + FirRpcStrictModeClassChecker.check(declaration, context, reporter) } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt b/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt deleted file mode 100644 index 6f7b2e0e1..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/pre_2_0_21/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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") - -package kotlinx.rpc.codegen.checkers.diagnostics - -import kotlinx.rpc.codegen.StrictMode -import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 -import org.jetbrains.kotlin.diagnostics.Severity -import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies -import org.jetbrains.kotlin.utils.DummyDelegate -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass -import kotlin.reflect.KProperty - -inline fun modded0(mode: StrictMode): DiagnosticFactory0DelegateProviderOnNull { - return DiagnosticFactory0DelegateProviderOnNull(mode, T::class) -} - -class DiagnosticFactory0DelegateProviderOnNull( - private val mode: StrictMode, - private val psiType: KClass<*>, -) { - operator fun provideDelegate( - @Suppress("unused") - thisRef: Any?, - prop: KProperty<*>, - ): ReadOnlyProperty { - val severity = when (mode) { - StrictMode.ERROR -> Severity.ERROR - StrictMode.WARNING -> Severity.WARNING - StrictMode.NONE -> null - } ?: return DummyDelegate(null) - - return DummyDelegate( - KtDiagnosticFactory0( - name = prop.name, - severity = severity, - defaultPositioningStrategy = SourceElementPositioningStrategies.DEFAULT, - psiType = psiType, - ), - ) - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt deleted file mode 100644 index 90269d1d8..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023-2024 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.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType - -class FirRpcSupertypeGenerator( - session: FirSession, - logger: MessageCollector, -) : FirRpcSupertypeGeneratorAbstract(session, logger) { - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List, - typeResolver: TypeResolveService, - ): List { - return computeAdditionalSupertypesAbstract(resolvedSupertypes).map { - it.constructClassLikeType(emptyArray(), isMarkedNullable = false) - } - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt index 684070a55..dad111824 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt @@ -71,18 +71,9 @@ class FirRpcServiceDeclarationCheckerVS( } } -class FirRpcStrictModeExpressionCheckerVS( - private val ctx: FirCheckersContext, -) : FirFunctionCallChecker(MppCheckerKind.Common) { - context(context: CheckerContext, reporter: DiagnosticReporter) - override fun check(expression: FirFunctionCall) { - FirRpcStrictModeExpressionChecker.check(ctx, expression, context, reporter) - } -} - -class FirRpcStrictModeClassCheckerVS(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) { +class FirRpcStrictModeClassCheckerVS : FirRegularClassChecker(MppCheckerKind.Common) { context(context: CheckerContext, reporter: DiagnosticReporter) override fun check(declaration: FirRegularClass) { - FirRpcStrictModeClassChecker.check(ctx, declaration, context, reporter) + FirRpcStrictModeClassChecker.check(declaration, context, reporter) } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt deleted file mode 100644 index 6f7b2e0e1..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2/kotlinx/rpc/codegen/checkers/diagnostics/DiagnosticFactories.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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") - -package kotlinx.rpc.codegen.checkers.diagnostics - -import kotlinx.rpc.codegen.StrictMode -import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 -import org.jetbrains.kotlin.diagnostics.Severity -import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies -import org.jetbrains.kotlin.utils.DummyDelegate -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass -import kotlin.reflect.KProperty - -inline fun modded0(mode: StrictMode): DiagnosticFactory0DelegateProviderOnNull { - return DiagnosticFactory0DelegateProviderOnNull(mode, T::class) -} - -class DiagnosticFactory0DelegateProviderOnNull( - private val mode: StrictMode, - private val psiType: KClass<*>, -) { - operator fun provideDelegate( - @Suppress("unused") - thisRef: Any?, - prop: KProperty<*>, - ): ReadOnlyProperty { - val severity = when (mode) { - StrictMode.ERROR -> Severity.ERROR - StrictMode.WARNING -> Severity.WARNING - StrictMode.NONE -> null - } ?: return DummyDelegate(null) - - return DummyDelegate( - KtDiagnosticFactory0( - name = prop.name, - severity = severity, - defaultPositioningStrategy = SourceElementPositioningStrategies.DEFAULT, - psiType = psiType, - ), - ) - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt deleted file mode 100644 index 90269d1d8..000000000 --- a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023-2024 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.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType - -class FirRpcSupertypeGenerator( - session: FirSession, - logger: MessageCollector, -) : FirRpcSupertypeGeneratorAbstract(session, logger) { - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List, - typeResolver: TypeResolveService, - ): List { - return computeAdditionalSupertypesAbstract(resolvedSupertypes).map { - it.constructClassLikeType(emptyArray(), isMarkedNullable = false) - } - } -} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt index 684070a55..dad111824 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/v_2_2_2/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt @@ -71,18 +71,9 @@ class FirRpcServiceDeclarationCheckerVS( } } -class FirRpcStrictModeExpressionCheckerVS( - private val ctx: FirCheckersContext, -) : FirFunctionCallChecker(MppCheckerKind.Common) { - context(context: CheckerContext, reporter: DiagnosticReporter) - override fun check(expression: FirFunctionCall) { - FirRpcStrictModeExpressionChecker.check(ctx, expression, context, reporter) - } -} - -class FirRpcStrictModeClassCheckerVS(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) { +class FirRpcStrictModeClassCheckerVS : FirRegularClassChecker(MppCheckerKind.Common) { context(context: CheckerContext, reporter: DiagnosticReporter) override fun check(declaration: FirRegularClass) { - FirRpcStrictModeClassChecker.check(ctx, declaration, context, reporter) + FirRpcStrictModeClassChecker.check(declaration, context, reporter) } } diff --git a/core/api/core.api b/core/api/core.api index 6623d8438..4830d8914 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -1,15 +1,4 @@ -public final class kotlinx/rpc/AwaitFieldInitializationKt { - public static final fun awaitFieldInitialization (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun awaitFieldInitialization (Ljava/lang/Object;Lkotlin/reflect/KClass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class kotlinx/rpc/RegisterFieldKt { - public static final fun registerPlainFlowField (Lkotlinx/rpc/RpcClient;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/descriptor/RpcServiceDescriptor;Ljava/lang/String;J)Lkotlinx/coroutines/flow/Flow; - public static final fun registerSharedFlowField (Lkotlinx/rpc/RpcClient;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/descriptor/RpcServiceDescriptor;Ljava/lang/String;J)Lkotlinx/coroutines/flow/SharedFlow; - public static final fun registerStateFlowField (Lkotlinx/rpc/RpcClient;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/descriptor/RpcServiceDescriptor;Ljava/lang/String;J)Lkotlinx/coroutines/flow/StateFlow; -} - -public abstract interface class kotlinx/rpc/RemoteService : kotlinx/coroutines/CoroutineScope { +public abstract interface class kotlinx/rpc/RemoteService { } public final class kotlinx/rpc/RpcCall { @@ -29,27 +18,14 @@ public final class kotlinx/rpc/RpcCall { public fun toString ()Ljava/lang/String; } -public abstract interface class kotlinx/rpc/RpcClient : kotlinx/coroutines/CoroutineScope { +public abstract interface class kotlinx/rpc/RpcClient { 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 { -} - -public abstract interface class kotlinx/rpc/RpcServer : kotlinx/coroutines/CoroutineScope { - public abstract fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V -} - -public final class kotlinx/rpc/UninitializedRpcFieldException : java/lang/Exception { - public fun (Ljava/lang/String;Lkotlin/reflect/KProperty;)V - public fun getMessage ()Ljava/lang/String; +public abstract interface class kotlinx/rpc/RpcServer { + public abstract fun deregisterService (Lkotlin/reflect/KClass;)V + public abstract fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function0;)V } public final class kotlinx/rpc/WithServiceKt { @@ -76,10 +52,6 @@ public final class kotlinx/rpc/descriptor/RpcCallable { public abstract interface class kotlinx/rpc/descriptor/RpcInvokator { } -public abstract interface class kotlinx/rpc/descriptor/RpcInvokator$Field : kotlinx/rpc/descriptor/RpcInvokator { - public abstract fun call (Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class kotlinx/rpc/descriptor/RpcInvokator$Method : kotlinx/rpc/descriptor/RpcInvokator { public abstract fun call (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt index 71f3ceaea..ccb3512ad 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt @@ -4,15 +4,12 @@ package kotlinx.rpc -import kotlinx.coroutines.CoroutineScope import kotlinx.rpc.annotations.Rpc /** * Marker interface for an RPC service. - * Provides type safety and [CoroutineScope] for [Rpc] annotated services. - * - * Every [RemoteService] service MUST be annotated with [Rpc] annotation. * * @see Rpc */ -public interface RemoteService : CoroutineScope +@Deprecated("Use of RemoteService is deprecated. Use only @Rpc annotation", level = DeprecationLevel.ERROR) +public interface RemoteService diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RpcCall.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RpcCall.kt index 6c123fd34..b7cc9a488 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RpcCall.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RpcCall.kt @@ -6,16 +6,13 @@ package kotlinx.rpc import kotlinx.rpc.descriptor.RpcServiceDescriptor -@Deprecated("Use RpcCall instead", ReplaceWith("RpcCall"), level = DeprecationLevel.ERROR) -public typealias RPCCall = RpcCall - /** - * Represents a method or field call of an RPC service. + * Represents a method call from an RPC service. * * @property descriptor [RpcServiceDescriptor] of a service that made the call. - * @property callableName The name of the callable. Can be the name of the method or field. + * @property callableName The name of the method being called. * @property data The data for the call. - * @property serviceId id of the service, that made the call. + * @property serviceId The id of the service that made the call. */ public data class RpcCall( val descriptor: RpcServiceDescriptor<*>, diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt index e1630a573..034101f73 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RpcClient.kt @@ -4,45 +4,23 @@ 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) -public typealias RPCClient = RpcClient /** * [RpcClient] represents an abstraction of an RPC client, that can handle requests from several RPC services, * transform them, send to the server and handle responses and errors. - * [CoroutineScope] defines the lifetime of the client. */ -public interface RpcClient : CoroutineScope { +public interface RpcClient { /** * This method is used by generated clients to perform a call to the server. * * @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 actual result of the call, for example, data from the server. + * @return result of the call, for example, data from the server. */ public suspend fun call(call: RpcCall): T - /** - * This method is used by generated clients to perform a call to the server. - * - * @param T type of the result - * @param serviceScope service's coroutine scope - * @param call an object that contains all required information about the called method, - * 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. @@ -50,18 +28,7 @@ public interface RpcClient : CoroutineScope { * @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. - * - * This function shouldn't be called directly. - * - * @param serviceId id of the new service. Used for service cancellation messages. + * @return result of the call, for example, data from the server */ - public fun provideStubContext(serviceId: Long): CoroutineContext + public fun callServerStreaming(call: RpcCall): Flow } diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RpcEagerField.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RpcEagerField.kt deleted file mode 100644 index 9f68337c7..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RpcEagerField.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 - -/** - * The field marked with this annotation will be initialized with the service creation. - */ -@Target(AnnotationTarget.PROPERTY) -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public annotation class RpcEagerField - -@Deprecated("Use RpcEagerField instead", ReplaceWith("RpcEagerField"), level = DeprecationLevel.ERROR) -public typealias RPCEagerField = RpcEagerField diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RpcServer.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RpcServer.kt index 887a5b29e..06b59f467 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RpcServer.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RpcServer.kt @@ -4,33 +4,43 @@ package kotlinx.rpc -import kotlinx.coroutines.CoroutineScope import kotlinx.rpc.annotations.Rpc -import kotlin.coroutines.CoroutineContext import kotlin.reflect.KClass -@Deprecated("Use RpcServer instead", ReplaceWith("RpcServer"), level = DeprecationLevel.ERROR) -public typealias RPCServer = RpcServer - /** * RpcServer is used to accept RPC messages, route them to a specific service, and process given responses. * Server may contain multiple services. - * [CoroutineScope] defines server lifetime. */ -public interface RpcServer : CoroutineScope { +public interface RpcServer { /** - * Registers new service to the server. Server will route all designated messages to it. + * Registers new service. Server will route all designated messages to it. * Service of any type should be unique on the server, but RpcServer doesn't specify the actual retention policy. * * @param Service the exact type of the server to be registered. - * For example, for service with `MyService` interface and `MyServiceImpl` implementation, - * type `MyService` should be specified explicitly. + * For example, for a service with `MyService` interface and `MyServiceImpl` implementation + * the type `MyService` should be specified explicitly. * @param serviceKClass [KClass] of the [Service]. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation */ public fun <@Rpc Service : Any> registerService( serviceKClass: KClass, - serviceFactory: (CoroutineContext) -> Service, + serviceFactory: () -> Service, + ) + + /** + * Deregisters a service. Server will stop routing messages to it. + * + * @param Service the exact type of the server to be deregistered, the same one that was used for registration. + * For example, for a service with `MyService` interface and `MyServiceImpl` implementation + * the type `MyService` should be specified explicitly. + * @param serviceKClass [KClass] of the [Service]. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation + */ + public fun <@Rpc Service : Any> deregisterService( + serviceKClass: KClass, ) } @@ -39,12 +49,14 @@ public interface RpcServer : CoroutineScope { * Service of any type should be unique on the server, but RpcServer doesn't specify the actual retention policy. * * @param Service the exact type of the server to be registered. - * For example, for service with `MyService` interface and `MyServiceImpl` implementation, - * type `MyService` should be specified explicitly. + * For example, for a service with `MyService` interface and `MyServiceImpl` implementation + * the type `MyService` should be specified explicitly. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation */ public inline fun <@Rpc reified Service : Any> RpcServer.registerService( - noinline serviceFactory: (CoroutineContext) -> Service, + noinline serviceFactory: () -> Service, ) { registerService(Service::class, serviceFactory) } diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRpcFieldException.kt b/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRpcFieldException.kt deleted file mode 100644 index 927c1cc48..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRpcFieldException.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 - -import kotlin.reflect.KProperty - -@Deprecated( - "Use UninitializedRpcFieldException instead", - ReplaceWith("UninitializedRpcFieldException"), - level = DeprecationLevel.ERROR, -) -public typealias UninitializedRPCFieldException = UninitializedRpcFieldException - -/** - * Thrown when an uninitialized field of an RPC service is accessed. - * - * Use [awaitFieldInitialization] to await for the field initialization - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public class UninitializedRpcFieldException(serviceName: String, property: KProperty<*>) : Exception() { - override val message: String = "${property.name} field of RPC service \"$serviceName\" in not initialized" -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/annotations/CheckedTypeAnnotation.kt b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/CheckedTypeAnnotation.kt index 3f461a6fd..0f29fa644 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/annotations/CheckedTypeAnnotation.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/CheckedTypeAnnotation.kt @@ -5,8 +5,11 @@ package kotlinx.rpc.annotations /** - * Marks an annotation as a one that marks - * a type argument as a one that requires its resolved type to be annotated this annotation. + * Meta annotation. + * Used to perform [annotation type-safety](https://kotlin.github.io/kotlinx-rpc/annotation-type-safety.html) checks. + * + * When an annotation class (for example, `@X`) is marked with `@CheckedTypeAnnotation` - + * Any other type can be marked with `@X` to perform safety checks on type parameters that are also marked with `@X`. * * Example: * ```kotlin diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt index d122b1852..3eda61e3e 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt @@ -4,39 +4,41 @@ package kotlinx.rpc.annotations -import kotlinx.rpc.RemoteService - /** * Every [Rpc] annotated interface will have a code generation process run on it, * making the interface effectively usable for RPC calls. * - * Every [Rpc] annotated interface MAY inherit from the [RemoteService] interface. - * If it is not done explicitly, the supertype will be added during the compilation process. - * In that case an IDE will highlight false-positive type mismatch errors, - * so it is recommended to add the [RemoteService] parent explicitly, until proper IDE support is provided. + * Example usage. * - * Example usage: + * Define an interface and mark it with `@Rpc`. + * Compiler plugin will ensure that all declarations inside the interface are valid. * ```kotlin - * // common code * @Rpc - * interface MyService : RemoteService { + * interface MyService { * suspend fun sayHello(firstName: String, lastName: String, age: Int): String * } - * // client code + * ``` + * On the client side use [kotlinx.rpc.RpcClient] to get a generated instance of the service, and use it to make calls: + * ```kotlin * val rpcClient: RpcClient * val myService = rpcClient.withService() * val greetingFromServer = myService.sayHello("Alex", "Smith", 35) - * // server code - * class MyServiceImpl(override val coroutineContext: CoroutineContext) : MyService { + * ``` + * On the server side, define an implementation of this interface and register it on an [kotlinx.rpc.RpcServer]: + * ```kotlin + * class MyServiceImpl : MyService { * override suspend fun sayHello(firstName: String, lastName: String, age: Int): String { * return "Hello, $firstName $lastName, of age $age. I am your server!" * } * } * val server: RpcServer - * server.registerService { ctx -> MyServiceImpl(ctx) } + * server.registerService { MyServiceImpl() } * ``` * - * @see [RemoteService] + * @see kotlinx.rpc.RpcClient + * @see kotlinx.rpc.RpcServer + * @see CheckedTypeAnnotation + * @see kotlinx.rpc.withService */ @CheckedTypeAnnotation @Target(AnnotationTarget.CLASS, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.TYPE_PARAMETER) diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt b/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt deleted file mode 100644 index 3a93aef0d..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 - -import kotlinx.rpc.annotations.Rpc -import kotlinx.rpc.descriptor.serviceDescriptorOf -import kotlinx.rpc.internal.RpcDeferredField -import kotlin.reflect.KClass - -/** - * Waits for the initialization of an RPC field in the generated client: - * - * ```kotlin - * @Rpc - * interface MyService : RemoteService { - * val stateFlow: StateFlow - * } - * - * val service = rpcClient.withService() - * val currentValue = service.awaitFieldInitialization { stateFlow }.value - * ``` - * - * @param T service type - * @param R field type - * @param getter function that returns the field of the context service to wait for. - * @return service filed after it was initialized. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public suspend fun <@Rpc T : Any, R> T.awaitFieldInitialization(getter: T.() -> R): R { - val field = getter() - - if (field is RpcDeferredField<*>) { - @Suppress("UNCHECKED_CAST") - return (field as RpcDeferredField).await() - } - - error("Please choose required field for a valid RPC client generated by RpcClient.withService method") -} - -/** - * Waits for the initialization of all RPC fields in the generated client: - * - * ```kotlin - * @Rpc - * interface MyService : RemoteService { - * val stateFlow1: StateFlow - * val stateFlow2: StateFlow - * } - * - * val service = rpcClient.withService() - * val currentValue = service.awaitFieldInitialization() - * // fields `stateFlow1` and `stateFlow2` are initialized - * ``` - * - * @param T service type - * @return specified service, after all of it's field were initialized. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public suspend inline fun <@Rpc reified T : Any> T.awaitFieldInitialization(): T { - return awaitFieldInitialization(T::class) -} - -/** - * Waits for the initialization of all RPC fields in the generated client: - * - * ```kotlin - * @Rpc - * interface MyService : RemoteService { - * val stateFlow1: StateFlow - * val stateFlow2: StateFlow - * } - * - * val service = rpcClient.withService() - * val currentValue = service.awaitFieldInitialization(MyService::class) - * // fields `stateFlow1` and `stateFlow2` are initialized - * ``` - * - * @param T service type - * @param kClass [KClass] of the [T] type. - * @return specified service, after all of it's field were initialized. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public suspend fun <@Rpc T : Any> T.awaitFieldInitialization(kClass: KClass): T { - serviceDescriptorOf(kClass) - .getFields(this) - .forEach { field -> - field.await() - } - - return this -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt b/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt index 3ace7facc..4873b9193 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/descriptor/RpcServiceDescriptor.kt @@ -8,7 +8,6 @@ import kotlinx.rpc.RpcClient import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.internal.* import kotlinx.rpc.internal.utils.ExperimentalRpcApi -import kotlinx.rpc.internal.utils.InternalRpcApi import kotlin.reflect.KClass import kotlin.reflect.KType @@ -43,13 +42,6 @@ public fun <@Rpc T : Any> serviceDescriptorOf(kClass: KClass): RpcServiceDesc public interface RpcServiceDescriptor<@Rpc T : Any> { public val fqName: String - @InternalRpcApi - @Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public fun getFields(service: T): List> - public fun getCallable(name: String): RpcCallable? public fun createInstance(serviceId: Long, client: RpcClient): T @@ -71,15 +63,6 @@ public sealed interface RpcInvokator<@Rpc T : Any> { public fun interface Method<@Rpc T : Any> : RpcInvokator { public suspend fun call(service: T, data: Any?): Any? } - - @ExperimentalRpcApi - @Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public fun interface Field<@Rpc T : Any> : RpcInvokator { - public fun call(service: T): Any? - } } @ExperimentalRpcApi diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/FieldDataObject.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/FieldDataObject.kt deleted file mode 100644 index 64007f9df..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/FieldDataObject.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlinx.serialization.Serializable - -/** - * Used for field initialization call - */ -@Serializable -@InternalRpcApi -public object FieldDataObject diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcDeferredField.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcDeferredField.kt deleted file mode 100644 index ff1651336..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcDeferredField.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.rpc.internal.utils.InternalRpcApi - -@InternalRpcApi -public interface RpcDeferredField { - public suspend fun await(): Self -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFieldProvider.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFieldProvider.kt deleted file mode 100644 index 2b58f865b..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFieldProvider.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.rpc.UninitializedRpcFieldException -import kotlin.reflect.KProperty - -internal class RpcFieldProvider( - private val serviceName: String, - private val deferred: Deferred = CompletableDeferred(), - val getter: T.() -> R, -) { - @OptIn(ExperimentalCoroutinesApi::class) - operator fun getValue(ref: Any?, property: KProperty<*>): R { - if (deferred.isCompleted) { - return deferred.getCompleted().getter() - } - - throw UninitializedRpcFieldException(serviceName, property) - } -} - -@Suppress("unused") -internal fun RpcFieldProvider( - serviceName: String, - deferred: CompletableDeferred = CompletableDeferred() -): RpcFieldProvider { - return RpcFieldProvider(serviceName, deferred) { this } -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFlow.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFlow.kt deleted file mode 100644 index a074d0226..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RpcFlow.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow - -internal sealed class RpcFlow>( - private val serviceName: String, - protected val deferred: Deferred, -) : RpcDeferredField { - override suspend fun await(): FlowT { - return deferred.await() - } - - internal class Plain( - serviceName: String, - deferred: Deferred>, - ) : RpcFlow>(serviceName, deferred), Flow { - override suspend fun collect(collector: FlowCollector) { - deferred.await().collect(collector) - } - } - - internal class Shared( - serviceName: String, - deferred: Deferred>, - ) : RpcFlow>(serviceName, deferred), SharedFlow { - override val replayCache: List by rpcProperty { replayCache } - - override suspend fun collect(collector: FlowCollector): Nothing { - deferred.await().collect(collector) - } - } - - internal class State( - serviceName: String, - deferred: Deferred>, - ) : RpcFlow>(serviceName, deferred), StateFlow { - override val value: T by rpcProperty { value } - - override val replayCache: List by rpcProperty { replayCache } - - override suspend fun collect(collector: FlowCollector): Nothing { - deferred.await().collect(collector) - } - } - - protected fun rpcProperty(getter: FlowT.() -> R): RpcFieldProvider { - return RpcFieldProvider(serviceName, deferred, getter) - } -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/ServiceScope.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/ServiceScope.kt deleted file mode 100644 index 3c496a663..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/ServiceScope.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.currentCoroutineContext -import kotlinx.coroutines.withContext -import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.coroutines.CoroutineContext - -@InternalRpcApi -public class ServiceScope(public val serviceCoroutineScope: CoroutineScope) : CoroutineContext.Element { - internal companion object Key : CoroutineContext.Key - - override val key: CoroutineContext.Key<*> = Key -} - -@InternalRpcApi -public suspend fun createServiceScope(serviceCoroutineScope: CoroutineScope): ServiceScope { - val context = currentCoroutineContext() - - if (context[ServiceScope.Key] != null) { - error("serviceScoped nesting is not allowed") - } - - return ServiceScope(serviceCoroutineScope) -} - -@InternalRpcApi -public suspend fun serviceScopeOrNull(): ServiceScope? { - return currentCoroutineContext()[ServiceScope.Key] -} - -@InternalRpcApi -@OptIn(ExperimentalContracts::class) -public suspend inline fun serviceScoped( - serviceCoroutineScope: CoroutineScope, - noinline block: suspend CoroutineScope.() -> T, -): T { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - - return withContext(createServiceScope(serviceCoroutineScope), block) -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/scopedClientCall.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/scopedClientCall.kt deleted file mode 100644 index 8a47691e1..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/scopedClientCall.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.internal - -import kotlinx.coroutines.CoroutineScope -import kotlinx.rpc.internal.utils.InternalRpcApi - -/** - * Scopes client RPC call from a service with [serviceScope]. - * - * Used by code generators. - */ -@InternalRpcApi -@Suppress("unused") -public suspend inline fun scopedClientCall(serviceScope: CoroutineScope, crossinline body: suspend () -> T): T { - return serviceScoped(serviceScope) { - body() - } -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/registerField.kt b/core/src/commonMain/kotlin/kotlinx/rpc/registerField.kt deleted file mode 100644 index 74f5b3987..000000000 --- a/core/src/commonMain/kotlin/kotlinx/rpc/registerField.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.rpc.descriptor.RpcServiceDescriptor -import kotlinx.rpc.internal.FieldDataObject -import kotlinx.rpc.internal.RpcFlow - -/** - * Registers Flow field of the interface. Sends initialization request, subscribes to emitted values - * and returns the instance of the flow to be consumed - * - * @param T type parameter for Flow - * @param serviceScope Service's coroutine scope - * @param descriptor descriptor of the service, that made the call - * that is used to be mapped to the corresponding field on a server. - * @param fieldName the name of the field. - * @param serviceId id of the service, that made the call - * @return Flow instance to be consumed. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public fun RpcClient.registerPlainFlowField( - serviceScope: CoroutineScope, - descriptor: RpcServiceDescriptor<*>, - fieldName: String, - serviceId: Long, -): Flow { - return RpcFlow.Plain(descriptor.fqName, initializeFlowField(serviceScope, descriptor, fieldName, serviceId)) -} - -/** - * Registers SharedFlow field of the interface. Sends initialization request, subscribes to emitted values - * and returns the instance of the flow to be consumed - * - * @param T type parameter for SharedFlow - * @param serviceScope Service's coroutine scope - * @param descriptor descriptor of the service, that made the call - * that is used to be mapped to the corresponding field on a server. - * @param fieldName the name of the field. - * @param serviceId id of the service, that made the call - * @return SharedFlow instance to be consumed. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public fun RpcClient.registerSharedFlowField( - serviceScope: CoroutineScope, - descriptor: RpcServiceDescriptor<*>, - fieldName: String, - serviceId: Long, -): SharedFlow { - return RpcFlow.Shared(descriptor.fqName, initializeFlowField(serviceScope, descriptor, fieldName, serviceId)) -} - -/** - * Registers StateFlow field of the interface. Sends initialization request, subscribes to emitted values - * and returns the instance of the flow to be consumed - * - * @param T type parameter for StateFlow - * @param serviceScope Service's coroutine scope - * @param descriptor descriptor of the service, that made the call - * that is used to be mapped to the corresponding field on a server. - * @param fieldName the name of the field. - * @param serviceId id of the service, that made the call - * @return StateFlow instance to be consumed. - */ -@Deprecated( - "Fields are deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, -) -public fun RpcClient.registerStateFlowField( - serviceScope: CoroutineScope, - descriptor: RpcServiceDescriptor<*>, - fieldName: String, - serviceId: Long, -): StateFlow { - return RpcFlow.State(descriptor.fqName, initializeFlowField(serviceScope, descriptor, fieldName, serviceId)) -} - -private fun > RpcClient.initializeFlowField( - serviceScope: CoroutineScope, - descriptor: RpcServiceDescriptor<*>, - fieldName: String, - serviceId: Long, -): Deferred { - return callAsync(serviceScope, RpcCall(descriptor, fieldName, FieldDataObject, serviceId)) -} diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt b/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt index 73df9f149..3aab53a8b 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt @@ -12,25 +12,25 @@ import kotlin.reflect.KClass import kotlin.reflect.KType /** - * Creates instance of the generated service [T], that is able to communicate with server using [RpcClient]. - * - * [awaitFieldInitialization] method can be used on that instance. + * Creates an instance of the generated service [T], that is able to communicate with a server using this [RpcClient]. * * @param T the exact type of the service to be created. * @return instance of the generated service. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation */ public inline fun <@Rpc reified T : Any> RpcClient.withService(): T { return withService(T::class) } /** - * Creates instance of the generated service [T], that is able to communicate with server using [RpcClient]. - * - * [awaitFieldInitialization] method can be used on that instance. + * Creates an instance of the generated service [T], that is able to communicate with a server using this [RpcClient]. * * @param T the exact type of the service to be created. * @param serviceKType [KType] of the service to be created. * @return instance of the generated service. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation */ public fun <@Rpc T : Any> RpcClient.withService(serviceKType: KType): T { return withService(serviceKType.rpcInternalKClass()) @@ -43,13 +43,13 @@ public fun <@Rpc T : Any> RpcClient.withService(serviceKType: KType): T { private val SERVICE_ID = atomic(0L) /** - * Creates instance of the generated service [T], that is able to communicate with server using [RpcClient]. - * - * [awaitFieldInitialization] method can be used on that instance. + * Creates an instance of the generated service [T], that is able to communicate with a server using this [RpcClient]. * * @param T the exact type of the service to be created. * @param serviceKClass [KClass] of the service to be created. * @return instance of the generated service. + * + * @see kotlinx.rpc.annotations.CheckedTypeAnnotation */ public fun <@Rpc T : Any> RpcClient.withService(serviceKClass: KClass): T { val descriptor = serviceDescriptorOf(serviceKClass) diff --git a/docs/pages/kotlinx-rpc/rpc.tree b/docs/pages/kotlinx-rpc/rpc.tree index aaf3fa079..979360ba4 100644 --- a/docs/pages/kotlinx-rpc/rpc.tree +++ b/docs/pages/kotlinx-rpc/rpc.tree @@ -24,7 +24,11 @@ - + + + + + @@ -36,6 +40,7 @@ + diff --git a/docs/pages/kotlinx-rpc/topics/0-8-0.topic b/docs/pages/kotlinx-rpc/topics/0-8-0.topic new file mode 100644 index 000000000..b61dfafd9 --- /dev/null +++ b/docs/pages/kotlinx-rpc/topics/0-8-0.topic @@ -0,0 +1,363 @@ + + + + + + +

+ Version 0.8.0 brings a lot of changes, + mainly targeted to remove inherently broken functionality and simplify kRPC protocol where possible. + This is reflected in the number of breaking changes and deprecations. +

+

+ This page aims to cover all such changes and associated migration instructions. +

+ + +

+ Strict mode is now enforced and can't be disabled. + See for detailed migrations. +

+
+ + +

+ The following changes are reflected in the kRPC protocol on the wire: +

+ +
  • + KrpcServer doesn't send CANCELLATION_ACK messages anymore. +
  • +
  • + KrpcClient sends REQUEST cancellation messages for every individually finished call, + canceled or finished successfully +
  • +
    +

    + Though changes should not affect most users, + for those who like to look at the wire it might be useful to know. +

    +
    + + +

    + Some changes in the behavior of kRPC clients and servers: +

    + +
  • +

    + Lifetime for client-side streams is changed. +

    +

    + Previously, the stream scopes bounded client-side streams. + However, stream scopes are completely removed now, + so the client-side streams lifetime is now bound to the request's lifetime. + This means that when the function returns, every client stream is closed. +

    +
  • +
  • +

    + Serial format is now only constructed once per client. +

    +

    + Previously, the serial format was constructed once per RPC call. + The serial format can be passed using the KrpcConfig. + And the builder code was executed once per every call. +

    +

    + Now this behavior is removed. + The serial format is constructed once per client. +

    +
  • +
  • +

    + Services are now instantiated once per service type (Rpc FQ name) + and not once per client-side instance. +

    +

    + Services lost their CoroutineScopes (see ). + That means that there are no individual lifetimes for each service instance now. + Instead, now each service stub on a client is merely a proxy for function calls. + And on the server side, the service implementation is instantiated once per service type. + To control this behavior more granularly on the server, new deregisterService + function is introduced. +

    + + For kRPC servers, the factory function for service instances is now executed once per service type: + + rpcServer.registerService<MyService> { MyServiceImpl() } + + +
  • +
  • +

    + Handshake is now cold. +

    +

    + Previously, the handshake was executed on client creation. + Now, the handshake is executed on the first RPC request. +

    +
  • + + + + + +
  • +

    + RpcClient.callServerStreaming lost its default implementation: +

    + + + + interface RpcClient { + fun <T> callServerStreaming(call: RpcCall): Flow<T> { + error("Not implemented") + } + } + + + interface RpcClient { + fun <T> callServerStreaming(call: RpcCall): Flow<T> + } + + +
  • +
  • +

    + @Rpc services lost their CoroutineScope: +

    + + + val service = client.withService<MyService>() + assert(service is CoroutineScope) // OK + + + val service = client.withService<MyService>() + assert(service is CoroutineScope) // fail + + +
  • +
  • +

    + RpcClient lost its CoroutineScope: +

    + + + interface RpcClient : CoroutineScope + + + interface RpcClient + + +
  • +
  • +

    + RpcServer lost its CoroutineScope: +

    + + + interface RpcServer : CoroutineScope + + + interface RpcServer + + +
  • +
  • +

    + RpcServer.registerService factory parameter changes type + from (CoroutineContext) -> Service to () -> Service: +

    + + + interface RpcServer { + fun <@Rpc Service : Any> registerService( + serviceKClass: KClass<Service>, + serviceFactory: (CoroutineContext) -> Service, + ) + } + + inline fun <@Rpc reified Service : Any> RpcServer.registerService( + noinline serviceFactory: (CoroutineContext) -> Service, + ) { + registerService(Service::class, serviceFactory) + } + + + interface RpcServer { + fun <@Rpc Service : Any> registerService( + serviceKClass: KClass<Service>, + serviceFactory: () -> Service, + ) + } + + inline fun <@Rpc reified Service : Any> RpcServer.registerService( + noinline serviceFactory: () -> Service, + ) { + registerService(Service::class, serviceFactory) + } + + +
  • +
  • +

    + RpcServer.registerService lost its CoroutineContext parameter: +

    + + + interface RpcServer + + + interface RpcServer { + fun <@Rpc Service : Any> deregisterService( + serviceKClass: KClass<Service>, + ) + } + + +
  • +
  • +

    + For Ktor, HttpClient.rpc extension function is now non-suspendable. +

    +
  • +
  • + KtorRpcClient.webSocketSession is now wrapped in Deferred: + + + interface KtorRpcClient : RpcClient { + val webSocketSession: WebSocketSession + } + + + interface KtorRpcClient : RpcClient { + val webSocketSession: Deferred<WebSocketSession> + } + + +
  • +
  • +

    + KrpcClient abstract class has two new abstract methods: + initializeConfig and initializeTransport. + They can be used to delay transport initialization until the first RPC call. +

    +

    + To mimic old behavior, InitializedKrpcClient can be used: +

    + + + class MyClient( + config: KrpcConfig, + transport: KrpcTransport, + ) : KrpcClient(config, transport) + + + class MyClient( + config: KrpcConfig, + transport: KrpcTransport, + ) : InitializedKrpcClient(config, transport) + + +
  • +
    +
    + + +

    + The following APIs are removed: +

    + +
  • kotlinx.rpc.RpcClient.callAsync - previously deprecated
  • +
  • kotlinx.rpc.RpcClient.provideStubContext
  • + +
  • kotlinx.rpc.registerPlainFlowField - previously deprecated
  • +
  • kotlinx.rpc.registerSharedFlowField - previously deprecated
  • +
  • kotlinx.rpc.registerStateFlowField - previously deprecated
  • +
  • kotlinx.rpc.awaitFieldInitialization - previously deprecated
  • +
  • kotlinx.rpc.UninitializedRpcFieldException - previously deprecated
  • +
  • kotlinx.rpc.UninitializedRPCFieldException - previously deprecated
  • +
  • kotlinx.rpc.RpcEagerField - previously deprecated
  • +
  • kotlinx.rpc.RPCCall - previously deprecated alias
  • +
  • kotlinx.rpc.RPCClient - previously deprecated alias
  • + +
  • kotlinx.rpc.descriptor.RpcInvokator.Field - previously deprecated
  • +
  • kotlinx.rpc.descriptor.RpcServiceDescriptor.getFields - previously deprecated
  • + +
  • kotlinx.rpc.krpc.StreamScope - previously deprecated
  • +
  • kotlinx.rpc.krpc.streamScoped - previously deprecated
  • +
  • kotlinx.rpc.krpc.withStreamScope - previously deprecated
  • +
  • kotlinx.rpc.krpc.invokeOnStreamScopeCompletion - previously deprecated
  • +
  • kotlinx.rpc.krpc.KrpcConfigBuilder.SharedFlowParametersBuilder - previously deprecated
  • +
  • kotlinx.rpc.krpc.KrpcConfigBuilder.sharedFlowParameters - previously deprecated
  • +
  • kotlinx.rpc.krpc.KrpcConfig.sharedFlowBuilder - previously deprecated
  • +
  • kotlinx.rpc.krpc.RPCTransport - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.RPCTransportMessage - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.RPCConfigBuilder - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.client.KRPCClient - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.server.RPCServer - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.server.KRPCServer - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.serialization.RPCSerialFormat - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.serialization.RPCSerialFormatBuilder - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.serialization.RPCSerialFormatConfiguration - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.ktor.client.RPC - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.ktor.client.installRPC - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.ktor.server.RPC - previously deprecated alias
  • +
  • kotlinx.rpc.krpc.ktor.server.RPCRoute - previously deprecated alias
  • +
    +
    + + + +
  • +

    + Gradle's rpc.strict extension is deprecated with an error. + Strict mode is now enforced and can't be disabled. + See for detailed migrations. +

    +
  • +
  • +

    + RemoteService is deprecated with error; + services are no longer having this interface added during the compilation. + See for services' lifetime information. +

    +
  • + + + + + +
  • +

    + MISSING_RPC_ANNOTATION compiler inspection is removed. +

    +
  • +
  • +

    + ABI incompatible change: KrpcTransport.receiveCatching is now an extension function. +

    +
  • +
  • +

    + The following compiler plugin options are removed: +

    + +
  • strict-stateFlow
  • +
  • strict-sharedFlow
  • +
  • strict-nested-flow
  • +
  • strict-stream-scope
  • +
  • strict-suspending-server-streaming
  • +
  • strict-not-top-level-server-flow
  • +
  • strict-fields
  • +
    + + +
    +
    diff --git a/docs/pages/kotlinx-rpc/topics/annotation-type-safety.topic b/docs/pages/kotlinx-rpc/topics/annotation-type-safety.topic index 135146a7b..be8df1ed2 100644 --- a/docs/pages/kotlinx-rpc/topics/annotation-type-safety.topic +++ b/docs/pages/kotlinx-rpc/topics/annotation-type-safety.topic @@ -29,7 +29,7 @@

    @Rpc - interface MyService : RemoteService + interface MyService class MyServiceImpl : MyService @@ -50,12 +50,31 @@ // T is resolved to MyService, // but 'body' returns MyServiceImpl - registerService<MyService> { ctx -> MyServiceImpl(ctx) } + registerService<MyService> { MyServiceImpl() } // Error: T is resolved to MyServiceImpl - registerService { ctx -> MyServiceImpl(ctx) } + registerService { MyServiceImpl() } +

    + Annotation type-safety can be enforced recursively: +

    + + @Rpc + annotation class Grpc + + @Grpc + interface MyGrpcService + + fun <@Rpc T> acceptAnyRpcType() + fun <@Grpc T> acceptOnlyGrpcType() + + acceptAnyRpcType<MyService>() // OK + acceptAnyRpcType<MyGrpcService>() // OK + + acceptOnlyGrpcType<MyService>() // Compiler time error + acceptOnlyGrpcType<MyGrpcService>() // OK + This feature is highly experimental and may lead to unexpected behaviour. If you encounter any issues, diff --git a/docs/pages/kotlinx-rpc/topics/configuration.topic b/docs/pages/kotlinx-rpc/topics/configuration.topic index 0b382bd18..18f195cb9 100644 --- a/docs/pages/kotlinx-rpc/topics/configuration.topic +++ b/docs/pages/kotlinx-rpc/topics/configuration.topic @@ -8,97 +8,78 @@ -

    KrpcConfig is a class used to configure KrpcClient and KrpcServer - (not to be confused with KrpcClient and KrpcServer). - It has two children: KrpcConfig.Client and KrpcConfig.Server. - Client and Server may have shared properties as well as distinct ones. - To create instances of these configurations, DSL builders are provided - (KrpcConfigBuilder.Client class with rpcClientConfig function - and KrpcConfigBuilder.Server class with rpcServerConfig function respectively): +

    + KrpcConfig is a class used to configure KrpcClient and KrpcServer + (not to be confused with RpcClient and RpcServer). +

    +

    + It has two children: KrpcConfig.Client and KrpcConfig.Server. + Client and Server may have shared properties as well as distinct ones. + To create instances of these configurations, DSL builders are provided: +

    + +
  • + rpcClientConfig +
  • +
  • + rpcServerConfig +
  • +
    + + + val config: KrpcConfig.Client = rpcClientConfig { // same for KrpcConfig.Server with rpcServerConfig + waitForServices = true // default parameter + } + +

    + The following configuration options are available: +

    + + + <code>serialization</code> DSL + +

    + This parameter defines how serialization should work in RPC services + and is present in both client and server configurations. +

    +

    + The serialization process is used to encode and decode data in RPC requests, + so that the data can be transferred through the network. +

    +

    + Currently only StringFormat and BinaryFormat from + kotlinx.serialization are supported, + and by default you can choose from Json, Protobuf or Cbor formats:

    - val config: KrpcConfig.Client = rpcClientConfig { // same for KrpcConfig.Server with rpcServerConfig - waitForServices = true // default parameter + rpcClientConfig { + serialization { + json { /* this: JsonBuilder from kotlinx.serialization */ } + cbor { /* this: CborBuilder from kotlinx.serialization */ } + protobuf { /* this: ProtobufBuilder from kotlinx.serialization */ } + } } -

    The following configuration options are available:

    - - - <code>serialization</code> DSL - -

    This parameter defines how serialization should work in RPC services - and is present in both client and server configurations.

    -

    The serialization process is used to encode and decode data in RPC requests, - so that the data can be transferred through the network.

    -

    Currently only StringFormat and BinaryFormat from - kotlinx.serialization are supported, - and by default you can choose from Json, Protobuf or Cbor formats:

    - - - rpcClientConfig { - serialization { - json { /* this: JsonBuilder from kotlinx.serialization */ } - cbor { /* this: CborBuilder from kotlinx.serialization */ } - protobuf { /* this: ProtobufBuilder from kotlinx.serialization */ } - } - } - -

    Only last defined format will be used to serialize requests. - If no format is specified, the error will be thrown. - You can also define a custom format.

    -
    - - - <code>sharedFlowParameters</code> DSL - - - - These parameters are deprecated since 0.5.0. For more information, - see the migration guide. - - - - rpcClientConfig { - sharedFlowParameters { - replay = 1 // default parameter - extraBufferCapacity = 10 // default parameter - onBufferOverflow = BufferOverflow.SUSPEND // default parameter - } - } - -

    This parameter is needed to decode SharedFlow parameters received from a peer. - MutableSharedFlow, the default function to create a SharedFlow instance, - has the following signature:

    - - - fun <T> MutableSharedFlow( - replay: Int = 0, - extraBufferCapacity: Int = 0, - onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND - ): MutableSharedFlow<T> { /* ... */ - } - -

    It creates a SharedFlowImpl class that contains these parameters as properties, - but this class in internal in kotlinx.coroutines and neither SharedFlow, - nor MutableShatedFlow interfaces define these properties, - which makes it impossible (at least for now) to send these properties from one endpoint to another. - But instances of these flows when deserialized should be created somehow, - so to overcome this - configuration parameter is created. - Configuration builder allows defining these parameters - and produces a builder function that is then placed into the KrpcConfig.

    -
    - - - <code>waitForServices</code> DSL - -

    waitForServices parameter is available for both client and server. - It specifies the behavior for an endpoint in situations - when the message for a service is received, - but the service is not present in KrpcClient or KrpcServer. - If set to true, the message will be stored in memory, - otherwise, the error will be sent to a peer endpoint, - saying that the message was not handled. - Default value is true.

    -
    +

    + Only last defined format will be used to serialize requests. + If no format is specified, a runtime error will be thrown. + You can also define a custom format. +

    + + + + <code>waitForServices</code> DSL + +

    + waitForServices parameter is available for both client and server. + It specifies the behavior for an endpoint in situations + when the message for a service is received, + but the service is not present in KrpcClient or KrpcServer. + If set to true, the message will be stored in memory, + otherwise, the error will be sent to a peer endpoint, + saying that the message was not handled. + Default value is true. +

    +
    diff --git a/docs/pages/kotlinx-rpc/topics/features.topic b/docs/pages/kotlinx-rpc/topics/features.topic index 8a11a73f9..c0b0c29d3 100644 --- a/docs/pages/kotlinx-rpc/topics/features.topic +++ b/docs/pages/kotlinx-rpc/topics/features.topic @@ -24,7 +24,7 @@ ) @Rpc - interface MyService : RemoteService { + interface MyService { fun sendStream(stream: Flow<Int>): Flow<String> suspend fun streamRequest(request: StreamRequest) @@ -44,7 +44,7 @@ ) @Rpc - interface MyService : RemoteService { + interface MyService { fun serverStream(): Flow<String> // ok suspend fun serverStream(): Flow<String> // not ok suspend fun serverStream(): StreamResult // not ok @@ -52,7 +52,7 @@ - Note that flows that are declared in classes (like in StreamResult) require a + Note that flows that are declared in classes (like in StreamRequest) require a Contextual annotation. diff --git a/docs/pages/kotlinx-rpc/topics/krpc-client.topic b/docs/pages/kotlinx-rpc/topics/krpc-client.topic new file mode 100644 index 000000000..ee70d0493 --- /dev/null +++ b/docs/pages/kotlinx-rpc/topics/krpc-client.topic @@ -0,0 +1,75 @@ + + + + + + + +

    + KrpcClient is an abstract class that implements RpcClient and kRPC protocol + logic. +

    + +

    + The client comes in two forms: +

    + +
  • + KrpcClient +
  • +
  • + InitializedKrpcClient +
  • +
    +

    + The only difference between them is that KrpcClient allows to delay the initialization + of the transport until the first RPC request is sent. + InitializedKrpcClient is initialized right away with a ready KrpcTransport + instance. +

    +
    + +

    + The only thing required to be implemented is the transporting of the raw data. + Abstract transport is represented by KrpcTransport interface. +

    +

    + To implement your own KrpcTransport + you need to be able to transfer strings and/or raw bytes (Kotlin's ByteArray). + Additionally, the library will provide you with integrations with different + libraries that are used to work with the network. +

    + +

    + See below an example usage of kRPC with a custom transport: +

    + + + class MySimpleRpcTransport : KrpcTransport { + val outChannel = Channel<KrpcTransportMessage>() + val inChannel = Channel<KrpcTransportMessage>() + + override val coroutineContext: CoroutineContext = Job() + + override suspend fun send(message: KrpcTransportMessage) { + outChannel.send(message) + } + + override suspend fun receive(): KrpcTransportMessage { + return inChannel.receive() + } + } + + class MySimpleRpcClient : KrpcClient(rpcClientConfig(), MySimpleRpcTransport()) + + val client = MySimpleRpcClient() + val service: MyService = client.withService<MyService>() + +
    +
    +
    diff --git a/docs/pages/kotlinx-rpc/topics/krpc-ktor.topic b/docs/pages/kotlinx-rpc/topics/krpc-ktor.topic new file mode 100644 index 000000000..d747c4056 --- /dev/null +++ b/docs/pages/kotlinx-rpc/topics/krpc-ktor.topic @@ -0,0 +1,151 @@ + + + + + + +

    + The kotlinx.rpc library provides integration with the Ktor + framework. + This includes both server and client APIs. + Under the hood, the library uses WebSocket plugin + to create a KrpcTransport and send and receive messages through it. +

    + +

    + kotlinx.rpc provides a way to plug-in into existing Ktor clients with your RPC services. + To do that, the following DSL can be used: +

    + + + val ktorClient = HttpClient { + installKrpc { + waitForServices = true + } + } + + val rpcClient: KtorKrpcClient = + ktorClient.rpc("ws://localhost:4242/services") { + rpcConfig { + waitForServices = false + } + } + + // get an RPC service + val myService: MyService = rpcClient.withService<MyService>() + + + Note that in this example, only the latter defined KrpcConfig will be used. + +
    + +

    + kotlinx.rpc provides a way to plug-in into existing server routing with your RPC + services. + To do that, the following DSL can be used: +

    + + + fun Application.module() { + install(Krpc) { + waitForServices = true + } + + routing { + rpc("/services") { + rpcConfig { + waitForServices = false + } + + registerService<MyService> { MyServiceImpl() } + registerService<MyOtherService> { MyOtherServiceImpl() } + // more services if needed + } + } + } + +
    + +

    + An example code for a Ktor web application may look like this: +

    + +

    + In common code, shared classes and services are defined: +

    + + @Serializable + data class ProcessedImage( + val url: String, + val numberOfCats: Int, + val numberOfDogs: Int + ) + + @Rpc + interface ImageService : RemoteService { + suspend fun processImage(url: String): ProcessedImage + } + +

    + In client code, create an HTTP client and access the service on a the desired route: +

    + + val client = HttpClient { + installKrpc { + serialization { + json() + } + } + } + + val service = client + .rpc("/image-recognizer") + .withService<ImageService>() + + service.processImage(url = "https://catsanddogs.com/cats/1") + +

    + In server code, provide an implementation of the ImageService and register it on a route: +

    + + class ImageServiceImpl : ImageService { + // some user defined classes + private val downloader = Downloader() + private val recognizer = AnimalRecognizer() + + override suspend fun processImage(url: Srting): ProcessedImage { + val image = downloader.loadImage(url) + return ProcessedImage( + url, + recognizer.getNumberOfCatsOnImage(image), + recognizer.getNumberOfDogsOnImage(image) + ) + } + } + + fun main() { + embeddedServer(Netty, port = 8080) { + install(Krpc) { + serialization { + json() + } + } + + routing { + rpc("/image-recognizer") { + registerService<ImageService> { ImageServiceImpl() } + } + } + }.start(wait = true) + } + +

    + For more details and complete examples, see the code samples. +

    +
    +
    diff --git a/docs/pages/kotlinx-rpc/topics/krpc-server.topic b/docs/pages/kotlinx-rpc/topics/krpc-server.topic new file mode 100644 index 000000000..d7da1d6f8 --- /dev/null +++ b/docs/pages/kotlinx-rpc/topics/krpc-server.topic @@ -0,0 +1,43 @@ + + + + + + + +

    + KrpcServer abstract class implements RpcServer + and all the logic for processing RPC messages + and again leaves KrpcTransport methods for the specific implementations + (see transports). +

    + +

    + Example usage with custom transport: +

    + + + // same MySimpleRpcTransport as in the client example above + class MySimpleRpcServer : KrpcServer(rpcServerConfig(), MySimpleRpcTransport()) + + val server = MySimpleRpcServer() + server.registerService<MyService> { MyServiceImpl() } + + +

    + Note that here we pass explicit MyService type parameter to the registerService + method. + You must explicitly specify the type of the service interface here, + otherwise the server service will not be found. +

    +

    + See for more details. +

    +
    +
    +
    diff --git a/docs/pages/kotlinx-rpc/topics/plugins.topic b/docs/pages/kotlinx-rpc/topics/plugins.topic index 67f4fe05d..c85326af0 100644 --- a/docs/pages/kotlinx-rpc/topics/plugins.topic +++ b/docs/pages/kotlinx-rpc/topics/plugins.topic @@ -9,22 +9,32 @@ xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/topic.v2.xsd" title="Gradle plugin" id="plugins">

    - The kotlinx.rpc library offers a Gradle plugin - that simplifies project configuration by automating repetitive tasks: `org.jetbrains.kotlinx.rpc.plugin` + The kotlinx.rpc library offers a Gradle + plugin + that simplifies project configuration by automating repetitive tasks and configuring code generation.

    - -

    - The org.jetbrains.kotlinx.rpc.plugin plugin sets up code generation configurations. -

    - - plugins { - kotlin("jvm") version "%kotlin-version%" - id("org.jetbrains.kotlinx.rpc.plugin") version "%kotlinx-rpc-version%" - } - -

    - For multi-project setups you must add the plugin to all modules where services are declared or used. -

    -
    + + plugins { + kotlin("jvm") version "%kotlin-version%" + id("org.jetbrains.kotlinx.rpc.plugin") version "%kotlinx-rpc-version%" + } + + + For multi-project setups you must add the plugin to all modules where services are declared or used. + + + Plugin provides an rpc extension: + + rpc { + annotationTypeSafetyEnabled = true + } + +

    Options:

    + +
  • + annotationTypeSafetyEnabled - whether to enable type safety checks for annotations. + See . +
  • +
    diff --git a/docs/pages/kotlinx-rpc/topics/rpc-clients.topic b/docs/pages/kotlinx-rpc/topics/rpc-clients.topic index 7aa8c2024..30deafd23 100644 --- a/docs/pages/kotlinx-rpc/topics/rpc-clients.topic +++ b/docs/pages/kotlinx-rpc/topics/rpc-clients.topic @@ -8,22 +8,22 @@ -

    - For each declared service, kotlinx.rpc will generate an actual client implementation - that can be used to send requests to a server. You must not use generated code directly. Instead, - you should use the APIs that will provide you with the instance of your interface. This generated instance is - commonly called a stub in RPC. -

    +

    + For each declared service, kotlinx.rpc will generate an actual client implementation + that can be used to send requests to a server. This generated instance is + commonly called a stub in RPC. +

    - Note that we talk about generated stubs (service implementations on the client side) - that must not be called directly. - There might be a case when the generated code is not a stub, but a service declaration itself - (for example, the services generated from -
    .proto files). - In this case, you can use the generated code. + Note that we talk about generated stubs (service interface implementations on the client side) + that must not be called directly. + There might be a case when the generated code is not a stub, but a service declaration itself + (for example, the services generated from + .proto files). + In this case, you can use the generated code. + See .

    - To be able to obtain an instance of your service, you need to have an RpcClient. + To be able to get an instance of your service, you need to have an RpcClient. You can call the withService() method on your client:

    @@ -31,6 +31,9 @@ val myService: MyService = rpcClient.withService<MyService>() + + Note that the type parameter of withService must be annotated with @Rpc annotation. +

    Now you have your client instance that is able to send RPC requests to your server. RpcClient can have multiple services that communicate through it. @@ -42,42 +45,7 @@

    You can provide your own implementations of the RpcClient. But kotlinx.rpc already provides one out-of-the-box solution that uses - in-house RPC protocol (called kRPC), and we are working on supporting more protocols - (with priority on gRPC). + in-house RPC protocol (called kRPC), and we are working on supporting more + protocols (see ).

    - - -

    KrpcClient is an abstract class that implements RpcClient and kRPC protocol - logic. - The only thing required to be implemented is the transporting of the raw data. - Abstract transport is represented by KrpcTransport interface.

    -

    To implement your own KrpcTransport - you need to be able to transfer strings and/or raw bytes (Kotlin's ByteArray). - Additionally, the library will provide you with integrations with different - libraries that are used to work with the network. -

    -

    See below an example usage of kRPC with a custom transport:

    - - - class MySimpleRpcTransport : KrpcTransport { - val outChannel = Channel<KrpcTransportMessage>() - val inChannel = Channel<KrpcTransportMessage>() - - override val coroutineContext: CoroutineContext = Job() - - override suspend fun send(message: KrpcTransportMessage) { - outChannel.send(message) - } - - override suspend fun receive(): KrpcTransportMessage { - return inChannel.receive() - } - } - - class MySimpleRpcClient : KrpcClient(rpcClientConfig(), MySimpleRpcTransport()) - - val client = MySimpleRpcClient() - val service: MyService = client.withService<MyService>() - - diff --git a/docs/pages/kotlinx-rpc/topics/rpc-servers.topic b/docs/pages/kotlinx-rpc/topics/rpc-servers.topic index 7f2e3b97c..3d9d9e104 100644 --- a/docs/pages/kotlinx-rpc/topics/rpc-servers.topic +++ b/docs/pages/kotlinx-rpc/topics/rpc-servers.topic @@ -8,51 +8,39 @@ -

    RpcServer interface represents an RPC server, - that accepts RPC messages and may contain multiple services to route to. - RpcServer uses data from incoming RPC messages - and routes it to the designated service and sends service's response back to the corresponding client. -

    -

    You can provide your own RpcServer implementation - or use the one provided out of the box. - Note that client and server must use the same RPC protocol to communicate.

    -

    Use registerService function to add your own factory for implemented RPC services. - This factory function should accept CoroutineContext argument and pass it to the service, - which should use it to override coroutineContext property of parent interface. - This ensures proper application lifetime for your services.

    -

    Example usage:

    +

    + RpcServer interface represents an RPC server, + that accepts RPC messages and may contain multiple services to route to. + RpcServer uses data from incoming RPC messages + and routes it to the designated service and sends service's response back to the corresponding client. +

    +

    + You can provide your own RpcServer implementation + or use the one provided out of the box. + Note that client and server must use the same RPC protocol to communicate. +

    +

    + Use registerService function to add your own factory for implemented RPC services: +

    - - val server: RpcServer + + val server: RpcServer - server.registerService<MyService> { ctx: CoroutineContext -> MyServiceImpl(ctx) } - -

    The registerService function requires the explicit type of the declared RPC service. + server.registerService<MyService> { MyServiceImpl() } + + +

    + The registerService function requires the explicit type of the declared RPC service. That means that the code will not work if you provide it with the type of the service implementation:

    // Wrong! Should be `MyService` as type argument - server.registerService<MyServiceImpl> { ctx: CoroutineContext -> MyServiceImpl(ctx) } + server.registerService<MyServiceImpl> { MyServiceImpl() } - -

    KrpcServer abstract class implements RpcServer - and all the logic for processing RPC messages - and again leaves RpcTransport methods for the specific implementations - (see transports).

    -

    Example usage with custom transport:

    - - - // same MySimpleRpcTransport as in the client example above - class MySimpleRpcServer : KrpcServer(rpcServerConfig(), MySimpleRpcTransport()) - - val server = MySimpleRpcServer() - server.registerService<MyService> { ctx -> MyServiceImpl(ctx) } - -

    Note that here we pass explicit MyService type parameter to the registerService - method. - You must explicitly specify the type of the service interface here, - otherwise the server service will not be found.

    -
    +

    + See for more details. +

    +
    diff --git a/docs/pages/kotlinx-rpc/topics/services.topic b/docs/pages/kotlinx-rpc/topics/services.topic index 0cfa5ecb2..50bf9eb09 100644 --- a/docs/pages/kotlinx-rpc/topics/services.topic +++ b/docs/pages/kotlinx-rpc/topics/services.topic @@ -9,45 +9,87 @@ xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/topic.v2.xsd" title="Services" id="services">

    Services are the centerpieces of the library. - A service is an interface annotated with the @Rpc annotation, - and contains a set of methods and fields - that can be executed or accessed remotely. - Additionally, a service always has a type of RemoteService, - which can be specified explicitly, or assumed implicitly by the compiler. + A service is an interface annotated with the @Rpc annotation, + and contains a set of methods that can be executed remotely.

    - - Note that implicit typing is currently not supported in IDEs, but is a work in progress. -

    A simple service can be declared as follows:

    - - @Rpc - interface MyService : RemoteService { - suspend fun hello(name: String): String - } - -

    Here we declare the method hello, that accepts one argument and returns a string. - The method is marked with a suspend modifier, which means that we use - coroutines - to send RPC requests. - Note that for now, only suspend methods are supported in service interfaces.

    - -

    Depending on the type of the protocol you use, services may support different features and - declarations.

    -
    -

    To be able to use a service both in client and server code, - the interface should be placed in the common module - — kudos to Kotlin Multiplatform.

    -

    Now we can implement the service, so server knows how to process incoming requests.

    - - - class MyServiceImpl( - override val coroutineContext: CoroutineContext, - ) : MyService { - override suspend fun hello(name: String): String { - return "Hello, $name! I'm server!" - } - } - -

    The server will use that implementation to answer the client requests.

    + + @Rpc + interface MyService { + suspend fun hello(name: String): String + } + +

    + Here we declare the method hello, that accepts one argument and returns a string. + The method is marked with a suspend modifier, which means that we use + coroutines + to send RPC requests. +

    + +

    + Depending on the type of the protocol you use, services may support different features and + declarations. +

    +
    +

    + To be able to use a service both in client and server code, + the interface should be placed in the common module + — kudos to Kotlin Multiplatform. +

    +

    + Now we can implement the service, so the server knows how to process incoming requests. +

    + + class MyServiceImpl : MyService { + override suspend fun hello(name: String): String { + return "Hello, $name! I'm server!" + } + } + +

    + The server will use that implementation to answer the client requests. +

    + +

    + The library supports streaming of data. + To declare a streaming method, you need to use the Flow type. + For example, to declare a method that returns a stream of integers: +

    + + @Rpc + interface MyService { + fun stream(): Flow<Int> + } + +

    + Note that the method is not marked with the suspend modifier. +

    +

    + You can also pass a Flow as a parameter to the method. + For example, to declare a method that accepts a stream of integers: +

    + + @Rpc + interface MyService { + suspend fun sendStream(stream: Flow<Int>) + } + +

    + Or make streams bidirectional: +

    + + @Rpc + interface MyService { + fun bidi(stream: Flow<Int>): Flow<Int> + } + + +

    + Note that the function is not suspend + only when the return type is a Flow. + Flow in parameter list does not affect the function's signature. +

    +
    +
    diff --git a/docs/pages/kotlinx-rpc/topics/strict-mode.topic b/docs/pages/kotlinx-rpc/topics/strict-mode.topic index 0d512e3ba..33e660682 100644 --- a/docs/pages/kotlinx-rpc/topics/strict-mode.topic +++ b/docs/pages/kotlinx-rpc/topics/strict-mode.topic @@ -10,11 +10,11 @@ title="Strict mode" id="strict-mode">

    - Starting with version 0.5.0, the library introduces major changes to the service APIs. - The following declarations will be gradually restricted: + Starting with version 0.5.0, the library introduced major changes to the service APIs. + The following declarations are now restricted:

    - String mode will be enforced in the 0.8.0 release. + Strict mode is enforced irreversibly since 0.8.0.

    Deprecation level: ERROR

    @@ -148,37 +148,4 @@ }
    - - -

    - Deprecation levels are controlled by the Gradle rpc extension: -

    - - // build.gradle.kts - plugins { - id("org.jetbrains.kotlinx.rpc.plugin") - } - - rpc { - strict { - stateFlow = RpcStrictMode.ERROR - sharedFlow = RpcStrictMode.ERROR - nestedFlow = RpcStrictMode.ERROR - notTopLevelServerFlow = RpcStrictMode.ERROR - fields = RpcStrictMode.ERROR - suspendingServerStreaming = RpcStrictMode.ERROR - streamScopedFunctions = RpcStrictMode.ERROR - } - } - -

    - Modes RpcStrictMode.NONE and RpcStrictMode.WARNING are available. -

    - - - Note that setting RpcStrictMode.NONE should not be done permanently. - All deprecated APIs will become errors in the future without an option to suppress them. - Consider your migration path in advance. - -
    diff --git a/docs/pages/kotlinx-rpc/topics/transport.topic b/docs/pages/kotlinx-rpc/topics/transport.topic index 8eb26bd7b..2beca318d 100644 --- a/docs/pages/kotlinx-rpc/topics/transport.topic +++ b/docs/pages/kotlinx-rpc/topics/transport.topic @@ -9,143 +9,21 @@ xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/topic.v2.xsd" title="Transport" id="transport"> -

    Transport layer exists to abstract from the RPC requests logic and focus on delivering and receiving - encoded RPC messages in kRPC Protocol. - This layer is represented by KrpcTransport interface. - It supports two message formats — string and binary, - and depending on which serialization format you choose, - one or the other will be used.

    - - -

    The kotlinx.rpc library provides integration with the Ktor - framework with the in-house RPC - protocol. - This includes both server and client APIs. - Under the hood, the library uses WebSocket plugin - to create a KrpcTransport and send and receive messages through it.

    - -

    kotlinx.rpc provides a way to plug-in into existing Ktor clients with your RPC services. - To do that, the following DSL can be used:

    - - - val ktorClient = HttpClient { - installKrpc { // this: KrpcConfigBuilder.Client - waitForServices = true - } - } - - val rpcClient: KtorKrpcClient = - ktorClient.rpc("ws://localhost:4242/services") { // this: HttpRequestBuilder - rpcConfig { // this: KrpcConfigBuilder.Client - waitForServices = false - } - } - - // access WebSocketSession that created the connection - rpcClient.webSocketSession - - // create RPC service - val myService: MyService = rpcClient.withService<MyService>() - -

    Note that in this example, only the latter defined KrpcConfig will be used.

    -
    - -

    kotlinx.rpc provides a way to plug-in into existing server routing with your RPC - services. - To do that, the following DSL can be used:

    - - - fun Application.module() { - install(Krpc) { // this: KrpcConfigBuilder.Server - waitForServices = true - } - - routing { - rpc("/services") { // this KrpcRoute, inherits WebSocketSession - rpcConfig { // this: KrpcConfigBuilder.Server - waitForServices = false - } - - registerService<MyService> { ctx -> MyServiceImpl(ctx) } - registerService<MyOtherService> { ctx - MyOtherServiceImpl(ctx) } - // etc - } - } - } - -
    - -

    An example code for a Ktor web application may look like this:

    - - - // ### COMMON CODE ### - @Serializable - data class ProcessedImage( - val url: String, - val numberOfCats: Int, - val numberOfDogs: Int - ) - - @Rpc - interface ImageService : RemoteService { - suspend fun processImage(url: String): ProcessedImage - } - - // ### CLIENT CODE ### - - val client = HttpClient { - installKrpc { - serialization { - json() - } - } - } - - val service = client.rpc("/image-recognizer").withService<ImageService>() - - service.processImage(url = "https://catsanddogs.com/cats/1") - - // ### SERVER CODE ### - - class ImageServiceImpl(override val coroutineContext: CoroutineContext) : ImageService { - // user defined classes - private val downloader = Downloader() - private val recognizer = AnimalRecognizer() - - override suspend fun processImage(url: Srting): ProcessedImage { - val image = downloader.loadImage(url) - return ProcessedImage( - url, - recognizer.getNumberOfCatsOnImage(image), - recognizer.getNumberOfDogsOnImage(image) - ) - } - } - - fun main() { - embeddedServer(Netty, port = 8080) { - install(Krpc) { - serialization { - json() - } - } - - routing { - rpc("/image-recognizer") { - registerService<ImageService> { ctx -> ImageServiceImpl(ctx) } - } - } - }.start(wait = true) - } - -

    For more details and complete examples, see the code samples. -

    -
    -
    - -

    Generally, there are no specific guidelines on how RPC should be set up for different transports, +

    + Transport layer exists to abstract from the RPC requests logic and focus on delivering and receiving + encoded RPC messages in kRPC Protocol. + This layer is represented by the KrpcTransport interface. + It supports two message formats — string and binary, + and depends on which serialization format you + choose. +

    + + +

    + Generally, there are no specific guidelines on how RPC should be set up for different transports, but structures and APIs used to develop integration with Ktor should outline the common approach. You can provide your own transport and even your own fully implemented protocols, - while the library will take care of code generation.

    + while the library will take care of code generation. +

    diff --git a/docs/pages/kotlinx-rpc/topics/versions.topic b/docs/pages/kotlinx-rpc/topics/versions.topic index 5532ec839..877238bb4 100644 --- a/docs/pages/kotlinx-rpc/topics/versions.topic +++ b/docs/pages/kotlinx-rpc/topics/versions.topic @@ -8,42 +8,47 @@ -

    As kotlinx.rpc uses Kotlin compiler plugin, - we rely on internal functionality that may change over time with any new Kotlin version. - To prevent the library from breaking with an incompatible Kotlin version, - we use version prefix for artifacts with code generating functionality. -

    -

    - We provide core version updates for all stable versions of - the last three - major Kotlin releases. - So if the last stable Kotlin version is %kotlin-version%, as at the time of writing this guide, - the following versions of Kotlin are supported: -

    - -
  • 2.0.0, 2.0.10, 2.0.20, 2.0.21
  • -
  • 2.1.0, 2.1.10, 2.1.20, 2.1.21
  • -
    +

    + As kotlinx.rpc uses Kotlin compiler plugin, + we rely on internal functionality that may change over time with any new Kotlin version. + To prevent the library from breaking with an incompatible Kotlin version, + we use version prefix for artifacts with code generating functionality. +

    +

    + We provide core version updates for all stable versions of + the last three + major Kotlin releases. + So if the last stable Kotlin version is %kotlin-version%, as at the time of writing this guide, + the following versions of Kotlin are supported: +

    + +
  • 2.0.0, 2.0.10, 2.0.20, 2.0.21
  • +
  • 2.1.0, 2.1.10, 2.1.20, 2.1.21
  • +
    +

    + Our code generation will support these versions (See more on code + generation artifacts). + Runtime artifacts are configured with + + language-version and api-version parameters + + for the oldest supported minor version of Kotlin. +

    + + The kotlinx-rpc library is currently not stable. + As a result, we cannot guarantee compatibility with all Kotlin versions for our runtime dependencies at this + time. + However, we are committed to maintaining compatibility as much as possible. + It is in our plans to ensure that all runtime dependencies are compatible with all supported Kotlin versions by + the time of the stable release. + +

    - Our code generation will support these versions (See more on code generation artifacts). - Runtime artifacts are configured with - - language-version and api-version parameters - - for the oldest supported minor version of Kotlin. + To simplify project configuration, our + is able to set proper runtime dependencies versions automatically based + on the project's Kotlin version and the Gradle plugin version + which is used as a core library version.

    - - The kotlinx-rpc library is currently not stable. - As a result, we cannot guarantee compatibility with all Kotlin versions for our runtime dependencies at this time. - However, we are committed to maintaining compatibility as much as possible. - It is in our plans to ensure that all runtime dependencies are compatible with all supported Kotlin versions by the time of the stable release. - - -

    - To simplify project configuration, both our Gradle plugins - are able to set proper runtime dependencies versions automatically based - on the project's Kotlin version and the Gradle plugin version - which is used as a core library version.

    plugins { // project's Kotlin plugin @@ -77,6 +82,6 @@ org.jetbrains.kotlinx:kotlinx-rpc-compiler-plugin-k2:%kotlin-version%-%kotlinx-rpc-version% org.jetbrains.kotlinx:kotlinx-rpc-compiler-plugin-backend:%kotlin-version%-%kotlinx-rpc-version% - Such dependencies are managed automatically, and should not be used explicitly. + These dependencies are managed automatically, and should not be used explicitly.
    diff --git a/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt b/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt index c64ed04a0..6f71a2318 100644 --- a/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt +++ b/gradle-plugin/src/main/kotlin/kotlinx/rpc/Extensions.kt @@ -31,8 +31,8 @@ open class RpcExtension @Inject constructor(objects: ObjectFactory) { /** * Strict mode settings. - * Allows configuring the reporting state of deprecated features. */ + @Deprecated("Strict mode enabled irreversibly. This option can't change it.", level = DeprecationLevel.ERROR) fun strict(configure: Action) { configure.execute(strict) } @@ -88,6 +88,7 @@ open class RpcStrictModeExtension @Inject constructor(objects: ObjectFactory) { * * Consider using regular streaming. */ + @Deprecated("Field are deprecated with level ERROR. This option can't change it.") val fields: Property = objects.strictModeProperty() private fun ObjectFactory.strictModeProperty( diff --git a/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt b/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt index d75dc0a5d..c70a82e61 100644 --- a/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt +++ b/gradle-plugin/src/main/kotlin/kotlinx/rpc/compilerPlugins.kt @@ -29,20 +29,8 @@ class CompilerPluginCli : KotlinCompilerPluginSupportPlugin by compilerPlugin({ val extension = it.target.project.extensions.findByType() ?: RpcExtension(it.target.project.objects) - val strict = extension.strict - it.target.project.provider { listOf( - SubpluginOption("strict-stateFlow", strict.stateFlow.get().toCompilerArg()), - SubpluginOption("strict-sharedFlow", strict.sharedFlow.get().toCompilerArg()), - SubpluginOption("strict-nested-flow", strict.nestedFlow.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) SubpluginOption("annotation-type-safety", extension.annotationTypeSafetyEnabled.get().toString()), ) diff --git a/krpc/krpc-client/api/krpc-client.api b/krpc/krpc-client/api/krpc-client.api index 42ce07884..4579e9b42 100644 --- a/krpc/krpc-client/api/krpc-client.api +++ b/krpc/krpc-client/api/krpc-client.api @@ -1,11 +1,17 @@ -public abstract class kotlinx/rpc/krpc/client/KrpcClient : kotlinx/rpc/krpc/internal/KrpcServiceHandler, kotlinx/rpc/RpcClient, kotlinx/rpc/krpc/internal/KrpcEndpoint { +public abstract class kotlinx/rpc/krpc/client/InitializedKrpcClient : kotlinx/rpc/krpc/client/KrpcClient { public fun (Lkotlinx/rpc/krpc/KrpcConfig$Client;Lkotlinx/rpc/krpc/KrpcTransport;)V + protected final fun initializeConfig ()Lkotlinx/rpc/krpc/KrpcConfig$Client; + protected final fun initializeTransport (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public abstract class kotlinx/rpc/krpc/client/KrpcClient : kotlinx/rpc/RpcClient, kotlinx/rpc/krpc/internal/KrpcEndpoint { + public fun ()V + public final fun awaitCompletion (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; 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; - protected final fun getLogger ()Lkotlinx/rpc/krpc/internal/logging/RpcInternalCommonLogger; + public final fun callServerStreaming (Lkotlinx/rpc/RpcCall;)Lkotlinx/coroutines/flow/Flow; + public final fun close (Ljava/lang/String;)V + public static synthetic fun close$default (Lkotlinx/rpc/krpc/client/KrpcClient;Ljava/lang/String;ILjava/lang/Object;)V + protected abstract fun initializeConfig ()Lkotlinx/rpc/krpc/KrpcConfig$Client; + protected abstract fun initializeTransport (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/krpc/krpc-client/build.gradle.kts b/krpc/krpc-client/build.gradle.kts index 8b91ed2e6..195b9dabd 100644 --- a/krpc/krpc-client/build.gradle.kts +++ b/krpc/krpc-client/build.gradle.kts @@ -28,14 +28,3 @@ kotlin { } } -rpc { - strict { - stateFlow = RpcStrictMode.NONE - sharedFlow = RpcStrictMode.NONE - nestedFlow = RpcStrictMode.NONE - streamScopedFunctions = RpcStrictMode.NONE - suspendingServerStreaming = RpcStrictMode.NONE - notTopLevelServerFlow = RpcStrictMode.NONE - fields = RpcStrictMode.NONE - } -} 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 94f1c630b..65dd4fcd9 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 @@ -8,118 +8,190 @@ import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.first 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.descriptor.RpcInvokator import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlinx.rpc.internal.utils.RpcInternalSupervisedCompletableDeferred import kotlinx.rpc.internal.utils.getOrNull import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap import kotlinx.rpc.krpc.* +import kotlinx.rpc.krpc.client.internal.ClientStreamContext +import kotlinx.rpc.krpc.client.internal.ClientStreamSerializer import kotlinx.rpc.krpc.client.internal.KrpcClientConnector +import kotlinx.rpc.krpc.client.internal.StreamCall import kotlinx.rpc.krpc.internal.* import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger import kotlinx.serialization.BinaryFormat +import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialFormat import kotlinx.serialization.StringFormat -import kotlin.coroutines.CoroutineContext +import kotlinx.serialization.modules.SerializersModule +import kotlin.collections.first +import kotlin.concurrent.Volatile import kotlin.coroutines.cancellation.CancellationException - -@Deprecated("Use KrpcClient instead", ReplaceWith("KrpcClient"), level = DeprecationLevel.ERROR) -public typealias KRPCClient = KrpcClient +import kotlin.properties.Delegates /** - * Default implementation of [RpcClient]. - * Takes care of tracking requests and responses, - * serializing data, tracking streams, processing exceptions, and other protocol responsibilities. - * Leaves out the delivery of encoded messages to the specific implementations. - * - * A simple example of how this client may be implemented: - * ```kotlin - * class MyTransport : RpcTransport { /*...*/ } + * Represents an initialized [KrpcClient] that wraps a predefined [config] and [transport] parameters. * - * class MyClient(config: RpcConfig.Client): KrpcClient(config, MyTransport()) - * ``` - * - * @property config configuration provided for that specific client. Applied to all services that use this client. + * @param config configuration provided for that specific client. Applied to all services that use this client. + * See [KrpcClient.initializeConfig]. * @param transport [KrpcTransport] instance that will be used to send and receive RPC messages. - * IMPORTANT: Must be exclusive to this client, otherwise unexpected behavior may occur. + * See [KrpcClient.initializeTransport]. */ -@OptIn(InternalCoroutinesApi::class) -public abstract class KrpcClient( - final override val config: KrpcConfig.Client, - transport: KrpcTransport, -) : KrpcServiceHandler(), RpcClient, KrpcEndpoint { - // we make a child here, so we can send cancellation messages before closing the connection - final override val coroutineContext: CoroutineContext = SupervisorJob(transport.coroutineContext.job) +public abstract class InitializedKrpcClient( + private val config: KrpcConfig.Client, + private val transport: KrpcTransport, +): KrpcClient() { + final override suspend fun initializeTransport(): KrpcTransport { + return transport + } - private val connector by lazy { - KrpcClientConnector(config.serialFormatInitializer.build(), transport, config.waitForServices) + final override fun initializeConfig(): KrpcConfig.Client { + return config } +} - private var connectionId: Long? = null +/** + * kRPC implementation of the [RpcClient]. + * Takes care of tracking requests and responses, + * serializing data, tracking streams, processing exceptions, and other protocol responsibilities. + * Leaves out the delivery of encoded messages to the specific implementations with [KrpcTransport]. + */ +@OptIn(InternalCoroutinesApi::class) +public abstract class KrpcClient : RpcClient, KrpcEndpoint { + /** + * Called once to provide [KrpcTransport] for this client. + * + * IMPORTANT: The provided instance must be exclusive to this client, otherwise unexpected behavior may occur. + */ + protected abstract suspend fun initializeTransport(): KrpcTransport - @InternalRpcApi - final override val sender: KrpcMessageSender - get() = connector + /** + * Called once to provide [KrpcConfig.Client] for this client. + * Called only after [initializeTransport]. + * + * Configuration is applied to all services that use this client. + */ + protected abstract fun initializeConfig(): KrpcConfig.Client - private val callCounter = atomic(0L) + /** + * Close this client, removing all the services and stopping accepting messages. + */ + public fun close(message: String? = null) { + if (!isTransportReady) { + return + } - final override val logger: RpcInternalCommonLogger = RpcInternalCommonLogger.logger(rpcInternalObjectId()) + internalScope.cancel(message ?: "Client closed") + } - private val serverSupportedPlugins: CompletableDeferred> = CompletableDeferred() + /** + * Waits until the client is closed. + */ + public suspend fun awaitCompletion() { + if (!isTransportReady) { + return + } - @InternalRpcApi - final override val supportedPlugins: Set - get() = serverSupportedPlugins.getOrNull() ?: emptySet() + internalScope.coroutineContext.job.join() + } - private var clientCancelled = false + /* + * ##################################################################### + * # # + * # INTERNALS AHEAD # + * # # + * ##################################################################### + */ - // callId to serviceTypeString - private val cancellingRequests = RpcInternalConcurrentHashMap() + private var isTransportReady: Boolean = false + private var transport: KrpcTransport by Delegates.notNull() - init { - coroutineContext.job.invokeOnCompletion(onCancelling = true) { - clientCancelled = true + private val config: KrpcConfig.Client by lazy { + initializeConfig() + } - sendCancellation(CancellationType.ENDPOINT, null, null, closeTransportAfterSending = true) - } + @Volatile + private var clientCancelled = false - launch { - connector.subscribeToGenericMessages(::handleGenericMessage) + private fun checkTransportReadiness() { + if (!isTransportReady) { + error( + "Internal error, please contact developers for the support. " + + "Transport is not initialized, first scope access must come from an RPC request." + ) } } - @OptIn(InternalCoroutinesApi::class) @InternalRpcApi - final override fun provideStubContext(serviceId: Long): CoroutineContext { - val childContext = SupervisorJob(coroutineContext.job).withClientStreamScope() + public val internalScope: CoroutineScope by lazy { + checkTransportReadiness() - childContext.job.invokeOnCompletion(onCancelling = true) { - if (!clientCancelled) { - // cancellation only by serviceId - sendCancellation(CancellationType.SERVICE, serviceId.toString(), null) + val context = SupervisorJob(transport.coroutineContext.job) + + context.job.invokeOnCompletion(onCancelling = true) { + clientCancelled = true + + sendCancellation(CancellationType.ENDPOINT, null, null, closeTransportAfterSending = true) + + @OptIn(DelicateCoroutinesApi::class) + @Suppress("detekt.GlobalCoroutineUsage") + GlobalScope.launch(CoroutineName("client-request-channels-closing")) { + requestChannels.values.forEach { it.close(CancellationException("Client cancelled")) } + requestChannels.clear() } } - return childContext + CoroutineScope(context) } - private val initHandshake: Job = launch { - connector.sendMessage(KrpcProtocolMessage.Handshake(KrpcPlugin.ALL)) + // we make a child here, so we can send cancellation messages before closing the connection + private val connector by lazy { + checkTransportReadiness() - connector.subscribeToProtocolMessages(::handleProtocolMessage) + KrpcClientConnector(config.serialFormatInitializer.build(), transport, config.waitForServices) } + private var connectionId: Long? = null + + @InternalRpcApi + final override val sender: KrpcMessageSender + get() = connector + + private val callCounter = atomic(0L) + + private val logger: RpcInternalCommonLogger = RpcInternalCommonLogger.logger(rpcInternalObjectId()) + + private val serverSupportedPlugins: CompletableDeferred> = CompletableDeferred() + + private val requestChannels = RpcInternalConcurrentHashMap>() + + @InternalRpcApi + final override val supportedPlugins: Set + get() = serverSupportedPlugins.getOrNull() ?: emptySet() + + // callId to serviceTypeString + private val cancellingRequests = RpcInternalConcurrentHashMap() + /** * Starts the handshake process and awaits for completion. * If the handshake was completed before, nothing happens. */ - private suspend fun awaitHandshakeCompletion() { - initHandshake.join() + private suspend fun initializeAndAwaitHandshakeCompletion() { + transport = initializeTransport() + isTransportReady = true + + connector.subscribeToGenericMessages(::handleGenericMessage) + connector.subscribeToProtocolMessages(::handleProtocolMessage) + + connector.sendMessage(KrpcProtocolMessage.Handshake(KrpcPlugin.ALL)) + serverSupportedPlugins.await() } @@ -144,179 +216,18 @@ 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, - ): Deferred { - val callable = call.descriptor.getCallable(call.callableName) - ?: error("Unexpected callable '${call.callableName}' for ${call.descriptor.fqName} service") - - val deferred = RpcInternalSupervisedCompletableDeferred(serviceScope.coroutineContext.job) - - /** - * Launched on the service scope (receiver) - * Moreover, this scope has [StreamScope] that is used to handle field streams. - * [StreamScope] is provided to a service via [provideStubContext]. - */ - serviceScope.launch { - val rpcCall = call(call, callable, deferred) - - deferred.invokeOnCompletion { cause -> - if (cause == null) { - rpcCall.streamContext.valueOrNull?.launchIf({ incomingHotFlowsAvailable }) { - handleIncomingHotFlows(it) - } - } - } - } - - return deferred - } - final override suspend fun call(call: RpcCall): T { - val callable = call.descriptor.getCallable(call.callableName) - ?: error("Unexpected callable '${call.callableName}' for ${call.descriptor.fqName} service") - - val callCompletableResult = RpcInternalSupervisedCompletableDeferred() - val rpcCall = call(call, callable, callCompletableResult) - val result = callCompletableResult.await() - - // incomingHotFlowsAvailable value is known after await - rpcCall.streamContext.valueOrNull?.launchIf({ incomingHotFlowsAvailable }) { - handleIncomingHotFlows(it) - } - - return result + return callServerStreaming(call).first() } - private suspend fun call( - call: RpcCall, - callable: RpcCallable<*>, - callResult: CompletableDeferred, - ): RpcCallStreamContextFormatAndId { - val wrappedCallResult = RequestCompletableDeferred(callResult) - val rpcCall = prepareAndExecuteCall(call, callable, wrappedCallResult) - - rpcCall.streamContext.valueOrNull?.launchIf({ outgoingStreamsAvailable }) { - handleOutgoingStreams(it, rpcCall.serialFormat, call.descriptor.fqName) - } - - val handle = serviceScopeOrNull()?.run { - serviceCoroutineScope.coroutineContext.job.invokeOnCompletion(onCancelling = true) { cause -> - // service can only be canceled, it can't complete successfully - callResult.completeExceptionally(CancellationException(cause)) - - rpcCall.streamContext.valueOrNull?.cancel("Service cancelled", cause) - } - } - - callResult.invokeOnCompletion { cause -> - if (cause != null) { - cancellingRequests[rpcCall.callId] = call.descriptor.fqName - - rpcCall.streamContext.valueOrNull?.cancel("Request failed", cause) - - if (!wrappedCallResult.callExceptionOccurred) { - sendCancellation(CancellationType.REQUEST, call.serviceId.toString(), rpcCall.callId) - } - - handle?.dispose() - } else { - val streamScope = rpcCall.streamContext.valueOrNull?.streamScope - - if (streamScope == null) { - handle?.dispose() - - connector.unsubscribeFromMessages(call.descriptor.fqName, rpcCall.callId) - } - - streamScope?.onScopeCompletion(rpcCall.callId) { - handle?.dispose() - - cancellingRequests[rpcCall.callId] = call.descriptor.fqName - - sendCancellation(CancellationType.REQUEST, call.serviceId.toString(), rpcCall.callId) - } - } - } - - return rpcCall - } - - private suspend fun prepareAndExecuteCall( - call: RpcCall, - callable: RpcCallable<*>, - callResult: RequestCompletableDeferred<*>, - ): RpcCallStreamContextFormatAndId { - // we should wait for the handshake to finish - awaitHandshakeCompletion() - - val id = callCounter.incrementAndGet() - - val callId = "$connectionId:${callable.name}:$id" - - logger.trace { "start a call[$callId] ${callable.name}" } - - val fallbackScope = serviceScopeOrNull() - ?.serviceCoroutineScope - ?.let { streamScopeOrNull(it) } - - val streamContext = LazyKrpcStreamContext(streamScopeOrNull(), fallbackScope) { - KrpcStreamContext(callId, config, connectionId, call.serviceId, it) - } - val serialFormat = prepareSerialFormat(streamContext) - val firstMessage = serializeRequest(callId, call, callable, serialFormat) - - @Suppress("UNCHECKED_CAST") - executeCall( - callId = callId, - streamContext = streamContext, - call = call, - callable = callable, - firstMessage = firstMessage, - serialFormat = serialFormat, - callResult = callResult as RequestCompletableDeferred - ) - - return RpcCallStreamContextFormatAndId(streamContext, serialFormat, callId) - } - - private data class RpcCallStreamContextFormatAndId( - val streamContext: LazyKrpcStreamContext, - val serialFormat: SerialFormat, - val callId: String, - ) - - private suspend fun executeCall( - callId: String, - streamContext: LazyKrpcStreamContext, - call: RpcCall, - callable: RpcCallable<*>, - firstMessage: KrpcCallMessage, - serialFormat: SerialFormat, - callResult: RequestCompletableDeferred, - ) { - connector.subscribeToCallResponse(call.descriptor.fqName, callId) { message -> - if (cancellingRequests.containsKey(callId)) { - return@subscribeToCallResponse - } - - handleMessage(message, streamContext, callable, serialFormat, callResult) - } - - connector.sendMessage(firstMessage) - } - - private val noFlowSerialFormat = config.serialFormatInitializer.build() - @Suppress("detekt.CyclomaticComplexMethod") - override fun callServerStreaming(call: RpcCall): Flow { + final override fun callServerStreaming(call: RpcCall): Flow { return flow { - awaitHandshakeCompletion() + if (clientCancelled) { + error("Client cancelled") + } + + initializeAndAwaitHandshakeCompletion() val id = callCounter.incrementAndGet() val callable = call.descriptor.getCallable(call.callableName) @@ -326,14 +237,9 @@ public abstract class KrpcClient( val channel = Channel() - val streamScope = StreamScope(currentCoroutineContext()) - try { - val streamContext = LazyKrpcStreamContext(streamScope, null) { - KrpcStreamContext(callId, config, connectionId, call.serviceId, it) - } - - val serialFormat = prepareSerialFormat(streamContext) + @Suppress("UNCHECKED_CAST") + requestChannels[callId] = channel as Channel val request = serializeRequest( callId = callId, @@ -343,36 +249,63 @@ public abstract class KrpcClient( pluginParams = mapOf(KrpcPluginKey.NON_SUSPENDING_SERVER_FLOW_MARKER to ""), ) - connector.sendMessage(request) - connector.subscribeToCallResponse(call.descriptor.fqName, callId) { message -> - handleServerStreamingMessage(message, channel, callable, call, callId) - } + if (cancellingRequests.containsKey(callId)) { + return@subscribeToCallResponse + } - streamContext.valueOrNull?.launchIf({ outgoingStreamsAvailable }) { - handleOutgoingStreams(it, serialFormat, call.descriptor.fqName) + handleServerStreamingMessage(message, channel, callable) } - while (true) { - val element = channel.receiveCatching() - if (element.isClosed) { - val ex = element.exceptionOrNull() ?: break - throw ex + connector.sendMessage(request) + + coroutineScope { + val clientStreamsJob = launch(CoroutineName("client-stream-root-${call.serviceId}-$callId")) { + supervisorScope { + clientStreamContext.streams[callId].orEmpty().forEach { + launch(CoroutineName("client-stream-${call.serviceId}-$callId-${it.streamId}")) { + handleOutgoingStream(it, serialFormat, call.descriptor.fqName) + } + } + } } - if (!element.isFailure) { - emit(element.getOrThrow()) + try { + consumeAndEmitServerMessages(channel) + } finally { + clientStreamsJob.cancelAndJoin() + clientStreamContext.streams.remove(callId) } } } catch (e: CancellationException) { - // sendCancellation is not suspending, so no need for NonCancellable - sendCancellation(CancellationType.REQUEST, call.serviceId.toString(), callId) - connector.unsubscribeFromMessages(call.descriptor.fqName, callId) + if (!clientCancelled) { + cancellingRequests[callId] = call.descriptor.fqName + + sendCancellation(CancellationType.REQUEST, call.descriptor.fqName, callId) + + connector.unsubscribeFromMessages(call.descriptor.fqName, callId) { + cancellingRequests.remove(callId) + } + } throw e } finally { - streamScope.close() channel.close() + requestChannels.remove(callId) + } + } + } + + private suspend fun FlowCollector.consumeAndEmitServerMessages(channel: Channel) { + while (true) { + val element = channel.receiveCatching() + if (element.isClosed) { + val ex = element.exceptionOrNull() ?: break + throw ex + } + + if (!element.isFailure) { + emit(element.getOrThrow()) } } } @@ -381,8 +314,6 @@ public abstract class KrpcClient( message: KrpcCallMessage, channel: Channel, callable: RpcCallable, - call: RpcCall, - callId: String, ) { when (message) { is KrpcCallMessage.CallData -> { @@ -405,10 +336,10 @@ public abstract class KrpcClient( is KrpcCallMessage.CallSuccess, is KrpcCallMessage.StreamMessage -> { val value = runCatching { - val serializerResult = noFlowSerialFormat.serializersModule + val serializerResult = serialFormat.serializersModule .rpcSerializerForType(callable.returnType) - decodeMessageData(noFlowSerialFormat, serializerResult, message) + decodeMessageData(serialFormat, serializerResult, message) } @Suppress("UNCHECKED_CAST") @@ -416,82 +347,21 @@ public abstract class KrpcClient( } 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, - callable: RpcCallable<*>, - serialFormat: SerialFormat, - callResult: RequestCompletableDeferred, - ) { - 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()!! - } - - callResult.callExceptionOccurred = true - callResult.completeExceptionally(result) - } - - is KrpcCallMessage.CallSuccess -> { - val value = runCatching { - val serializerResult = serialFormat.serializersModule.rpcSerializerForType(callable.returnType) - - decodeMessageData(serialFormat, serializerResult, message) - } - - callResult.completeWith(value) - } - - is KrpcCallMessage.StreamCancel -> { - streamContext.awaitInitialized().cancelStream(message) - } - - is KrpcCallMessage.StreamFinished -> { - streamContext.awaitInitialized().closeStream(message) - } - - is KrpcCallMessage.StreamMessage -> { - streamContext.awaitInitialized().send(message, serialFormat) - } - } - } - @InternalRpcApi final override suspend fun handleCancellation(message: KrpcGenericMessage) { when (val type = message.cancellationType()) { CancellationType.ENDPOINT -> { - cancel("Closing client after server cancellation") // we cancel this client - } - - CancellationType.CANCELLATION_ACK -> { - val callId = message[KrpcPluginKey.CANCELLATION_ID] - ?: error("Expected CANCELLATION_ID for cancellation of type 'request'") - - val serviceTypeString = cancellingRequests.remove(callId) ?: return - connector.unsubscribeFromMessages(serviceTypeString, callId) + internalScope.cancel("Closing client after server cancellation") // we cancel this client } else -> { @@ -513,7 +383,10 @@ public abstract class KrpcClient( val serializerData = serialFormat.serializersModule.rpcSerializerForType(callable.dataType) return when (serialFormat) { is StringFormat -> { - val stringValue = serialFormat.encodeToString(serializerData, call.data) + val stringValue = clientStreamContext.scoped(callId, call.serviceId) { + serialFormat.encodeToString(serializerData, call.data) + } + KrpcCallMessage.CallDataString( callId = callId, serviceType = call.descriptor.fqName, @@ -527,7 +400,10 @@ public abstract class KrpcClient( } is BinaryFormat -> { - val binaryValue = serialFormat.encodeToByteArray(serializerData, call.data) + val binaryValue = clientStreamContext.scoped(callId, call.serviceId) { + serialFormat.encodeToByteArray(serializerData, call.data) + } + KrpcCallMessage.CallDataBinary( callId = callId, serviceType = call.descriptor.fqName, @@ -545,8 +421,104 @@ public abstract class KrpcClient( } } } -} -private class RequestCompletableDeferred(delegate: CompletableDeferred) : CompletableDeferred by delegate { - var callExceptionOccurred: Boolean = false + private suspend fun handleOutgoingStream( + outgoingStream: StreamCall, + serialFormat: SerialFormat, + serviceTypeString: String, + ) { + try { + collectAndSendOutgoingStream( + serialFormat = serialFormat, + flow = outgoingStream.stream, + outgoingStream = outgoingStream, + serviceTypeString = serviceTypeString, + ) + } catch (e: CancellationException) { + throw e + } catch (@Suppress("detekt.TooGenericExceptionCaught") cause: Throwable) { + val serializedReason = serializeException(cause) + val message = KrpcCallMessage.StreamCancel( + callId = outgoingStream.callId, + serviceType = serviceTypeString, + streamId = outgoingStream.streamId, + cause = serializedReason, + connectionId = outgoingStream.connectionId, + serviceId = outgoingStream.serviceId, + ) + sender.sendMessage(message) + + throw cause + } + + val message = KrpcCallMessage.StreamFinished( + callId = outgoingStream.callId, + serviceType = serviceTypeString, + streamId = outgoingStream.streamId, + connectionId = outgoingStream.connectionId, + serviceId = outgoingStream.serviceId, + ) + + sender.sendMessage(message) + } + + private suspend fun collectAndSendOutgoingStream( + serialFormat: SerialFormat, + flow: Flow<*>, + serviceTypeString: String, + outgoingStream: StreamCall, + ) { + flow.collect { + val message = when (serialFormat) { + is StringFormat -> { + val stringData = serialFormat.encodeToString(outgoingStream.elementSerializer, it) + KrpcCallMessage.StreamMessageString( + callId = outgoingStream.callId, + serviceType = serviceTypeString, + streamId = outgoingStream.streamId, + data = stringData, + connectionId = outgoingStream.connectionId, + serviceId = outgoingStream.serviceId, + ) + } + + is BinaryFormat -> { + val binaryData = serialFormat.encodeToByteArray(outgoingStream.elementSerializer, it) + KrpcCallMessage.StreamMessageBinary( + callId = outgoingStream.callId, + serviceType = serviceTypeString, + streamId = outgoingStream.streamId, + data = binaryData, + connectionId = outgoingStream.connectionId, + serviceId = outgoingStream.serviceId, + ) + } + + else -> { + unsupportedSerialFormatError(serialFormat) + } + } + + sender.sendMessage(message) + } + } + + private val clientStreamContext: ClientStreamContext = ClientStreamContext(connectionId = connectionId) + + private val serialFormat: SerialFormat by lazy { + val module = SerializersModule { + contextual(Flow::class) { + @Suppress("UNCHECKED_CAST") + ClientStreamSerializer(clientStreamContext, it.first() as KSerializer) + } + } + + config.serialFormatInitializer.applySerializersModuleAndBuild(module) + } + + private fun RpcCallable<*>.toMessageCallType(): KrpcCallMessage.CallType { + return when (invokator) { + is RpcInvokator.Method -> KrpcCallMessage.CallType.Method + } + } } diff --git a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamContext.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamContext.kt new file mode 100644 index 000000000..772588d87 --- /dev/null +++ b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamContext.kt @@ -0,0 +1,56 @@ +/* + * 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.internal + +import kotlinx.atomicfu.atomic +import kotlinx.coroutines.flow.Flow +import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap +import kotlinx.rpc.internal.utils.thread.RpcInternalThreadLocal +import kotlinx.serialization.KSerializer + +internal class ClientStreamContext(private val connectionId: Long?) { + val streams = RpcInternalConcurrentHashMap>() + + private val currentCallId = RpcInternalThreadLocal() + private val currentServiceId = RpcInternalThreadLocal() + + fun scoped(callId: String, serviceId: Long, body: () -> T): T { + try { + currentCallId.set(callId) + currentServiceId.set(serviceId) + return body() + } finally { + currentCallId.remove() + currentServiceId.remove() + } + } + + private val streamIdCounter = atomic(0L) + + fun registerClientStream(value: Flow<*>, elementKind: KSerializer<*>): String { + val callId = currentCallId.get() ?: error("No call id") + val serviceId = currentServiceId.get() ?: error("No service id") + val streamId = "$STREAM_ID_PREFIX${streamIdCounter.getAndIncrement()}" + + @Suppress("UNCHECKED_CAST") + val stream = StreamCall( + callId = callId, + streamId = streamId, + stream = value, + elementSerializer = elementKind as KSerializer, + connectionId = connectionId, + serviceId = serviceId + ) + + @Suppress("UNCHECKED_CAST") + streams.merge(callId, listOf(stream)) { old, new -> old + new } + + return streamId + } + + private companion object { + private const val STREAM_ID_PREFIX = "stream:" + } +} diff --git a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamSerializer.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamSerializer.kt new file mode 100644 index 000000000..d677dbf7f --- /dev/null +++ b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/ClientStreamSerializer.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.rpc.krpc.client.internal + +import kotlinx.coroutines.flow.Flow +import kotlinx.rpc.krpc.internal.StreamSerializer +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal class ClientStreamSerializer( + val context: ClientStreamContext, + val elementType: KSerializer, +) : KSerializer>, StreamSerializer() { + override val descriptor: SerialDescriptor by lazy { + buildClassSerialDescriptor("ClientStreamSerializer") { + element(STREAM_ID_SERIAL_NAME, streamIdDescriptor) + } + } + + override fun deserialize(decoder: Decoder): Flow<*> { + error("This method must not be called. Please report to the developer.") + } + + override fun serialize(encoder: Encoder, value: Flow<*>) { + val id = context.registerClientStream(value, elementType) + + encoder.encodeString(id) + } +} diff --git a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/KrpcClientConnector.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/KrpcClientConnector.kt index 105ead2e1..ebee09b5c 100644 --- a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/KrpcClientConnector.kt +++ b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/KrpcClientConnector.kt @@ -36,9 +36,8 @@ internal class KrpcClientConnector private constructor( } ) - @Suppress("unused") - fun unsubscribeFromMessages(serviceTypeString: String, callId: String) { - connector.unsubscribeFromMessages(CallSubscriptionId.Service(serviceTypeString, callId)) + fun unsubscribeFromMessages(serviceTypeString: String, callId: String, callback: () -> Unit = {}) { + connector.unsubscribeFromMessages(CallSubscriptionId.Service(serviceTypeString, callId), callback) } suspend fun subscribeToCallResponse( diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamCall.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/StreamCall.kt similarity index 56% rename from krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamCall.kt rename to krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/StreamCall.kt index 6d22b4f25..4c4a556c5 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamCall.kt +++ b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/internal/StreamCall.kt @@ -1,16 +1,16 @@ /* - * 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 +package kotlinx.rpc.krpc.client.internal +import kotlinx.coroutines.flow.Flow import kotlinx.serialization.KSerializer -internal data class KrpcStreamCall( +internal data class StreamCall( val callId: String, val streamId: String, - val stream: Any, - val kind: StreamKind, + val stream: Flow<*>, val elementSerializer: KSerializer, val connectionId: Long?, val serviceId: Long?, diff --git a/krpc/krpc-core/api/krpc-core.api b/krpc/krpc-core/api/krpc-core.api index 517af2dde..7b7696b17 100644 --- a/krpc/krpc-core/api/krpc-core.api +++ b/krpc/krpc-core/api/krpc-core.api @@ -1,29 +1,23 @@ public abstract interface class kotlinx/rpc/krpc/KrpcConfig { public abstract fun getSerialFormatInitializer ()Lkotlinx/rpc/krpc/serialization/KrpcSerialFormatBuilder; - public abstract fun getSharedFlowBuilder ()Lkotlin/jvm/functions/Function0; public abstract fun getWaitForServices ()Z } public final class kotlinx/rpc/krpc/KrpcConfig$Client : kotlinx/rpc/krpc/KrpcConfig { public fun getSerialFormatInitializer ()Lkotlinx/rpc/krpc/serialization/KrpcSerialFormatBuilder; - public fun getSharedFlowBuilder ()Lkotlin/jvm/functions/Function0; public fun getWaitForServices ()Z } public final class kotlinx/rpc/krpc/KrpcConfig$Server : kotlinx/rpc/krpc/KrpcConfig { public fun getSerialFormatInitializer ()Lkotlinx/rpc/krpc/serialization/KrpcSerialFormatBuilder; - public fun getSharedFlowBuilder ()Lkotlin/jvm/functions/Function0; public fun getWaitForServices ()Z } public abstract class kotlinx/rpc/krpc/KrpcConfigBuilder { - protected final fun getSharedFlowBuilder ()Lkotlin/jvm/functions/Function0; public final fun getWaitForServices ()Z protected final fun rpcSerialFormat ()Lkotlinx/rpc/krpc/serialization/KrpcSerialFormatBuilder; public final fun serialization (Lkotlin/jvm/functions/Function1;)V - protected final fun setSharedFlowBuilder (Lkotlin/jvm/functions/Function0;)V public final fun setWaitForServices (Z)V - public final fun sharedFlowParameters (Lkotlin/jvm/functions/Function1;)V } public final class kotlinx/rpc/krpc/KrpcConfigBuilder$Client : kotlinx/rpc/krpc/KrpcConfigBuilder { @@ -36,17 +30,6 @@ public final class kotlinx/rpc/krpc/KrpcConfigBuilder$Server : kotlinx/rpc/krpc/ public final fun build ()Lkotlinx/rpc/krpc/KrpcConfig$Server; } -public final class kotlinx/rpc/krpc/KrpcConfigBuilder$SharedFlowParametersBuilder { - public static final field DEFAULT_EXTRA_BUFFER_CAPACITY I - public static final field DEFAULT_REPLAY I - public final fun getExtraBufferCapacity ()I - public final fun getOnBufferOverflow ()Lkotlinx/coroutines/channels/BufferOverflow; - public final fun getReplay ()I - public final fun setExtraBufferCapacity (I)V - public final fun setOnBufferOverflow (Lkotlinx/coroutines/channels/BufferOverflow;)V - public final fun setReplay (I)V -} - public final class kotlinx/rpc/krpc/KrpcConfigKt { public static final fun rpcClientConfig (Lkotlin/jvm/functions/Function1;)Lkotlinx/rpc/krpc/KrpcConfig$Client; public static synthetic fun rpcClientConfig$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/rpc/krpc/KrpcConfig$Client; @@ -56,12 +39,11 @@ public final class kotlinx/rpc/krpc/KrpcConfigKt { public abstract interface class kotlinx/rpc/krpc/KrpcTransport : kotlinx/coroutines/CoroutineScope { public abstract fun receive (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun receiveCatching-IoAF18A (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun send (Lkotlinx/rpc/krpc/KrpcTransportMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class kotlinx/rpc/krpc/KrpcTransport$DefaultImpls { - public static fun receiveCatching-IoAF18A (Lkotlinx/rpc/krpc/KrpcTransport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +public final class kotlinx/rpc/krpc/KrpcTransportKt { + public static final fun receiveCatching (Lkotlinx/rpc/krpc/KrpcTransport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class kotlinx/rpc/krpc/KrpcTransportMessage { @@ -77,15 +59,3 @@ public final class kotlinx/rpc/krpc/KrpcTransportMessage$StringMessage : kotlinx public final fun getValue ()Ljava/lang/String; } -public final class kotlinx/rpc/krpc/StreamScope : java/lang/AutoCloseable { - public fun close ()V -} - -public final class kotlinx/rpc/krpc/StreamScopeKt { - public static final fun StreamScope (Lkotlin/coroutines/CoroutineContext;)Lkotlinx/rpc/krpc/StreamScope; - public static final fun invokeOnStreamScopeCompletion (ZLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun invokeOnStreamScopeCompletion$default (ZLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun streamScoped (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withStreamScope (Lkotlinx/rpc/krpc/StreamScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - diff --git a/krpc/krpc-core/build.gradle.kts b/krpc/krpc-core/build.gradle.kts index 29040a7dc..fe19a6840 100644 --- a/krpc/krpc-core/build.gradle.kts +++ b/krpc/krpc-core/build.gradle.kts @@ -14,6 +14,8 @@ plugins { applyAtomicfuPlugin() kotlin { + compilerOptions.freeCompilerArgs.add("-Xexpect-actual-classes") + sourceSets { commonMain { dependencies { @@ -28,15 +30,3 @@ kotlin { } } } - -rpc { - strict { - stateFlow = RpcStrictMode.NONE - sharedFlow = RpcStrictMode.NONE - nestedFlow = RpcStrictMode.NONE - streamScopedFunctions = RpcStrictMode.NONE - suspendingServerStreaming = RpcStrictMode.NONE - notTopLevelServerFlow = RpcStrictMode.NONE - fields = RpcStrictMode.NONE - } -} diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcConfig.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcConfig.kt index 962e965e1..566afada2 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcConfig.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcConfig.kt @@ -4,115 +4,14 @@ package kotlinx.rpc.krpc -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.rpc.internal.utils.InternalRpcApi import kotlinx.rpc.krpc.serialization.KrpcSerialFormat import kotlinx.rpc.krpc.serialization.KrpcSerialFormatBuilder import kotlinx.rpc.krpc.serialization.KrpcSerialFormatConfiguration -@Deprecated("Use KrpcConfigBuilder instead", ReplaceWith("KrpcConfigBuilder"), level = DeprecationLevel.ERROR) -public typealias RPCConfigBuilder = KrpcConfigBuilder - /** * Builder for [KrpcConfig]. Provides DSL to configure parameters for KrpcClient and/or KrpcServer. */ -public sealed class KrpcConfigBuilder private constructor() { - /** - * DSL for parameters of [MutableSharedFlow] and [SharedFlow]. - * - * This is a temporary solution that hides the problem of transferring these parameters. - * [SharedFlow] and [MutableSharedFlow] do not define theirs 'replay', 'extraBufferCapacity' and 'onBufferOverflow' - * parameters, and thus they cannot be encoded and transferred. - * So then creating their instance on an endpoint, the library should know which parameters to use. - */ - @Deprecated( - "SharedFlow support is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - @Suppress("MemberVisibilityCanBePrivate") - public class SharedFlowParametersBuilder internal constructor() { - /** - * The number of values replayed to new subscribers (cannot be negative, defaults to zero). - */ - @Deprecated( - "SharedFlow support is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public var replay: Int = DEFAULT_REPLAY - - /** - * The number of values buffered in addition to replay. - * emit does not suspend while there is a buffer space remaining - * (optional, cannot be negative, defaults to zero). - */ - @Deprecated( - "SharedFlow support is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public var extraBufferCapacity: Int = DEFAULT_EXTRA_BUFFER_CAPACITY - - /** - * Configures an emit action on buffer overflow. - * Optional, defaults to suspending attempts to emit a value. - * Values other than [BufferOverflow.SUSPEND] are supported only when replay > 0 or extraBufferCapacity > 0. - * Buffer overflow can happen only when there is at least one subscriber - * that is not ready to accept the new value. - * In the absence of subscribers only the most recent replay values are stored - * and the buffer overflow behavior is never triggered and has no effect. - */ - @Deprecated( - "SharedFlow support is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public var onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND - - @InternalRpcApi - public fun builder(): () -> MutableSharedFlow = { - @Suppress("DEPRECATION") - MutableSharedFlow(replay, extraBufferCapacity, onBufferOverflow) - } - - private companion object { - /** - * Default value of [replay] - */ - const val DEFAULT_REPLAY = 1 - /** - * Default value of [extraBufferCapacity] - */ - const val DEFAULT_EXTRA_BUFFER_CAPACITY = 10 - } - } - - @Suppress("DEPRECATION") - protected var sharedFlowBuilder: () -> MutableSharedFlow = SharedFlowParametersBuilder().builder() - - /** - * @see SharedFlowParametersBuilder - */ - @Deprecated( - "SharedFlow support is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-5-0.html", - level = DeprecationLevel.WARNING, - ) - public fun sharedFlowParameters(builder: @Suppress("DEPRECATION") SharedFlowParametersBuilder.() -> Unit) { - @Suppress("DEPRECATION") - sharedFlowBuilder = SharedFlowParametersBuilder().apply(builder).builder() - } - - private var serialFormatInitializer: KrpcSerialFormatBuilder<*, *>? = null - - private val configuration = object : KrpcSerialFormatConfiguration { - override fun register(rpcSerialFormatInitializer: KrpcSerialFormatBuilder.Binary<*, *>) { - serialFormatInitializer = rpcSerialFormatInitializer - } - - override fun register(rpcSerialFormatInitializer: KrpcSerialFormatBuilder.String<*, *>) { - serialFormatInitializer = rpcSerialFormatInitializer - } - } - +public sealed class KrpcConfigBuilder protected constructor() { /** * DSL for serialization configuration. * @@ -132,18 +31,11 @@ public sealed class KrpcConfigBuilder private constructor() { configuration.builder() } - protected fun rpcSerialFormat(): KrpcSerialFormatBuilder<*, *> { - return when (val format = serialFormatInitializer) { - null -> error("Please, choose serialization format") - else -> format - } - } - /** - * A flag indicating whether the client should wait for subscribers + * A flag indicating whether a client or a server should wait for subscribers * if no service is available to process a message immediately. - * If false, the endpoint that sent the message will receive call exception - * that says that there were no services to process its message. + * If `false`, the endpoint that sent the unprocessed message will receive a call exception + * saying there were no services to process the message. */ public var waitForServices: Boolean = true @@ -153,7 +45,6 @@ public sealed class KrpcConfigBuilder private constructor() { public class Client : KrpcConfigBuilder() { public fun build(): KrpcConfig.Client { return KrpcConfig.Client( - sharedFlowBuilder = sharedFlowBuilder, serialFormatInitializer = rpcSerialFormat(), waitForServices = waitForServices, ) @@ -166,34 +57,65 @@ public sealed class KrpcConfigBuilder private constructor() { public class Server : KrpcConfigBuilder() { public fun build(): KrpcConfig.Server { return KrpcConfig.Server( - sharedFlowBuilder = sharedFlowBuilder, serialFormatInitializer = rpcSerialFormat(), waitForServices = waitForServices, ) } } -} -@Deprecated("Use KrpcConfig instead", ReplaceWith("KrpcConfig"), level = DeprecationLevel.ERROR) -public typealias RPCConfig = KrpcConfig + /* + * ##################################################################### + * # # + * # CLASS INTERNALS AHEAD # + * # # + * ##################################################################### + */ + + private var serialFormatInitializer: KrpcSerialFormatBuilder<*, *>? = null + + private val configuration = object : KrpcSerialFormatConfiguration { + override fun register(rpcSerialFormatInitializer: KrpcSerialFormatBuilder.Binary<*, *>) { + serialFormatInitializer = rpcSerialFormatInitializer + } + + override fun register(rpcSerialFormatInitializer: KrpcSerialFormatBuilder.String<*, *>) { + serialFormatInitializer = rpcSerialFormatInitializer + } + } + + protected fun rpcSerialFormat(): KrpcSerialFormatBuilder<*, *> { + return when (val format = serialFormatInitializer) { + null -> error("Please, choose serialization format") + else -> format + } + } +} /** * Configuration class that is used by kRPC protocol's client and server (KrpcClient and KrpcServer). */ public sealed interface KrpcConfig { - @InternalRpcApi - public val sharedFlowBuilder: () -> MutableSharedFlow - @InternalRpcApi + /** + * @see KrpcConfigBuilder.serialization + */ public val serialFormatInitializer: KrpcSerialFormatBuilder<*, *> - @InternalRpcApi + + /** + * @see KrpcConfigBuilder.waitForServices + */ public val waitForServices: Boolean /** * @see [KrpcConfig] */ public class Client internal constructor( - override val sharedFlowBuilder: () -> MutableSharedFlow, + /** + * @see KrpcConfigBuilder.serialization + */ override val serialFormatInitializer: KrpcSerialFormatBuilder<*, *>, + /** + * @see KrpcConfigBuilder.waitForServices + */ override val waitForServices: Boolean, ) : KrpcConfig @@ -201,8 +123,13 @@ public sealed interface KrpcConfig { * @see [KrpcConfig] */ public class Server internal constructor( - override val sharedFlowBuilder: () -> MutableSharedFlow, + /** + * @see KrpcConfigBuilder.serialization + */ override val serialFormatInitializer: KrpcSerialFormatBuilder<*, *>, + /** + * @see KrpcConfigBuilder.waitForServices + */ override val waitForServices: Boolean, ) : KrpcConfig } diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcTransport.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcTransport.kt index 0a5b15673..563913f19 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcTransport.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/KrpcTransport.kt @@ -6,56 +6,59 @@ package kotlinx.rpc.krpc import kotlinx.coroutines.CoroutineScope -@Deprecated("Use KrpcTransportMessage instead", ReplaceWith("KrpcTransportMessage"), level = DeprecationLevel.ERROR) -public typealias RPCTransportMessage = KrpcTransportMessage - /** * A single message that can be transferred from one RPC endpoint to another. * Can be either of string or binary type. */ public sealed interface KrpcTransportMessage { + /** + * A single message of the string type that can be transferred from one RPC endpoint to another. + */ public class StringMessage(public val value: String) : KrpcTransportMessage + /** + * A single message of the binary type that can be transferred from one RPC endpoint to another. + */ public class BinaryMessage(public val value: ByteArray) : KrpcTransportMessage } -@Deprecated("Use KrpcTransport instead", ReplaceWith("KrpcTransport"), level = DeprecationLevel.ERROR) -public typealias RPCTransport = KrpcTransport - /** * An abstraction of transport capabilities for KrpcClient and KrpcServer. * * For developers of custom transports: * - The implementation should be able to handle both binary and string formats, * though not necessary if you absolutely sure that only one will be supplied and received. - * - The KrpcClient and KrpcServer suppose that they have exclusive instance of transport. + * - The KrpcClient and KrpcServer suppose that they have an exclusive instance of transport. * That means that each client or/and server should have only one transport instance, * otherwise some messages may be lost or processed incorrectly. - * - The implementation should manage lifetime of the connection using its [CoroutineScope]. * - * Good example of the implementation is KtorTransport, that uses websocket protocol to deliver messages. + * [CoroutineScope] is used to define connection's lifetime. + * If canceled, no messages will be able to go to the other side, + * so ideally, it should be canceled only after its client or server is. + * + * A good example of the implementation is KtorTransport, that uses websocket protocol to deliver messages. */ public interface KrpcTransport : CoroutineScope { /** - * Sends a single encoded RPC message over network (or any other medium) to a peer endpoint. + * Sends a single encoded RPC message over a network (or any other medium) to a peer endpoint. * * @param message a message to send. Either of string or binary type. */ public suspend fun send(message: KrpcTransportMessage) /** - * Suspends until next RPC message from a peer endpoint is received and then returns it. + * Suspends until the next RPC message from a peer endpoint is received and then returns it. * - * @return received RPC message. + * @return the received RPC message. */ public suspend fun receive(): KrpcTransportMessage +} - /** - * Suspends until next RPC message from a peer endpoint is received and then returns it. - * - * @return received RPC message as a [Result]. - */ - public suspend fun receiveCatching(): Result { - return runCatching { receive() } - } +/** + * Suspends until the next RPC message from a peer endpoint is received and then returns it. + * + * @return the received RPC message as a [Result]. + */ +public suspend fun KrpcTransport.receiveCatching(): Result { + return runCatching { receive() } } diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/StreamScope.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/StreamScope.kt deleted file mode 100644 index 90b75b662..000000000 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/StreamScope.kt +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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 - -import kotlinx.coroutines.* -import kotlinx.rpc.internal.utils.ExperimentalRpcApi -import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.coroutineContext -import kotlin.js.JsName - -/** - * Stream scope handles all RPC streams that are launched inside it. - * Streams are alive until stream scope is. Streams can outlive their initial request scope. - * - * Streams are grouped by the request that initiated them. - * Each group can have a completion callback associated with it. - * - * Stream scope is a child of the [CoroutineContext] it was created in. - * Failure of one request will not cancel all streams in the others. - */ -@OptIn(InternalCoroutinesApi::class) -@Deprecated( - "StreamScope is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-6-0.html", - level = DeprecationLevel.WARNING -) -public class StreamScope internal constructor( - parentContext: CoroutineContext, - internal val role: Role, -) : AutoCloseable { - internal class Element(internal val scope: StreamScope) : CoroutineContext.Element { - override val key: CoroutineContext.Key = Key - - internal companion object Key : CoroutineContext.Key - } - - internal val contextElement = Element(this) - - private val scopeJob = SupervisorJob(parentContext.job) - - private val requests = RpcInternalConcurrentHashMap() - - init { - scopeJob.invokeOnCompletion { - close() - } - } - - @InternalRpcApi - public fun onScopeCompletion(handler: (Throwable?) -> Unit) { - scopeJob.invokeOnCompletion(handler) - } - - @InternalRpcApi - public fun onScopeCompletion(callId: String, handler: (Throwable?) -> Unit) { - getRequestScope(callId).coroutineContext.job.invokeOnCompletion(onCancelling = true, handler = handler) - } - - @InternalRpcApi - public fun cancelRequestScopeById(callId: String, message: String, cause: Throwable?): Job? { - return requests.remove(callId)?.apply { cancel(message, cause) }?.coroutineContext?.job - } - - // Group stream launches by callId. In case one fails, so do others - @InternalRpcApi - public fun launch(callId: String, block: suspend CoroutineScope.() -> Unit): Job { - return getRequestScope(callId).launch(block = block) - } - - override fun close() { - scopeJob.cancel("Stream scope closed") - requests.clear() - } - - private fun getRequestScope(callId: String): CoroutineScope { - return requests.computeIfAbsent(callId) { CoroutineScope(Job(scopeJob.job)) } - } - - internal class CallScope(val callId: String) : CoroutineContext.Element { - object Key : CoroutineContext.Key - - override val key: CoroutineContext.Key<*> = Key - } - - @InternalRpcApi - public enum class Role { - Client, Server; - } -} - -@InternalRpcApi -public fun CoroutineContext.withClientStreamScope(): CoroutineContext = withStreamScope(StreamScope.Role.Client) - -@InternalRpcApi -public fun CoroutineContext.withServerStreamScope(): CoroutineContext = withStreamScope(StreamScope.Role.Server) - -@OptIn(InternalCoroutinesApi::class) -internal fun CoroutineContext.withStreamScope(role: StreamScope.Role): CoroutineContext { - return this + StreamScope(this, role).contextElement.apply { - this@withStreamScope.job.invokeOnCompletion(onCancelling = true) { scope.close() } - } -} - -@InternalRpcApi -public suspend fun streamScopeOrNull(): StreamScope? { - return currentCoroutineContext()[StreamScope.Element.Key]?.scope -} - -@InternalRpcApi -public fun streamScopeOrNull(scope: CoroutineScope): StreamScope? { - return scope.coroutineContext[StreamScope.Element.Key]?.scope -} - -internal fun noStreamScopeError(): Nothing { - error( - "Stream scopes can only be used inside the 'streamScoped' block. \n" + - "To use stream scope API on a client - wrap your call with 'streamScoped' block.\n" + - "To use stream scope API on a server - use must use 'streamScoped' block for this call on a client." - ) -} - -@InternalRpcApi -public suspend fun callScoped(callId: String, block: suspend CoroutineScope.() -> T): T { - val context = currentCoroutineContext() - - if (context[StreamScope.CallScope.Key] != null) { - error("Nested callScoped calls are not allowed") - } - - val callScope = StreamScope.CallScope(callId) - - return withContext(callScope, block) -} - -/** - * Defines lifetime for all RPC streams that are used inside it. - * When the [block] ends - all streams that were created inside it are canceled. - * The same happens when an exception is thrown. - * - * All RPC calls that use streams, either sending or receiving them, - * MUST use this scope to define their lifetime. - * - * Lifetimes inside [streamScoped] are hierarchical, - * meaning that there is parent lifetime for all calls inside this block, - * and each call has its own lifetime independent of others. - * This also means that all streams from one call share the same lifetime. - * - * Examples: - * ```kotlin - * streamScoped { - * val flow = flow { /* ... */ } - * service.sendStream(flow) // will stop sending updates when 'streamScoped' block is finished - * } - * ``` - * - * ```kotlin - * streamScoped { - * launch { - * val flow1 = flow { /* ... */ } - * service.sendStream(flow) - * } - * - * // if call with 'flow1' is canceled or failed - this flow will continue working - * launch { - * val flow2 = flow { /* ... */ } - * service.sendStream(flow) - * } - * } - * ``` - */ -@Deprecated( - "streamScoped is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-6-0.html", - level = DeprecationLevel.WARNING -) -@OptIn(ExperimentalContracts::class) -public suspend fun streamScoped(block: suspend CoroutineScope.() -> T): T { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - - val context = currentCoroutineContext() - .apply { - checkContextForStreamScope() - } - - val streamScope = StreamScope(context, StreamScope.Role.Client) - - return withContext(streamScope.contextElement) { - streamScope.use { - block() - } - } -} - -private fun CoroutineContext.checkContextForStreamScope() { - if (this[StreamScope.Element] != null) { - error( - "One of the following caused a failure: \n" + - "- nested 'streamScoped' or `withStreamScope` calls are not allowed.\n" + - "- 'streamScoped' or `withStreamScope` calls are not allowed in server RPC services." - ) - } -} - -/** - * Creates a [StreamScope] entity for manual stream management. - */ -@JsName("StreamScope_fun") -@ExperimentalRpcApi -@Deprecated( - "StreamScoped is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-6-0.html", - level = DeprecationLevel.WARNING -) -public fun StreamScope(parent: CoroutineContext): StreamScope { - parent.checkContextForStreamScope() - - return StreamScope(parent, StreamScope.Role.Client) -} - -/** - * Adds manually managed [StreamScope] to the current context. - */ -@OptIn(ExperimentalContracts::class) -@ExperimentalRpcApi -@Deprecated( - "withStreamScope is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-6-0.html", - level = DeprecationLevel.WARNING -) -public suspend fun withStreamScope(scope: StreamScope, block: suspend CoroutineScope.() -> T): T { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - - currentCoroutineContext().checkContextForStreamScope() - - return withContext(scope.contextElement, block) -} - -/** - * This is a callback that will run when stream scope (created by [streamScoped] function) ends. - * Typically, this is used to release stream resources that may be occupied by a call: - * ```kotlin - * // service on server - * override suspend fun returnStateFlow(): StateFlow { - * val state = MutableStateFlow(-1) - * - * incomingHotFlowJob = launch { - * repeat(Int.MAX_VALUE) { value -> - * state.value = value - * - * delay(1000) // intense work - * } - * } - * - * // release resources allocated for state flow, when it is closed on the client - * invokeOnStreamScopeCompletion { - * incomingHotFlowJob.cancel() - * } - * - * return state - * } - * ``` - */ -@ExperimentalRpcApi -@Deprecated( - "invokeOnStreamScopeCompletion is deprecated, see https://kotlin.github.io/kotlinx-rpc/0-6-0.html", - level = DeprecationLevel.WARNING -) -public suspend fun invokeOnStreamScopeCompletion(throwIfNoScope: Boolean = true, block: (Throwable?) -> Unit) { - val streamScope = streamScopeOrNull() ?: noStreamScopeError() - - if (streamScope.role == StreamScope.Role.Client) { - streamScope.onScopeCompletion(block) - return - } - - val callScope = coroutineContext[StreamScope.CallScope.Key] - - when { - callScope != null -> streamScope.onScopeCompletion(callScope.callId, block) - - throwIfNoScope -> error( - "'invokeOnStreamScopeCompletion' can only be called with corresponding 'streamScoped' block on a client" - ) - } -} diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/CancellationType.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/CancellationType.kt index 9855e3c6f..b268df712 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/CancellationType.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/CancellationType.kt @@ -11,8 +11,10 @@ import kotlinx.rpc.internal.utils.InternalRpcApi @Suppress("detekt.MagicNumber") public enum class CancellationType(override val uniqueIndex: Int) : RpcInternalIndexedEnum { ENDPOINT(0), + @Deprecated("Service cancellation is deprecated.") SERVICE(1), REQUEST(2), + @Deprecated("Cancellation acknowledgement is deprecated.") CANCELLATION_ACK(3), ; diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcConnector.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcConnector.kt index ed1b04829..bf4808223 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcConnector.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcConnector.kt @@ -5,16 +5,21 @@ package kotlinx.rpc.krpc.internal import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.rpc.internal.utils.InternalRpcApi +import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap import kotlinx.rpc.krpc.KrpcTransport import kotlinx.rpc.krpc.KrpcTransportMessage import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLoggerContainer +import kotlinx.rpc.krpc.receiveCatching import kotlinx.serialization.* +import kotlin.time.Duration.Companion.seconds @InternalRpcApi public interface KrpcMessageSender : CoroutineScope { @@ -39,7 +44,7 @@ private typealias KrpcMessageHandler = suspend (KrpcMessage) -> Unit * DO NOT use actual dumper in production! */ @InternalRpcApi -public class KrpcConnector( +public class KrpcConnector( private val serialFormat: SerialFormat, private val transport: KrpcTransport, private val waitForSubscribers: Boolean = true, @@ -49,10 +54,9 @@ public class KrpcConnector( private val role = if (isServer) SERVER_ROLE else CLIENT_ROLE private val logger = RpcInternalCommonLogger.logger(rpcInternalObjectId(role)) - private val mutex = Mutex() - - private val waiting = mutableMapOf>() - private val subscriptions = mutableMapOf() + private val waiting = RpcInternalConcurrentHashMap>() + private val subscriptions = RpcInternalConcurrentHashMap() + private val processWaitersLocks = RpcInternalConcurrentHashMap() private val dumpLogger by lazy { RpcInternalDumpLoggerContainer.provide() } @@ -78,19 +82,23 @@ public class KrpcConnector( transport.send(transportMessage) } - public fun unsubscribeFromMessages(key: SubscriptionKey) { - launch { mutex.withLock { subscriptions.remove(key) } } + public fun unsubscribeFromMessages(key: SubscriptionKey, callback: () -> Unit = {}) { + launch(CoroutineName("krpc-connector-unsubscribe-$key")) { + delay(15.seconds) + subscriptions.remove(key) + processWaitersLocks.remove(key) + }.invokeOnCompletion { + callback() + } } public suspend fun subscribeToMessages(key: SubscriptionKey, handler: KrpcMessageHandler) { - mutex.withLock { - subscriptions[key] = handler - processWaiters(key, handler) - } + subscriptions[key] = handler + processWaiters(key, handler) } init { - launch { + launch(CoroutineName("krpc-connector-receive-loop")) { while (true) { processMessage(transport.receiveCatching().getOrNull() ?: break) } @@ -119,7 +127,7 @@ public class KrpcConnector( processMessage(message) } - private suspend fun processMessage(message: KrpcMessage) = mutex.withLock { + private suspend fun processMessage(message: KrpcMessage) = withLockForKey(message.getKey()) { when (message) { is KrpcCallMessage -> processServiceMessage(message) is KrpcProtocolMessage, is KrpcGenericMessage -> processNonServiceMessage(message) @@ -139,7 +147,7 @@ public class KrpcConnector( } HandlerResult.NoSubscription -> { - waiting.getOrPut(message.getKey()) { mutableListOf() }.add(message) + waiting.computeIfAbsent(message.getKey()) { mutableListOf() }.add(message) } HandlerResult.Success -> {} // ok @@ -152,7 +160,7 @@ public class KrpcConnector( // todo better exception processing probably if (result != HandlerResult.Success) { if (waitForSubscribers) { - waiting.getOrPut(message.getKey()) { mutableListOf() }.add(message) + waiting.computeIfAbsent(message.getKey()) { mutableListOf() }.add(message) val reason = when (result) { is HandlerResult.Failure -> { @@ -160,7 +168,7 @@ public class KrpcConnector( } is HandlerResult.NoSubscription -> { - "No service with key '${message.getKey()}' and '${message.serviceType}' type was registered." + + "No service with key '${message.getKey()}' and '${message.serviceType}' type was registered. " + "Available: keys: [${subscriptions.keys.joinToString()}]" } @@ -171,7 +179,7 @@ public class KrpcConnector( logger.warn((result as? HandlerResult.Failure)?.cause) { "No registered service of ${message.serviceType} service type " + - "was able to process message at the moment. Waiting for new services." + + "was able to process message ($message) at the moment. Waiting for new services. " + "Reason: $reason" } @@ -182,7 +190,7 @@ public class KrpcConnector( val cause = IllegalStateException( "Failed to process call ${message.callId} for service ${message.serviceType}, " + - "${subscriptions.size} attempts failed", + "${subscriptions.values.size} attempts failed", initialCause, ) @@ -225,18 +233,24 @@ public class KrpcConnector( } private suspend fun processWaiters(key: SubscriptionKey, handler: KrpcMessageHandler) { - if (waiting.isEmpty()) return + withLockForKey(key) { + if (waiting.values.isEmpty()) return - val iterator = waiting[key]?.iterator() ?: return - while (iterator.hasNext()) { - val message = iterator.next() + val iterator = waiting[key]?.iterator() ?: return + while (iterator.hasNext()) { + val message = iterator.next() - if (tryHandle(message, handler) == HandlerResult.Success) { - iterator.remove() + val tryHandle = tryHandle(message, handler) + if (tryHandle == HandlerResult.Success) { + iterator.remove() + } } } } + private suspend inline fun withLockForKey(key: SubscriptionKey, action: () -> T): T = + processWaitersLocks.computeIfAbsent(key) { Mutex() }.withLock(action = action) + internal companion object { const val SEND_PHASE = "Send" const val RECEIVE_PHASE = "Receive" diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcEndpoint.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcEndpoint.kt index 88c8f1070..3289f0a24 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcEndpoint.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcEndpoint.kt @@ -4,6 +4,7 @@ package kotlinx.rpc.krpc.internal +import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.rpc.internal.utils.InternalRpcApi @@ -30,7 +31,7 @@ public interface KrpcEndpoint { return } - val sendJob = sender.launch { + val sendJob = sender.launch(CoroutineName("krpc-endpoint-cancellation-$serviceId-$cancellationId")) { val message = KrpcGenericMessage( connectionId = null, pluginParams = listOfNotNull( diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcMessage.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcMessage.kt index 63ba30f37..64b678038 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcMessage.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcMessage.kt @@ -115,7 +115,9 @@ public sealed interface KrpcCallMessage : KrpcMessage { @Serializable @SerialName("org.jetbrains.krpc.internal.transport.RPCMessage.CallType") public enum class CallType { - Method, Field, + Method, + @Deprecated("Fields are not supported anymore. Use Method instead.") + Field, } @InternalRpcApi 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 6804eeb14..55243646a 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 @@ -55,6 +55,11 @@ public enum class KrpcPlugin( * This feature adds support for proper service/request cancellation over the network. */ NON_SUSPENDING_SERVER_FLOWS(3, KrpcVersion.V_0_6_0), + + /** + * Clients don't require cancellation acknowledgement from the peer server. + */ + NO_ACK_CANCELLATION(4, KrpcVersion.V_0_8_0), ; @InternalRpcApi diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcServiceHandler.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcServiceHandler.kt deleted file mode 100644 index 487327fd6..000000000 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcServiceHandler.kt +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 - -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.rpc.descriptor.RpcCallable -import kotlinx.rpc.descriptor.RpcInvokator -import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlinx.rpc.krpc.KrpcConfig -import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger -import kotlinx.serialization.BinaryFormat -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialFormat -import kotlinx.serialization.StringFormat -import kotlinx.serialization.modules.SerializersModule - -@InternalRpcApi -public abstract class KrpcServiceHandler { - protected abstract val sender: KrpcMessageSender - protected abstract val config: KrpcConfig - protected abstract val logger: RpcInternalCommonLogger - - protected suspend fun handleIncomingHotFlows(streamContext: KrpcStreamContext) { - for (hotFlow in streamContext.incomingHotFlows) { - streamContext.launch { - /** Start consuming incoming requests, see [KrpcIncomingHotFlow.emit] */ - hotFlow.emit(null) - } - } - } - - protected suspend fun handleOutgoingStreams( - streamContext: KrpcStreamContext, - serialFormat: SerialFormat, - serviceTypeString: String, - ) { - val mutex = Mutex() - for (outgoingStream in streamContext.outgoingStreams) { - streamContext.launch { - try { - when (outgoingStream.kind) { - StreamKind.Flow, StreamKind.SharedFlow, StreamKind.StateFlow -> { - val stream = outgoingStream.stream as Flow<*> - - collectAndSendOutgoingStream( - mutex = mutex, - serialFormat = serialFormat, - flow = stream, - outgoingStream = outgoingStream, - serviceTypeString = serviceTypeString, - ) - } - } - } catch (e : CancellationException) { - // canceled by a streamScope - throw e - } catch (@Suppress("detekt.TooGenericExceptionCaught") cause: Throwable) { - mutex.withLock { - val serializedReason = serializeException(cause) - val message = KrpcCallMessage.StreamCancel( - callId = outgoingStream.callId, - serviceType = serviceTypeString, - streamId = outgoingStream.streamId, - cause = serializedReason, - connectionId = outgoingStream.connectionId, - serviceId = outgoingStream.serviceId, - ) - sender.sendMessage(message) - } - throw cause - } - - mutex.withLock { - val message = KrpcCallMessage.StreamFinished( - callId = outgoingStream.callId, - serviceType = serviceTypeString, - streamId = outgoingStream.streamId, - connectionId = outgoingStream.connectionId, - serviceId = outgoingStream.serviceId, - ) - - sender.sendMessage(message) - } - } - } - } - - @Suppress("detekt.LongParameterList") - private suspend fun collectAndSendOutgoingStream( - mutex: Mutex, - serialFormat: SerialFormat, - flow: Flow<*>, - serviceTypeString: String, - outgoingStream: KrpcStreamCall, - ) { - flow.collect { - // because we can send new message for the new flow, - // which is not published with `transport.send(message)` - mutex.withLock { - val message = when (serialFormat) { - is StringFormat -> { - val stringData = serialFormat.encodeToString(outgoingStream.elementSerializer, it) - KrpcCallMessage.StreamMessageString( - callId = outgoingStream.callId, - serviceType = serviceTypeString, - streamId = outgoingStream.streamId, - data = stringData, - connectionId = outgoingStream.connectionId, - serviceId = outgoingStream.serviceId, - ) - } - - is BinaryFormat -> { - val binaryData = serialFormat.encodeToByteArray(outgoingStream.elementSerializer, it) - KrpcCallMessage.StreamMessageBinary( - callId = outgoingStream.callId, - serviceType = serviceTypeString, - streamId = outgoingStream.streamId, - data = binaryData, - connectionId = outgoingStream.connectionId, - serviceId = outgoingStream.serviceId, - ) - } - - else -> { - unsupportedSerialFormatError(serialFormat) - } - } - - sender.sendMessage(message) - } - } - } - - protected fun prepareSerialFormat(rpcFlowContext: LazyKrpcStreamContext): SerialFormat { - val module = SerializersModule { - contextual(Flow::class) { - @Suppress("UNCHECKED_CAST") - StreamSerializer.Flow(rpcFlowContext.initialize(), it.first() as KSerializer) - } - - contextual(SharedFlow::class) { - @Suppress("UNCHECKED_CAST") - StreamSerializer.SharedFlow(rpcFlowContext.initialize(), it.first() as KSerializer) - } - - contextual(StateFlow::class) { - @Suppress("UNCHECKED_CAST") - StreamSerializer.StateFlow(rpcFlowContext.initialize(), it.first() as KSerializer) - } - } - - return config.serialFormatInitializer.applySerializersModuleAndBuild(module) - } - - protected fun RpcCallable<*>.toMessageCallType(): KrpcCallMessage.CallType { - return when (invokator) { - is RpcInvokator.Method -> KrpcCallMessage.CallType.Method - is RpcInvokator.Field -> KrpcCallMessage.CallType.Field - } - } -} diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamContext.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamContext.kt deleted file mode 100644 index 73fbd3a24..000000000 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/KrpcStreamContext.kt +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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 - -import kotlinx.atomicfu.atomic -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.selects.select -import kotlinx.rpc.internal.utils.InternalRpcApi -import kotlinx.rpc.internal.utils.getDeferred -import kotlinx.rpc.internal.utils.getOrNull -import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap -import kotlinx.rpc.internal.utils.set -import kotlinx.rpc.krpc.KrpcConfig -import kotlinx.rpc.krpc.StreamScope -import kotlinx.rpc.krpc.noStreamScopeError -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialFormat -import kotlin.coroutines.CoroutineContext - -@InternalRpcApi -public class LazyKrpcStreamContext( - public val streamScopeOrNull: StreamScope?, - private val fallbackScope: StreamScope? = null, - private val initializer: (StreamScope) -> KrpcStreamContext, -) { - private val deferred = CompletableDeferred() - private val lazyValue by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { - if (streamScopeOrNull == null && (STREAM_SCOPES_ENABLED || fallbackScope == null)) { - noStreamScopeError() - } - - // null pointer is impossible - val streamScope = streamScopeOrNull ?: fallbackScope!! - initializer(streamScope).also { deferred.complete(it) } - } - - public suspend fun awaitInitialized(): KrpcStreamContext = deferred.await() - - public val valueOrNull: KrpcStreamContext? get() = if (deferred.isCompleted) lazyValue else null - - public fun initialize(): KrpcStreamContext = lazyValue -} - -@InternalRpcApi -public class KrpcStreamContext( - private val callId: String, - private val config: KrpcConfig, - private val connectionId: Long?, - private val serviceId: Long?, - public val streamScope: StreamScope, -) { - private companion object { - private const val STREAM_ID_PREFIX = "stream:" - } - private val closed = CompletableDeferred() - - // thread-safe set - private val closedStreams = RpcInternalConcurrentHashMap>() - - @InternalRpcApi - public inline fun launchIf( - condition: KrpcStreamContext.() -> Boolean, - noinline block: suspend CoroutineScope.(KrpcStreamContext) -> Unit, - ) { - if (condition(this)) { - launch(block) - } - } - - public fun launch(block: suspend CoroutineScope.(KrpcStreamContext) -> Unit) { - streamScope.launch(callId) { - block(this@KrpcStreamContext) - } - } - - public fun cancel(message: String, cause: Throwable?): Job? { - return streamScope.cancelRequestScopeById(callId, message, cause) - } - - init { - streamScope.onScopeCompletion(callId) { cause -> - close(cause) - } - } - - private val streamIdCounter = atomic(0L) - - public val incomingHotFlowsAvailable: Boolean get() = incomingHotFlowsInitialized - - public val outgoingStreamsAvailable: Boolean get() = outgoingStreamsInitialized - - private var incomingStreamsInitialized: Boolean = false - private val incomingStreams by lazy { - incomingStreamsInitialized = true - RpcInternalConcurrentHashMap>() - } - - private var incomingChannelsInitialized: Boolean = false - private val incomingChannels by lazy { - incomingChannelsInitialized = true - RpcInternalConcurrentHashMap?>>() - } - - private var outgoingStreamsInitialized: Boolean = false - internal val outgoingStreams: Channel by lazy { - outgoingStreamsInitialized = true - Channel(capacity = Channel.UNLIMITED) - } - - private var incomingHotFlowsInitialized: Boolean = false - internal val incomingHotFlows: Channel> by lazy { - incomingHotFlowsInitialized = true - Channel(Channel.UNLIMITED) - } - - internal fun registerOutgoingStream( - stream: StreamT, - streamKind: StreamKind, - elementSerializer: KSerializer, - ): String { - val id = "$STREAM_ID_PREFIX${streamIdCounter.getAndIncrement()}" - outgoingStreams.trySend( - KrpcStreamCall( - callId = callId, - streamId = id, - stream = stream, - kind = streamKind, - elementSerializer = elementSerializer, - connectionId = connectionId, - serviceId = serviceId, - ) - ) - return id - } - - internal fun prepareIncomingStream( - streamId: String, - streamKind: StreamKind, - stateFlowInitialValue: Any?, - elementSerializer: KSerializer, - ): StreamT { - val incoming: Channel = Channel(Channel.UNLIMITED) - incomingChannels[streamId] = incoming - - val stream = streamOf(streamId, streamKind, stateFlowInitialValue, incoming) - incomingStreams[streamId] = KrpcStreamCall( - callId = callId, - streamId = streamId, - stream = stream, - kind = streamKind, - elementSerializer = elementSerializer, - connectionId = connectionId, - serviceId = serviceId, - ) - return stream - } - - @Suppress("UNCHECKED_CAST") - private fun streamOf( - streamId: String, - streamKind: StreamKind, - stateFlowInitialValue: Any?, - incoming: Channel, - ): StreamT { - suspend fun consumeFlow(collector: FlowCollector, onError: (Throwable) -> Unit) { - fun onClose() { - incoming.cancel() - - closedStreams[streamId] = Unit - incomingChannels.remove(streamId)?.complete(null) - incomingStreams.remove(streamId) - } - - for (message in incoming) { - when (message) { - is StreamCancel -> { - onClose() - onError(message.cause ?: streamCanceled()) - } - - is StreamEnd -> { - onClose() - if (streamKind != StreamKind.Flow) { - onError(streamCanceled()) - } - - return - } - - else -> { - collector.emit(message) - } - } - } - } - - return when (streamKind) { - StreamKind.Flow -> { - flow { - consumeFlow(this) { e -> throw e } - } - } - - StreamKind.SharedFlow -> { - val sharedFlow: MutableSharedFlow = config.sharedFlowBuilder() - - object : RpcIncomingHotFlow(sharedFlow, ::consumeFlow), MutableSharedFlow by sharedFlow { - override suspend fun collect(collector: FlowCollector): Nothing { - super.collect(collector) - } - - override suspend fun emit(value: Any?) { - super.emit(value) - } - }.also { incomingHotFlows.trySend(it) } - } - - StreamKind.StateFlow -> { - val stateFlow = MutableStateFlow(stateFlowInitialValue) - - object : RpcIncomingHotFlow(stateFlow, ::consumeFlow), MutableStateFlow by stateFlow { - override suspend fun collect(collector: FlowCollector): Nothing { - super.collect(collector) - } - - override suspend fun emit(value: Any?) { - super.emit(value) - } - }.also { incomingHotFlows.trySend(it) } - } - } as StreamT - } - - public suspend fun closeStream(message: KrpcCallMessage.StreamFinished) { - incomingChannelOf(message.streamId)?.send(StreamEnd) - } - - public suspend fun cancelStream(message: KrpcCallMessage.StreamCancel) { - incomingChannelOf(message.streamId)?.send(StreamCancel(message.cause.deserialize())) - } - - public suspend fun send(message: KrpcCallMessage.StreamMessage, serialFormat: SerialFormat) { - val info: KrpcStreamCall? = select { - incomingStreams.getDeferred(message.streamId).onAwait { it } - closedStreams.getDeferred(message.streamId).onAwait { null } - closed.onAwait { null } - } - if (info == null) return - val result = decodeMessageData(serialFormat, info.elementSerializer, message) - val channel = incomingChannelOf(message.streamId) - channel?.send(result) - } - - private suspend fun incomingChannelOf(streamId: String): Channel? { - return select { - incomingChannels.getDeferred(streamId).onAwait { it } - closedStreams.getDeferred(streamId).onAwait { null } - closed.onAwait { null } - } - } - - private fun close(cause: Throwable?) { - if (closed.isCompleted) { - return - } - - closed.complete(Unit) - - if (incomingChannelsInitialized) { - for (channel in incomingChannels.values) { - if (!channel.isCompleted) { - continue - } - - @OptIn(ExperimentalCoroutinesApi::class) - channel.getCompleted()?.apply { - trySend(StreamEnd) - - // close for sending, but not for receiving our cancel message, if possible. - close(cause) - } - } - - incomingChannels.clear() - } - - if (incomingStreamsInitialized) { - incomingStreams.values - .mapNotNull { it.getOrNull()?.stream } - .filterIsInstance() - .forEach { stream -> - stream.subscriptionContexts.forEach { - it.cancel(CancellationException("Stream closed", cause)) - } - } - - incomingStreams.clear() - } - - if (outgoingStreamsInitialized) { - outgoingStreams.close() - } - - if (incomingHotFlowsInitialized) { - incomingHotFlows.close() - } - } -} - -private fun streamCanceled() = NoSuchElementException("Stream canceled") - -private object StreamEnd - -private class StreamCancel(val cause: Throwable? = null) - -private abstract class RpcIncomingHotFlow( - private val rawFlow: MutableSharedFlow, - private val consume: suspend (FlowCollector, onError: (Throwable) -> Unit) -> Unit, -) : MutableSharedFlow { - val subscriptionContexts by lazy { mutableSetOf() } - - override suspend fun collect(collector: FlowCollector): Nothing { - val context = currentCoroutineContext() - - if (context.isActive) { - subscriptionContexts.add(context) - - context.job.invokeOnCompletion { - subscriptionContexts.remove(context) - } - } - - try { - rawFlow.collect(collector) - } finally { - subscriptionContexts.remove(context) - } - } - - // value can be ignored, as actual values are coming from the rawFlow - override suspend fun emit(value: Any?) { - consume(rawFlow) { e -> - subscriptionContexts.forEach { it.cancel(CancellationException(e.message, e)) } - - subscriptionContexts.clear() - } - } -} 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 7b8a3009a..fb310ec5e 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 @@ -8,13 +8,7 @@ package kotlinx.rpc.krpc.internal * Release versions of the library */ internal enum class KrpcVersion { - /** - * Version 0.1.0 - */ V_0_1_0_BETA, - - /** - * Version 0.6.0 - */ V_0_6_0, + V_0_8_0, } diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/StreamSerializer.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/StreamSerializer.kt index f34e22c77..0bdef9be7 100644 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/StreamSerializer.kt +++ b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/StreamSerializer.kt @@ -1,87 +1,20 @@ /* - * 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 -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder +import kotlinx.rpc.internal.utils.InternalRpcApi +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor -internal sealed class StreamSerializer(private val streamKind: StreamKind) : KSerializer { - companion object { - private const val STREAM_SERIALIZER_NAME_PREFIX = "StreamSerializer" +@Suppress("PropertyName", "detekt.VariableNaming") +@InternalRpcApi +public abstract class StreamSerializer { + protected val STREAM_ID_SERIAL_NAME: String = "streamId" + protected val STREAM_ID_SERIALIZER_NAME: String = "StreamIdSerializer" - private const val STREAM_ID_SERIAL_NAME = "streamId" - private const val STREAM_ID_SERIALIZER_NAME = "StreamIdSerializer" - - private const val STATE_FLOW_INITIAL_VALUE_SERIAL_NAME = "stateFlowInitialValue" - } - - protected abstract val context: KrpcStreamContext - protected abstract val elementType: KSerializer - - protected open fun ClassSerialDescriptorBuilder.descriptorExtension() { } - - protected open fun decodeStateFlowInitialValue(decoder: Decoder): Any? { return null } - - protected open fun encodeStateFlowInitialValue(encoder: Encoder, flow: StreamT) { } - - override val descriptor: SerialDescriptor by lazy { - buildClassSerialDescriptor("$STREAM_SERIALIZER_NAME_PREFIX.${streamKind.name}") { - element(STREAM_ID_SERIAL_NAME, PrimitiveSerialDescriptor(STREAM_ID_SERIALIZER_NAME, PrimitiveKind.STRING)) - descriptorExtension() - } - } - - override fun deserialize(decoder: Decoder): StreamT { - val streamId = decoder.decodeString() - - val stateFlowValue = decodeStateFlowInitialValue(decoder) - - return context.prepareIncomingStream(streamId, streamKind, stateFlowValue, elementType) as StreamT - } - - override fun serialize(encoder: Encoder, value: StreamT) { - val id = context.registerOutgoingStream(value, streamKind, elementType) - - encoder.encodeString(id) - - encodeStateFlowInitialValue(encoder, value) - } - - class Flow( - override val context: KrpcStreamContext, - override val elementType: KSerializer, - ) : StreamSerializer>(StreamKind.Flow) - - class SharedFlow( - override val context: KrpcStreamContext, - override val elementType: KSerializer, - ) : StreamSerializer>(StreamKind.SharedFlow) - - class StateFlow( - override val context: KrpcStreamContext, - override val elementType: KSerializer, - ) : StreamSerializer>(StreamKind.StateFlow) { - override fun ClassSerialDescriptorBuilder.descriptorExtension() { - element(STATE_FLOW_INITIAL_VALUE_SERIAL_NAME, elementType.descriptor, isOptional = true) - } - - @OptIn(ExperimentalSerializationApi::class) - override fun decodeStateFlowInitialValue(decoder: Decoder): Any? { - return decoder.decodeNullableSerializableValue(elementType) - } - - @OptIn(ExperimentalSerializationApi::class) - override fun encodeStateFlowInitialValue(encoder: Encoder, flow: kotlinx.coroutines.flow.StateFlow) { - encoder.encodeNullableSerializableValue(elementType, flow.value) - } - } -} - -internal enum class StreamKind { - Flow, SharedFlow, StateFlow; + protected val streamIdDescriptor: SerialDescriptor = + PrimitiveSerialDescriptor(STREAM_ID_SERIALIZER_NAME, PrimitiveKind.STRING) } diff --git a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/devStreamScope.kt b/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/devStreamScope.kt deleted file mode 100644 index ca89f135a..000000000 --- a/krpc/krpc-core/src/commonMain/kotlin/kotlinx/rpc/krpc/internal/devStreamScope.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.rpc.krpc.internal - -import kotlinx.rpc.internal.utils.InternalRpcApi - -/** - * For legacy internal users ONLY. - * Special dev builds may set this value to `false`. - * - * If the value is `false`, absence of [kotlinx.rpc.krpc.streamScoped] for a call - * is replaced with service's [kotlinx.rpc.krpc.StreamScope] - * obtained via [kotlinx.rpc.krpc.withClientStreamScope]. - */ -@InternalRpcApi -public const val STREAM_SCOPES_ENABLED: Boolean = true 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 64a0821c4..199d0fbbe 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 @@ -1,26 +1,19 @@ public final class kotlinx/rpc/krpc/ktor/client/KrpcKt { public static final fun getKrpc ()Lio/ktor/client/plugins/api/ClientPlugin; - public static final fun getRPC ()Lio/ktor/client/plugins/api/ClientPlugin; public static final fun installKrpc (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;)V public static synthetic fun installKrpc$default (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V - public static final fun installRPC (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;)V - public static synthetic fun installRPC$default (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } public final class kotlinx/rpc/krpc/ktor/client/KtorClientDslKt { - public static final fun rpc (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun rpc (Lio/ktor/client/HttpClient;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun rpc$default (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun rpc$default (Lio/ktor/client/HttpClient;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun rpc (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlinx/rpc/krpc/ktor/client/KtorRpcClient; + public static final fun rpc (Lio/ktor/client/HttpClient;Lkotlin/jvm/functions/Function1;)Lkotlinx/rpc/krpc/ktor/client/KtorRpcClient; + public static synthetic fun rpc$default (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/rpc/krpc/ktor/client/KtorRpcClient; + public static synthetic fun rpc$default (Lio/ktor/client/HttpClient;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/rpc/krpc/ktor/client/KtorRpcClient; public static final fun rpcConfig (Lio/ktor/client/request/HttpRequestBuilder;Lkotlin/jvm/functions/Function1;)V public static synthetic fun rpcConfig$default (Lio/ktor/client/request/HttpRequestBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } public abstract interface class kotlinx/rpc/krpc/ktor/client/KtorRpcClient : kotlinx/rpc/RpcClient { - 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; + public abstract fun getWebSocketSession ()Lkotlinx/coroutines/Deferred; } diff --git a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/Krpc.kt b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/Krpc.kt index aef216e9f..867a180ec 100644 --- a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/Krpc.kt +++ b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/Krpc.kt @@ -12,9 +12,6 @@ import kotlinx.rpc.krpc.KrpcConfigBuilder internal val KrpcClientPluginAttributesKey = AttributeKey("KrpcClientPluginAttributesKey") -@Deprecated("Use Krpc instead", ReplaceWith("Krpc"), level = DeprecationLevel.ERROR) -public val RPC: ClientPlugin get() = Krpc - /** * Ktor client plugin that allows to configure RPC globally for all instances obtained via [rpc] functions. */ @@ -22,11 +19,6 @@ public val Krpc: ClientPlugin = createClientPlugin("Kr client.attributes.put(KrpcClientPluginAttributesKey, pluginConfig) } -@Deprecated("Use installKrpc instead", ReplaceWith("installKrpc"), level = DeprecationLevel.ERROR) -public fun HttpClientConfig<*>.installRPC(configure: KrpcConfigBuilder.Client.() -> Unit = {}) { - installKrpc(configure) -} - /** * Installs [WebSockets] and [Krpc] client plugins */ diff --git a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorClientDsl.kt b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorClientDsl.kt index f54ee0a3c..8ed20197b 100644 --- a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorClientDsl.kt +++ b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorClientDsl.kt @@ -9,9 +9,7 @@ import io.ktor.client.plugins.* import io.ktor.client.plugins.websocket.* import io.ktor.client.request.* import io.ktor.util.* -import kotlinx.rpc.RpcClient import kotlinx.rpc.krpc.KrpcConfigBuilder -import kotlinx.rpc.krpc.rpcClientConfig private val KrpcRequestConfigAttributeKey = AttributeKey Unit>( name = "KrpcRequestConfigAttributeKey" @@ -29,14 +27,17 @@ public fun HttpRequestBuilder.rpcConfig(configBuilder: KrpcConfigBuilder.Client. } /** - * Configures [RpcClient] for the following path. Provides means for additional configuration via [block]. + * Configures [KtorRpcClient] for the following path. Provides means for additional configuration via [block]. * Note that the [WebSockets] plugin is required for these calls. * * @param urlString The URL to use for the request. - * @param block Optional configuration for the - * @return An instance of [RpcClient] that is configured to send messages to the server. + * @param block Optional configuration for the [HttpRequestBuilder]. + * @return An instance of [KtorRpcClient] that is configured to send messages to the server. + * The instance is cold and will establish WebSocket connection on the first request. + * + * @See [KtorRpcClient] */ -public suspend fun HttpClient.rpc( +public fun HttpClient.rpc( urlString: String, block: HttpRequestBuilder.() -> Unit = {}, ): KtorRpcClient { @@ -47,30 +48,28 @@ public suspend fun HttpClient.rpc( } /** - * Configures [RpcClient] for the following path. Provides means for additional configuration via [block]. + * Configures [KtorRpcClient] for the following path. Provides means for additional configuration via [block]. * Note that the [WebSockets] plugin is required for these calls. * - * @param block Optional configuration for the - * @return An instance of [RpcClient] that is configured to send messages to the server. + * @param block Optional configuration for the [HttpRequestBuilder]. + * @return An instance of [KtorRpcClient] that is configured to send messages to the server. + * The instance is cold and will establish WebSocket connection on the first request. + * + * @See [KtorRpcClient] */ -public suspend fun HttpClient.rpc( +public fun HttpClient.rpc( block: HttpRequestBuilder.() -> Unit = {}, ): KtorRpcClient { pluginOrNull(WebSockets) ?: error("RPC for client requires $WebSockets plugin to be installed firstly") - var requestConfigBuilder: KrpcConfigBuilder.Client.() -> Unit = {} - val session = webSocketSession { - block() + val pluginConfigBuilder = attributes.getOrNull(KrpcClientPluginAttributesKey) - attributes.getOrNull(KrpcRequestConfigAttributeKey)?.let { - requestConfigBuilder = it + return KtorKrpcClientImpl(pluginConfigBuilder) { configSetter -> + webSocketSession { + block() + + attributes.getOrNull(KrpcRequestConfigAttributeKey)?.let { configSetter(it) } } } - - val pluginConfigBuilder = attributes.getOrNull(KrpcClientPluginAttributesKey) - val rpcConfig = pluginConfigBuilder?.apply(requestConfigBuilder)?.build() - ?: rpcClientConfig(requestConfigBuilder) - - return KtorKrpcClientImpl(session, rpcConfig) } diff --git a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorRpcClient.kt b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorRpcClient.kt index 922f88441..9c3a52b35 100644 --- a/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorRpcClient.kt +++ b/krpc/krpc-ktor/krpc-ktor-client/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/client/KtorRpcClient.kt @@ -5,21 +5,52 @@ package kotlinx.rpc.krpc.ktor.client import io.ktor.websocket.* +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Deferred import kotlinx.rpc.RpcClient import kotlinx.rpc.krpc.KrpcConfig +import kotlinx.rpc.krpc.KrpcConfigBuilder +import kotlinx.rpc.krpc.KrpcTransport import kotlinx.rpc.krpc.client.KrpcClient import kotlinx.rpc.krpc.ktor.KtorTransport +import kotlinx.rpc.krpc.rpcClientConfig /** * [RpcClient] implementation for Ktor, containing [webSocketSession] object, * that is used to maintain connection. + * + * Client is cold, meaning the connection will be established on the first request. + * [webSocketSession] will be completed when the connection is established. */ public interface KtorRpcClient : RpcClient { - public val webSocketSession: WebSocketSession + /** + * Cold [WebSocketSession] object. Instantiated when the connection is established on the first request. + */ + public val webSocketSession: Deferred } internal class KtorKrpcClientImpl( - override val webSocketSession: WebSocketSession, - config: KrpcConfig.Client, -): KrpcClient(config, KtorTransport(webSocketSession)), KtorRpcClient + private val pluginConfigBuilder: KrpcConfigBuilder.Client?, + private val webSocketSessionFactory: suspend ( + configSetter: (KrpcConfigBuilder.Client.() -> Unit) -> Unit, + ) -> WebSocketSession, +): KrpcClient(), KtorRpcClient { + private var requestConfigBuilder: KrpcConfigBuilder.Client.() -> Unit = {} + private val _webSocketSession = CompletableDeferred() + override val webSocketSession: Deferred = _webSocketSession + + override suspend fun initializeTransport(): KrpcTransport { + val session = webSocketSessionFactory { + requestConfigBuilder = it + } + + _webSocketSession.complete(session) + return KtorTransport(session) + } + + override fun initializeConfig(): KrpcConfig.Client { + return pluginConfigBuilder?.apply(requestConfigBuilder)?.build() + ?: rpcClientConfig(requestConfigBuilder) + } +} diff --git a/krpc/krpc-ktor/krpc-ktor-core/build.gradle.kts b/krpc/krpc-ktor/krpc-ktor-core/build.gradle.kts index 89bf807cd..6e27be3eb 100644 --- a/krpc/krpc-ktor/krpc-ktor-core/build.gradle.kts +++ b/krpc/krpc-ktor/krpc-ktor-core/build.gradle.kts @@ -26,10 +26,17 @@ kotlin { implementation(projects.krpc.krpcSerialization.krpcSerializationJson) implementation(projects.krpc.krpcKtor.krpcKtorServer) implementation(projects.krpc.krpcKtor.krpcKtorClient) + implementation(projects.krpc.krpcLogging) implementation(libs.kotlin.test) implementation(libs.ktor.server.netty) implementation(libs.ktor.server.test.host) + implementation(libs.ktor.server.websockets) + implementation(libs.ktor.client.core) + implementation(libs.ktor.client.websockets) + implementation(libs.ktor.client.cio) + implementation(libs.logback.classic) + implementation(libs.coroutines.debug) } } } diff --git a/krpc/krpc-ktor/krpc-ktor-core/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/KtorTransport.kt b/krpc/krpc-ktor/krpc-ktor-core/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/KtorTransport.kt index ed12adc72..b46bd644b 100644 --- a/krpc/krpc-ktor/krpc-ktor-core/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/KtorTransport.kt +++ b/krpc/krpc-ktor/krpc-ktor-core/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/KtorTransport.kt @@ -16,7 +16,7 @@ public class KtorTransport( ) : KrpcTransport, CoroutineScope by webSocketSession { /** - * Sends a single encoded RPC message over network (or any other medium) to a peer endpoint. + * Sends a single encoded RPC message over a network (or any other medium) to a peer endpoint. * * @param message a message to send. Either of string or binary type. */ @@ -33,9 +33,9 @@ public class KtorTransport( } /** - * Suspends until next RPC message from a peer endpoint is received and then returns it. + * Suspends until the next RPC message from a peer endpoint is received and then returns it. * - * @return received RPC message. + * @return the received RPC message. */ override suspend fun receive(): KrpcTransportMessage { return when (val message = webSocketSession.incoming.receive()) { diff --git a/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/kotlin/kotlinx/rpc/krpc/ktor/KtorTransportTest.kt b/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/kotlin/kotlinx/rpc/krpc/ktor/KtorTransportTest.kt index b7584d98a..9eb506b42 100644 --- a/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/kotlin/kotlinx/rpc/krpc/ktor/KtorTransportTest.kt +++ b/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/kotlin/kotlinx/rpc/krpc/ktor/KtorTransportTest.kt @@ -6,11 +6,23 @@ package kotlinx.rpc.krpc.ktor +import io.ktor.client.* +import io.ktor.client.engine.cio.* +import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.server.application.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* +import io.ktor.server.response.* +import io.ktor.server.routing.* import io.ktor.server.testing.* -import kotlinx.coroutines.cancel -import kotlinx.rpc.RemoteService +import kotlinx.coroutines.* +import kotlinx.coroutines.debug.DebugProbes +import kotlinx.coroutines.test.runTest import kotlinx.rpc.annotations.Rpc +import kotlinx.rpc.krpc.client.KrpcClient +import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLogger +import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLoggerContainer import kotlinx.rpc.krpc.ktor.client.installKrpc import kotlinx.rpc.krpc.ktor.client.rpc import kotlinx.rpc.krpc.ktor.client.rpcConfig @@ -19,16 +31,22 @@ import kotlinx.rpc.krpc.ktor.server.rpc import kotlinx.rpc.krpc.serialization.json.json import kotlinx.rpc.withService import org.junit.Assert.assertEquals -import kotlin.coroutines.CoroutineContext +import org.junit.platform.commons.logging.Logger +import org.junit.platform.commons.logging.LoggerFactory +import java.net.ServerSocket +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit +import kotlin.coroutines.cancellation.CancellationException +import kotlin.test.Ignore import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds @Rpc -interface NewService : RemoteService { +interface NewService { suspend fun echo(value: String): String } class NewServiceImpl( - override val coroutineContext: CoroutineContext, private val call: ApplicationCall, ) : NewService { @Suppress("UastIncorrectHttpHeaderInspection") @@ -38,6 +56,23 @@ class NewServiceImpl( } } +@Rpc +interface SlowService { + suspend fun verySlow(): String +} + +class SlowServiceImpl : SlowService { + val received = CompletableDeferred() + + override suspend fun verySlow(): String { + received.complete(Unit) + + delay(Int.MAX_VALUE.toLong()) + + error("Must not be called") + } +} + class KtorTransportTest { @Test fun testEcho() = testApplication { @@ -54,7 +89,7 @@ class KtorTransportTest { waitForServices = true } - registerService { NewServiceImpl(it, call) } + registerService { NewServiceImpl(call) } } } @@ -77,7 +112,6 @@ class KtorTransportTest { assertEquals("Hello, world!", firstActual) - serviceWithGlobalConfig.cancel() clientWithGlobalConfig.cancel() val clientWithNoConfig = createClient { @@ -98,7 +132,133 @@ class KtorTransportTest { assertEquals("Hello, world!", secondActual) - serviceWithLocalConfig.cancel() clientWithNoConfig.cancel() } + + @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) + @Test + @Ignore("Wait for Ktor fix (https://github.com/ktorio/ktor/pull/4927) or apply workaround if rejected") + fun testEndpointsTerminateWhenWsDoes() = runTest(timeout = 15.seconds) { + DebugProbes.install() + + val logger = setupLogger() + + val port: Int = findFreePort() + + val newPool = Executors.newCachedThreadPool().asCoroutineDispatcher() + + val serverReady = CompletableDeferred() + val dropServer = CompletableDeferred() + + val service = SlowServiceImpl() + + @Suppress("detekt.GlobalCoroutineUsage") + val serverJob = GlobalScope.launch(CoroutineName("server")) { + withContext(newPool) { + val server = embeddedServer( + factory = Netty, + port = port, + parentCoroutineContext = newPool, + ) { + install(Krpc) + + routing { + get { + call.respondText("hello") + } + + rpc("/rpc") { + rpcConfig { + serialization { + json() + } + } + + registerService { service } + } + } + }.start(wait = false) + + serverReady.complete(Unit) + + dropServer.await() + + server.stop(shutdownGracePeriod = 100L, shutdownTimeout = 100L, timeUnit = TimeUnit.MILLISECONDS) + } + + logger.info { "Server stopped" } + } + + val ktorClient = HttpClient(CIO) { + installKrpc { + serialization { + json() + } + } + } + + serverReady.await() + + assertEquals("hello", ktorClient.get("http://0.0.0.0:$port").bodyAsText()) + + val rpcClient = ktorClient.rpc("ws://0.0.0.0:$port/rpc") + + launch { + try { + rpcClient.withService().verySlow() + error("Must not be called") + } catch (_: CancellationException) { + logger.info { "Cancellation exception caught for RPC request" } + ensureActive() + } + } + + service.received.await() + + logger.info { "Received RPC request" } + + dropServer.complete(Unit) + + logger.info { "Waiting for RPC client to complete" } + + (rpcClient as KrpcClient).awaitCompletion() + + logger.info { "RPC client completed" } + + ktorClient.close() + newPool.close() + + serverJob.cancel() + } + + private fun findFreePort(): Int { + val port: Int + while (true) { + val socket = try { + ServerSocket(0) + } catch (_: Throwable) { + continue + } + + port = socket.localPort + socket.close() + break + } + return port + } + + private fun setupLogger(): Logger { + val logger = LoggerFactory.getLogger(KtorTransportTest::class.java) + + RpcInternalDumpLoggerContainer.set(object : RpcInternalDumpLogger { + + override val isEnabled: Boolean = true + + override fun dump(vararg tags: String, message: () -> String) { + logger.info { "[${tags.joinToString()}] ${message()}" } + } + }) + + return logger + } } diff --git a/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/resources/logback.xml b/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/resources/logback.xml new file mode 100644 index 000000000..5ccb239b2 --- /dev/null +++ b/krpc/krpc-ktor/krpc-ktor-core/src/jvmTest/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/krpc/krpc-ktor/krpc-ktor-server/api/krpc-ktor-server.api b/krpc/krpc-ktor/krpc-ktor-server/api/krpc-ktor-server.api index 7ed6450b0..feb0180fb 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/api/krpc-ktor-server.api +++ b/krpc/krpc-ktor/krpc-ktor-server/api/krpc-ktor-server.api @@ -1,6 +1,5 @@ public final class kotlinx/rpc/krpc/ktor/server/KrpcKt { public static final fun getKrpc ()Lio/ktor/server/application/ApplicationPlugin; - public static final fun getRPC ()Lio/ktor/server/application/ApplicationPlugin; } public final class kotlinx/rpc/krpc/ktor/server/KrpcRoute : io/ktor/server/websocket/DefaultWebSocketServerSession { @@ -16,7 +15,7 @@ public final class kotlinx/rpc/krpc/ktor/server/KrpcRoute : io/ktor/server/webso public fun getOutgoing ()Lkotlinx/coroutines/channels/SendChannel; public fun getPingIntervalMillis ()J public fun getTimeoutMillis ()J - public final fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V + public final fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function0;)V public final fun rpcConfig (Lkotlin/jvm/functions/Function1;)V public fun send (Lio/ktor/websocket/Frame;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun setMasking (Z)V diff --git a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/Krpc.kt b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/Krpc.kt index 41ac1076c..f14dc06a7 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/Krpc.kt +++ b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/Krpc.kt @@ -11,9 +11,6 @@ import kotlinx.rpc.krpc.KrpcConfigBuilder internal val KrpcServerPluginAttributesKey = AttributeKey("KrpcServerPluginAttributesKey") -@Deprecated("Use Krpc instead", ReplaceWith("Krpc"), level = DeprecationLevel.ERROR) -public val RPC: ApplicationPlugin get() = Krpc - /** * Ktor server plugin that allows to configure RPC globally for all mounted servers. */ diff --git a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KrpcRoute.kt b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KrpcRoute.kt index efff16c5e..bcd6e5088 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KrpcRoute.kt +++ b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KrpcRoute.kt @@ -8,15 +8,11 @@ import io.ktor.server.websocket.* import kotlinx.rpc.RpcServer import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.krpc.KrpcConfigBuilder -import kotlin.coroutines.CoroutineContext import kotlin.reflect.KClass -@Deprecated("Use KrpcRoute instead", ReplaceWith("KrpcRoute"), level = DeprecationLevel.ERROR) -public typealias RPCRoute = KrpcRoute - /** - * RpcRoute class represents an RPC server that is mounted in Ktor routing. - * This class provides API to register services and optionally setup configuration. + * [KrpcRoute] class represents an RPC server mounted in Ktor routing. + * This class provides an API to register services and optionally setup configuration. */ public class KrpcRoute( webSocketSession: DefaultWebSocketServerSession @@ -40,14 +36,14 @@ public class KrpcRoute( * Service of any type should be unique on the server, but RpcServer does not specify the actual retention policy. * * @param Service the exact type of the server to be registered. - * For example for service with `MyService` interface and `MyServiceImpl` implementation, + * For example, for service with `MyService` interface and `MyServiceImpl` implementation, * type `MyService` should be specified explicitly. * @param serviceKClass [KClass] of the [Service]. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. */ public fun <@Rpc Service : Any> registerService( serviceKClass: KClass, - serviceFactory: (CoroutineContext) -> Service, + serviceFactory: () -> Service, ) { registrations.add { server -> server.registerService(serviceKClass, serviceFactory) @@ -59,12 +55,12 @@ public class KrpcRoute( * Service of any type should be unique on the server, but RpcServer does not specify the actual retention policy. * * @param Service the exact type of the server to be registered. - * For example for service with `MyService` interface and `MyServiceImpl` implementation, + * For example, for service with `MyService` interface and `MyServiceImpl` implementation, * type `MyService` should be specified explicitly. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. */ public inline fun <@Rpc reified Service : Any> registerService( - noinline serviceFactory: (CoroutineContext) -> Service, + noinline serviceFactory: () -> Service, ) { registerService(Service::class, serviceFactory) } diff --git a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt index 927e61a67..ae4e5e574 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt +++ b/krpc/krpc-ktor/krpc-ktor-server/src/commonMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt @@ -54,6 +54,6 @@ private fun Route.createRpcServer(rpcRouteBuilder: KrpcRoute.() -> Unit) { registration(server) } - server.coroutineContext.job.join() + server.internalScope.coroutineContext.job.join() } } diff --git a/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormat.kt b/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormat.kt index 3f1f129a7..5e8c060d7 100644 --- a/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormat.kt +++ b/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormat.kt @@ -10,9 +10,6 @@ import kotlinx.serialization.SerialFormat import kotlinx.serialization.StringFormat import kotlinx.serialization.modules.SerializersModule -@Deprecated("Use KrpcSerialFormat instead", ReplaceWith("KrpcSerialFormat"), level = DeprecationLevel.ERROR) -public typealias RPCSerialFormat = KrpcSerialFormat - /** * [KrpcSerialFormat] interface defines an object which helps kRPC protocol to work with various serialization formats * @@ -35,13 +32,6 @@ public interface KrpcSerialFormat { public fun FormatBuilder.applySerializersModule(serializersModule: SerializersModule) } -@Deprecated( - "Use KrpcSerialFormatBuilder instead", - ReplaceWith("KrpcSerialFormatBuilder"), - level = DeprecationLevel.ERROR, -) -public typealias RPCSerialFormatBuilder = KrpcSerialFormatBuilder - /** * Special wrapper class that is used to register serialization format in [KrpcSerialFormatConfiguration] * Comes in two instances: [KrpcSerialFormatBuilder.Binary] and [KrpcSerialFormatBuilder.String] diff --git a/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormatConfiguration.kt b/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormatConfiguration.kt index 3e777102b..fa764ddc6 100644 --- a/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormatConfiguration.kt +++ b/krpc/krpc-serialization/krpc-serialization-core/src/commonMain/kotlin/kotlinx/rpc/krpc/serialization/KrpcSerialFormatConfiguration.kt @@ -4,13 +4,6 @@ package kotlinx.rpc.krpc.serialization -@Deprecated( - "Use KrpcSerialFormatConfiguration instead", - ReplaceWith("KrpcSerialFormatConfiguration"), - level = DeprecationLevel.ERROR, -) -public typealias RPCSerialFormatConfiguration = KrpcSerialFormatConfiguration - /** * Special interface to configure serialization for a kRPC protocol in KrpcConfig * ```kotlin diff --git a/krpc/krpc-server/api/krpc-server.api b/krpc/krpc-server/api/krpc-server.api index 41b38da45..7d1f9c37c 100644 --- a/krpc/krpc-server/api/krpc-server.api +++ b/krpc/krpc-server/api/krpc-server.api @@ -1,6 +1,9 @@ public abstract class kotlinx/rpc/krpc/server/KrpcServer : kotlinx/rpc/RpcServer, kotlinx/rpc/krpc/internal/KrpcEndpoint { public fun (Lkotlinx/rpc/krpc/KrpcConfig$Server;Lkotlinx/rpc/krpc/KrpcTransport;)V - public final fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; - public final fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V + public final fun awaitCompletion (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun close (Ljava/lang/String;)V + public static synthetic fun close$default (Lkotlinx/rpc/krpc/server/KrpcServer;Ljava/lang/String;ILjava/lang/Object;)V + public fun deregisterService (Lkotlin/reflect/KClass;)V + public final fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function0;)V } diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/KrpcServer.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/KrpcServer.kt index 8782071d4..898f3a266 100644 --- a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/KrpcServer.kt +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/KrpcServer.kt @@ -17,25 +17,15 @@ import kotlinx.rpc.krpc.internal.* import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger import kotlinx.rpc.krpc.server.internal.KrpcServerConnector import kotlinx.rpc.krpc.server.internal.KrpcServerService -import kotlin.coroutines.CoroutineContext +import kotlin.concurrent.Volatile import kotlin.reflect.KClass -@Deprecated("Use KrpcServer instead", ReplaceWith("KrpcServer"), level = DeprecationLevel.ERROR) -public typealias KRPCServer = KrpcServer - /** - * Default implementation of [RpcServer]. + * kRPC implementation of the [RpcServer]. * Takes care of tracking requests and responses, * serializing data, tracking streams, processing exceptions, and other protocol responsibilities. * Routes resulting messages to the proper registered services. - * Leaves out the delivery of encoded messages to the specific implementations. - * - * A simple example of how this server may be implemented: - * ```kotlin - * class MyTransport : KrpcTransport { /*...*/ } - * - * class MyServer(config: KrpcConfig.Server): KrpcServer(config, MyTransport()) - * ``` + * Leaves out the delivery of encoded messages to the specific implementations with [KrpcTransport]. * * @param config configuration provided for that specific server. Applied to all services that use this server. * @param transport [KrpcTransport] instance that will be used to send and receive RPC messages. @@ -46,8 +36,31 @@ public abstract class KrpcServer( private val config: KrpcConfig.Server, transport: KrpcTransport, ) : RpcServer, KrpcEndpoint { - // we make a child here, so we can send cancellation messages before closing the connection - final override val coroutineContext: CoroutineContext = SupervisorJob(transport.coroutineContext.job) + + /** + * Close this server, removing all the services and stopping accepting messages. + */ + public fun close(message: String? = null) { + internalScope.cancel(message ?: "Server closed") + } + + /** + * Waits until the server is closed. + */ + public suspend fun awaitCompletion() { + internalScope.coroutineContext.job.join() + } + + /* + * ##################################################################### + * # # + * # INTERNALS AHEAD # + * # # + * ##################################################################### + */ + + @InternalRpcApi + public val internalScope: CoroutineScope = CoroutineScope(SupervisorJob(transport.coroutineContext.job)) private val logger = RpcInternalCommonLogger.logger(rpcInternalObjectId()) @@ -66,21 +79,19 @@ public abstract class KrpcServer( final override var supportedPlugins: Set = emptySet() private set - private val rpcServices = RpcInternalConcurrentHashMap>() - - // compatibility with clients that do not have serviceId - private var nullRpcServices = RpcInternalConcurrentHashMap>() + private val rpcServices = RpcInternalConcurrentHashMap>() + @Volatile private var cancelledByClient = false init { - coroutineContext.job.invokeOnCompletion(onCancelling = true) { + internalScope.coroutineContext.job.invokeOnCompletion(onCancelling = true) { if (!cancelledByClient) { sendCancellation(CancellationType.ENDPOINT, null, null, closeTransportAfterSending = true) } } - launch { + internalScope.launch(CoroutineName("krpc-server-generic-protocol-messages")) { connector.subscribeToProtocolMessages(::handleProtocolMessage) connector.subscribeToGenericMessages(::handleGenericMessage) @@ -105,20 +116,14 @@ public abstract class KrpcServer( final override fun <@Rpc Service : Any> registerService( serviceKClass: KClass, - serviceFactory: (CoroutineContext) -> Service, + serviceFactory: () -> Service, ) { val descriptor = serviceDescriptorOf(serviceKClass) - launch { + internalScope.launch(CoroutineName("krpc-server-service-$descriptor")) { connector.subscribeToServiceMessages(descriptor.fqName) { message -> - val rpcServerService = when (val id = message.serviceId) { - null -> nullRpcServices.computeIfAbsent(descriptor.fqName) { - createNewServiceInstance(descriptor, serviceFactory) - } - - else -> rpcServices.computeIfAbsent(id) { - createNewServiceInstance(descriptor, serviceFactory) - } + val rpcServerService = rpcServices.computeIfAbsent(descriptor.fqName) { + createNewServiceInstance(descriptor, serviceFactory) } rpcServerService.accept(message) @@ -126,23 +131,23 @@ public abstract class KrpcServer( } } + override fun <@Rpc Service : Any> deregisterService(serviceKClass: KClass) { + connector.unsubscribeFromServiceMessages(serviceDescriptorOf(serviceKClass).fqName) + rpcServices.remove(serviceDescriptorOf(serviceKClass).fqName) + } + private fun <@Rpc Service : Any> createNewServiceInstance( descriptor: RpcServiceDescriptor, - serviceFactory: (CoroutineContext) -> Service, + serviceFactory: () -> Service, ): KrpcServerService { - val serviceInstanceContext = SupervisorJob(coroutineContext.job) - return KrpcServerService( - service = serviceFactory(serviceInstanceContext), + service = serviceFactory(), descriptor = descriptor, config = config, connector = connector, - coroutineContext = serviceInstanceContext, - ).apply { - coroutineContext.job.invokeOnCompletion { - connector.unsubscribeFromServiceMessages(descriptor.fqName) - } - } + supportedPlugins = supportedPlugins, + serverScope = internalScope, + ) } @InternalRpcApi @@ -151,25 +156,18 @@ public abstract class KrpcServer( CancellationType.ENDPOINT -> { cancelledByClient = true - cancel("Server cancelled by client") + internalScope.cancel("Server cancelled by client") rpcServices.clear() } - CancellationType.SERVICE -> { - val serviceId = message[KrpcPluginKey.CLIENT_SERVICE_ID]?.toLongOrNull() - ?: error("Expected CLIENT_SERVICE_ID for cancellation of type 'service' as Long value") - - rpcServices[serviceId]?.cancel("Service cancelled by client") - } - CancellationType.REQUEST -> { - val serviceId = message[KrpcPluginKey.CLIENT_SERVICE_ID]?.toLongOrNull() - ?: error("Expected CLIENT_SERVICE_ID for cancellation of type 'request' as Long value") + val serviceType = message[KrpcPluginKey.CLIENT_SERVICE_ID] + ?: error("Expected CLIENT_SERVICE_ID for cancellation of type 'request'") val callId = message[KrpcPluginKey.CANCELLATION_ID] ?: error("Expected CANCELLATION_ID for cancellation of type 'request'") - rpcServices[serviceId]?.cancelRequest(callId, "Request cancelled by client") + rpcServices[serviceType]?.cancelRequestWithOptionalAck(callId, "Request cancelled by client") } else -> { diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerConnector.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerConnector.kt index 804c9d249..886441247 100644 --- a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerConnector.kt +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/KrpcServerConnector.kt @@ -33,8 +33,8 @@ internal class KrpcServerConnector private constructor( } ) - fun unsubscribeFromServiceMessages(serviceTypeString: String) { - connector.unsubscribeFromMessages(MessageKey.Service(serviceTypeString)) + fun unsubscribeFromServiceMessages(serviceTypeString: String, callback: () -> Unit = {}) { + connector.unsubscribeFromMessages(MessageKey.Service(serviceTypeString), callback) } suspend fun subscribeToServiceMessages( 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 c7d5532ed..5f4a10cb4 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 @@ -11,39 +11,27 @@ import kotlinx.rpc.descriptor.RpcInvokator import kotlinx.rpc.descriptor.RpcServiceDescriptor import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap import kotlinx.rpc.krpc.KrpcConfig -import kotlinx.rpc.krpc.callScoped import kotlinx.rpc.krpc.internal.* import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger -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 +import kotlinx.serialization.modules.SerializersModule import kotlin.reflect.typeOf internal class KrpcServerService<@Rpc T : Any>( private val service: T, private val descriptor: RpcServiceDescriptor, - override val config: KrpcConfig.Server, + private val config: KrpcConfig.Server, private val connector: KrpcServerConnector, - coroutineContext: CoroutineContext, -) : KrpcServiceHandler(), CoroutineScope { - override val logger = RpcInternalCommonLogger.logger(rpcInternalObjectId(descriptor.fqName)) - override val sender: KrpcMessageSender get() = connector - private val scope: CoroutineScope = this - - override val coroutineContext: CoroutineContext = coroutineContext.withServerStreamScope() + private val serverScope: CoroutineScope, + private val supportedPlugins: Set, +) { + private val logger = RpcInternalCommonLogger.logger(rpcInternalObjectId(descriptor.fqName)) private val requestMap = RpcInternalConcurrentHashMap() - init { - coroutineContext.job.invokeOnCompletion { - logger.trace { "Service completed with $it" } - } - } - suspend fun accept(message: KrpcCallMessage) { val result = runCatching { processMessage(message) @@ -71,7 +59,7 @@ internal class KrpcServerService<@Rpc T : Any>( connectionId = message.connectionId, ) - sender.sendMessage(errorMessage) + connector.sendMessage(errorMessage) } } @@ -97,37 +85,24 @@ internal class KrpcServerService<@Rpc T : Any>( is KrpcCallMessage.StreamCancel -> { // if no stream is present, it probably was already canceled - getAndAwaitStreamContext(message) - ?.cancelStream(message) + serverStreamContext.cancelStream(message) } is KrpcCallMessage.StreamFinished -> { // if no stream is present, it probably was already finished - getAndAwaitStreamContext(message) - ?.closeStream(message) + serverStreamContext.closeStream(message) } is KrpcCallMessage.StreamMessage -> { - requestMap[message.callId]?.streamContext?.apply { - awaitInitialized().send(message, prepareSerialFormat(this)) - } ?: error("Invalid request call id: ${message.callId}") + serverStreamContext.send(message, serialFormat) } } } - private suspend fun getAndAwaitStreamContext(message: KrpcCallMessage): KrpcStreamContext? { - return requestMap[message.callId]?.streamContext?.awaitInitialized() - } - @Suppress("detekt.ThrowsCount", "detekt.LongMethod") private fun handleCall(callData: KrpcCallMessage.CallData) { val callId = callData.callId - val streamContext = LazyKrpcStreamContext(streamScopeOrNull(scope)) { - KrpcStreamContext(callId, config, callData.connectionId, callData.serviceId, it) - } - val serialFormat = prepareSerialFormat(streamContext) - val isMethod = when (callData.callType) { KrpcCallMessage.CallType.Method -> true KrpcCallMessage.CallType.Field -> false @@ -135,6 +110,14 @@ internal class KrpcServerService<@Rpc T : Any>( .endsWith("\$method") // compatibility with beta-4.2 clients } + if (!isMethod) { + error( + "Service ${descriptor.fqName} doesn't support fields calls, " + + "but got a field call: ${callData.callableName} with callId $callId. " + + "Please, update the client version or change the call type to method." + ) + } + val callableName = callData.callableName .substringBefore('$') // compatibility with beta-4.2 clients @@ -148,14 +131,16 @@ internal class KrpcServerService<@Rpc T : Any>( val data = if (isMethod) { val serializerModule = serialFormat.serializersModule val paramsSerializer = serializerModule.rpcSerializerForType(callable.dataType) - decodeMessageData(serialFormat, paramsSerializer, callData) + serverStreamContext.scoped(callId) { + decodeMessageData(serialFormat, paramsSerializer, callData) + } } else { null } var failure: Throwable? = null - val requestJob = launch(start = CoroutineStart.LAZY) { + val requestJob = serverScope.launch(start = CoroutineStart.LAZY) { try { val markedNonSuspending = callData.pluginParams.orEmpty() .contains(KrpcPluginKey.NON_SUSPENDING_SERVER_FLOW_MARKER) @@ -171,13 +156,7 @@ internal class KrpcServerService<@Rpc T : Any>( val value = when (val invokator = callable.invokator) { is RpcInvokator.Method -> { - callScoped(callId) { - invokator.call(service, data) - } - } - - is RpcInvokator.Field -> { - invokator.call(service) + invokator.call(service, data) } }.let { interceptedValue -> // KRPC-173 @@ -216,27 +195,17 @@ internal class KrpcServerService<@Rpc T : Any>( cause = serializedCause, connectionId = callData.connectionId, serviceId = callData.serviceId, - ).also { sender.sendMessage(it) } + ).also { connector.sendMessage(it) } } - if (failure == null) { - streamContext.valueOrNull?.apply { - launchIf({ incomingHotFlowsAvailable }) { - handleIncomingHotFlows(it) - } - - launchIf({ outgoingStreamsAvailable }) { - handleOutgoingStreams(it, serialFormat, descriptor.fqName) - } - } ?: run { - cancelRequest(callId, fromJob = true) - } - } else { + if (failure != null) { cancelRequest(callId, "Server request failed", failure, fromJob = true) + } else { + cancelRequest(callId, fromJob = true) } } - requestMap[callId] = RpcRequest(requestJob, streamContext) + requestMap[callId] = RpcRequest(requestJob, serverStreamContext) requestJob.start() } @@ -275,7 +244,7 @@ internal class KrpcServerService<@Rpc T : Any>( } } - sender.sendMessage(result) + connector.sendMessage(result) } private suspend fun sendFlowMessages( @@ -352,18 +321,40 @@ internal class KrpcServerService<@Rpc T : Any>( fromJob: Boolean = false, ) { requestMap.remove(callId)?.cancelAndClose(callId, message, cause, fromJob) + } - // acknowledge the cancellation - sender.sendMessage( - KrpcGenericMessage( - connectionId = null, - pluginParams = mapOf( - KrpcPluginKey.GENERIC_MESSAGE_TYPE to KrpcGenericMessage.CANCELLATION_TYPE, - KrpcPluginKey.CANCELLATION_TYPE to CancellationType.CANCELLATION_ACK.toString(), - KrpcPluginKey.CANCELLATION_ID to callId, + suspend fun cancelRequestWithOptionalAck( + callId: String, + message: String? = null, + cause: Throwable? = null, + ) { + cancelRequest(callId, message, cause, fromJob = false) + + if (!supportedPlugins.contains(KrpcPlugin.NO_ACK_CANCELLATION)) { + connector.sendMessage( + KrpcGenericMessage( + connectionId = null, + pluginParams = mapOf( + KrpcPluginKey.GENERIC_MESSAGE_TYPE to KrpcGenericMessage.CANCELLATION_TYPE, + KrpcPluginKey.CANCELLATION_TYPE to CancellationType.CANCELLATION_ACK.toString(), + KrpcPluginKey.CANCELLATION_ID to callId, + ) ) ) - ) + } + } + + private val serverStreamContext: ServerStreamContext = ServerStreamContext() + + private val serialFormat: SerialFormat by lazy { + val module = SerializersModule { + contextual(Flow::class) { + @Suppress("UNCHECKED_CAST") + ServerStreamSerializer(serverStreamContext, it.first() as KSerializer) + } + } + + config.serialFormatInitializer.applySerializersModuleAndBuild(module) } companion object { @@ -373,7 +364,7 @@ internal class KrpcServerService<@Rpc T : Any>( } } -internal class RpcRequest(val handlerJob: Job, val streamContext: LazyKrpcStreamContext) { +internal class RpcRequest(val handlerJob: Job, val streamContext: ServerStreamContext) { suspend fun cancelAndClose( callId: String, message: String? = null, @@ -390,13 +381,6 @@ internal class RpcRequest(val handlerJob: Job, val streamContext: LazyKrpcStream handlerJob.join() } - val ctx = streamContext.valueOrNull - if (ctx == null) { - streamContext.streamScopeOrNull - ?.cancelRequestScopeById(callId, message ?: "Scope cancelled", cause) - ?.join() - } else { - ctx.cancel(message ?: "Request cancelled", cause)?.join() - } + streamContext.removeCall(callId, cause) } } diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamContext.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamContext.kt new file mode 100644 index 000000000..8e2f01b73 --- /dev/null +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamContext.kt @@ -0,0 +1,96 @@ +/* + * 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.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap +import kotlinx.rpc.internal.utils.thread.RpcInternalThreadLocal +import kotlinx.rpc.krpc.internal.KrpcCallMessage +import kotlinx.rpc.krpc.internal.decodeMessageData +import kotlinx.rpc.krpc.internal.deserialize +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialFormat + +internal class ServerStreamContext { + private val currentCallId = RpcInternalThreadLocal() + + fun scoped(callId: String, body: () -> T): T { + try { + currentCallId.set(callId) + return body() + } finally { + currentCallId.remove() + } + } + + private val streams = RpcInternalConcurrentHashMap>() + + suspend fun send(message: KrpcCallMessage.StreamMessage, serialFormat: SerialFormat) { + val call = streams[message.callId]?.get(message.streamId) ?: return + val data = scoped(message.streamId) { + decodeMessageData(serialFormat, call.elementSerializer, message) + } + call.channel.send(data) + } + + suspend fun cancelStream(message: KrpcCallMessage.StreamCancel) { + streams[message.callId]?.get(message.streamId)?.channel?.send(StreamCancel(message.cause.deserialize())) + } + + suspend fun closeStream(message: KrpcCallMessage.StreamFinished) { + streams[message.callId]?.get(message.streamId)?.channel?.send(StreamEnd) + } + + fun removeCall(callId: String, cause: Throwable?) { + streams.remove(callId)?.values?.forEach { + it.channel.close(cause) + } + } + + fun prepareClientStream(streamId: String, elementKind: KSerializer): Flow { + val callId = currentCallId.get() ?: error("No call id") + + val channel = Channel(Channel.UNLIMITED) + + @Suppress("UNCHECKED_CAST") + val map = streams.computeIfAbsent(callId) { RpcInternalConcurrentHashMap() } + map[streamId] = StreamCall(callId, streamId, channel, elementKind) + + fun onClose() { + channel.cancel() + map.remove(streamId) + } + + val flow = flow { + for (message in channel) { + when (message) { + is StreamCancel -> { + onClose() + throw message.cause ?: streamCanceled() + } + + is StreamEnd -> { + onClose() + + return@flow + } + + else -> { + emit(message) + } + } + } + } + + return flow + } + + private fun streamCanceled(): Throwable = NoSuchElementException("Stream canceled") +} + +private data class StreamCancel(val cause: Throwable? = null) +private data object StreamEnd diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamSerializer.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamSerializer.kt new file mode 100644 index 000000000..be9b292bc --- /dev/null +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/ServerStreamSerializer.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023-2024 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.flow.Flow +import kotlinx.rpc.krpc.internal.StreamSerializer +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal class ServerStreamSerializer( + val context: ServerStreamContext, + val elementType: KSerializer, +) : KSerializer>, StreamSerializer() { + override val descriptor: SerialDescriptor by lazy { + buildClassSerialDescriptor("ServerStreamSerializer") { + element(STREAM_ID_SERIAL_NAME, streamIdDescriptor) + } + } + + override fun deserialize(decoder: Decoder): Flow<*> { + val streamId = decoder.decodeString() + + return context.prepareClientStream(streamId, elementType) + } + + override fun serialize(encoder: Encoder, value: Flow<*>) { + error("This method must not be called. Please report to the developer.") + } +} diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/StreamCall.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/StreamCall.kt new file mode 100644 index 000000000..9ff3fb526 --- /dev/null +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/StreamCall.kt @@ -0,0 +1,15 @@ +/* + * 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.channels.Channel +import kotlinx.serialization.KSerializer + +internal data class StreamCall( + val callId: String, + val streamId: String, + val channel: Channel, + val elementSerializer: KSerializer, +) diff --git a/krpc/krpc-test/build.gradle.kts b/krpc/krpc-test/build.gradle.kts index 0ba1b3566..ba1b5a810 100644 --- a/krpc/krpc-test/build.gradle.kts +++ b/krpc/krpc-test/build.gradle.kts @@ -28,6 +28,7 @@ kotlin { api(projects.krpc.krpcCore) api(projects.krpc.krpcServer) api(projects.krpc.krpcClient) + api(projects.krpc.krpcLogging) implementation(projects.krpc.krpcSerialization.krpcSerializationJson) @@ -39,6 +40,7 @@ kotlin { jvmMain { dependencies { + implementation(libs.coroutines.debug) implementation(libs.kotlin.test.junit) } } @@ -101,15 +103,3 @@ tasks.register("moveToGold") { } } } - -rpc { - strict { - stateFlow = RpcStrictMode.NONE - sharedFlow = RpcStrictMode.NONE - nestedFlow = RpcStrictMode.NONE - streamScopedFunctions = RpcStrictMode.NONE - suspendingServerStreaming = RpcStrictMode.NONE - notTopLevelServerFlow = RpcStrictMode.NONE - fields = RpcStrictMode.NONE - } -} diff --git a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestClient.kt b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestClient.kt index 5799f4328..8008a31be 100644 --- a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestClient.kt +++ b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestClient.kt @@ -6,6 +6,7 @@ package kotlinx.rpc.krpc.test import kotlinx.rpc.krpc.KrpcConfig import kotlinx.rpc.krpc.KrpcTransport +import kotlinx.rpc.krpc.client.InitializedKrpcClient import kotlinx.rpc.krpc.client.KrpcClient /** @@ -17,4 +18,4 @@ import kotlinx.rpc.krpc.client.KrpcClient class KrpcTestClient( config: KrpcConfig.Client, transport: KrpcTransport, -) : KrpcClient(config, transport) +) : InitializedKrpcClient(config, transport) diff --git a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt index ac23ea832..45aca6030 100644 --- a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt +++ b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestService.kt @@ -5,9 +5,6 @@ package kotlinx.rpc.krpc.test import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.serialization.Contextual import kotlinx.serialization.Serializable @@ -45,7 +42,7 @@ data class LocalDateTime( @Suppress("detekt.TooManyFunctions") @Rpc -interface KrpcTestService : RemoteService { +interface KrpcTestService { fun nonSuspendFlow(): Flow fun nonSuspendFlowErrorOnEmit(): Flow fun nonSuspendFlowErrorOnReturn(): Flow @@ -73,29 +70,15 @@ interface KrpcTestService : RemoteService { ): String suspend fun incomingStreamSyncCollect(arg1: Flow): Int - suspend fun incomingStreamAsyncCollect(arg1: Flow): Int - suspend fun outgoingStream(): Flow - suspend fun bidirectionalStream(arg1: Flow): Flow - suspend fun echoStream(arg1: Flow): Flow + suspend fun incomingStreamSyncCollectMultiple(arg1: Flow, arg2: Flow, arg3: Flow): Int + fun outgoingStream(): Flow + fun bidirectionalStream(arg1: Flow): Flow + fun echoStream(arg1: Flow): Flow suspend fun streamInDataClass(payloadWithStream: PayloadWithStream): Int - suspend fun streamInStream(payloadWithStream: Flow): Int - suspend fun streamOutDataClass(): PayloadWithStream - suspend fun streamOfStreamsInReturn(): Flow> - suspend fun streamOfPayloadsInReturn(): Flow - - suspend fun streamInDataClassWithStream(payloadWithPayload: PayloadWithPayload): Int - suspend fun streamInStreamWithStream(payloadWithPayload: Flow): Int - suspend fun returnPayloadWithPayload(): PayloadWithPayload - suspend fun returnFlowPayloadWithPayload(): Flow - - suspend fun bidirectionalFlowOfPayloadWithPayload( - payloadWithPayload: Flow - ): Flow - - suspend fun getNInts(n: Int): Flow - suspend fun getNIntsBatched(n: Int): Flow> + fun getNInts(n: Int): Flow + fun getNIntsBatched(n: Int): Flow> suspend fun bytes(byteArray: ByteArray) suspend fun nullableBytes(byteArray: ByteArray?) @@ -107,39 +90,11 @@ interface KrpcTestService : RemoteService { suspend fun nullableInt(v: Int?): Int? suspend fun nullableList(v: List?): List? - suspend fun delayForever(): Flow + fun delayForever(): Flow suspend fun answerToAnything(arg: String): Int suspend fun krpc173() fun unitFlow(): Flow - - val plainFlowOfInts : Flow - - val plainFlowOfFlowsOfInts : Flow> - - val plainFlowOfFlowsOfFlowsOfInts : Flow>> - - val sharedFlowOfInts : SharedFlow - - val sharedFlowOfFlowsOfInts : SharedFlow> - - val sharedFlowOfFlowsOfFlowsOfInts : SharedFlow>> - - val stateFlowOfInts : StateFlow - - val stateFlowOfFlowsOfInts : StateFlow> - - val stateFlowOfFlowsOfFlowsOfInts : StateFlow>> - - suspend fun emitNextForStateFlowOfInts(value: Int) - - suspend fun emitNextForStateFlowOfFlowsOfInts(value: Int) - - suspend fun emitNextForStateFlowOfFlowsOfFlowsOfInts(value: Int) - - suspend fun sharedFlowInFunction(sharedFlow: SharedFlow): StateFlow - - suspend fun stateFlowInFunction(stateFlow: StateFlow): StateFlow } diff --git a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt index 014fc62d6..2ec18fb82 100644 --- a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt +++ b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.kt @@ -6,18 +6,14 @@ package kotlinx.rpc.krpc.test import kotlinx.coroutines.* import kotlinx.coroutines.flow.* +import kotlinx.coroutines.test.TestScope import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resumeWithException import kotlin.test.assertContentEquals import kotlin.test.assertEquals @OptIn(ExperimentalCoroutinesApi::class) -class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : KrpcTestService { - companion object { - const val SHARED_FLOW_REPLAY = 5 - } - +class KrpcTestServiceBackend : KrpcTestService { override fun nonSuspendFlow(): Flow { return flow { repeat(10) { @@ -133,27 +129,23 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : return arg1.count() } - val incomingStreamAsyncCollectLatch = CompletableDeferred() - - @OptIn(DelicateCoroutinesApi::class) - override suspend fun incomingStreamAsyncCollect(arg1: Flow): Int { - @Suppress("detekt.GlobalCoroutineUsage") - GlobalScope.launch { - assertContentEquals(listOf("test1", "test2", "test3"), arg1.toList()) - incomingStreamAsyncCollectLatch.complete(Unit) - } - return 5 + override suspend fun incomingStreamSyncCollectMultiple( + arg1: Flow, + arg2: Flow, + arg3: Flow, + ): Int { + return arg1.count() + arg2.count() + arg3.count() } - override suspend fun outgoingStream(): Flow { + override fun outgoingStream(): Flow { return flow { emit("a"); emit("b"); emit("c") } } - override suspend fun bidirectionalStream(arg1: Flow): Flow { + override fun bidirectionalStream(arg1: Flow): Flow { return arg1.map { it.reversed() } } - override suspend fun echoStream(arg1: Flow): Flow = flow { + override fun echoStream(arg1: Flow): Flow = flow { arg1.collect { emit(it) } @@ -163,55 +155,7 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : return payloadWithStream.payload.length + payloadWithStream.stream.count() } - // necessary for older Kotlin versions - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(FlowPreview::class) - override suspend fun streamInStream(payloadWithStream: Flow): Int { - return payloadWithStream.flatMapConcat { it.stream }.count() - } - - override suspend fun streamOutDataClass(): PayloadWithStream { - return payload() - } - - override suspend fun streamOfStreamsInReturn(): Flow> { - return flow { - emit(flow { emit("a"); emit("b"); emit("c") }) - emit(flow { emit("1"); emit("2"); emit("3") }) - } - } - - override suspend fun streamOfPayloadsInReturn(): Flow { - return payloadStream() - } - - override suspend fun streamInDataClassWithStream(payloadWithPayload: PayloadWithPayload): Int { - assertContentEquals(KrpcTransportTestBase.expectedPayloadWithPayload(10), payloadWithPayload.collect()) - return 5 - } - - override suspend fun streamInStreamWithStream(payloadWithPayload: Flow): Int { - payloadWithPayload.collectIndexed { index, payload -> - assertContentEquals(KrpcTransportTestBase.expectedPayloadWithPayload(index), payload.collect()) - } - return 5 - } - - override suspend fun returnPayloadWithPayload(): PayloadWithPayload { - return payloadWithPayload() - } - - override suspend fun returnFlowPayloadWithPayload(): Flow { - return payloadWithPayloadStream() - } - - override suspend fun bidirectionalFlowOfPayloadWithPayload( - payloadWithPayload: Flow - ): Flow { - return payloadWithPayload - } - - override suspend fun getNInts(n: Int): Flow { + override fun getNInts(n: Int): Flow { return flow { for (it in 1..n) { emit(it) @@ -219,7 +163,7 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : } } - override suspend fun getNIntsBatched(n: Int): Flow> { + override fun getNIntsBatched(n: Int): Flow> { return flow { for (it in (1..n).chunked(1000)) { emit(it) @@ -264,7 +208,7 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : override suspend fun nullableInt(v: Int?): Int? = v override suspend fun nullableList(v: List?): List? = v - override suspend fun delayForever(): Flow = flow { + override fun delayForever(): Flow = flow { emit(true) delay(Int.MAX_VALUE.toLong()) } @@ -287,68 +231,8 @@ class KrpcTestServiceBackend(override val coroutineContext: CoroutineContext) : emit(Unit) } } - - override val plainFlowOfInts: Flow = plainFlow { it } - - override val plainFlowOfFlowsOfInts: Flow> = plainFlow { plainFlow { i -> i } } - - override val plainFlowOfFlowsOfFlowsOfInts: Flow>> = plainFlow { plainFlow { plainFlow { i -> i } } } - - override val sharedFlowOfInts: SharedFlow = - sharedFlowOfT { it } - - override val sharedFlowOfFlowsOfInts: SharedFlow> = - sharedFlowOfT { sharedFlowOfT { it } } - - override val sharedFlowOfFlowsOfFlowsOfInts: SharedFlow>> = - sharedFlowOfT { sharedFlowOfT { sharedFlowOfT { it } } } - - override val stateFlowOfInts: MutableStateFlow = - stateFlowOfT { it } - - override val stateFlowOfFlowsOfInts: MutableStateFlow> = - stateFlowOfT { stateFlowOfT { it } } - - override val stateFlowOfFlowsOfFlowsOfInts: MutableStateFlow>> = - stateFlowOfT { stateFlowOfT { stateFlowOfT { it } } } - - override suspend fun emitNextForStateFlowOfInts(value: Int) { - stateFlowOfInts.emit(value) - } - - override suspend fun emitNextForStateFlowOfFlowsOfInts(value: Int) { - stateFlowOfFlowsOfInts.value.emit(value) - stateFlowOfFlowsOfInts.emit(MutableStateFlow(value)) - } - - override suspend fun emitNextForStateFlowOfFlowsOfFlowsOfInts(value: Int) { - stateFlowOfFlowsOfFlowsOfInts.value.value.emit(value) - stateFlowOfFlowsOfFlowsOfInts.value.emit(MutableStateFlow(value)) - stateFlowOfFlowsOfFlowsOfInts.emit(MutableStateFlow(MutableStateFlow(value))) - } - - override suspend fun sharedFlowInFunction(sharedFlow: SharedFlow): StateFlow { - val state = MutableStateFlow(-1) - - launch { - assertEquals(listOf(0, 1, 2, 3, 4), sharedFlow.take(5).toList()) - state.emit(1) - } - - return state - } - - override suspend fun stateFlowInFunction(stateFlow: StateFlow): StateFlow { - val state = MutableStateFlow(-1) - assertEquals(-1, stateFlow.value) - - launch { - assertEquals(42, stateFlow.first { it == 42 }) - state.emit(1) - } - - return state - } } internal expect fun runThreadIfPossible(runner: () -> Unit) + +internal expect fun TestScope.debugCoroutines() diff --git a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt index a994cf08e..10ce18120 100644 --- a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt +++ b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/KrpcTransportTestBase.kt @@ -12,13 +12,11 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.* import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.test.runTest -import kotlinx.rpc.awaitFieldInitialization import kotlinx.rpc.krpc.KrpcTransport import kotlinx.rpc.krpc.rpcClientConfig import kotlinx.rpc.krpc.rpcServerConfig import kotlinx.rpc.krpc.serialization.KrpcSerialFormatConfiguration import kotlinx.rpc.krpc.server.KrpcServer -import kotlinx.rpc.krpc.streamScoped import kotlinx.rpc.registerService import kotlinx.rpc.withService import kotlinx.serialization.KSerializer @@ -70,10 +68,6 @@ abstract class KrpcTransportTestBase { private val serverConfig by lazy { rpcServerConfig { - sharedFlowParameters { - replay = KrpcTestServiceBackend.SHARED_FLOW_REPLAY - } - serialization { serializationConfig() } @@ -82,10 +76,6 @@ abstract class KrpcTransportTestBase { private val clientConfig by lazy { rpcClientConfig { - sharedFlowParameters { - replay = KrpcTestServiceBackend.SHARED_FLOW_REPLAY - } - serialization { serializationConfig() } @@ -102,8 +92,8 @@ abstract class KrpcTransportTestBase { @BeforeTest fun start() { backend = KrpcTestServer(serverConfig, serverTransport) - backend.registerService { ctx -> - KrpcTestServiceBackend(ctx).also { + backend.registerService { + KrpcTestServiceBackend().also { server = it } } @@ -111,11 +101,6 @@ abstract class KrpcTransportTestBase { client = KrpcTestClient(clientConfig, clientTransport).withService() } - @AfterTest - fun end() { - backend.cancel() - } - @Test fun nonSuspend() = runTest { assertEquals(List(10) { it }, client.nonSuspendFlow().toList()) @@ -142,7 +127,6 @@ abstract class KrpcTransportTestBase { expected = List(10) { it * 2 }, actual = client.nonSuspendBidirectional(List(10) { it }.asFlow()).toList(), ) - print(1) } @Test @@ -153,12 +137,6 @@ abstract class KrpcTransportTestBase { ) } - @Test - fun empty() { - backend.cancel() - client.cancel() - } - @Test fun returnType() = runTest { assertEquals("test", client.returnType()) @@ -263,175 +241,59 @@ abstract class KrpcTransportTestBase { @Test fun incomingStreamSyncCollect() = runTest { - val result = streamScoped { - client.incomingStreamSyncCollect(flowOf("test1", "test2", "test3")) - } + val result = client.incomingStreamSyncCollect(flowOf("test1", "test2", "test3")) assertEquals(3, result) } @Test - fun incomingStreamAsyncCollect() = runTest { - val result = streamScoped { - client.incomingStreamAsyncCollect(flowOf("test1", "test2", "test3")).also { - server.incomingStreamAsyncCollectLatch.await() - } - } + fun incomingStreamSyncCollectMultiple() = runTest { + val result = client.incomingStreamSyncCollectMultiple( + flowOf("test1", "test2", "test3"), + flowOf("test1", "test2", "test3"), + flowOf("test1", "test2", "test3"), + ) - assertEquals(5, result) + assertEquals(9, result) } @Test fun outgoingStream() = runTest { - streamScoped { - val result = client.outgoingStream() - assertEquals(listOf("a", "b", "c"), result.toList(mutableListOf())) - } + val result = client.outgoingStream() + assertEquals(listOf("a", "b", "c"), result.toList(mutableListOf())) } @Test fun bidirectionalStream() = runTest { - streamScoped { - val result = client.bidirectionalStream(flowOf("test1", "test2", "test3")) - assertEquals( - listOf("test1".reversed(), "test2".reversed(), "test3".reversed()), - result.toList(mutableListOf()), - ) - } + val result = client.bidirectionalStream(flowOf("test1", "test2", "test3")) + assertEquals( + listOf("test1".reversed(), "test2".reversed(), "test3".reversed()), + result.toList(mutableListOf()), + ) } @Test fun streamInDataClass() = runTest { - streamScoped { - val result = client.streamInDataClass(payload()) - assertEquals(8, result) - } - } - - @Test - fun streamInStream() = runTest { - streamScoped { - val result = client.streamInStream(payloadStream()) - assertEquals(30, result) - } - } - - @Test - fun streamOutDataClass() = runTest { - streamScoped { - val result = client.streamOutDataClass() - assertEquals("test0", result.payload) - assertEquals(listOf("a0", "b0", "c0"), result.stream.toList(mutableListOf())) - } - } - - @Test - fun streamOfStreamsInReturn() = runTest { - streamScoped { - val result = client.streamOfStreamsInReturn().map { - it.toList(mutableListOf()) - }.toList(mutableListOf()) - assertEquals(listOf(listOf("a", "b", "c"), listOf("1", "2", "3")), result) - } + val result = client.streamInDataClass(payload()) + assertEquals(8, result) } @Test - fun streamOfPayloadsInReturn() = runTest { - streamScoped { - val result = client.streamOfPayloadsInReturn().map { - it.stream.toList(mutableListOf()).joinToString() - }.toList(mutableListOf()).joinToString() - assertEquals( - "a0, b0, c0, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, " + - "b4, c4, a5, b5, c5, a6, b6, c6, a7, b7, c7, a8, b8, c8, a9, b9, c9", - result, - ) - } - } - - @Test - fun streamInDataClassWithStream() = runTest { - streamScoped { - val result = client.streamInDataClassWithStream(payloadWithPayload()) - assertEquals(5, result) - } - } - - @Test - fun streamInStreamWithStream() = runTest { - val result = streamScoped { - client.streamInStreamWithStream(payloadWithPayloadStream()) - } - assertEquals(5, result) - } - - @Test - fun returnPayloadWithPayload() = runTest { - streamScoped { - assertContentEquals(expectedPayloadWithPayload(10), client.returnPayloadWithPayload().collect()) - } - } - - @Test - fun returnFlowPayloadWithPayload() = runTest { - streamScoped { - client.returnFlowPayloadWithPayload().collectIndexed { index, payloadWithPayload -> - assertContentEquals(expectedPayloadWithPayload(index), payloadWithPayload.collect()) - } - } - } - - @Test - fun bidirectionalFlowOfPayloadWithPayload() = runTest { - streamScoped { - val result = client.bidirectionalFlowOfPayloadWithPayload( - flow { - repeat(5) { - emit(payloadWithPayload(10)) - } - }, - ) - - val all = result.toList().onEach { - assertContentEquals(expectedPayloadWithPayload(10), it.collect()) - }.size - - assertEquals(5, all) - } - } - - @Test - fun bidirectionalAsyncStream() = runTest { - streamScoped { - val flow = MutableSharedFlow(1) - val result = client.echoStream(flow.take(10)) - launch { - var id = 0 - result.collect { - assertEquals(id, it) - id++ - flow.emit(id) - } - } - - flow.emit(0) - } + fun bidirectionalEchoStream() = runTest { + val result = client.echoStream(flowOf(1, 2, 3)).toList().sum() + assertEquals(6, result) } @Test fun `RPC should be able to receive 100_000 ints in reasonable time`() = runTest { - streamScoped { - val n = 100_000 - assertEquals(client.getNInts(n).last(), n) - } + val n = 100_000 + assertEquals(client.getNInts(n).last(), n) } @Test fun `RPC should be able to receive 100_000 ints with batching in reasonable time`() = runTest { - streamScoped { - val n = 100_000 - assertEquals(client.getNIntsBatched(n).last().last(), n) - } + val n = 100_000 + assertEquals(client.getNIntsBatched(n).last().last(), n) } @Test @@ -447,7 +309,7 @@ abstract class KrpcTransportTestBase { try { client.throwsIllegalArgument("me") fail("Exception expected: throwsIllegalArgument") - } catch (e : AssertionError) { + } catch (e: AssertionError) { throw e } catch (e: Throwable) { assertEquals("me", e.message) @@ -455,7 +317,7 @@ abstract class KrpcTransportTestBase { try { client.throwsSerializableWithMessageAndCause("me") fail("Exception expected: throwsSerializableWithMessageAndCause") - } catch (e : AssertionError) { + } catch (e: AssertionError) { throw e } catch (e: Throwable) { assertEquals("me", e.message) @@ -464,7 +326,7 @@ abstract class KrpcTransportTestBase { try { client.throwsThrowable("me") fail("Exception expected: throwsThrowable") - } catch (e : AssertionError) { + } catch (e: AssertionError) { throw e } catch (e: Throwable) { assertEquals("me", e.message) @@ -472,7 +334,7 @@ abstract class KrpcTransportTestBase { try { client.throwsUNSTOPPABLEThrowable("me") fail("Exception expected: throwsUNSTOPPABLEThrowable") - } catch (e : AssertionError) { + } catch (e: AssertionError) { throw e } catch (e: Throwable) { assertEquals("me", e.message) @@ -498,10 +360,8 @@ abstract class KrpcTransportTestBase { val flag: Channel = Channel() val remote = launch { try { - streamScoped { - client.delayForever().collect { - flag.send(it) - } + client.delayForever().collect { + flag.send(it) } } catch (e: CancellationException) { throw e @@ -531,8 +391,9 @@ abstract class KrpcTransportTestBase { return@runTest } - val inContinuation = Semaphore(1) + val inContinuation = Semaphore(permits = 1, acquiredPermits = 1) val running = AtomicTest() + val gate = CompletableDeferred() // start a coroutine that block the thread after continuation val c1 = async(Dispatchers.Default) { // make a rpc call @@ -545,13 +406,14 @@ abstract class KrpcTransportTestBase { inContinuation.release() // let's block the thread + gate.complete(Unit) while (running.atomic.value) { // do nothing } } // wait, till the Rpc continuation thread is blocked - delay(100) + gate.await() assertTrue(inContinuation.tryAcquire()) val c2 = async { // make a call @@ -573,143 +435,6 @@ abstract class KrpcTransportTestBase { fun testUnitFlow() = runTest { assertEquals(Unit, client.unitFlow().toList().single()) } - - @Test - fun testPlainFlowOfInts() = runTest { - val flow = client.plainFlowOfInts.toList() - assertEquals(List(5) { it }, flow) - } - - @Test - fun testPlainFlowOfFlowsOfInts() = runTest { - val lists = client.plainFlowOfFlowsOfInts.map { - it.toList() - }.toList() - - assertEquals(List(5) { List(5) { it } }, lists) - } - - @Test - fun testPlainFlowOfFlowsOfFlowsOfInts() = runTest { - val lists = client.plainFlowOfFlowsOfFlowsOfInts.map { - it.map { i -> i.toList() }.toList() - }.toList() - - assertEquals(List(5) { List(5) { List(5) { it } } }, lists) - } - - @Test - fun testSharedFlowOfInts() = runTest { - val list1 = client.sharedFlowOfInts.take(5).toList() - val list2 = client.sharedFlowOfInts.take(3).toList() - - assertEquals(List(5) { it }, list1) - assertEquals(List(3) { it }, list2) - } - - @Test - fun testSharedFlowOfFlowsOfInts() = runTest { - val list1 = client.sharedFlowOfFlowsOfInts.take(5).map { - it.take(5).toList() - }.toList() - - val list2 = client.sharedFlowOfFlowsOfInts.take(3).map { - it.take(3).toList() - }.toList() - - assertEquals(List(5) { List(5) { it } }, list1) - assertEquals(List(3) { List(3) { it } }, list2) - } - - @Test - fun testSharedFlowOfFlowsOfFlowsOfInts() = runTest { - val list1 = client.sharedFlowOfFlowsOfFlowsOfInts.take(5).map { - it.take(5).map { i -> i.take(5).toList() }.toList() - }.toList() - - val list2 = client.sharedFlowOfFlowsOfFlowsOfInts.take(3).map { - it.take(3).map { i -> i.take(3).toList() }.toList() - }.toList() - - assertEquals(List(5) { List(5) { List(5) { it } } }, list1) - assertEquals(List(3) { List(3) { List(3) { it } } }, list2) - } - - @Test - fun testStateFlowOfInts() = runTest { - val flow = client.awaitFieldInitialization { stateFlowOfInts } - - assertEquals(-1, flow.value) - - client.emitNextForStateFlowOfInts(42) - - assertEquals(42, flow.first { it == 42 }) - } - - @Test - fun testStateFlowOfFlowsOfInts() = runTest { - val flow1 = client.awaitFieldInitialization { stateFlowOfFlowsOfInts } - val flow2 = flow1.value - - assertEquals(-1, flow2.value) - - client.emitNextForStateFlowOfFlowsOfInts(42) - - assertEquals(42, flow2.first { it == 42 }) - assertEquals(42, flow1.first { it.value == 42 }.value) - } - - @Test - fun testStateFlowOfFlowsOfFlowsOfInts() = runTest { - val flow1 = client.awaitFieldInitialization { stateFlowOfFlowsOfFlowsOfInts } - val flow2 = flow1.value - val flow3 = flow2.value - - assertEquals(-1, flow3.value) - - client.emitNextForStateFlowOfFlowsOfFlowsOfInts(42) - - assertEquals(42, flow3.first { it == 42 }) - assertEquals(42, flow2.first { it.value == 42 }.value) - assertEquals(42, flow1.first { it.value.value == 42 }.value.value) - } - - @Test - fun testSharedFlowInFunction() = runTest { - streamScoped { - val flow = sharedFlowOfT { it } - - val state = client.sharedFlowInFunction(flow) - - assertEquals(1, state.first { it == 1 }) - } - } - - @Test - fun testStateFlowInFunction() = runTest { - streamScoped { - val flow = stateFlowOfT { it } - - val state = client.stateFlowInFunction(flow) - - flow.emit(42) - - assertEquals(1, state.first { it == 1 }) - } - } - - @Test - fun testAwaitAllFields() = runTest { - with(client.awaitFieldInitialization()) { - assertEquals(-1, stateFlowOfInts.value) - assertEquals(-1, stateFlowOfFlowsOfInts.value.value) - assertEquals(-1, stateFlowOfFlowsOfFlowsOfInts.value.value.value) - } - } - - companion object { - fun expectedPayloadWithPayload(size: Int) = List(size) { listOf("a$it", "b$it", "c$it") } - } } internal expect val isJs: Boolean diff --git a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/Payloads.kt b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/Payloads.kt index 2523a6f26..49bacea50 100644 --- a/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/Payloads.kt +++ b/krpc/krpc-test/src/commonMain/kotlin/kotlinx/rpc/krpc/test/Payloads.kt @@ -1,32 +1,19 @@ +@file:Suppress("detekt.MatchingDeclarationName") + /* * 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 -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.launch import kotlinx.serialization.Contextual import kotlinx.serialization.Serializable @Serializable data class PayloadWithStream(val payload: String, val stream: @Contextual Flow) -@Serializable -data class PayloadWithPayload(val payload: String, val flow: @Contextual Flow) { - suspend fun collect(): List> { - return flow.map { - it.stream.toList() - }.toList() - } -} - fun payload(index: Int = 0): PayloadWithStream { return PayloadWithStream( "test$index", @@ -34,48 +21,6 @@ fun payload(index: Int = 0): PayloadWithStream { ) } -fun payloadWithPayload(index: Int = 10): PayloadWithPayload { - return PayloadWithPayload("test$index", payloadStream(index)) -} - -fun payloadStream(count: Int = 10): Flow { - return flow { - repeat(count) { - emit(payload(it)) - } - } -} - -fun payloadWithPayloadStream(count: Int = 10): Flow { - return flow { - repeat(count) { - emit(payloadWithPayload(it)) - } - } -} - fun plainFlow(count: Int = 5, get: (Int) -> T): Flow { return flow { repeat(count) { emit(get(it)) } } } - -private fun > CoroutineScope.runSharedFlow( - flow: FlowT, - count: Int = KrpcTestServiceBackend.SHARED_FLOW_REPLAY, - getter: (Int) -> T, -) = apply { - launch { - repeat(count) { - flow.emit(getter(it)) - } - } -} - -fun CoroutineScope.sharedFlowOfT(getter: (Int) -> T): MutableSharedFlow { - return MutableSharedFlow(KrpcTestServiceBackend.SHARED_FLOW_REPLAY).also { flow -> - runSharedFlow(flow) { getter(it) } - } -} - -fun stateFlowOfT(getter: (Int) -> T): MutableStateFlow { - return MutableStateFlow(getter(-1)) -} diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransport.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransport.kt index d4cda5500..fb7c0b565 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransport.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransport.kt @@ -4,6 +4,7 @@ package kotlinx.rpc.krpc.test +import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob @@ -12,6 +13,8 @@ import kotlinx.coroutines.job import kotlinx.rpc.krpc.KrpcTransport import kotlinx.rpc.krpc.KrpcTransportMessage import kotlin.coroutines.CoroutineContext +import kotlin.time.Clock +import kotlin.time.ExperimentalTime class LocalTransport(parentScope: CoroutineScope? = null) : CoroutineScope { override val coroutineContext = parentScope?.run { SupervisorJob(coroutineContext.job) } @@ -20,10 +23,15 @@ class LocalTransport(parentScope: CoroutineScope? = null) : CoroutineScope { private val clientIncoming = Channel() private val serverIncoming = Channel() + val lastMessageSentOnClient = atomic(0L) + val lastMessageSentOnServer = atomic(0L) + val client: KrpcTransport = object : KrpcTransport { override val coroutineContext: CoroutineContext = Job(this@LocalTransport.coroutineContext.job) + @OptIn(ExperimentalTime::class) override suspend fun send(message: KrpcTransportMessage) { + lastMessageSentOnClient.getAndSet(Clock.System.now().toEpochMilliseconds()) serverIncoming.send(message) } @@ -35,7 +43,9 @@ class LocalTransport(parentScope: CoroutineScope? = null) : CoroutineScope { val server: KrpcTransport = object : KrpcTransport { override val coroutineContext: CoroutineContext = Job(this@LocalTransport.coroutineContext) + @OptIn(ExperimentalTime::class) override suspend fun send(message: KrpcTransportMessage) { + lastMessageSentOnServer.getAndSet(Clock.System.now().toEpochMilliseconds()) clientIncoming.send(message) } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt index b8d033106..2cd704c01 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/LocalTransportTest.kt @@ -12,6 +12,7 @@ import kotlinx.rpc.krpc.serialization.cbor.cbor import kotlinx.rpc.krpc.serialization.json.json import kotlinx.rpc.krpc.serialization.protobuf.protobuf import kotlinx.serialization.ExperimentalSerializationApi +import kotlin.test.Test abstract class LocalTransportTest : KrpcTransportTestBase() { private val transport = LocalTransport() @@ -50,11 +51,15 @@ class ProtoBufLocalTransportTest : LocalTransportTest() { } // 'null' is not supported in ProtoBuf + @Test override fun nullable(): TestResult = runTest { } + @Test override fun testByteArraySerialization(): TestResult = runTest { } + @Test override fun testNullables(): TestResult = runTest { } + @Test override fun testNullableLists(): TestResult = runTest { } } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt index 2ca024a48..f714c20d7 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt @@ -9,11 +9,10 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.job import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.test.TestScope -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.internal.utils.hex.rpcInternalHexToReadableBinary import kotlinx.rpc.krpc.KrpcConfig -import kotlinx.rpc.krpc.client.KrpcClient +import kotlinx.rpc.krpc.client.InitializedKrpcClient import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLogger import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLoggerContainer @@ -24,7 +23,6 @@ import kotlinx.rpc.krpc.server.KrpcServer import kotlinx.rpc.registerService import kotlinx.rpc.withService import kotlinx.serialization.BinaryFormat -import kotlin.coroutines.CoroutineContext abstract class ProtocolTestBase { protected fun runTest( @@ -80,9 +78,7 @@ abstract class ProtocolTestBase { val defaultServer by lazy { ProtocolTestServer(serverConfig, transport).apply { - registerService { - ProtocolTestServiceImpl(transport.coroutineContext) - } + registerService { ProtocolTestServiceImpl() } } } @@ -91,13 +87,11 @@ abstract class ProtocolTestBase { } @Rpc -interface ProtocolTestService : RemoteService { +interface ProtocolTestService { suspend fun sendRequest() } -private class ProtocolTestServiceImpl( - override val coroutineContext: CoroutineContext, -) : ProtocolTestService { +private class ProtocolTestServiceImpl : ProtocolTestService { override suspend fun sendRequest() { // nothing } @@ -111,4 +105,4 @@ class ProtocolTestServer( class ProtocolTestClient( config: KrpcConfig.Client, transport: LocalTransport, -) : KrpcClient(config, transport.client) +) : InitializedKrpcClient(config, transport.client) diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt index 54267498e..04b74ebc9 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt @@ -6,16 +6,10 @@ @file:Suppress("PackageDirectoryMismatch") package org.jetbrains.krpc.test.api.util -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.krpc.test.plainFlow -import kotlinx.rpc.krpc.test.sharedFlowOfT -import kotlinx.rpc.krpc.test.stateFlowOfT import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext @Serializable data class SamplingData( @@ -23,29 +17,17 @@ data class SamplingData( ) @Rpc -interface SamplingService : RemoteService { +interface SamplingService { suspend fun echo(arg1: String, data: SamplingData): SamplingData suspend fun clientStream(flow: Flow): List - suspend fun clientNestedStream(flow: Flow>): List> - - suspend fun serverFlow(): Flow - - suspend fun serverNestedFlow(): Flow> + fun serverFlow(): Flow suspend fun callException() - - val plainFlow: Flow - - val sharedFlow: SharedFlow - - val stateFlow: StateFlow - - suspend fun emitNextInStateFlow(next: Int) } -class SamplingServiceImpl(override val coroutineContext: CoroutineContext) : SamplingService { +class SamplingServiceImpl : SamplingService { override suspend fun echo(arg1: String, data: SamplingData): SamplingData { return data } @@ -54,33 +36,11 @@ class SamplingServiceImpl(override val coroutineContext: CoroutineContext) : Sam return flow.toList() } - override suspend fun clientNestedStream(flow: Flow>): List> { - return flow.map { it.toList() }.toList() - } - - override suspend fun serverFlow(): Flow { + override fun serverFlow(): Flow { return plainFlow { SamplingData("data") } } - override suspend fun serverNestedFlow(): Flow> { - return plainFlow { plainFlow { it } } - } - override suspend fun callException() { error("Server exception") } - - override val plainFlow: Flow = plainFlow { it } - - override val sharedFlow: SharedFlow = sharedFlowOfT { it } - - override val stateFlow: MutableStateFlow = stateFlowOfT { it } - - override suspend fun emitNextInStateFlow(next: Int) { - launch { - // CallSuccess and StreamMessage may race, so we prevent this - delay(500) - stateFlow.value = next - } - } } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt index c85f45d91..88ab602b4 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt @@ -17,24 +17,23 @@ import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLoggerContainer import kotlinx.rpc.krpc.rpcClientConfig import kotlinx.rpc.krpc.rpcServerConfig import kotlinx.rpc.krpc.serialization.json.json -import kotlin.coroutines.CoroutineContext -import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFails import kotlin.test.assertTrue +import kotlin.time.Duration.Companion.seconds @Rpc -interface Echo : RemoteService { +interface Echo { suspend fun echo(message: String): String } @Rpc -interface Second : RemoteService { +interface Second { suspend fun second(message: String): String } -class EchoImpl(override val coroutineContext: CoroutineContext) : Echo { +class EchoImpl : Echo { val received = atomic(0) override suspend fun echo(message: String): String { @@ -43,7 +42,7 @@ class EchoImpl(override val coroutineContext: CoroutineContext) : Echo { } } -class SecondServer(override val coroutineContext: CoroutineContext) : Second { +class SecondServer : Second { val received = atomic(0) override suspend fun second(message: String): String { @@ -71,27 +70,30 @@ class TransportTest { private fun serverOf( localTransport: LocalTransport, - config: (KrpcConfigBuilder.Server.() -> Unit)? = null + config: (KrpcConfigBuilder.Server.() -> Unit)? = null, ): RpcServer { val serverConfig = config?.let { rpcServerConfig(it) } ?: serverConfig return KrpcTestServer(serverConfig, localTransport.server) } - private fun runTest(block: suspend TestScope.() -> Unit): TestResult = kotlinx.coroutines.test.runTest { - val logger = RpcInternalCommonLogger.logger("TransportTest") + private fun runTest(block: suspend TestScope.() -> Unit): TestResult = + kotlinx.coroutines.test.runTest(timeout = 15.seconds) { + debugCoroutines() - RpcInternalDumpLoggerContainer.set(object : RpcInternalDumpLogger { - override val isEnabled: Boolean = true + val logger = RpcInternalCommonLogger.logger("TransportTest") - override fun dump(vararg tags: String, message: () -> String) { - logger.info { "${tags.joinToString(" ") { "[$it]" }} ${message()}" } - } - }) + RpcInternalDumpLoggerContainer.set(object : RpcInternalDumpLogger { + override val isEnabled: Boolean = true - block() + override fun dump(vararg tags: String, message: () -> String) { + logger.info { "${tags.joinToString(" ") { "[$it]" }} ${message()}" } + } + }) - RpcInternalDumpLoggerContainer.set(null) - } + block() + + RpcInternalDumpLoggerContainer.set(null) + } @Test fun testUsingWrongService() = runTest { @@ -111,10 +113,10 @@ class TransportTest { waitForServices = false } - server.registerService { EchoImpl(it) } + server.registerService { EchoImpl() } result.await() - server.cancel() + transports.cancel() } @Test @@ -128,12 +130,12 @@ class TransportTest { val server = serverOf(transports) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } + val echoServices = server.registerServiceAndReturn { EchoImpl() } assertEquals("foo", result.await()) assertEquals(1, echoServices.single().received.value) - server.cancel() + transports.cancel() } @Test @@ -148,13 +150,13 @@ class TransportTest { } val server = serverOf(transports) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } + val echoServices = server.registerServiceAndReturn { EchoImpl() } val response = result.awaitAll() assertTrue { response.all { it == "foo" } } assertEquals(10, echoServices.single().received.value) - server.cancel() + transports.cancel() } @Test @@ -163,7 +165,7 @@ class TransportTest { val client = clientOf(transports) - val result = List(10) { + val result = List(3) { async { val service = client.withService() service.echo("foo") @@ -171,16 +173,15 @@ class TransportTest { } val server = serverOf(transports) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } + val echoServices = server.registerServiceAndReturn { EchoImpl() } val response = result.awaitAll() assertTrue { response.all { it == "foo" } } - assertEquals(10, echoServices.sumOf { it.received.value }) + assertEquals(3, echoServices.sumOf { it.received.value }) - server.cancel() + transports.coroutineContext.job.cancelAndJoin() } - @Test fun testLateConnectWithManyCallsAndClients() = runTest { val transports = LocalTransport() @@ -199,13 +200,13 @@ class TransportTest { } val server = serverOf(transports) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } + val echoServices = server.registerServiceAndReturn { EchoImpl() } val response = result.awaitAll().flatten() assertTrue { response.all { it == "foo" } } assertEquals(100, echoServices.sumOf { it.received.value }) - server.cancel() + transports.cancel() } @Test @@ -227,43 +228,24 @@ class TransportTest { val server = serverOf(transports) delay(1000) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } + val echoServices = server.registerServiceAndReturn { EchoImpl() } assertEquals("foo", firstResult.await()) assertEquals(1, echoServices.single().received.value) - echoServices.single().cancel() delay(1000) - val secondServices = server.registerServiceAndReturn { SecondServer(it) } + val secondServices = server.registerServiceAndReturn { SecondServer() } assertEquals("bar", secondResult.await()) assertEquals(1, secondServices.single().received.value) - secondServices.single().cancel() - - server.cancel() - } - @Test - @Ignore - fun testCancelFromClientToServer() = runTest { - val transports = LocalTransport() - - val client = clientOf(transports).withService() - - val server = serverOf(transports) - val echoServices = server.registerServiceAndReturn { EchoImpl(it) } - - client.cancel() - echoServices.single().coroutineContext.job.join() - assertTrue(echoServices.single().coroutineContext.job.isCancelled) + transports.cancel() } private inline fun <@Rpc reified Service : Any, reified Impl : Service> RpcServer.registerServiceAndReturn( - crossinline body: (CoroutineContext) -> Impl, + crossinline body: () -> Impl, ): List { val instances = mutableListOf() - registerService { ctx -> - body(ctx).also { instances.add(it) } - } + registerService { body().also { instances.add(it) } } return instances } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt index 5bed4e894..9ffe82c24 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt @@ -7,45 +7,30 @@ package kotlinx.rpc.krpc.test.cancellation import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc -import kotlinx.rpc.krpc.invokeOnStreamScopeCompletion -import kotlin.coroutines.CoroutineContext -import kotlin.properties.Delegates -import kotlin.test.assertIs @Rpc -interface CancellationService : RemoteService { +interface CancellationService { suspend fun longRequest() suspend fun serverDelay(millis: Long) suspend fun callException() - suspend fun incomingStream(): Flow + fun incomingStream(): Flow suspend fun outgoingStream(stream: Flow) + suspend fun outgoingStreamAsync(stream: Flow) + suspend fun outgoingStreamWithDelayedResponse(stream: Flow) suspend fun outgoingStreamWithException(stream: Flow) - suspend fun outgoingHotFlow(stream: StateFlow) - - suspend fun incomingHotFlow(): StateFlow - - val fastFieldFlow: Flow - - val slowFieldFlow: Flow - - suspend fun closedStreamScopeCallback() - - suspend fun closedStreamScopeCallbackWithStream(): Flow - fun nonSuspendable(): Flow } -class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : CancellationService { +class CancellationServiceImpl : CancellationService { val delayCounter = atomic(0) val consumedIncomingValues = mutableListOf() val firstIncomingConsumed = CompletableDeferred() @@ -66,7 +51,7 @@ class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : error("callException") } - override suspend fun incomingStream(): Flow { + override fun incomingStream(): Flow { return resumableFlow(fence) } @@ -74,6 +59,15 @@ class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : consume(stream) } + @OptIn(DelicateCoroutinesApi::class) + override suspend fun outgoingStreamAsync(stream: Flow) { + @Suppress("detekt.GlobalCoroutineUsage") + GlobalScope.launch { + consume(stream) + } + firstIncomingConsumed.await() + } + override suspend fun outgoingStreamWithDelayedResponse(stream: Flow) { consume(stream) @@ -89,86 +83,16 @@ class CancellationServiceImpl(override val coroutineContext: CoroutineContext) : error("exception in request") } - val hotFlowMirror = MutableStateFlow(-1) - val hotFlowConsumedSize = CompletableDeferred() - - override suspend fun outgoingHotFlow(stream: StateFlow) { - launch { - var cnt = 0 - - val cancellation = runCatching { - stream.collect { - cnt++ - hotFlowMirror.emit(it) - } - } - - val result = runCatching { - assertIs(cancellation.exceptionOrNull(), "Cancellation should be thrown") - - cnt - } - - hotFlowConsumedSize.completeWith(result) - } - } - - var incomingHotFlowJob by Delegates.notNull() - - override suspend fun incomingHotFlow(): StateFlow { - val state = MutableStateFlow(-1) - - incomingHotFlowJob = launch { - repeat(Int.MAX_VALUE) { value -> - state.value = value - - hotFlowMirror.first { it == value } - } - } - - invokeOnStreamScopeCompletion { - incomingHotFlowJob.cancel() - } - - return state - } - - override val fastFieldFlow: Flow = resumableFlow(fence) - - val emittedFromSlowField = mutableListOf() - - override val slowFieldFlow: Flow = resumableFlow(fence) { - emittedFromSlowField.add(it) - } - - val streamScopeCallbackResult = CompletableDeferred() - - override suspend fun closedStreamScopeCallback() { - invokeOnStreamScopeCompletion { cause -> - streamScopeCallbackResult.complete(cause) - } - } - - override suspend fun closedStreamScopeCallbackWithStream(): Flow { - invokeOnStreamScopeCompletion { cause -> - streamScopeCallbackResult.complete(cause) - } - - return resumableFlow(fence) - } - - private fun consume(stream: Flow) { - launch { - try { - stream.collect { - if (!firstIncomingConsumed.isCompleted) { - firstIncomingConsumed.complete(it) - } - consumedIncomingValues.add(it) + private suspend fun consume(stream: Flow) { + try { + stream.collect { + if (!firstIncomingConsumed.isCompleted) { + firstIncomingConsumed.complete(it) } - } finally { - consumedAll.complete(Unit) + consumedIncomingValues.add(it) } + } finally { + consumedAll.complete(Unit) } } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt index d30d7d667..dcf356156 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationTest.kt @@ -5,15 +5,11 @@ package kotlinx.rpc.krpc.test.cancellation import kotlinx.coroutines.* -import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.test.runTest -import kotlinx.rpc.krpc.StreamScope -import kotlinx.rpc.krpc.internal.STREAM_SCOPES_ENABLED -import kotlinx.rpc.krpc.invokeOnStreamScopeCompletion -import kotlinx.rpc.krpc.streamScoped -import kotlinx.rpc.krpc.withStreamScope import kotlinx.rpc.withService import kotlin.test.* @@ -39,31 +35,6 @@ class CancellationTest { stopAllAndJoin() } - @Test - fun testCancelServiceScope() = runCancellationTest { - val firstRequestJob = launch { - service.serverDelay(300) - } - - val secondRequestJob = launch { - service.serverDelay(300) - } - - unskippableDelay(150) // wait for requests to reach server - service.cancel() - firstRequestJob.join() - secondRequestJob.join() - - assertTrue(firstRequestJob.isCancelled, "Expected firstRequestJob to be cancelled") - assertTrue(secondRequestJob.isCancelled, "Expected secondRequestJob to be cancelled") - - assertEquals(0, serverInstances.single().delayCounter.value, "Expected both requests to be cancelled") - - checkAlive(serviceAlive = false) - checkAlive(expectAlive = false, serverInstances.single().join(), "server instance") - stopAllAndJoin() - } - @Test fun testCallException() = runCancellationTest { val requestJob = launch { @@ -92,35 +63,6 @@ class CancellationTest { stopAllAndJoin() } - @Test - fun testCancelServiceWithOtherService() = runCancellationTest { - val firstRequestJob = launch { - service.serverDelay(300) - } - - val secondService = client.withService() - - val secondRequestJob = launch { - secondService.serverDelay(300) - } - - unskippableDelay(150) // wait for requests to reach server - secondService.cancel() - firstRequestJob.join() - secondRequestJob.join() - - assertFalse(firstRequestJob.isCancelled, "Expected firstRequestJob not to be cancelled") - assertTrue(secondRequestJob.isCancelled, "Expected secondRequestJob to be cancelled") - - assertEquals(2, serverInstances.size, "Expected two service instances on a server") - assertEquals(1, serverInstances.sumOf { it.delayCounter.value }, "Expected one request to succeed") - - val secondServiceInstance = serverInstances.single { it.delayCounter.value == 0 }.join() - checkAlive(expectAlive = false, secondServiceInstance, "server instance") - checkAlive() - stopAllAndJoin() - } - @Test fun testCancelClient() = runCancellationTest { val firstRequestJob = launch { @@ -134,7 +76,7 @@ class CancellationTest { } unskippableDelay(150) // wait for requests to reach server - client.cancel() + client.close() firstRequestJob.join() secondRequestJob.join() @@ -143,14 +85,10 @@ class CancellationTest { assertEquals(0, serverInstances.sumOf { it.delayCounter.value }, "Expected no requests to succeed") - client.join() - server.join() + client.awaitCompletion() + server.awaitCompletion() - checkAlive(serviceAlive = false, clientAlive = false, serverAlive = false) - checkAlive(expectAlive = false, secondService, "second service") - serverInstances.forEachIndexed { i, impl -> - checkAlive(expectAlive = false, impl.join(), "server instance $i") - } + checkAlive(clientAlive = false, serverAlive = false) stopAllAndJoin() } @@ -167,7 +105,7 @@ class CancellationTest { } unskippableDelay(150) // wait for requests to reach server - server.cancel() + server.close() firstRequestJob.join() secondRequestJob.join() @@ -176,462 +114,150 @@ class CancellationTest { assertEquals(0, serverInstances.sumOf { it.delayCounter.value }, "Expected no requests to succeed") - client.join() - server.join() - - checkAlive(serviceAlive = false, clientAlive = false, serverAlive = false) - checkAlive(expectAlive = false, secondService, "second service") - serverInstances.forEachIndexed { i, impl -> - checkAlive(expectAlive = false, impl.join(), "server instance $i") - } - stopAllAndJoin() - } - - @Test - fun testStreamScopeOutgoing() = runCancellationTest { - val fence = CompletableDeferred() - - streamScoped { - service.outgoingStream(resumableFlow(fence)) - serverInstance().firstIncomingConsumed.await() - } - - fence.complete(Unit) - serverInstance().consumedAll.await() - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - - stopAllAndJoin() - } - - @Test - fun testStreamScopeAbsentForOutgoingStream() = runCancellationTest { - val fence = CompletableDeferred() - - if (STREAM_SCOPES_ENABLED) { - assertFailsWith { - service.outgoingStream(resumableFlow(fence)) - } - } else { - service.outgoingStream(resumableFlow(fence)) - } - - stopAllAndJoin() - } - - @Test - fun testStreamScopeAbsentForIncomingStream() = runCancellationTest { - if (STREAM_SCOPES_ENABLED) { - assertFailsWith { - service.incomingStream() - } - } else { - service.incomingStream() - } - - stopAllAndJoin() - } - - @Test - fun testStreamScopeIncoming() = runCancellationTest { - val first: Int - val flow = streamScoped { - service.incomingStream().apply { first = first() } - } - - serverInstance().fence.complete(Unit) - val consumed = flow.toList() - - assertEquals(0, first) - assertContentEquals(emptyList(), consumed) + client.awaitCompletion() + server.awaitCompletion() + checkAlive(clientAlive = false, serverAlive = false) stopAllAndJoin() } @Test - fun testExceptionInStreamScope() = runCancellationTest { - val fence = CompletableDeferred() + fun testStreamOutgoing() = runCancellationTest { + service.outgoingStream( + flow { + repeat(2) { + emit(it) - runCatching { - streamScoped { - service.outgoingStream(resumableFlow(fence)) - serverInstance().firstIncomingConsumed.await() - error("exception in stream scope") + if (it == 0) { + serverInstance().firstIncomingConsumed.await() + } + } } - } - - fence.complete(Unit) + ) serverInstance().consumedAll.await() - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) + assertContentEquals(listOf(0, 1), serverInstance().consumedIncomingValues) stopAllAndJoin() } @Test - fun testExceptionInRequest() = runCancellationTest { - val fence = CompletableDeferred() - - streamScoped { - runCatching { - service.outgoingStreamWithException(resumableFlow(fence)) - } - - // to be sure that exception canceled the stream and not scope closure - serverInstance().consumedAll.await() - } - - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - - stopAllAndJoin() - } - - @Test - fun testNestedStreamScopesForbidden() = runTest { - assertFailsWith { - streamScoped { streamScoped { } } - } - } - - @Test - fun testExceptionInRequestDoesNotCancelOtherRequests() = runCancellationTest { + fun testOutgoingFlowLifetime() = runCancellationTest { val fence = CompletableDeferred() - val result = streamScoped { - val flow = service.incomingStream() - runCatching { - service.outgoingStreamWithException(resumableFlow(fence)) - } - - fence.complete(Unit) - serverInstance().fence.complete(Unit) - - flow.toList() - } + service.outgoingStreamAsync(resumableFlow(fence)) serverInstance().consumedAll.await() assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - assertContentEquals(List(2) { it }, result) - stopAllAndJoin() } @Test - fun testRequestCancellationCancelsStream() = runCancellationTest { - val fence = CompletableDeferred() - streamScoped { - val job = launch { - service.outgoingStreamWithDelayedResponse(resumableFlow(fence)) - } - - serverInstance().firstIncomingConsumed.await() - - job.cancel("Test request cancelled") - job.join() - assertTrue("Job must be canceled") { job.isCancelled } - - // close by request cancel and not scope closure - serverInstance().consumedAll.await() - } - - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - - stopAllAndJoin() - } + fun testStreamIncoming() = runCancellationTest { + var first: Int = -1 + val flow = service.incomingStream() - @Test - fun testRequestCancellationCancelsStreamButNotOthers() = runCancellationTest { - val fence = CompletableDeferred() - val result = streamScoped { - val job = launch { - service.outgoingStreamWithDelayedResponse(resumableFlow(fence)) + val consumed = flow.mapNotNull { + if (it == 0) { + first = it + serverInstance().fence.complete(Unit) + null + } else { + it } + }.toList() - val flow = service.incomingStream() - - serverInstance().firstIncomingConsumed.await() - - job.cancel("Test request cancelled") - job.join() - assertTrue("Job must be canceled") { job.isCancelled } - serverInstance().fence.complete(Unit) - - // close by request cancel and not scope closure - serverInstance().consumedAll.await() - - flow.toList() - } - - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - assertContentEquals(List(2) { it }, result) + assertEquals(0, first) + assertContentEquals(listOf(1), consumed) stopAllAndJoin() } @Test - fun testServiceCancellationCancelsStream() = runCancellationTest { + fun testRequestCancellationCancelsStream() = runCancellationTest { val fence = CompletableDeferred() - streamScoped { - launch { - service.outgoingStream(resumableFlow(fence)) - } - serverInstance().firstIncomingConsumed.await() - - service.cancel("Test request cancelled") - service.join() - - serverInstance().consumedAll.await() + val job = launch { + service.outgoingStreamWithDelayedResponse(resumableFlow(fence)) } - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - - stopAllAndJoin() - } - - @Test - fun testServiceCancellationCancelsStreamButNotOthers() = runCancellationTest { - val fence = CompletableDeferred() - val secondServiceResult = streamScoped { - launch { - service.outgoingStream(resumableFlow(fence)) - } - - serverInstance().firstIncomingConsumed.await() + serverInstance().firstIncomingConsumed.await() - val secondServiceFlow = client - .withService() - .incomingStream() - - service.cancel("Test request cancelled") - service.join() - - serverInstances[1].fence.complete(Unit) - - secondServiceFlow.toList() - } + job.cancel("Test request cancelled") + job.join() + assertTrue("Job must be canceled") { job.isCancelled } + // close by request cancel and not scope closure serverInstance().consumedAll.await() assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - assertContentEquals(List(2) { it }, secondServiceResult) stopAllAndJoin() } @Test - fun testScopeClosureCancelsAllStreams() = runCancellationTest { + fun testRequestCancellationCancelsStreamButNotOthers() = runCancellationTest { val fence = CompletableDeferred() - streamScoped { - service.outgoingStream(resumableFlow(fence)) - - client.withService().outgoingStream(resumableFlow(fence)) - - serverInstance().firstIncomingConsumed.await() - - while (true) { - if (serverInstances.size == 2) { - serverInstances[1].firstIncomingConsumed.await() - break - } - - unskippableDelay(50) - } - } - - serverInstances.forEach { it.consumedAll.await() } - - assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) - assertContentEquals(listOf(0), serverInstances[1].consumedIncomingValues) - - stopAllAndJoin() - } - - @Test - fun testFieldFlowWorksWithNoScope() = runCancellationTest { - val result = service.fastFieldFlow - - serverInstance().fence.complete(Unit) - - assertContentEquals(List(2) { it }, result.toList()) - - stopAllAndJoin() - } - - @Test - fun testServiceCancellationCancelsFieldFlow() = runCancellationTest { - val flow = service.slowFieldFlow - val firstCollected = CompletableDeferred() - val allCollected = mutableListOf() - val job = launch { - flow.collect { - allCollected.add(it) - - if (!firstCollected.isCompleted) { - firstCollected.complete(it) - } - } + service.outgoingStreamWithDelayedResponse(resumableFlow(fence)) } - firstCollected.await() + val flow = service.incomingStream() - service.cancel("Service cancelled") + serverInstance().firstIncomingConsumed.await() + job.cancel("Test request cancelled") job.join() - assertContentEquals(listOf(0), allCollected) - assertContentEquals(listOf(0), serverInstance().emittedFromSlowField) - - stopAllAndJoin() - } - - @Test - fun testInvokeOnStreamScopeCompletionOnServerWithNoStreams() = runCancellationTest { - streamScoped { - service.closedStreamScopeCallback() - } - - serverInstance().streamScopeCallbackResult.await() - - stopAllAndJoin() - } + assertTrue("Job must be canceled") { job.isCancelled } + serverInstance().fence.complete(Unit) - @Test - fun testInvokeOnStreamScopeCompletionOnServer() = runCancellationTest { - val result = streamScoped { - service.closedStreamScopeCallbackWithStream().also { - serverInstance().fence.complete(Unit) - }.toList() - } + // close by request cancel and not scope closure + serverInstance().consumedAll.await() - serverInstance().streamScopeCallbackResult.await() + val result = flow.toList() + assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) assertContentEquals(List(2) { it }, result) stopAllAndJoin() } @Test - fun testInvokeOnStreamScopeCompletionOnClient() = runCancellationTest { - val streamScopeCompleted = CompletableDeferred() - - streamScoped { - service.closedStreamScopeCallback() - - invokeOnStreamScopeCompletion { - streamScopeCompleted.complete(Unit) - } + fun testClientCancellationCancelsStream() = runCancellationTest { + val fence = CompletableDeferred() + launch { + service.outgoingStream(resumableFlow(fence)) } - streamScopeCompleted.await() - - stopAllAndJoin() - } - - @Test - fun testOutgoingHotFlow() = runCancellationTest { - streamScoped { - val state = MutableStateFlow(-2) - - service.outgoingHotFlow(state) + serverInstance().firstIncomingConsumed.await() - val mirror = serverInstance().hotFlowMirror - mirror.first { it == -2 } // initial value + client.close("Test request cancelled") + client.awaitCompletion() - repeat(3) { value -> - state.value = value - mirror.first { it == value } - } - } - - assertEquals(4, serverInstance().hotFlowConsumedSize.await()) - - stopAllAndJoin() - } - - @Test - fun testIncomingHotFlow() = runCancellationTest { - val state = streamScoped { - val state = service.incomingHotFlow() - - val mirror = serverInstance().hotFlowMirror - repeat(3) { value -> - state.first { it == value } - mirror.value = value - } - - state.first { it == 3 } - - state - } + serverInstance().consumedAll.await() - serverInstance().incomingHotFlowJob.join() - assertEquals(3, state.value) - assertEquals(2, serverInstance().hotFlowMirror.value) + assertContentEquals(listOf(0), serverInstance().consumedIncomingValues) stopAllAndJoin() } @Test fun testCancelledClientCancelsFlows() = runCancellationTest { - streamScoped { - val flow = service.incomingStream() - - assertEquals(0, flow.first()) - client.cancel() - val rest = flow.toList() - - assertTrue("Rest must be empty, as flow was closed") { rest.isEmpty() } - } - - stopAllAndJoin() - } - - @Test - fun manualStreamScopeNoCancel() = runCancellationTest { - val myJob = Job() - val streamScope = StreamScope(myJob) - - val unrelatedJob = Job() - - var first: Int = -1 - val deferredFlow = CoroutineScope(unrelatedJob).async { - withStreamScope(streamScope) { - service.incomingStream().apply { first = first() } + val flow = service.incomingStream() + var caught: Throwable? = null + + flow.catch { + caught = it + }.collect { + if (it == 0) { + client.close() + } else { + fail("Expected the request to fail with cancellation of the client") } } - val flow= deferredFlow.await() - serverInstance().fence.complete(Unit) - val consumed = flow.toList() - - assertEquals(0, first) - assertContentEquals(listOf(1), consumed) - - stopAllAndJoin() - } - - @Test - fun manualStreamScopeWithCancel() = runCancellationTest { - val myJob = Job() - val streamScope = StreamScope(myJob) - - val unrelatedJob = Job() - - var first: Int = -1 - val deferredFlow = CoroutineScope(unrelatedJob).async { - withStreamScope(streamScope) { - service.incomingStream().apply { first = first() } - } - } - val flow= deferredFlow.await() - - streamScope.close() - serverInstance().fence.complete(Unit) - val consumed = flow.toList() - - assertEquals(0, first) - assertContentEquals(emptyList(), consumed) + assertNotNull(caught, "Expected cancellation exception") stopAllAndJoin() } @@ -640,7 +266,7 @@ class CancellationTest { fun testCancelledClientCancelsRequest() = runCancellationTest { launch { serverInstance().firstIncomingConsumed.await() - client.cancel("Cancelled by test") + client.close("Cancelled by test") } try { @@ -653,23 +279,6 @@ class CancellationTest { stopAllAndJoin() } - @Test - fun testCancelledServiceCancelsRequest() = runCancellationTest { - launch { - serverInstance().firstIncomingConsumed.await() - service.cancel("Cancelled by test") - } - - try { - service.longRequest() - fail("Expected the request to fail to cancellation") - } catch (_: CancellationException) { - // success - } - - stopAllAndJoin() - } - @Test fun testCancellingNonSuspendable() = runCancellationTest { val flow = service.nonSuspendable() @@ -716,7 +325,7 @@ class CancellationTest { private fun CancellationToolkit.processFlowAndLeaveUnusedForGC( firstDone: CompletableDeferred, - latch: CompletableDeferred + latch: CompletableDeferred, ): Job { val flow = service.nonSuspendable() val requestJob = launch { @@ -729,14 +338,12 @@ class CancellationTest { } private fun CancellationToolkit.checkAlive( - serviceAlive: Boolean = true, clientAlive: Boolean = true, serverAlive: Boolean = true, transportAlive: Boolean = true, ) { - checkAlive(serviceAlive, service, "service") - checkAlive(clientAlive, client, "client") - checkAlive(serverAlive, server, "server") + checkAlive(clientAlive, client.internalScope, "client") + checkAlive(serverAlive, server.internalScope, "server") checkAlive(transportAlive, transport, "transport") } @@ -752,8 +359,5 @@ class CancellationTest { private val CoroutineScope.isCompleted get() = coroutineContext.job.isCompleted private val CoroutineScope.isCancelled get() = coroutineContext.job.isCancelled - @Suppress("SuspendFunctionOnCoroutineScope") - private suspend fun CoroutineScope.join() = apply { coroutineContext.job.join() } - private suspend fun CancellationToolkit.stopAllAndJoin() = transport.coroutineContext.job.cancelAndJoin() } diff --git a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationToolkit.kt b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationToolkit.kt index 1614ff10d..187df520c 100644 --- a/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationToolkit.kt +++ b/krpc/krpc-test/src/commonTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationToolkit.kt @@ -16,14 +16,18 @@ import kotlinx.rpc.krpc.rpcServerConfig import kotlinx.rpc.krpc.serialization.json.json import kotlinx.rpc.krpc.test.KrpcTestClient import kotlinx.rpc.krpc.test.KrpcTestServer -import kotlinx.rpc.krpc.test.KrpcTestServiceBackend import kotlinx.rpc.krpc.test.LocalTransport +import kotlinx.rpc.krpc.test.debugCoroutines import kotlinx.rpc.registerService import kotlinx.rpc.withService +import kotlin.time.Duration.Companion.seconds fun runCancellationTest(body: suspend CancellationToolkit.() -> Unit): TestResult { - return runTest { - CancellationToolkit(this).apply { body() } + return runTest(timeout = 15.seconds) { + debugCoroutines() + CancellationToolkit(this).apply { + body() + } } } @@ -51,10 +55,6 @@ class CancellationToolkit(scope: CoroutineScope) : CoroutineScope by scope { val client by lazy { KrpcTestClient(rpcClientConfig { serializationConfig() - - sharedFlowParameters { - replay = KrpcTestServiceBackend.SHARED_FLOW_REPLAY - } }, transport.client) } @@ -66,7 +66,7 @@ class CancellationToolkit(scope: CoroutineScope) : CoroutineScope by scope { val server = KrpcTestServer(rpcServerConfig { serializationConfig() }, transport.server).apply { registerService { - CancellationServiceImpl(it).also { impl -> + CancellationServiceImpl().also { impl -> if (!firstServerInstance.isCompleted) { firstServerInstance.complete(impl) } diff --git a/krpc/krpc-test/src/jsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.js.kt b/krpc/krpc-test/src/jsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.js.kt index 5a01eb69d..e1cc13031 100644 --- a/krpc/krpc-test/src/jsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.js.kt +++ b/krpc/krpc-test/src/jsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.js.kt @@ -4,6 +4,12 @@ package kotlinx.rpc.krpc.test +import kotlinx.coroutines.test.TestScope + actual inline fun runThreadIfPossible(runner: () -> Unit) { runner() } + +@Suppress("detekt.EmptyFunctionBlock") +internal actual fun TestScope.debugCoroutines() { +} diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.jvm.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.jvm.kt index 9142c37fa..864ee2d54 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.jvm.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.jvm.kt @@ -4,6 +4,15 @@ package kotlinx.rpc.krpc.test +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.debug.DebugProbes +import kotlinx.coroutines.test.TestScope + actual fun runThreadIfPossible(runner: () -> Unit) { Thread(runner).start() } + +@OptIn(ExperimentalCoroutinesApi::class) +internal actual fun TestScope.debugCoroutines() { + DebugProbes.install() +} diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/ApiVersioningTest.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/ApiVersioningTest.kt index 9c0e1fee8..c99def244 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/ApiVersioningTest.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/ApiVersioningTest.kt @@ -4,10 +4,7 @@ package kotlinx.rpc.krpc.test.api -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList -import kotlinx.rpc.awaitFieldInitialization import kotlinx.rpc.krpc.internal.CancellationType import kotlinx.rpc.krpc.internal.KrpcMessage import kotlinx.rpc.krpc.internal.KrpcPlugin @@ -67,17 +64,6 @@ class ApiVersioningTest { } } - @Test - @Ignore("Nested flows proved to be unstable") - fun testClientNestedStreamSampling() = wireSamplingTest("clientNestedStream") { - sample { - val response = clientNestedStream(plainFlow { plainFlow { it } }).join() - val expected = List(5) { List(5) { it } }.join() - - assertEquals(expected, response) - } - } - @Test @Ignore("Flow sampling tests are too unstable. Ignored until better fix") fun testServerStreamSampling() = wireSamplingTest("serverStream") { @@ -89,17 +75,6 @@ class ApiVersioningTest { } } - @Test - @Ignore("Nested flows proved to be unstable") - fun testServerNestedStreamSampling() = wireSamplingTest("serverNestedStream") { - sample { - val response = serverNestedFlow().map { it.toList() }.toList().join() - val expected = List(5) { List(5) { it } }.join() - - assertEquals(expected, response) - } - } - @Test fun testCallExceptionSampling() = wireSamplingTest("callException") { // ignore protobuf here, as it's hard to properly sample stacktrace @@ -114,49 +89,6 @@ class ApiVersioningTest { } } - @Test - @Ignore("Flow sampling tests are too unstable. Ignored until better fix") - fun testPlainFlowSampling() = wireSamplingTest("plainFlow") { - sample { - val response = plainFlow.toList().joinToString() - val expected = List(5) { it }.joinToString() - - assertEquals(expected, response) - } - } - - @Test - @Ignore("First value in stateFlow and CallSuccess for its initialization have a race") - fun testSharedFlowSampling() = wireSamplingTest("sharedFlow") { - sample { - val response = sharedFlow.take(5).toList().joinToString() - val expected = List(5) { it }.joinToString() - - assertEquals(expected, response) - } - } - - @Test - @Ignore("First value in stateFlow and CallSuccess for its initialization have a race") - fun testStateFlowSampling() = wireSamplingTest("stateFlow") { - sample { - val state = awaitFieldInitialization { stateFlow } - assertEquals(-1, state.value) - - val newFlow = state.take(2) - - newFlow.collect { - when (it) { - -1 -> emitNextInStateFlow(10) - 10 -> assertEquals(10, state.value) - else -> error("Unexpected value in flow: $it") - } - } - } - } - - private fun List>.join() = joinToString { "[${it.joinToString()}]" } - companion object { val LIBRARY_VERSION_DIR = System.getenv("LIBRARY_VERSION")?.versionToDirName() ?: error("Expected LIBRARY_VERSION env variable") diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/WireSamplingTestScope.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/WireSamplingTestScope.kt index 60ab4e205..df05355b0 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/WireSamplingTestScope.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/WireSamplingTestScope.kt @@ -6,6 +6,8 @@ package kotlinx.rpc.krpc.test.api import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.delay import kotlinx.coroutines.job import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestResult @@ -13,7 +15,9 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.internal.utils.hex.rpcInternalHexToReadableBinary +import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap import kotlinx.rpc.krpc.KrpcTransportMessage +import kotlinx.rpc.krpc.client.KrpcClient import kotlinx.rpc.krpc.internal.logging.RpcInternalCommonLogger import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLogger import kotlinx.rpc.krpc.internal.logging.RpcInternalDumpLoggerContainer @@ -24,13 +28,13 @@ import kotlinx.rpc.krpc.serialization.json.json import kotlinx.rpc.krpc.serialization.protobuf.protobuf import kotlinx.rpc.krpc.test.KrpcTestClient import kotlinx.rpc.krpc.test.KrpcTestServer -import kotlinx.rpc.krpc.test.KrpcTestServiceBackend import kotlinx.rpc.krpc.test.LocalTransport import kotlinx.rpc.krpc.test.api.ApiVersioningTest.Companion.latestVersionOrCurrent import kotlinx.rpc.krpc.test.api.util.GoldComparable import kotlinx.rpc.krpc.test.api.util.GoldComparisonResult import kotlinx.rpc.krpc.test.api.util.GoldUtils import kotlinx.rpc.krpc.test.api.util.checkGold +import kotlinx.rpc.krpc.test.debugCoroutines import kotlinx.rpc.registerService import kotlinx.rpc.withService import kotlinx.serialization.ExperimentalSerializationApi @@ -39,10 +43,19 @@ import org.jetbrains.krpc.test.api.util.SamplingServiceImpl import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.name +import kotlin.reflect.full.callSuspend +import kotlin.reflect.full.memberFunctions +import kotlin.reflect.full.memberProperties +import kotlin.reflect.jvm.isAccessible +import kotlin.time.Clock +import kotlin.time.Duration.Companion.seconds +import kotlin.time.ExperimentalTime @Suppress("RedundantUnitReturnType") fun wireSamplingTest(name: String, sampling: suspend WireSamplingTestScope.() -> Unit): TestResult { - return runTest { + return runTest(timeout = 15.seconds) { + debugCoroutines() + WireSamplingTestScope(name, this).apply { sampling() @@ -67,10 +80,24 @@ class WireSamplingTestScope(private val sampleName: String, scope: TestScope) : val fails = mutableListOf() formats.forEach { format -> val finishedToolkit = WireToolkit(this, format).apply { + initClient() + server // init server service.block() + @Suppress("UNCHECKED_CAST") + val requests = KrpcClient::class.memberProperties + .single { it.name == "requestChannels" } + .apply { + isAccessible = true + } + .get(client) as RpcInternalConcurrentHashMap> + + while (requests.values.isNotEmpty()) { + delay(100) + } + stop() } @@ -90,6 +117,13 @@ class WireSamplingTestScope(private val sampleName: String, scope: TestScope) : fails.failIfAnyCauses() } + private suspend fun WireToolkit.initClient() { + KrpcClient::class.memberFunctions.single { it.name == "initializeTransport" }.apply { + isAccessible = true + callSuspend(client) + } + } + var skipOldServerTests: Boolean = true suspend fun runSimulatorTests() { @@ -126,6 +160,7 @@ class WireSamplingTestScope(private val sampleName: String, scope: TestScope) : val oldClientToolkit = WireToolkit(this, format, logger) logger.info { "Running wire test: old client (version: $version) with current server on $format format" } + oldClientToolkit.initClient() oldClientToolkit.server // init server for ((role, _, message) in dump.filter { it.phase == Phase.Send }) { when (role) { @@ -201,10 +236,6 @@ private class WireToolkit(scope: CoroutineScope, format: SamplingFormat, val log serialization { format.init(this) } - - sharedFlowParameters { - replay = KrpcTestServiceBackend.SHARED_FLOW_REPLAY - } }, transport.client) } @@ -214,7 +245,7 @@ private class WireToolkit(scope: CoroutineScope, format: SamplingFormat, val log val server by lazy { KrpcTestServer(rpcServerConfig { serialization { format.init(this) } }, transport.server).apply { - registerService { SamplingServiceImpl(it) } + registerService { SamplingServiceImpl() } } } @@ -238,8 +269,25 @@ private class WireToolkit(scope: CoroutineScope, format: SamplingFormat, val log } suspend fun stop() { - transport.coroutineContext.job.cancelAndJoin() + @OptIn(ExperimentalTime::class) + while (true) { + val now = Clock.System.now().toEpochMilliseconds() + if (now - transport.lastMessageSentOnClient.value > 400 && + now - transport.lastMessageSentOnServer.value > 400 + ) { + break + } + + delay(100) + } + RpcInternalDumpLoggerContainer.set(null) + + client.close() + server.close() + client.awaitCompletion() + server.awaitCompletion() + transport.coroutineContext.job.cancelAndJoin() } init { @@ -284,7 +332,7 @@ data class DumpLog( .map { it.trim() } .filter { !it.startsWith("//") && it.isNotBlank() } .map { line -> - val (prefix, log) = line.split("\$", limit = 2).map { it.trim() } + val (prefix, log) = line.split("$", limit = 2).map { it.trim() } val (role, phase) = prefix.split(" ") DumpLog(Role.fromText(role), Phase.fromText(phase), log) diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPlugin.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPlugin.gold deleted file mode 100644 index 4176f7d12..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPlugin.gold +++ /dev/null @@ -1,4 +0,0 @@ -kotlinx.rpc.krpc.internal.RPCPlugin - UNKNOWN - HANDSHAKE - CANCELLATION \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPluginKey.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPluginKey.gold deleted file mode 100644 index 50c4302c0..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCPluginKey.gold +++ /dev/null @@ -1,6 +0,0 @@ -kotlinx.rpc.krpc.internal.RPCPluginKey - UNKNOWN - GENERIC_MESSAGE_TYPE - CANCELLATION_TYPE - CANCELLATION_ID - CLIENT_SERVICE_ID \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallData.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallData.gold similarity index 63% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallData.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallData.gold index 41691ec47..d4581352a 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallData.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallData.gold @@ -1,7 +1,7 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallData [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallData] +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.RPCCallMessage.CallType + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType - callableName: kotlin.String - callId: kotlin.String - connectionId: kotlin.Long @@ -13,6 +13,6 @@ org.jetbrains.krpc.internal.transport.RPCMessage.CallData [Declared name: kotlin - serviceType: kotlin.String org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallDataBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallDataBinary org.jetbrains.krpc.RPCMessage.CallData - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallDataString \ No newline at end of file + - 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_1_0/CallDataBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataBinary.gold similarity index 74% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallDataBinary.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataBinary.gold index 5413c5673..b0edd5b46 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallDataBinary.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataBinary.gold @@ -1,8 +1,8 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallDataBinary] +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.RPCCallMessage.CallType + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType - method: kotlin.String - Declared name: callableName - connectionId: kotlin.Long diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallDataString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataString.gold similarity index 78% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallDataString.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataString.gold index 35cc4b870..b9ba5971b 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallDataString.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallDataString.gold @@ -1,8 +1,8 @@ -org.jetbrains.krpc.RPCMessage.CallData [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallDataString] +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.RPCCallMessage.CallType + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallType - method: kotlin.String - Declared name: callableName - connectionId: kotlin.Long diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallException.gold similarity index 87% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallException.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallException.gold index 9918a124c..3b7dfc0e7 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallException.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallException.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.CallException [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallException] +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 diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallResult.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallResult.gold similarity index 65% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallResult.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallResult.gold index 2756efe77..2e7672b9e 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallResult.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallResult.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.CallResult [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallResult] +org.jetbrains.krpc.RPCMessage.CallResult [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallResult] - callId: kotlin.String - connectionId: kotlin.Long - Nullable @@ -9,6 +9,6 @@ org.jetbrains.krpc.RPCMessage.CallResult [Declared name: kotlinx.rpc.krpc.intern - serviceType: kotlin.String org.jetbrains.krpc.RPCMessage.CallException - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallException + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallException org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccess \ No newline at end of file + - 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_1_0/CallSuccess.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccess.gold similarity index 62% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccess.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccess.gold index 258763583..f34c74a72 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccess.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccess.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccess] +org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccess] - callId: kotlin.String - connectionId: kotlin.Long - Nullable @@ -9,6 +9,6 @@ org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess [Declared name: kot - serviceType: kotlin.String org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccessBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessBinary org.jetbrains.krpc.RPCMessage.CallSuccess - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccessString \ No newline at end of file + - 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_1_0/CallSuccessBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessBinary.gold similarity index 78% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccessBinary.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessBinary.gold index a970d3fd2..e8cd58905 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccessBinary.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessBinary.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccessBinary] +org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessBinary] - callId: kotlin.String - connectionId: kotlin.Long - Nullable diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccessString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessString.gold similarity index 83% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccessString.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessString.gold index 1bc411c8d..34c961851 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallSuccessString.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallSuccessString.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallSuccessString] +org.jetbrains.krpc.RPCMessage.CallSuccess [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallSuccessString] - callId: kotlin.String - connectionId: kotlin.Long - Nullable diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallType.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallType.gold similarity index 56% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallType.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallType.gold index 53641ac68..84b5971b3 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/CallType.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/CallType.gold @@ -1,3 +1,3 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallType [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallType] +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_1_0/Failure.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Failure.gold similarity index 66% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/Failure.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Failure.gold index 040889b18..f01da216f 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/Failure.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Failure.gold @@ -1,8 +1,8 @@ -org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Failure [Declared name: kotlinx.rpc.krpc.internal.RPCProtocolMessage.Failure] +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.RPCMessage + - 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_1_0/Handshake.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Handshake.gold similarity index 71% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/Handshake.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Handshake.gold index 91dd33f3b..2f5e2be80 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/Handshake.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/Handshake.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake [Declared name: kotlinx.rpc.krpc.internal.RPCProtocolMessage.Handshake] +org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake [Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Handshake] - connectionId: kotlin.Long - Nullable - pluginParams: kotlin.collections.Map diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCCallMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcCallMessage.gold similarity index 57% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCCallMessage.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcCallMessage.gold index f600a1605..0273b93a3 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCCallMessage.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcCallMessage.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage] +org.jetbrains.krpc.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage] - callId: kotlin.String - serviceId: kotlin.Long - Nullable @@ -9,12 +9,12 @@ org.jetbrains.krpc.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.RPCCallM - Nullable org.jetbrains.krpc.internal.transport.RPCMessage.CallData - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallData + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallData org.jetbrains.krpc.RPCMessage.CallResult - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.CallResult + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.CallResult org.jetbrains.krpc.RPCMessage.StreamCancel - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamCancel + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamCancel org.jetbrains.krpc.RPCMessage.StreamFinished - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamFinished + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamFinished org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessage \ No newline at end of file + - 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_1_0/RPCGenericMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcGenericMessage.gold similarity index 75% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCGenericMessage.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcGenericMessage.gold index d348496e8..b27a3f009 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCGenericMessage.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcGenericMessage.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCGenericMessage [Declared name: kotlinx.rpc.krpc.internal.RPCGenericMessage] +org.jetbrains.krpc.internal.transport.RPCGenericMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcGenericMessage] - connectionId: kotlin.Long - Nullable - pluginParams: kotlin.collections.Map diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcMessage.gold similarity index 57% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCMessage.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcMessage.gold index 08a35a547..6924a1c42 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCMessage.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcMessage.gold @@ -1,12 +1,12 @@ -org.jetbrains.krpc.internal.transport.RPCMessage [Declared name: kotlinx.rpc.krpc.internal.RPCMessage] +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.RPCCallMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage org.jetbrains.krpc.internal.transport.RPCGenericMessage - - Declared name: kotlinx.rpc.krpc.internal.RPCGenericMessage + - Declared name: kotlinx.rpc.krpc.internal.KrpcGenericMessage org.jetbrains.krpc.internal.transport.RPCProtocolMessage - - Declared name: kotlinx.rpc.krpc.internal.RPCProtocolMessage \ No newline at end of file + - 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_8_0/KrpcPlugin.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcPlugin.gold new file mode 100644 index 000000000..0735462c8 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcPlugin.gold @@ -0,0 +1,6 @@ +kotlinx.rpc.krpc.internal.KrpcPlugin + UNKNOWN + HANDSHAKE + CANCELLATION + NON_SUSPENDING_SERVER_FLOWS + NO_ACK_CANCELLATION \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcPluginKey.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcPluginKey.gold new file mode 100644 index 000000000..137d218c5 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_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_1_0/RPCProtocolMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcProtocolMessage.gold similarity index 58% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCProtocolMessage.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcProtocolMessage.gold index 87d80d025..7e80aac18 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/RPCProtocolMessage.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/KrpcProtocolMessage.gold @@ -1,9 +1,9 @@ -org.jetbrains.krpc.internal.transport.RPCProtocolMessage [Declared name: kotlinx.rpc.krpc.internal.RPCProtocolMessage] +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.RPCProtocolMessage.Failure + - Declared name: kotlinx.rpc.krpc.internal.KrpcProtocolMessage.Failure org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake - - Declared name: kotlinx.rpc.krpc.internal.RPCProtocolMessage.Handshake \ No newline at end of file + - 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_1_0/SerializedException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/SerializedException.gold similarity index 100% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/SerializedException.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/SerializedException.gold diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StackElement.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StackElement.gold similarity index 100% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StackElement.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StackElement.gold diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamCancel.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamCancel.gold similarity index 89% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamCancel.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamCancel.gold index ac17cf82a..8e6bd5e5e 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamCancel.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamCancel.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.StreamCancel [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamCancel] +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 diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamFinished.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamFinished.gold similarity index 85% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamFinished.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamFinished.gold index 8f782fdfa..a260d7d75 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamFinished.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamFinished.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.StreamFinished [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamFinished] +org.jetbrains.krpc.RPCMessage.StreamFinished [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamFinished] - callId: kotlin.String - connectionId: kotlin.Long - Nullable diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessage.gold similarity index 63% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessage.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessage.gold index 7d2d2b4b6..e07485913 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessage.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessage.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessage] +org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessage] - streamId: kotlin.String - callId: kotlin.String - connectionId: kotlin.Long @@ -10,6 +10,6 @@ org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage [Declared name: k - serviceType: kotlin.String org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessageBinary + - Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageBinary org.jetbrains.krpc.RPCMessage.StreamMessage - - Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessageString \ No newline at end of file + - 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_1_0/StreamMessageBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageBinary.gold similarity index 80% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessageBinary.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageBinary.gold index a48ca9832..6da67510f 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessageBinary.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageBinary.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessageBinary] +org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageBinary] - callId: kotlin.String - connectionId: kotlin.Long - Nullable diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessageString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageString.gold similarity index 85% rename from krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessageString.gold rename to krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageString.gold index 23d4f4447..3316fc14e 100644 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_1_0/StreamMessageString.gold +++ b/krpc/krpc-test/src/jvmTest/resources/class_dumps/0_8_0/StreamMessageString.gold @@ -1,4 +1,4 @@ -org.jetbrains.krpc.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.RPCCallMessage.StreamMessageString] +org.jetbrains.krpc.RPCMessage.StreamMessage [Declared name: kotlinx.rpc.krpc.internal.KrpcCallMessage.StreamMessageString] - callId: kotlin.String - connectionId: kotlin.Long - Nullable diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallData.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallData.gold deleted file mode 100644 index 30b7228d9..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallData.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallData - - callId: kotlin.String - - method: kotlin.String - - Declared name: callableName - - data: kotlin.String - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallException.gold deleted file mode 100644 index 8084f57e1..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallException.gold +++ /dev/null @@ -1,4 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallException - - callId: kotlin.String - - cause: org.jetbrains.krpc.SerializedException - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallResult.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallResult.gold deleted file mode 100644 index a84cf2181..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallResult.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallResult - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.RPCMessage.CallException - org.jetbrains.krpc.RPCMessage.CallSuccess \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallSuccess.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallSuccess.gold deleted file mode 100644 index 7d43fb770..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/CallSuccess.gold +++ /dev/null @@ -1,4 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallSuccess - - callId: kotlin.String - - data: kotlin.String - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/RPCMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/RPCMessage.gold deleted file mode 100644 index 7a5195186..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/RPCMessage.gold +++ /dev/null @@ -1,9 +0,0 @@ -org.jetbrains.krpc.RPCMessage - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.RPCMessage.CallData - org.jetbrains.krpc.RPCMessage.CallResult - org.jetbrains.krpc.RPCMessage.StreamCancel - org.jetbrains.krpc.RPCMessage.StreamFinished - org.jetbrains.krpc.RPCMessage.StreamMessage \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/SerializedException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/SerializedException.gold deleted file mode 100644 index f41665be5..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/SerializedException.gold +++ /dev/null @@ -1,7 +0,0 @@ -org.jetbrains.krpc.SerializedException - - cause: org.jetbrains.krpc.SerializedException - - Nullable - - 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/4_2_beta/StackElement.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StackElement.gold deleted file mode 100644 index 301ab9113..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StackElement.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.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/4_2_beta/StreamCancel.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamCancel.gold deleted file mode 100644 index 0bcfd6a37..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamCancel.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamCancel - - callId: kotlin.String - - cause: org.jetbrains.krpc.SerializedException - - 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/4_2_beta/StreamFinished.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamFinished.gold deleted file mode 100644 index 2fdb19288..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamFinished.gold +++ /dev/null @@ -1,5 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamFinished - - callId: kotlin.String - - 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/4_2_beta/StreamMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamMessage.gold deleted file mode 100644 index 164a434a1..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/4_2_beta/StreamMessage.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamMessage - - callId: kotlin.String - - data: kotlin.String - - 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/5_3_beta/CallData.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallData.gold deleted file mode 100644 index c50fb64c7..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallData.gold +++ /dev/null @@ -1,10 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallData - - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType - - Nullable - - callableName: kotlin.String - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary - org.jetbrains.krpc.RPCMessage.CallData - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallDataString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataBinary.gold deleted file mode 100644 index de72728d0..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataBinary.gold +++ /dev/null @@ -1,8 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary - - callId: kotlin.String - - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType - - Nullable - - method: kotlin.String - - Declared name: callableName - - data: kotlin.ByteArray - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataString.gold deleted file mode 100644 index 16d569139..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallDataString.gold +++ /dev/null @@ -1,8 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallData [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallDataString] - - callId: kotlin.String - - callType: org.jetbrains.krpc.internal.transport.RPCMessage.CallType - - Nullable - - method: kotlin.String - - Declared name: callableName - - data: kotlin.String - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallException.gold deleted file mode 100644 index 98b4c5d7d..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallException.gold +++ /dev/null @@ -1,5 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallException [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallException] - - callId: kotlin.String - - cause: org.jetbrains.krpc.SerializedException - - Declared name: org.jetbrains.krpc.internal.transport.SerializedException - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallResult.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallResult.gold deleted file mode 100644 index 1c43e6014..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallResult.gold +++ /dev/null @@ -1,7 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallResult [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallResult] - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.RPCMessage.CallException - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallException - org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccess.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccess.gold deleted file mode 100644 index f75972d36..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccess.gold +++ /dev/null @@ -1,7 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccess - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary - org.jetbrains.krpc.RPCMessage.CallSuccess - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessBinary.gold deleted file mode 100644 index 6188fccb5..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessBinary.gold +++ /dev/null @@ -1,4 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary - - callId: kotlin.String - - data: kotlin.ByteArray - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessString.gold deleted file mode 100644 index 3a7450093..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallSuccessString.gold +++ /dev/null @@ -1,4 +0,0 @@ -org.jetbrains.krpc.RPCMessage.CallSuccess [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessString] - - callId: kotlin.String - - data: kotlin.String - - serviceType: kotlin.String \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallType.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallType.gold deleted file mode 100644 index 05e5d2187..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/CallType.gold +++ /dev/null @@ -1,3 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.CallType - Method - Field \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/RPCMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/RPCMessage.gold deleted file mode 100644 index 9ce6c01c1..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/RPCMessage.gold +++ /dev/null @@ -1,12 +0,0 @@ -org.jetbrains.krpc.RPCMessage [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage] - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.internal.transport.RPCMessage.CallData - org.jetbrains.krpc.RPCMessage.CallResult - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.CallResult - org.jetbrains.krpc.RPCMessage.StreamCancel - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamCancel - org.jetbrains.krpc.RPCMessage.StreamFinished - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamFinished - org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/SerializedException.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/SerializedException.gold deleted file mode 100644 index 1d9410c05..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/SerializedException.gold +++ /dev/null @@ -1,8 +0,0 @@ -org.jetbrains.krpc.SerializedException [Declared name: kotlinx.rpc.internal.transport.SerializedException] - - cause: org.jetbrains.krpc.SerializedException - - Nullable - - Declared name: kotlinx.rpc.internal.transport.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/5_3_beta/StackElement.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StackElement.gold deleted file mode 100644 index af58763db..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StackElement.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.StackElement [Declared name: kotlinx.rpc.internal.transport.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/5_3_beta/StreamCancel.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamCancel.gold deleted file mode 100644 index b6328c906..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamCancel.gold +++ /dev/null @@ -1,7 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamCancel [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamCancel] - - callId: kotlin.String - - cause: org.jetbrains.krpc.SerializedException - - Declared name: org.jetbrains.krpc.internal.transport.SerializedException - - 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/5_3_beta/StreamFinished.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamFinished.gold deleted file mode 100644 index 4cc577231..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamFinished.gold +++ /dev/null @@ -1,5 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamFinished [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamFinished] - - callId: kotlin.String - - 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/5_3_beta/StreamMessage.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessage.gold deleted file mode 100644 index f946eeb9c..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessage.gold +++ /dev/null @@ -1,8 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessage - - streamId: kotlin.String - - callId: kotlin.String - - serviceType: kotlin.String - - org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary - org.jetbrains.krpc.RPCMessage.StreamMessage - - Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageString \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessageBinary.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessageBinary.gold deleted file mode 100644 index ca3d8e5d5..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessageBinary.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary - - callId: kotlin.String - - data: kotlin.ByteArray - - 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/5_3_beta/StreamMessageString.gold b/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessageString.gold deleted file mode 100644 index 2a5bd168e..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/class_dumps/5_3_beta/StreamMessageString.gold +++ /dev/null @@ -1,6 +0,0 @@ -org.jetbrains.krpc.RPCMessage.StreamMessage [Declared name: org.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageString] - - callId: kotlin.String - - data: kotlin.String - - 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 7733354c7..1317fc12a 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,4 +1,5 @@ UNKNOWN - 0 HANDSHAKE - 1 CANCELLATION - 2 -NON_SUSPENDING_SERVER_FLOWS - 3 \ No newline at end of file +NON_SUSPENDING_SERVER_FLOWS - 3 +NO_ACK_CANCELLATION - 4 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/callException_json.gold deleted file mode 100644 index 684eab404..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/callException_json.gold +++ /dev/null @@ -1,8 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:kotlinx.rpc.SamplingServiceClient.CallException_RPCData: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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData: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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_json.gold deleted file mode 100644 index fd230e3c2..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_json.gold +++ /dev/null @@ -1,20 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"clientStream","callType":"Method","data":"{\"flow\":\"stream:0\"}","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"clientStream","callType":"Method","data":"{\"flow\":\"stream:0\"}","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"[0,1,2,3,4]","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"[0,1,2,3,4]","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_protobuf.gold deleted file mode 100644 index 551823903..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/clientStream_protobuf.gold +++ /dev/null @@ -1,40 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??clientStream ?*???stream:00?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791295010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0c636c69656e7453747265616d20002a0a0a0873747265616d3a3030013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??clientStream ?*???stream:00?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791295010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0c636c69656e7453747265616d20002a0a0a0873747265616d3a3030013801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Client] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e69736865641283010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791286010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Server] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e69736865641283010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???????? ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791281010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0605000102030420012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???????? ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791281010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0605000102030420012801 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_json.gold deleted file mode 100644 index 263c006ae..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_json.gold +++ /dev/null @@ -1,8 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:kotlinx.rpc.SamplingServiceClient.Echo_RPCData: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:kotlinx.rpc.SamplingServiceClient.Echo_RPCData: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:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_protobuf.gold deleted file mode 100644 index e18195d38..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/echo_protobuf.gold +++ /dev/null @@ -1,16 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?r?21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912720a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?r?21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912720a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_json.gold deleted file mode 100644 index 4b81c9275..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_json.gold +++ /dev/null @@ -1,20 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"plainFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"plainFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_protobuf.gold deleted file mode 100644 index 2021a232b..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/plainFlow_protobuf.gold +++ /dev/null @@ -1,40 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?}?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??plainFlow ?*?0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127d0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a09706c61696e466c6f7720012a0030013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?}?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??plainFlow ?*?0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127d0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a09706c61696e466c6f7720012a0030013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?x?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Server] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e697368656412780a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?x?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Client] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e697368656412780a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_json.gold deleted file mode 100644 index 3d4c8ecfc..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_json.gold +++ /dev/null @@ -1,20 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"serverFlow","callType":"Method","data":"{}","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"serverFlow","callType":"Method","data":"{}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_protobuf.gold deleted file mode 100644 index ffc0b2684..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/serverStream_protobuf.gold +++ /dev/null @@ -1,40 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??serverFlow ?*?0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791287010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736572766572466c6f7720002a0030013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??serverFlow ?*?0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791287010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736572766572466c6f7720002a0030013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791282010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791282010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Server] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e69736865641281010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791289010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a046461746128013001 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 ?(? -[Client] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e69736865641281010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3020012801 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_json.gold deleted file mode 100644 index 06afa54dd..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_json.gold +++ /dev/null @@ -1,18 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"sharedFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"sharedFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_protobuf.gold deleted file mode 100644 index 2cb051a23..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/sharedFlow_protobuf.gold +++ /dev/null @@ -1,36 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?~?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??sharedFlow ?*?0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127e0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736861726564466c6f7720012a0030013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?~?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??sharedFlow ?*?0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127e0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736861726564466c6f7720012a0030013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a3020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010028013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010128013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010228013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010328013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010428013001 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_json.gold deleted file mode 100644 index fc797910e..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_json.gold +++ /dev/null @@ -1,16 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"stateFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"stateFlow","callType":"Field","data":"{}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"-1","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"-1","connectionId":1,"serviceId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"emitNextInStateFlow","callType":"Method","data":"{\"next\":10}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"-1","connectionId":1,"serviceId":1} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"emitNextInStateFlow","callType":"Method","data":"{\"next\":10}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"-1","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{}","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{}","connectionId":1,"serviceId":1} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"10","connectionId":1,"serviceId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"10","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_protobuf.gold deleted file mode 100644 index 2cf473349..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_1_0/stateFlow_protobuf.gold +++ /dev/null @@ -1,32 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?}?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stateFlow ?*?0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127d0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a097374617465466c6f7720012a0030013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?}?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stateFlow ?*?0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127d0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a097374617465466c6f7720012a0030013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0?????????? ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791283010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a130873747265616d3a30ffffffffffffffffff0120012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0?????????? ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791283010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a130873747265616d3a30ffffffffffffffffff0120012801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService??emitNextInStateFlow ?*???0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279129b010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a13656d69744e657874496e5374617465466c6f7720002a02080a30013801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???????????(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791284010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220affffffffffffffffff0128013001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService??emitNextInStateFlow ?*???0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279129b010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a13656d69744e657874496e5374617465466c6f7720002a02080a30013801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???????????(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791284010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220affffffffffffffffff0128013001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService?? ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791282010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0020012801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService?? ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e6172791282010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0020012801 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010a28013001 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?{?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??(?0? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e617279127b0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010a28013001 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/callException_json.gold deleted file mode 100644 index 6c996c8f2..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/callException_json.gold +++ /dev/null @@ -1,10 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:kotlinx.rpc.SamplingServiceClient.CallException_RPCData: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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData: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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1"}} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"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:kotlinx.rpc.SamplingServiceClient.CallException_RPCData:1"}} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_json.gold deleted file mode 100644 index 346ffb89c..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_json.gold +++ /dev/null @@ -1,9 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:kotlinx.rpc.SamplingServiceClient.Echo_RPCData: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:kotlinx.rpc.SamplingServiceClient.Echo_RPCData: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:kotlinx.rpc.SamplingServiceClient.Echo_RPCData: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:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1"}} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_protobuf.gold deleted file mode 100644 index a178c55ae..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_1/echo_protobuf.gold +++ /dev/null @@ -1,18 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?r?21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912720a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 -// decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage?{???????????????cancellation???????????????CANCELLATION_ACK??????????????21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1 -[Server] [Send] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d657373616765127b1219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b123f088380feffffffffffff011232313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a31 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?r?21:kotlinx.rpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912720a32313a6b6f746c696e782e7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/callException_json.gold deleted file mode 100644 index 3950cea98..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/callException_json.gold +++ /dev/null @@ -1,10 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"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":null,"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":null,"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_2_3/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/echo_json.gold deleted file mode 100644 index 572d659f2..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/echo_json.gold +++ /dev/null @@ -1,10 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766]} -[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"connectionId":1} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766],"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_2_3/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/echo_protobuf.gold deleted file mode 100644 index 7e5144b53..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_2_3/echo_protobuf.gold +++ /dev/null @@ -1,20 +0,0 @@ -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake???????????????????????? -[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651216088180feffffffffffff01088280feffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?????????????????????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b651218088180feffffffffffff01088280feffffffffffff011001 -// 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: ?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 -// 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 -[Client] [Receive] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d65737361676512a0011219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b1264088380feffffffffffff011257313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a31 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/callException_json.gold index 44dd288b1..286a96bf7 100644 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/callException_json.gold +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/callException_json.gold @@ -5,6 +5,5 @@ [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 +[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"}} diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_json.gold index 572d659f2..3c8637539 100644 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_json.gold +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_json.gold @@ -5,6 +5,5 @@ [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 +[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"}} diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_protobuf.gold index 7e5144b53..3d481f5b1 100644 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_protobuf.gold +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_4_0/echo_protobuf.gold @@ -12,9 +12,7 @@ [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: ?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 // 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 -[Client] [Receive] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d65737361676512a0011219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b1264088380feffffffffffff011257313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a31 \ No newline at end of file +[Client] [Receive] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d65737361676512a0011219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b1264088380feffffffffffff011257313a6f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963652e60247270635365727669636553747562602e606563686f247270634d6574686f64603a31 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 index 8a3ceff5d..3d7fa87f4 100644 --- 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 @@ -5,6 +5,5 @@ [Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:callException: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:callException: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:callException: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:callException:1"}} [Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:callException: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:callException:1"}} 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 index 37c083ac4..e8d34906e 100644 --- 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 @@ -5,6 +5,5 @@ [Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:echo: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:echo: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:echo: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:echo:1"}} [Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:echo: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:echo:1"}} 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 index d52bc3ab5..78db12d34 100644 --- 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 @@ -12,8 +12,6 @@ [Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912590a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801 // decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?H??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? [Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912480a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 -// decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage?Q???????????????cancellation???????????????CANCELLATION_ACK???????????????1:echo:1 -[Server] [Send] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d65737361676512511219088180feffffffffffff01120c63616e63656c6c6174696f6e121d088280feffffffffffff01121043414e43454c4c4154494f4e5f41434b1215088380feffffffffffff011208313a6563686f3a31 // decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?H??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? [Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912480a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 // decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage?Q???????????????cancellation???????????????CANCELLATION_ACK???????????????1:echo:1 diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/callException_json.gold new file mode 100644 index 000000000..c9c382ff5 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/callException_json.gold @@ -0,0 +1,8 @@ +[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764]} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764]} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764],"connectionId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764],"connectionId":1} +[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:callException:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}","connectionId":1,"serviceId":1,"pluginParams":{"-32763":""}} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:callException:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}","connectionId":1,"serviceId":1,"pluginParams":{"-32763":""}} +[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:callException:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:callException:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"},"connectionId":1,"serviceId":1} diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_json.gold new file mode 100644 index 000000000..7f68cc990 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_json.gold @@ -0,0 +1,10 @@ +[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764]} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764]} +[Server] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764],"connectionId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake","supportedPlugins":[-32767,-32766,-32765,-32764],"connectionId":1} +[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:echo:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}","connectionId":1,"serviceId":1,"pluginParams":{"-32763":""}} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:echo:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}","connectionId":1,"serviceId":1,"pluginParams":{"-32763":""}} +[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:echo:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} +[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:echo:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}","connectionId":1,"serviceId":1} +[Client] [Send] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"REQUEST","-32764":"org.jetbrains.krpc.test.api.util.SamplingService","-32765":"1:echo:1"}} +[Server] [Receive] $ {"type":"org.jetbrains.krpc.internal.transport.RPCGenericMessage","connectionId":null,"pluginParams":{"-32767":"cancellation","-32766":"REQUEST","-32764":"org.jetbrains.krpc.test.api.util.SamplingService","-32765":"1:echo:1"}} diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_protobuf.gold new file mode 100644 index 000000000..bc4821607 --- /dev/null +++ b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/0_8_0/echo_protobuf.gold @@ -0,0 +1,20 @@ +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?,???????????????????????????????????????????? +[Client] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b65122c088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01088480feffffffffffff01 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?,???????????????????????????????????????????? +[Server] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b65122c088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01088480feffffffffffff01 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?.?????????????????????????????????????????????? +[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b65122e088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01088480feffffffffffff011001 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCProtocolMessage.Handshake?.?????????????????????????????????????????????? +[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504350726f746f636f6c4d6573736167652e48616e647368616b65122e088180feffffffffffff01088280feffffffffffff01088380feffffffffffff01088480feffffffffffff011001 +// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?h??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8?B?????????????? +[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912680a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801420d088580feffffffffffff011200 +// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?h??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data0?8?B?????????????? +[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912680a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a046461746130013801420d088580feffffffffffff011200 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?H??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? +[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912480a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 +// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?H??1:echo:1?0org.jetbrains.krpc.test.api.util.SamplingService????data ?(? +[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912480a08313a6563686f3a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a046461746120012801 +// decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage??????????????????cancellation???????????????REQUEST?=????????????0org.jetbrains.krpc.test.api.util.SamplingService???????????????1:echo:1 +[Client] [Send] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d6573736167651287011219088180feffffffffffff01120c63616e63656c6c6174696f6e1214088280feffffffffffff01120752455155455354123d088480feffffffffffff0112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651215088380feffffffffffff011208313a6563686f3a31 +// decoded: ?7org.jetbrains.krpc.internal.transport.RPCGenericMessage??????????????????cancellation???????????????REQUEST?=????????????0org.jetbrains.krpc.test.api.util.SamplingService???????????????1:echo:1 +[Server] [Receive] $ 0a376f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e52504347656e657269634d6573736167651287011219088180feffffffffffff01120c63616e63656c6c6174696f6e1214088280feffffffffffff01120752455155455354123d088480feffffffffffff0112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651215088380feffffffffffff011208313a6563686f3a31 diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/callException_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/callException_json.gold deleted file mode 100644 index 309ea7e0b..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/callException_json.gold +++ /dev/null @@ -1,4 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"callException","callType":"Method","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:org.jetbrains.krpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"}} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallException","callId":"1:org.jetbrains.krpc.SamplingServiceClient.CallException_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","cause":{"toStringMessage":"java.lang.IllegalStateException: Server exception","message":"Server exception","stacktrace":[],"cause":null,"className":"java.lang.IllegalStateException"}} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_json.gold deleted file mode 100644 index 6e7104fc0..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_json.gold +++ /dev/null @@ -1,16 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"clientStream","callType":"Method","data":"{\"flow\":\"stream:0\"}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"clientStream","callType":"Method","data":"{\"flow\":\"stream:0\"}"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"[0,1,2,3,4]"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"[0,1,2,3,4]"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_protobuf.gold deleted file mode 100644 index ed240998b..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/clientStream_protobuf.gold +++ /dev/null @@ -1,32 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??clientStream ?*???stream:0 -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791291010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0c636c69656e7453747265616d20002a0a0a0873747265616d3a30 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??clientStream ?*???stream:0 -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791291010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0c636c69656e7453747265616d20002a0a0a0873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished???A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Client] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e6973686564127f0a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791282010a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished???A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Server] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e6973686564127f0a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?}?A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127d0a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a06050001020304 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?}?A1:org.jetbrains.krpc.SamplingServiceClient.ClientStream_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127d0a41313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e436c69656e7453747265616d5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a06050001020304 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_json.gold deleted file mode 100644 index 9615c918c..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_json.gold +++ /dev/null @@ -1,4 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"echo","callType":"Method","data":"{\"arg1\":\"Hello\",\"data\":{\"data\":\"data\"}}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{\"data\":\"data\"}"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_protobuf.gold deleted file mode 100644 index 1e53265a5..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/echo_protobuf.gold +++ /dev/null @@ -1,8 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????91:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791286010a39313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a0464617461 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????91:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??echo ?*???Hello????data -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791286010a39313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a046563686f20002a0f0a0548656c6c6f12060a0464617461 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?91:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a39313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a0464617461 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?91:org.jetbrains.krpc.SamplingServiceClient.Echo_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService????data -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a39313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e4563686f5f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a060a0464617461 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_json.gold deleted file mode 100644 index 2c76fb0f7..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_json.gold +++ /dev/null @@ -1,16 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"plainFlow","callType":"Field","data":"{}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"plainFlow","callType":"Field","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_protobuf.gold deleted file mode 100644 index 7df170b85..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/plainFlow_protobuf.gold +++ /dev/null @@ -1,32 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??plainFlow ?*? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a09706c61696e466c6f7720012a00 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??plainFlow ?*? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a09706c61696e466c6f7720012a00 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?t?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Server] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e697368656412740a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?t?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Client] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e697368656412740a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_json.gold deleted file mode 100644 index 9b72d37d9..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_json.gold +++ /dev/null @@ -1,16 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"serverFlow","callType":"Method","data":"{}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"serverFlow","callType":"Method","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"{\"data\":\"data\"}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamFinished","callId":"1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_protobuf.gold deleted file mode 100644 index bc0fed99a..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/serverStream_protobuf.gold +++ /dev/null @@ -1,32 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??serverFlow ?*? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736572766572466c6f7720002a00 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??serverFlow ?*? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791283010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736572766572466c6f7720002a00 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?~??1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127e0a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?~??1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127e0a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?}??1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Server] [Send] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e6973686564127d0a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?????1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"???data -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791285010a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022060a0464617461 -// decoded: ?,org.jetbrains.krpc.RPCMessage.StreamFinished?}??1:org.jetbrains.krpc.SamplingServiceClient.ServerFlow_RPCData:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0 -[Client] [Receive] $ 0a2c6f72672e6a6574627261696e732e6b7270632e5250434d6573736167652e53747265616d46696e6973686564127d0a3f313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e536572766572466c6f775f525043446174613a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_json.gold deleted file mode 100644 index 7bd94f78f..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_json.gold +++ /dev/null @@ -1,14 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"sharedFlow","callType":"Field","data":"{}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"sharedFlow","callType":"Field","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\""} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"0"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"1"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"2"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"3"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"4"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_protobuf.gold deleted file mode 100644 index c147a170f..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/sharedFlow_protobuf.gold +++ /dev/null @@ -1,28 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?z?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??sharedFlow ?*? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127a0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736861726564466c6f7720012a00 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?z?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??sharedFlow ?*? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e617279127a0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0a736861726564466c6f7720012a00 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?u?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0 -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e61727912750a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a090873747265616d3a30 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220100 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220101 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220102 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220103 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220104 \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_json.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_json.gold deleted file mode 100644 index 4ca6bbe16..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_json.gold +++ /dev/null @@ -1,12 +0,0 @@ -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"stateFlow","callType":"Field","data":"{}"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"stateFlow","callType":"Field","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"-1"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"\"stream:0\"-1"} -[Client] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"emitNextInStateFlow","callType":"Method","data":"{\"next\":10}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"-1"} -[Server] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallData","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","method":"emitNextInStateFlow","callType":"Method","data":"{\"next\":10}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"-1"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{}"} -[Server] [Send] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"10"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.CallSuccess","callId":"1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","data":"{}"} -[Client] [Receive] $ {"type":"org.jetbrains.krpc.RPCMessage.StreamMessage","callId":"1:org.jetbrains.krpc.client.internal.FieldDataObject:1","serviceType":"org.jetbrains.krpc.test.api.util.SamplingService","flowId":"stream:0","data":"10"} \ No newline at end of file diff --git a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_protobuf.gold b/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_protobuf.gold deleted file mode 100644 index b8bf0397e..000000000 --- a/krpc/krpc-test/src/jvmTest/resources/wire_dumps/5_3_beta/stateFlow_protobuf.gold +++ /dev/null @@ -1,24 +0,0 @@ -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stateFlow ?*? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a097374617465466c6f7720012a00 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary?y?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stateFlow ?*? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e61727912790a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a097374617465466c6f7720012a00 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary???61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0?????????? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127f0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a130873747265616d3a30ffffffffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary???61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService???stream:0?????????? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127f0a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a130873747265616d3a30ffffffffffffffffff01 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService??emitNextInStateFlow ?*??? -[Client] [Send] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791297010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a13656d69744e657874496e5374617465466c6f7720002a02080a -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??????????? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791280010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220affffffffffffffffff01 -// decoded: ??org.jetbrains.krpc.internal.transport.RPCMessage.CallDataBinary????H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService??emitNextInStateFlow ?*??? -[Server] [Receive] $ 0a3f6f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c4461746142696e6172791297010a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a13656d69744e657874496e5374617465466c6f7720002a02080a -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary????61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"??????????? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e6172791280010a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a30220affffffffffffffffff01 -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?~?H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService?? -[Server] [Send] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127e0a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a00 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Server] [Send] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010a -// decoded: ?Borg.jetbrains.krpc.internal.transport.RPCMessage.CallSuccessBinary?~?H1:org.jetbrains.krpc.SamplingServiceClient.EmitNextInStateFlow_RPCData:2?0org.jetbrains.krpc.test.api.util.SamplingService?? -[Client] [Receive] $ 0a426f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e43616c6c5375636365737342696e617279127e0a48313a6f72672e6a6574627261696e732e6b7270632e53616d706c696e6753657276696365436c69656e742e456d69744e657874496e5374617465466c6f775f525043446174613a3212306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a00 -// decoded: ?Dorg.jetbrains.krpc.internal.transport.RPCMessage.StreamMessageBinary?w?61:org.jetbrains.krpc.client.internal.FieldDataObject:1?0org.jetbrains.krpc.test.api.util.SamplingService??stream:0"?? -[Client] [Receive] $ 0a446f72672e6a6574627261696e732e6b7270632e696e7465726e616c2e7472616e73706f72742e5250434d6573736167652e53747265616d4d65737361676542696e61727912770a36313a6f72672e6a6574627261696e732e6b7270632e636c69656e742e696e7465726e616c2e4669656c64446174614f626a6563743a3112306f72672e6a6574627261696e732e6b7270632e746573742e6170692e7574696c2e53616d706c696e67536572766963651a0873747265616d3a3022010a \ No newline at end of file diff --git a/krpc/krpc-test/src/nativeMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.native.kt b/krpc/krpc-test/src/nativeMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.native.kt index 72c450a8e..4d4073c72 100644 --- a/krpc/krpc-test/src/nativeMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.native.kt +++ b/krpc/krpc-test/src/nativeMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.native.kt @@ -4,6 +4,7 @@ package kotlinx.rpc.krpc.test +import kotlinx.coroutines.test.TestScope import kotlin.native.concurrent.ObsoleteWorkersApi import kotlin.native.concurrent.Worker @@ -11,3 +12,7 @@ import kotlin.native.concurrent.Worker actual fun runThreadIfPossible(runner: () -> Unit) { Worker.start(errorReporting = true).executeAfter(0L, runner) } + +@Suppress("detekt.EmptyFunctionBlock") +internal actual fun TestScope.debugCoroutines() { +} diff --git a/krpc/krpc-test/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.wasmJs.kt b/krpc/krpc-test/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.wasmJs.kt index 5a01eb69d..84b7631cb 100644 --- a/krpc/krpc-test/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.wasmJs.kt +++ b/krpc/krpc-test/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/test/KrpcTestServiceBackend.wasmJs.kt @@ -4,6 +4,11 @@ package kotlinx.rpc.krpc.test +import kotlinx.coroutines.test.TestScope + actual inline fun runThreadIfPossible(runner: () -> Unit) { runner() } + +internal actual fun TestScope.debugCoroutines() { +} diff --git a/tests/compiler-plugin-tests/src/main/kotlin/kotlinx/rpc/codegen/test/TestRpcClient.kt b/tests/compiler-plugin-tests/src/main/kotlin/kotlinx/rpc/codegen/test/TestRpcClient.kt index eeb8d11cb..d52504bad 100644 --- a/tests/compiler-plugin-tests/src/main/kotlin/kotlinx/rpc/codegen/test/TestRpcClient.kt +++ b/tests/compiler-plugin-tests/src/main/kotlin/kotlinx/rpc/codegen/test/TestRpcClient.kt @@ -4,44 +4,18 @@ package kotlinx.rpc.codegen.test -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.rpc.RpcCall import kotlinx.rpc.RpcClient -import kotlin.coroutines.CoroutineContext @Suppress("UNCHECKED_CAST", "unused") object TestRpcClient : RpcClient { - override val coroutineContext: CoroutineContext = Job() - override suspend fun call(call: RpcCall): T { return "call_42" as T } - @OptIn(DelicateCoroutinesApi::class) - @Suppress("detekt.GlobalCoroutineUsage") - override fun callAsync(serviceScope: CoroutineScope, call: RpcCall): Deferred { - val callable = call.descriptor.getCallable(call.callableName) - ?: error("No callable found for ${call.callableName}") - - val value = when (callable.name) { - "plainFlow" -> flow { emit("registerPlainFlowField_42") } - - "sharedFlow" -> MutableSharedFlow(1).also { - GlobalScope.launch { it.emit("registerSharedFlowField_42") } - } - - "stateFlow" -> MutableStateFlow("registerStateFlowField_42") - - else -> error("Unknown callable name: ${call.callableName}") - } - - return CompletableDeferred(value as T) - } - - override fun provideStubContext(serviceId: Long): CoroutineContext { - return coroutineContext + override fun callServerStreaming(call: RpcCall): Flow { + return flow { emit("stream_42" as T) } } } diff --git a/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/BoxTestGenerated.java b/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/BoxTestGenerated.java index 9b0b0c3e5..b204c706c 100644 --- a/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/BoxTestGenerated.java +++ b/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/BoxTestGenerated.java @@ -27,12 +27,6 @@ public void testCustomParameterTypes() { runTest("src/testData/box/customParameterTypes.kt"); } - @Test - @TestMetadata("fields.kt") - public void testFields() { - runTest("src/testData/box/fields.kt"); - } - @Test @TestMetadata("flowParameter.kt") public void testFlowParameter() { diff --git a/tests/compiler-plugin-tests/src/test/kotlin/kotlinx/rpc/codegen/test/services/ExtensionRegistrarConfigurator.kt b/tests/compiler-plugin-tests/src/test/kotlin/kotlinx/rpc/codegen/test/services/ExtensionRegistrarConfigurator.kt index 9b86738f1..228579de0 100644 --- a/tests/compiler-plugin-tests/src/test/kotlin/kotlinx/rpc/codegen/test/services/ExtensionRegistrarConfigurator.kt +++ b/tests/compiler-plugin-tests/src/test/kotlin/kotlinx/rpc/codegen/test/services/ExtensionRegistrarConfigurator.kt @@ -5,8 +5,6 @@ package kotlinx.rpc.codegen.test.services import kotlinx.rpc.codegen.RpcFirConfigurationKeys -import kotlinx.rpc.codegen.StrictMode -import kotlinx.rpc.codegen.StrictModeConfigurationKeys import kotlinx.rpc.codegen.registerRpcExtensions import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar import org.jetbrains.kotlin.config.CompilerConfiguration @@ -25,18 +23,6 @@ class ExtensionRegistrarConfigurator(testServices: TestServices) : EnvironmentCo module: TestModule, configuration: CompilerConfiguration, ) { - val strictMode = module.directives[RpcDirectives.RPC_STRICT_MODE] - if (strictMode.isNotEmpty()) { - val mode = StrictMode.fromCli(strictMode.single()) ?: StrictMode.ERROR - configuration.put(StrictModeConfigurationKeys.STATE_FLOW, mode) - configuration.put(StrictModeConfigurationKeys.SHARED_FLOW, mode) - configuration.put(StrictModeConfigurationKeys.NESTED_FLOW, mode) - configuration.put(StrictModeConfigurationKeys.STREAM_SCOPED_FUNCTIONS, mode) - configuration.put(StrictModeConfigurationKeys.SUSPENDING_SERVER_STREAMING, mode) - configuration.put(StrictModeConfigurationKeys.NOT_TOP_LEVEL_SERVER_FLOW, mode) - configuration.put(StrictModeConfigurationKeys.FIELDS, mode) - } - val annotationTypeSafety = module.directives[RpcDirectives.ANNOTATION_TYPE_SAFETY] if (annotationTypeSafety.isNotEmpty()) { configuration.put( @@ -53,6 +39,5 @@ class ExtensionRegistrarConfigurator(testServices: TestServices) : EnvironmentCo } object RpcDirectives : SimpleDirectivesContainer() { - val RPC_STRICT_MODE by stringDirective("none, warning or error", DirectiveApplicability.Module) val ANNOTATION_TYPE_SAFETY by stringDirective("true or false", DirectiveApplicability.Module) } 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 99523dc30..aaa43832f 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 @@ -311,7 +311,7 @@ FILE fqName: fileName:/customParameterTypes.kt index: CONST Int type=kotlin.Int value=0 value: CALL 'public final fun (): kotlin.String declared in .TestData' type=kotlin.String origin=GET_PROPERTY $this: GET_VAR 'self: .TestData declared in .TestData.write$Self' type=.TestData origin=null - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RemoteService] + CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlin.Any] annotations: Rpc $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService @@ -339,25 +339,6 @@ FILE fqName: fileName:/customParameterTypes.kt RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final]' type=kotlinx.rpc.RpcClient origin=null receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient - FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final] - EXPRESSION_BODY - CALL 'public abstract fun provideStubContext (serviceId: kotlin.Long): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient' type=kotlin.coroutines.CoroutineContext origin=null - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.coroutines.CoroutineContext - correspondingProperty: PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.coroutines.CoroutineContext declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final]' type=kotlin.coroutines.CoroutineContext origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub.Companion PROPERTY name:fqName visibility:public modality:FINAL [val] @@ -530,16 +511,6 @@ FILE fqName: fileName:/customParameterTypes.kt $this: CALL 'private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' type=kotlin.collections.Map.BoxService>> origin=GET_PROPERTY $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=.BoxService.$rpcServiceStub.Companion origin=null key: GET_VAR 'name: kotlin.String declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=kotlin.String origin=null - FUN name:getFields visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, service:.BoxService) returnType:kotlin.collections.List> - overridden: - public abstract fun getFields (service: T of kotlinx.rpc.descriptor.RpcServiceDescriptor): kotlin.collections.List> declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getFields (service: .BoxService): kotlin.collections.List> declared in .BoxService.$rpcServiceStub.Companion' - TYPE_OP type=kotlin.collections.List> origin=CAST typeOperand=kotlin.collections.List> - CALL 'public final fun emptyList (): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null - : kotlin.Any? CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] CLASS name:test1$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass] annotations: Serializable(with = ) @@ -1112,24 +1083,17 @@ FILE fqName: fileName:/customParameterTypes.kt VALUE_PARAMETER name:testData index:0 type:.TestData BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun test1 (testData: .TestData): kotlin.String declared in .BoxService.$rpcServiceStub' - CALL 'public final fun scopedClientCall (serviceScope: kotlinx.coroutines.CoroutineScope, body: kotlin.coroutines.SuspendFunction0): T of kotlinx.rpc.internal.scopedClientCall declared in kotlinx.rpc.internal' type=kotlin.String origin=null + CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null : kotlin.String - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test1' type=kotlinx.coroutines.CoroutineScope origin=null - body: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String [suspend] - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.test1' - CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null - : kotlin.String - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test1' type=.BoxService.$rpcServiceStub origin=null - call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - callableName: CONST String type=kotlin.String value="test1" - data: CONSTRUCTOR_CALL 'public constructor (testData: .TestData) declared in .BoxService.$rpcServiceStub.test1$rpcMethod' type=.BoxService.$rpcServiceStub.test1$rpcMethod origin=null - testData: GET_VAR 'testData: .TestData declared in .BoxService.$rpcServiceStub.test1' type=.TestData origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test1' type=.BoxService.$rpcServiceStub origin=null + $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test1' type=.BoxService.$rpcServiceStub origin=null + call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null + descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion + callableName: CONST String type=kotlin.String value="test1" + data: CONSTRUCTOR_CALL 'public constructor (testData: .TestData) declared in .BoxService.$rpcServiceStub.test1$rpcMethod' type=.BoxService.$rpcServiceStub.test1$rpcMethod origin=null + testData: GET_VAR 'testData: .TestData declared in .BoxService.$rpcServiceStub.test1' type=.TestData origin=null + serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test1' type=.BoxService.$rpcServiceStub origin=null FUN name:test2 visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub, testData:.TestData) returnType:kotlin.String [suspend] overridden: public abstract fun test2 (testData: .TestData): kotlin.String declared in .BoxService @@ -1137,36 +1101,29 @@ FILE fqName: fileName:/customParameterTypes.kt VALUE_PARAMETER name:testData index:0 type:.TestData BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun test2 (testData: .TestData): kotlin.String declared in .BoxService.$rpcServiceStub' - CALL 'public final fun scopedClientCall (serviceScope: kotlinx.coroutines.CoroutineScope, body: kotlin.coroutines.SuspendFunction0): T of kotlinx.rpc.internal.scopedClientCall declared in kotlinx.rpc.internal' type=kotlin.String origin=null + CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null : kotlin.String - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test2' type=kotlinx.coroutines.CoroutineScope origin=null - body: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String [suspend] - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.test2' - CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null - : kotlin.String - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test2' type=.BoxService.$rpcServiceStub origin=null - call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - callableName: CONST String type=kotlin.String value="test2" - data: CONSTRUCTOR_CALL 'public constructor (testData: .TestData) declared in .BoxService.$rpcServiceStub.test2$rpcMethod' type=.BoxService.$rpcServiceStub.test2$rpcMethod origin=null - testData: GET_VAR 'testData: .TestData declared in .BoxService.$rpcServiceStub.test2' type=.TestData origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test2' type=.BoxService.$rpcServiceStub origin=null + $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test2' type=.BoxService.$rpcServiceStub origin=null + call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null + descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion + callableName: CONST String type=kotlin.String value="test2" + data: CONSTRUCTOR_CALL 'public constructor (testData: .TestData) declared in .BoxService.$rpcServiceStub.test2$rpcMethod' type=.BoxService.$rpcServiceStub.test2$rpcMethod origin=null + testData: GET_VAR 'testData: .TestData declared in .BoxService.$rpcServiceStub.test2' type=.TestData origin=null + serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.test2' type=.BoxService.$rpcServiceStub origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.RemoteService + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.RemoteService + public open fun hashCode (): kotlin.Int declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService + public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN name:test1 visibility:public modality:ABSTRACT <> ($this:.BoxService, testData:.TestData) returnType:kotlin.String [suspend] $this: VALUE_PARAMETER name: type:.BoxService @@ -1174,14 +1131,6 @@ FILE fqName: fileName:/customParameterTypes.kt FUN name:test2 visibility:public modality:ABSTRACT <> ($this:.BoxService, testData:.TestData) returnType:kotlin.String [suspend] $this: VALUE_PARAMETER name: type:.BoxService VALUE_PARAMETER name:testData index:0 type:.TestData - PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RemoteService) returnType:kotlin.coroutines.CoroutineContext [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RemoteService FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' diff --git a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.txt b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.txt index 8f4220e9c..757864040 100644 --- a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.fir.txt @@ -37,7 +37,7 @@ FILE: customParameterTypes.kt } } - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlin/Any| { public abstract suspend fun test1(testData: R|TestData|): R|kotlin/String| public abstract suspend fun test2(testData: R|TestData|): R|kotlin/String| diff --git a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt index e8f0b5472..ea977aaac 100644 --- a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt +++ b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking import kotlinx.serialization.Serializable -import kotlinx.rpc.RemoteService import kotlinx.rpc.withService import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient @@ -14,7 +13,7 @@ import kotlinx.rpc.codegen.test.TestRpcClient data class TestData(val value: String) @Rpc -interface BoxService : RemoteService { +interface BoxService { suspend fun test1(testData: TestData): String suspend fun test2(testData: TestData): String 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 deleted file mode 100644 index 1dab42ad0..000000000 --- a/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt +++ /dev/null @@ -1,591 +0,0 @@ -FILE fqName: fileName:/fields.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RemoteService] - annotations: - Rpc - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService - CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedStubKey] CLASS name:$rpcServiceStub modality:FINAL visibility:public superTypes:[.BoxService] - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub - PROPERTY name:__rpc_stub_id visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:__rpc_stub_id type:kotlin.Long visibility:private [final] - EXPRESSION_BODY - GET_VAR '__rpc_stub_id: kotlin.Long declared in .BoxService.$rpcServiceStub.' type=kotlin.Long origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.Long - correspondingProperty: PROPERTY name:__rpc_stub_id visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_stub_id type:kotlin.Long visibility:private [final]' type=kotlin.Long origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:__rpc_client visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final] - EXPRESSION_BODY - GET_VAR '__rpc_client: kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub.' type=kotlinx.rpc.RpcClient origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlinx.rpc.RpcClient - correspondingProperty: PROPERTY name:__rpc_client visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final]' type=kotlinx.rpc.RpcClient origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient - FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final] - EXPRESSION_BODY - CALL 'public abstract fun provideStubContext (serviceId: kotlin.Long): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient' type=kotlin.coroutines.CoroutineContext origin=null - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.coroutines.CoroutineContext - correspondingProperty: PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.coroutines.CoroutineContext declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final]' type=kotlin.coroutines.CoroutineContext origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:plainFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract plainFlow: kotlinx.coroutines.flow.Flow declared in .BoxService - FIELD PROPERTY_DELEGATE name:plainFlow$delegate type:kotlin.Lazy> visibility:private [final] - EXPRESSION_BODY - CALL 'public final fun lazy (initializer: kotlin.Function0): kotlin.Lazy declared in kotlin' type=kotlin.Lazy> origin=null - : kotlinx.coroutines.flow.Flow - initializer: FUN_EXPR type=kotlin.Function0> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlinx.coroutines.flow.Flow - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub.plainFlow$delegate' - CALL 'public final fun registerPlainFlowField (serviceScope: kotlinx.coroutines.CoroutineScope, descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, fieldName: kotlin.String, serviceId: kotlin.Long): kotlinx.coroutines.flow.Flow declared in kotlinx.rpc' type=kotlinx.coroutines.flow.Flow origin=null - : kotlin.String - $receiver: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=kotlinx.coroutines.CoroutineScope origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - fieldName: CONST String type=kotlin.String value="plainFlow" - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlinx.coroutines.flow.Flow - correspondingProperty: PROPERTY name:plainFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract fun (): kotlinx.coroutines.flow.Flow declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub' - CALL 'public final fun getValue (thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): T of kotlin.getValue declared in kotlin' type=kotlinx.coroutines.flow.Flow origin=null - : kotlinx.coroutines.flow.Flow - $receiver: GET_FIELD 'FIELD PROPERTY_DELEGATE name:plainFlow$delegate type:kotlin.Lazy> visibility:private [final] declared in .BoxService.$rpcServiceStub' type=kotlin.Lazy> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - thisRef: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - property: PROPERTY_REFERENCE 'public final plainFlow: kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub' field=null getter='public final fun (): kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub' setter=null type=kotlin.reflect.KProperty1<.BoxService.$rpcServiceStub, kotlinx.coroutines.flow.Flow> origin=PROPERTY_REFERENCE_FOR_DELEGATE - PROPERTY name:sharedFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract sharedFlow: kotlinx.coroutines.flow.SharedFlow declared in .BoxService - FIELD PROPERTY_DELEGATE name:sharedFlow$delegate type:kotlin.Lazy> visibility:private [final] - EXPRESSION_BODY - CALL 'public final fun lazy (initializer: kotlin.Function0): kotlin.Lazy declared in kotlin' type=kotlin.Lazy> origin=null - : kotlinx.coroutines.flow.SharedFlow - initializer: FUN_EXPR type=kotlin.Function0> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlinx.coroutines.flow.SharedFlow - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService.$rpcServiceStub.sharedFlow$delegate' - CALL 'public final fun registerSharedFlowField (serviceScope: kotlinx.coroutines.CoroutineScope, descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, fieldName: kotlin.String, serviceId: kotlin.Long): kotlinx.coroutines.flow.SharedFlow declared in kotlinx.rpc' type=kotlinx.coroutines.flow.SharedFlow origin=null - : kotlin.String - $receiver: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=kotlinx.coroutines.CoroutineScope origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - fieldName: CONST String type=kotlin.String value="sharedFlow" - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlinx.coroutines.flow.SharedFlow - correspondingProperty: PROPERTY name:sharedFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService.$rpcServiceStub' - CALL 'public final fun getValue (thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): T of kotlin.getValue declared in kotlin' type=kotlinx.coroutines.flow.SharedFlow origin=null - : kotlinx.coroutines.flow.SharedFlow - $receiver: GET_FIELD 'FIELD PROPERTY_DELEGATE name:sharedFlow$delegate type:kotlin.Lazy> visibility:private [final] declared in .BoxService.$rpcServiceStub' type=kotlin.Lazy> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - thisRef: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - property: PROPERTY_REFERENCE 'public final sharedFlow: kotlinx.coroutines.flow.SharedFlow declared in .BoxService.$rpcServiceStub' field=null getter='public final fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService.$rpcServiceStub' setter=null type=kotlin.reflect.KProperty1<.BoxService.$rpcServiceStub, kotlinx.coroutines.flow.SharedFlow> origin=PROPERTY_REFERENCE_FOR_DELEGATE - PROPERTY name:stateFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract stateFlow: kotlinx.coroutines.flow.StateFlow declared in .BoxService - FIELD PROPERTY_DELEGATE name:stateFlow$delegate type:kotlin.Lazy> visibility:private [final] - EXPRESSION_BODY - CALL 'public final fun lazy (initializer: kotlin.Function0): kotlin.Lazy declared in kotlin' type=kotlin.Lazy> origin=null - : kotlinx.coroutines.flow.StateFlow - initializer: FUN_EXPR type=kotlin.Function0> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlinx.coroutines.flow.StateFlow - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService.$rpcServiceStub.stateFlow$delegate' - CALL 'public final fun registerStateFlowField (serviceScope: kotlinx.coroutines.CoroutineScope, descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, fieldName: kotlin.String, serviceId: kotlin.Long): kotlinx.coroutines.flow.StateFlow declared in kotlinx.rpc' type=kotlinx.coroutines.flow.StateFlow origin=null - : kotlin.String - $receiver: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=kotlinx.coroutines.CoroutineScope origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - fieldName: CONST String type=kotlin.String value="stateFlow" - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DELEGATED_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlinx.coroutines.flow.StateFlow - correspondingProperty: PROPERTY name:stateFlow visibility:public modality:FINAL [delegated,val] - overridden: - public abstract fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService.$rpcServiceStub' - CALL 'public final fun getValue (thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): T of kotlin.getValue declared in kotlin' type=kotlinx.coroutines.flow.StateFlow origin=null - : kotlinx.coroutines.flow.StateFlow - $receiver: GET_FIELD 'FIELD PROPERTY_DELEGATE name:stateFlow$delegate type:kotlin.Lazy> visibility:private [final] declared in .BoxService.$rpcServiceStub' type=kotlin.Lazy> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - thisRef: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - property: PROPERTY_REFERENCE 'public final stateFlow: kotlinx.coroutines.flow.StateFlow declared in .BoxService.$rpcServiceStub' field=null getter='public final fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService.$rpcServiceStub' setter=null type=kotlin.reflect.KProperty1<.BoxService.$rpcServiceStub, kotlinx.coroutines.flow.StateFlow> origin=PROPERTY_REFERENCE_FOR_DELEGATE - CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>] - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub.Companion - PROPERTY name:fqName visibility:public modality:FINAL [val] - overridden: - public abstract fqName: kotlin.String declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - FIELD PROPERTY_BACKING_FIELD name:fqName type:kotlin.String visibility:private [final] - EXPRESSION_BODY - CONST String type=kotlin.String value="BoxService" - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlin.String - correspondingProperty: PROPERTY name:fqName visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.String declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.Companion' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:fqName type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.' type=.BoxService.$rpcServiceStub.Companion origin=null - PROPERTY name:plainFlowInvokator visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:plainFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final] - EXPRESSION_BODY - TYPE_OP type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=SAM_CONVERSION typeOperand=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - FUN_EXPR type=kotlin.Function1<.BoxService, kotlin.Any?> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (service:.BoxService) returnType:kotlin.Any? - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (service: .BoxService): kotlin.Any? declared in .BoxService.$rpcServiceStub.Companion.plainFlowInvokator' - CALL 'public abstract fun (): kotlinx.coroutines.flow.Flow declared in .BoxService' type=kotlinx.coroutines.flow.Flow origin=null - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.plainFlowInvokator.' type=.BoxService origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - correspondingProperty: PROPERTY name:plainFlowInvokator visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:plainFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final]' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.' type=.BoxService.$rpcServiceStub.Companion origin=null - PROPERTY name:sharedFlowInvokator visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:sharedFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final] - EXPRESSION_BODY - TYPE_OP type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=SAM_CONVERSION typeOperand=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - FUN_EXPR type=kotlin.Function1<.BoxService, kotlin.Any?> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (service:.BoxService) returnType:kotlin.Any? - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (service: .BoxService): kotlin.Any? declared in .BoxService.$rpcServiceStub.Companion.sharedFlowInvokator' - CALL 'public abstract fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService' type=kotlinx.coroutines.flow.SharedFlow origin=null - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.sharedFlowInvokator.' type=.BoxService origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - correspondingProperty: PROPERTY name:sharedFlowInvokator visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:sharedFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final]' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.' type=.BoxService.$rpcServiceStub.Companion origin=null - PROPERTY name:stateFlowInvokator visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:stateFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final] - EXPRESSION_BODY - TYPE_OP type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=SAM_CONVERSION typeOperand=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - FUN_EXPR type=kotlin.Function1<.BoxService, kotlin.Any?> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (service:.BoxService) returnType:kotlin.Any? - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (service: .BoxService): kotlin.Any? declared in .BoxService.$rpcServiceStub.Companion.stateFlowInvokator' - CALL 'public abstract fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService' type=kotlinx.coroutines.flow.StateFlow origin=null - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.stateFlowInvokator.' type=.BoxService origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.BoxService.$rpcServiceStub.Companion) returnType:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> - correspondingProperty: PROPERTY name:stateFlowInvokator visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:stateFlowInvokator type:kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> visibility:private [final]' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.' type=.BoxService.$rpcServiceStub.Companion origin=null - PROPERTY name:callableMap visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:callableMap type:kotlin.collections.Map.BoxService>> visibility:private [final] - EXPRESSION_BODY - CALL 'public final fun mapOf (vararg pairs: kotlin.Pair): kotlin.collections.Map declared in kotlin.collections' type=kotlin.collections.Map.BoxService>> origin=null - : kotlin.String - : kotlinx.rpc.descriptor.RpcCallable<.BoxService> - pairs: VARARG type=kotlin.Array.BoxService>>> varargElementType=kotlin.Pair.BoxService>> - 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="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, 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 - kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null - : kotlinx.rpc.internal.FieldDataObject - returnType: 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 - invokator: CALL 'private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=GET_PROPERTY - $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, 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 - kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null - : kotlinx.rpc.internal.FieldDataObject - returnType: 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.SharedFlow - invokator: CALL 'private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=GET_PROPERTY - $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, 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 - kType: CALL 'public final fun typeOf (): kotlin.reflect.KType declared in kotlin.reflect' type=kotlin.reflect.KType origin=null - : kotlinx.rpc.internal.FieldDataObject - returnType: 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.StateFlow - invokator: CALL 'private final fun (): kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> declared in .BoxService.$rpcServiceStub.Companion' type=kotlinx.rpc.descriptor.RpcInvokator.Field<.BoxService> origin=GET_PROPERTY - $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 - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:callableMap type:kotlin.collections.Map.BoxService>> visibility:private [final]' type=kotlin.collections.Map.BoxService>> origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.' type=.BoxService.$rpcServiceStub.Companion origin=null - CONSTRUCTOR visibility:private <> () returnType:.BoxService.$rpcServiceStub.Companion [primary] - BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=kotlin.Unit - FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:kotlin.Any - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] - overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:kotlin.Any - FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] - overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:kotlin.Any - FUN name:createInstance visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, serviceId:kotlin.Long, client:kotlinx.rpc.RpcClient) returnType:.BoxService - overridden: - public abstract fun createInstance (serviceId: kotlin.Long, client: kotlinx.rpc.RpcClient): T of kotlinx.rpc.descriptor.RpcServiceDescriptor declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:serviceId index:0 type:kotlin.Long - VALUE_PARAMETER name:client index:1 type:kotlinx.rpc.RpcClient - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun createInstance (serviceId: kotlin.Long, client: kotlinx.rpc.RpcClient): .BoxService declared in .BoxService.$rpcServiceStub.Companion' - CONSTRUCTOR_CALL 'public constructor (__rpc_stub_id: kotlin.Long, __rpc_client: kotlinx.rpc.RpcClient) declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - __rpc_stub_id: GET_VAR 'serviceId: kotlin.Long declared in .BoxService.$rpcServiceStub.Companion.createInstance' type=kotlin.Long origin=null - __rpc_client: GET_VAR 'client: kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub.Companion.createInstance' type=kotlinx.rpc.RpcClient origin=null - FUN name:getCallable visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, name:kotlin.String) returnType:kotlinx.rpc.descriptor.RpcCallable? - overridden: - public abstract fun getCallable (name: kotlin.String): kotlinx.rpc.descriptor.RpcCallable? declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:name index:0 type:kotlin.String - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getCallable (name: kotlin.String): kotlinx.rpc.descriptor.RpcCallable? declared in .BoxService.$rpcServiceStub.Companion' - CALL 'public abstract fun get (key: K of kotlin.collections.Map): V of kotlin.collections.Map? declared in kotlin.collections.Map' type=kotlinx.rpc.descriptor.RpcCallable? origin=GET_ARRAY_ELEMENT - $this: CALL 'private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' type=kotlin.collections.Map.BoxService>> origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=.BoxService.$rpcServiceStub.Companion origin=null - key: GET_VAR 'name: kotlin.String declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=kotlin.String origin=null - FUN name:getFields visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, service:.BoxService) returnType:kotlin.collections.List> - overridden: - public abstract fun getFields (service: T of kotlinx.rpc.descriptor.RpcServiceDescriptor): kotlin.collections.List> declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getFields (service: .BoxService): kotlin.collections.List> declared in .BoxService.$rpcServiceStub.Companion' - TYPE_OP type=kotlin.collections.List> origin=CAST typeOperand=kotlin.collections.List> - CALL 'public final fun listOf (vararg elements: T of kotlin.collections.listOf): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null - : kotlin.Any? - elements: VARARG type=kotlin.Array varargElementType=kotlin.Any? - CALL 'public abstract fun (): kotlinx.coroutines.flow.Flow declared in .BoxService' type=kotlinx.coroutines.flow.Flow origin=GET_PROPERTY - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.getFields' type=.BoxService origin=null - CALL 'public abstract fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService' type=kotlinx.coroutines.flow.SharedFlow origin=GET_PROPERTY - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.getFields' type=.BoxService origin=null - CALL 'public abstract fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService' type=kotlinx.coroutines.flow.StateFlow origin=GET_PROPERTY - $this: GET_VAR 'service: .BoxService declared in .BoxService.$rpcServiceStub.Companion.getFields' type=.BoxService origin=null - CONSTRUCTOR visibility:public <> (__rpc_stub_id:kotlin.Long, __rpc_client:kotlinx.rpc.RpcClient) returnType:.BoxService.$rpcServiceStub [primary] - VALUE_PARAMETER name:__rpc_stub_id index:0 type:kotlin.Long - VALUE_PARAMETER name:__rpc_client index:1 type:kotlinx.rpc.RpcClient - BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedStubKey] CLASS name:$rpcServiceStub modality:FINAL visibility:public superTypes:[.BoxService]' type=kotlin.Unit - FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in .BoxService - $this: VALUE_PARAMETER name: type:kotlin.Any - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] - overridden: - public open fun hashCode (): kotlin.Int declared in .BoxService - $this: VALUE_PARAMETER name: type:kotlin.Any - FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] - overridden: - public open fun toString (): kotlin.String declared in .BoxService - $this: VALUE_PARAMETER name: type:kotlin.Any - FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlin.Any - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] - overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlin.Any - FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] - overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlin.Any - PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RemoteService) returnType:kotlin.coroutines.CoroutineContext [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RemoteService - PROPERTY name:plainFlow visibility:public modality:ABSTRACT [val] - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.BoxService) returnType:kotlinx.coroutines.flow.Flow - correspondingProperty: PROPERTY name:plainFlow visibility:public modality:ABSTRACT [val] - $this: VALUE_PARAMETER name: type:.BoxService - PROPERTY name:sharedFlow visibility:public modality:ABSTRACT [val] - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.BoxService) returnType:kotlinx.coroutines.flow.SharedFlow - correspondingProperty: PROPERTY name:sharedFlow visibility:public modality:ABSTRACT [val] - $this: VALUE_PARAMETER name: type:.BoxService - PROPERTY name:stateFlow visibility:public modality:ABSTRACT [val] - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.BoxService) returnType:kotlinx.coroutines.flow.StateFlow - correspondingProperty: PROPERTY name:stateFlow visibility:public modality:ABSTRACT [val] - $this: VALUE_PARAMETER name: type:.BoxService - FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' - CALL 'public final fun runBlocking (context: kotlin.coroutines.CoroutineContext, block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): T of kotlinx.coroutines.runBlocking declared in kotlinx.coroutines' type=kotlin.String origin=null - : kotlin.String - block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlinx.coroutines.CoroutineScope) returnType:kotlin.String [suspend] - $receiver: VALUE_PARAMETER name:$this$runBlocking type:kotlinx.coroutines.CoroutineScope - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .box' - BLOCK type=kotlin.String origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val] - CALL 'public final fun withTimeoutOrNull (timeMillis: kotlin.Long, block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): T of kotlinx.coroutines.withTimeoutOrNull? declared in kotlinx.coroutines' type=kotlin.String? origin=null - : kotlin.String - timeMillis: CONST Long type=kotlin.Long value=1000 - block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlinx.coroutines.CoroutineScope) returnType:kotlin.String [suspend] - $receiver: VALUE_PARAMETER name:$this$withTimeoutOrNull type:kotlinx.coroutines.CoroutineScope - BLOCK_BODY - VAR name:plainFlow type:kotlin.collections.List [val] - CALL 'public final fun toList (destination: kotlin.collections.MutableList): kotlin.collections.List declared in kotlinx.coroutines.flow' type=kotlin.collections.List origin=null - : kotlin.String - $receiver: CALL 'public abstract fun (): kotlinx.coroutines.flow.Flow declared in .BoxService' type=kotlinx.coroutines.flow.Flow origin=GET_PROPERTY - $this: CALL 'public final fun withService (): T of kotlinx.rpc.withService declared in kotlinx.rpc' type=.BoxService origin=null - : .BoxService - $receiver: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:TestRpcClient modality:FINAL visibility:public superTypes:[kotlinx.rpc.RpcClient]' type=kotlinx.rpc.codegen.test.TestRpcClient - VAR name:sharedFlow type:kotlin.collections.List [val] - CALL 'public final fun toList (destination: kotlin.collections.MutableList): kotlin.collections.List declared in kotlinx.coroutines.flow' type=kotlin.collections.List origin=null - : kotlin.String - $receiver: CALL 'public final fun take (count: kotlin.Int): kotlinx.coroutines.flow.Flow declared in kotlinx.coroutines.flow' type=kotlinx.coroutines.flow.Flow origin=null - : kotlin.String - $receiver: CALL 'public abstract fun (): kotlinx.coroutines.flow.SharedFlow declared in .BoxService' type=kotlinx.coroutines.flow.SharedFlow origin=GET_PROPERTY - $this: CALL 'public final fun withService (): T of kotlinx.rpc.withService declared in kotlinx.rpc' type=.BoxService origin=null - : .BoxService - $receiver: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:TestRpcClient modality:FINAL visibility:public superTypes:[kotlinx.rpc.RpcClient]' type=kotlinx.rpc.codegen.test.TestRpcClient - count: CONST Int type=kotlin.Int value=1 - VAR name:stateFlow type:kotlin.String [val] - CALL 'public abstract fun (): T of kotlinx.coroutines.flow.StateFlow declared in kotlinx.coroutines.flow.StateFlow' type=kotlin.String origin=GET_PROPERTY - $this: CALL 'public abstract fun (): kotlinx.coroutines.flow.StateFlow declared in .BoxService' type=kotlinx.coroutines.flow.StateFlow origin=GET_PROPERTY - $this: CALL 'public final fun withService (): T of kotlinx.rpc.withService declared in kotlinx.rpc' type=.BoxService origin=null - : .BoxService - $receiver: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:TestRpcClient modality:FINAL visibility:public superTypes:[kotlinx.rpc.RpcClient]' type=kotlinx.rpc.codegen.test.TestRpcClient - VAR name:failures type:kotlin.collections.MutableList [val] - CALL 'public final fun mutableListOf (): kotlin.collections.MutableList declared in kotlin.collections' type=kotlin.collections.MutableList origin=null - : kotlin.String - WHEN type=kotlin.Unit origin=IF - BRANCH - if: WHEN type=kotlin.Boolean origin=OROR - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.List' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'val plainFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - arg1: CONST Int type=kotlin.Int value=1 - then: CONST Boolean type=kotlin.Boolean value=true - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: CALL 'public abstract fun get (index: kotlin.Int): E of kotlin.collections.List declared in kotlin.collections.List' type=kotlin.String origin=GET_ARRAY_ELEMENT - $this: GET_VAR 'val plainFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - index: CONST Int type=kotlin.Int value=0 - arg1: CONST String type=kotlin.String value="registerPlainFlowField_42" - then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit - BLOCK type=kotlin.Boolean origin=null - CALL 'public abstract fun add (element: E of kotlin.collections.MutableList): kotlin.Boolean declared in kotlin.collections.MutableList' type=kotlin.Boolean origin=null - $this: GET_VAR 'val failures: kotlin.collections.MutableList declared in .box..' type=kotlin.collections.MutableList origin=null - element: STRING_CONCATENATION type=kotlin.String - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="plainFlow.size = " - CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.List' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'val plainFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - CONST String type=kotlin.String value=" (expected 1), " - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="plainFlow[0] = \"" - CALL 'public final fun getOrNull (index: kotlin.Int): T of kotlin.collections.getOrNull? declared in kotlin.collections' type=kotlin.String? origin=null - : kotlin.String - $receiver: GET_VAR 'val plainFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - index: CONST Int type=kotlin.Int value=0 - CONST String type=kotlin.String value="\" (expected \"registerPlainFlowField_42\")" - WHEN type=kotlin.Unit origin=IF - BRANCH - if: WHEN type=kotlin.Boolean origin=OROR - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.List' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'val sharedFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - arg1: CONST Int type=kotlin.Int value=1 - then: CONST Boolean type=kotlin.Boolean value=true - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: CALL 'public abstract fun get (index: kotlin.Int): E of kotlin.collections.List declared in kotlin.collections.List' type=kotlin.String origin=GET_ARRAY_ELEMENT - $this: GET_VAR 'val sharedFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - index: CONST Int type=kotlin.Int value=0 - arg1: CONST String type=kotlin.String value="registerSharedFlowField_42" - then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit - BLOCK type=kotlin.Boolean origin=null - CALL 'public abstract fun add (element: E of kotlin.collections.MutableList): kotlin.Boolean declared in kotlin.collections.MutableList' type=kotlin.Boolean origin=null - $this: GET_VAR 'val failures: kotlin.collections.MutableList declared in .box..' type=kotlin.collections.MutableList origin=null - element: STRING_CONCATENATION type=kotlin.String - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="sharedFlow.size = " - CALL 'public abstract fun (): kotlin.Int declared in kotlin.collections.List' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'val sharedFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - CONST String type=kotlin.String value=" (expected 1), " - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="sharedFlow[0] = \"" - CALL 'public final fun getOrNull (index: kotlin.Int): T of kotlin.collections.getOrNull? declared in kotlin.collections' type=kotlin.String? origin=null - : kotlin.String - $receiver: GET_VAR 'val sharedFlow: kotlin.collections.List declared in .box..' type=kotlin.collections.List origin=null - index: CONST Int type=kotlin.Int value=0 - CONST String type=kotlin.String value="\" (expected \"registerSharedFlowField_42\")" - WHEN type=kotlin.Unit origin=IF - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_VAR 'val stateFlow: kotlin.String declared in .box..' type=kotlin.String origin=null - arg1: CONST String type=kotlin.String value="registerStateFlowField_42" - then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit - BLOCK type=kotlin.Boolean origin=null - CALL 'public abstract fun add (element: E of kotlin.collections.MutableList): kotlin.Boolean declared in kotlin.collections.MutableList' type=kotlin.Boolean origin=null - $this: GET_VAR 'val failures: kotlin.collections.MutableList declared in .box..' type=kotlin.collections.MutableList origin=null - element: STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="stateFlow = \"" - GET_VAR 'val stateFlow: kotlin.String declared in .box..' type=kotlin.String origin=null - CONST String type=kotlin.String value="\" (expected \"registerStateFlowField_42\")" - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .box.' - BLOCK type=kotlin.String origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String? [val] - BLOCK type=kotlin.String? origin=SAFE_CALL - VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val] - BLOCK type=kotlin.String? origin=SAFE_CALL - VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.collections.MutableList? [val] - CALL 'public final fun takeIf (predicate: kotlin.Function1): T of kotlin.takeIf? declared in kotlin' type=kotlin.collections.MutableList? origin=null - : kotlin.collections.MutableList - $receiver: GET_VAR 'val failures: kotlin.collections.MutableList declared in .box..' type=kotlin.collections.MutableList origin=null - predicate: FUN_EXPR type=kotlin.Function1, kotlin.Boolean> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.collections.MutableList) returnType:kotlin.Boolean - VALUE_PARAMETER name:it index:0 type:kotlin.collections.MutableList - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.collections.MutableList): kotlin.Boolean declared in .box..' - CALL 'public final fun isNotEmpty (): kotlin.Boolean declared in kotlin.collections' type=kotlin.Boolean origin=null - : kotlin.String - $receiver: GET_VAR 'it: kotlin.collections.MutableList declared in .box...' type=kotlin.collections.MutableList origin=null - WHEN type=kotlin.String? origin=null - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_3: kotlin.collections.MutableList? declared in .box..' type=kotlin.collections.MutableList? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: CONST Null type=kotlin.Nothing? value=null - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: CALL 'public final fun joinToString (separator: kotlin.CharSequence, prefix: kotlin.CharSequence, postfix: kotlin.CharSequence, limit: kotlin.Int, truncated: kotlin.CharSequence, transform: kotlin.Function1?): kotlin.String declared in kotlin.collections' type=kotlin.String origin=null - : kotlin.String - $receiver: GET_VAR 'val tmp_3: kotlin.collections.MutableList? declared in .box..' type=kotlin.collections.MutableList? origin=null - separator: CONST String type=kotlin.String value=";" - WHEN type=kotlin.String? origin=null - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_2: kotlin.String? declared in .box..' type=kotlin.String? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: CONST Null type=kotlin.Nothing? value=null - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.String origin=null - : kotlin.String - : kotlin.String - $receiver: GET_VAR 'val tmp_2: kotlin.String? declared in .box..' type=kotlin.String? origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.String - VALUE_PARAMETER name:it index:0 type:kotlin.String - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.String): kotlin.String declared in .box..' - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="Fail: " - GET_VAR 'it: kotlin.String declared in .box...' type=kotlin.String origin=null - WHEN type=kotlin.String origin=null - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_1: kotlin.String? declared in .box..' type=kotlin.String? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: CONST String type=kotlin.String value="OK" - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_1: kotlin.String? declared in .box..' type=kotlin.String? origin=null - WHEN type=kotlin.String origin=null - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_0: kotlin.String? declared in .box.' type=kotlin.String? origin=null - arg1: CONST Null type=kotlin.Nothing? value=null - then: CONST String type=kotlin.String value="Fail: test timed out" - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_0: kotlin.String? declared in .box.' type=kotlin.String? origin=null diff --git a/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt b/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt deleted file mode 100644 index 26699a18d..000000000 --- a/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt +++ /dev/null @@ -1,55 +0,0 @@ -FILE: fields.kt - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { - public abstract val plainFlow: R|kotlinx/coroutines/flow/Flow| - public get(): R|kotlinx/coroutines/flow/Flow| - - public abstract val sharedFlow: R|kotlinx/coroutines/flow/SharedFlow| - public get(): R|kotlinx/coroutines/flow/SharedFlow| - - public abstract val stateFlow: R|kotlinx/coroutines/flow/StateFlow| - public get(): R|kotlinx/coroutines/flow/StateFlow| - - public final class $rpcServiceStub : R|kotlin/Any| { - public final companion object Companion : R|kotlin/Any| { - } - - } - - } - public final fun box(): R|kotlin/String| { - ^box R|kotlinx/coroutines/runBlocking|( = runBlocking@fun R|kotlinx/coroutines/CoroutineScope|.(): R|kotlin/String| { - ^ R|kotlinx/coroutines/withTimeoutOrNull|(Long(1000), = withTimeoutOrNull@fun R|kotlinx/coroutines/CoroutineScope|.(): R|kotlin/String| { - lval plainFlow: R|kotlin/collections/List| = Q|kotlinx/rpc/codegen/test/TestRpcClient|.R|kotlinx/rpc/withService|().R|/BoxService.plainFlow|.R|kotlinx/coroutines/flow/toList|() - lval sharedFlow: R|kotlin/collections/List| = Q|kotlinx/rpc/codegen/test/TestRpcClient|.R|kotlinx/rpc/withService|().R|/BoxService.sharedFlow|.R|kotlinx/coroutines/flow/take|(Int(1)).R|kotlinx/coroutines/flow/toList|() - lval stateFlow: R|kotlin/String| = Q|kotlinx/rpc/codegen/test/TestRpcClient|.R|kotlinx/rpc/withService|().R|/BoxService.stateFlow|.R|SubstitutionOverride| - lval failures: R|kotlin/collections/MutableList| = R|kotlin/collections/mutableListOf|() - when () { - !=(R|/plainFlow|.R|SubstitutionOverride|, Int(1)) || !=(R|/plainFlow|.R|SubstitutionOverride|(Int(0)), String(registerPlainFlowField_42)) -> { - R|/failures|.R|SubstitutionOverride|(((String(plainFlow.size = ), R|/plainFlow|.R|SubstitutionOverride|, String( (expected 1), )), (String(plainFlow[0] = ), String("), R|/plainFlow|.R|kotlin/collections/getOrNull|(Int(0)), String("), String( (expected ), String("), String(registerPlainFlowField_42), String("), String())))) - } - } - - when () { - !=(R|/sharedFlow|.R|SubstitutionOverride|, Int(1)) || !=(R|/sharedFlow|.R|SubstitutionOverride|(Int(0)), String(registerSharedFlowField_42)) -> { - R|/failures|.R|SubstitutionOverride|(((String(sharedFlow.size = ), R|/sharedFlow|.R|SubstitutionOverride|, String( (expected 1), )), (String(sharedFlow[0] = ), String("), R|/sharedFlow|.R|kotlin/collections/getOrNull|(Int(0)), String("), String( (expected ), String("), String(registerSharedFlowField_42), String("), String())))) - } - } - - when () { - !=(R|/stateFlow|, String(registerStateFlowField_42)) -> { - R|/failures|.R|SubstitutionOverride|((String(stateFlow = ), String("), R|/stateFlow|, String("), String( (expected ), String("), String(registerStateFlowField_42), String("), String()))) - } - } - - ^ R|/failures|.R|kotlin/takeIf||>( = takeIf@fun (it: R|kotlin/collections/MutableList|): R|kotlin/Boolean| { - ^ R|/it|.R|kotlin/collections/isNotEmpty|() - } - )?.{ $subj$.R|kotlin/collections/joinToString|(String(;)) }?.{ $subj$.R|kotlin/let|( = let@fun (it: R|kotlin/String|): R|kotlin/String| { - ^ (String(Fail: ), R|/it|) - } - ) } ?: String(OK) - } - ) ?: String(Fail: test timed out) - } - ) - } diff --git a/tests/compiler-plugin-tests/src/testData/box/fields.kt b/tests/compiler-plugin-tests/src/testData/box/fields.kt deleted file mode 100644 index 59fd99ec0..000000000 --- a/tests/compiler-plugin-tests/src/testData/box/fields.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import kotlinx.rpc.RemoteService -import kotlinx.rpc.withService -import kotlinx.rpc.annotations.Rpc -import kotlinx.rpc.codegen.test.TestRpcClient - -@Rpc -interface BoxService : RemoteService { - val plainFlow: Flow - - val sharedFlow: SharedFlow - - val stateFlow: StateFlow -} - -fun box(): String = runBlocking { - withTimeoutOrNull(1000) { - val plainFlow = TestRpcClient.withService().plainFlow.toList() - val sharedFlow = TestRpcClient.withService().sharedFlow.take(1).toList() - val stateFlow = TestRpcClient.withService().stateFlow.value - - val failures = mutableListOf() - - if (plainFlow.size != 1 || plainFlow[0] != "registerPlainFlowField_42") { - failures.add( - "plainFlow.size = ${plainFlow.size} (expected 1), " + - "plainFlow[0] = \"${plainFlow.getOrNull(0)}\" (expected \"registerPlainFlowField_42\")" - ) - } - - if (sharedFlow.size != 1 || sharedFlow[0] != "registerSharedFlowField_42") { - failures.add( - "sharedFlow.size = ${sharedFlow.size} (expected 1), " + - "sharedFlow[0] = \"${sharedFlow.getOrNull(0)}\" (expected \"registerSharedFlowField_42\")" - ) - } - - if (stateFlow != "registerStateFlowField_42") { - failures.add("stateFlow = \"$stateFlow\" (expected \"registerStateFlowField_42\")") - } - - failures.takeIf { it.isNotEmpty() } - ?.joinToString(";") - ?.let { "Fail: $it" } - ?: "OK" - } ?: "Fail: test timed out" -} 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 21fc1a54a..7caead7bc 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 @@ -1,5 +1,5 @@ FILE fqName: fileName:/flowParameter.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RemoteService] + CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlin.Any] annotations: Rpc $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService @@ -27,25 +27,6 @@ FILE fqName: fileName:/flowParameter.kt RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final]' type=kotlinx.rpc.RpcClient origin=null receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient - FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final] - EXPRESSION_BODY - CALL 'public abstract fun provideStubContext (serviceId: kotlin.Long): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient' type=kotlin.coroutines.CoroutineContext origin=null - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.coroutines.CoroutineContext - correspondingProperty: PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.coroutines.CoroutineContext declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final]' type=kotlin.coroutines.CoroutineContext origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub.Companion PROPERTY name:fqName visibility:public modality:FINAL [val] @@ -167,16 +148,6 @@ FILE fqName: fileName:/flowParameter.kt $this: CALL 'private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' type=kotlin.collections.Map.BoxService>> origin=GET_PROPERTY $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=.BoxService.$rpcServiceStub.Companion origin=null key: GET_VAR 'name: kotlin.String declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=kotlin.String origin=null - FUN name:getFields visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, service:.BoxService) returnType:kotlin.collections.List> - overridden: - public abstract fun getFields (service: T of kotlinx.rpc.descriptor.RpcServiceDescriptor): kotlin.collections.List> declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getFields (service: .BoxService): kotlin.collections.List> declared in .BoxService.$rpcServiceStub.Companion' - TYPE_OP type=kotlin.collections.List> origin=CAST typeOperand=kotlin.collections.List> - CALL 'public final fun emptyList (): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null - : kotlin.Any? CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] CLASS name:stream$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass] annotations: Serializable(with = ) @@ -525,48 +496,33 @@ FILE fqName: fileName:/flowParameter.kt VALUE_PARAMETER name:flow index:0 type:kotlinx.coroutines.flow.Flow BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun stream (flow: kotlinx.coroutines.flow.Flow): kotlin.String declared in .BoxService.$rpcServiceStub' - CALL 'public final fun scopedClientCall (serviceScope: kotlinx.coroutines.CoroutineScope, body: kotlin.coroutines.SuspendFunction0): T of kotlinx.rpc.internal.scopedClientCall declared in kotlinx.rpc.internal' type=kotlin.String origin=null + CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null : kotlin.String - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.stream' type=kotlinx.coroutines.CoroutineScope origin=null - body: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String [suspend] - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.stream' - CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null - : kotlin.String - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.stream' type=.BoxService.$rpcServiceStub origin=null - call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - callableName: CONST String type=kotlin.String value="stream" - data: CONSTRUCTOR_CALL 'public constructor (flow: kotlinx.coroutines.flow.Flow) declared in .BoxService.$rpcServiceStub.stream$rpcMethod' type=.BoxService.$rpcServiceStub.stream$rpcMethod origin=null - flow: GET_VAR 'flow: kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub.stream' type=kotlinx.coroutines.flow.Flow origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.stream' type=.BoxService.$rpcServiceStub origin=null + $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.stream' type=.BoxService.$rpcServiceStub origin=null + call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null + descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion + callableName: CONST String type=kotlin.String value="stream" + data: CONSTRUCTOR_CALL 'public constructor (flow: kotlinx.coroutines.flow.Flow) declared in .BoxService.$rpcServiceStub.stream$rpcMethod' type=.BoxService.$rpcServiceStub.stream$rpcMethod origin=null + flow: GET_VAR 'flow: kotlinx.coroutines.flow.Flow declared in .BoxService.$rpcServiceStub.stream' type=kotlinx.coroutines.flow.Flow origin=null + serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.stream' type=.BoxService.$rpcServiceStub origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.RemoteService + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.RemoteService + public open fun hashCode (): kotlin.Int declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService + public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN name:stream visibility:public modality:ABSTRACT <> ($this:.BoxService, flow:kotlinx.coroutines.flow.Flow) returnType:kotlin.String [suspend] $this: VALUE_PARAMETER name: type:.BoxService VALUE_PARAMETER name:flow index:0 type:kotlinx.coroutines.flow.Flow - PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RemoteService) returnType:kotlin.coroutines.CoroutineContext [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RemoteService FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' diff --git a/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.txt b/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.txt index bbcf6fbd8..faa22955a 100644 --- a/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/flowParameter.fir.txt @@ -1,5 +1,5 @@ FILE: flowParameter.kt - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlin/Any| { public abstract suspend fun stream(flow: R|kotlinx/coroutines/flow/Flow|): R|kotlin/String| public final class $rpcServiceStub : R|kotlin/Any| { diff --git a/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt b/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt index bf1be1abf..054984b29 100644 --- a/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt +++ b/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt @@ -4,13 +4,12 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RemoteService import kotlinx.rpc.withService import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient @Rpc -interface BoxService : RemoteService { +interface BoxService { // plugin should add @Contextual annotation to the flow parameter in the generated class suspend fun stream(flow: Flow): String } 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 b5f47934b..2dc4375cf 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 @@ -1,6 +1,6 @@ Module: lib FILE fqName: fileName:/module_lib_multiModule.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RemoteService] + CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlin.Any] annotations: Rpc $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService @@ -28,25 +28,6 @@ FILE fqName: fileName:/module_lib_multiModule.kt RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final]' type=kotlinx.rpc.RpcClient origin=null receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient - FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final] - EXPRESSION_BODY - CALL 'public abstract fun provideStubContext (serviceId: kotlin.Long): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient' type=kotlin.coroutines.CoroutineContext origin=null - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.coroutines.CoroutineContext - correspondingProperty: PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.coroutines.CoroutineContext declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final]' type=kotlin.coroutines.CoroutineContext origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub.Companion PROPERTY name:fqName visibility:public modality:FINAL [val] @@ -160,16 +141,6 @@ FILE fqName: fileName:/module_lib_multiModule.kt $this: CALL 'private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' type=kotlin.collections.Map.BoxService>> origin=GET_PROPERTY $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=.BoxService.$rpcServiceStub.Companion origin=null key: GET_VAR 'name: kotlin.String declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=kotlin.String origin=null - FUN name:getFields visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, service:.BoxService) returnType:kotlin.collections.List> - overridden: - public abstract fun getFields (service: T of kotlinx.rpc.descriptor.RpcServiceDescriptor): kotlin.collections.List> declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getFields (service: .BoxService): kotlin.collections.List> declared in .BoxService.$rpcServiceStub.Companion' - TYPE_OP type=kotlin.collections.List> origin=CAST typeOperand=kotlin.collections.List> - CALL 'public final fun emptyList (): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null - : kotlin.Any? CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass] annotations: Serializable(with = ) @@ -258,46 +229,31 @@ FILE fqName: fileName:/module_lib_multiModule.kt $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun simple (): kotlin.String declared in .BoxService.$rpcServiceStub' - CALL 'public final fun scopedClientCall (serviceScope: kotlinx.coroutines.CoroutineScope, body: kotlin.coroutines.SuspendFunction0): T of kotlinx.rpc.internal.scopedClientCall declared in kotlinx.rpc.internal' type=kotlin.String origin=null + CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null : kotlin.String - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=kotlinx.coroutines.CoroutineScope origin=null - body: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String [suspend] - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.simple' - CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null - : kotlin.String - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null - call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - callableName: CONST String type=kotlin.String value="simple" - data: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass]' type=.BoxService.$rpcServiceStub.simple$rpcMethod - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null + $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null + call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null + descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion + callableName: CONST String type=kotlin.String value="simple" + data: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass]' type=.BoxService.$rpcServiceStub.simple$rpcMethod + serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.RemoteService + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.RemoteService + public open fun hashCode (): kotlin.Int declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService + public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN name:simple visibility:public modality:ABSTRACT <> ($this:.BoxService) returnType:kotlin.String [suspend] $this: VALUE_PARAMETER name: type:.BoxService - PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RemoteService) returnType:kotlin.coroutines.CoroutineContext [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RemoteService Module: main FILE fqName: fileName:/module_main_multiModule.kt FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String diff --git a/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.txt b/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.txt index 92835fc84..41556d0b0 100644 --- a/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/multiModule.fir.txt @@ -1,6 +1,6 @@ Module: lib FILE: module_lib_multiModule.kt - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlin/Any| { public abstract suspend fun simple(): R|kotlin/String| public final class $rpcServiceStub : R|kotlin/Any| { diff --git a/tests/compiler-plugin-tests/src/testData/box/multiModule.kt b/tests/compiler-plugin-tests/src/testData/box/multiModule.kt index a575bb86d..7d668b0a0 100644 --- a/tests/compiler-plugin-tests/src/testData/box/multiModule.kt +++ b/tests/compiler-plugin-tests/src/testData/box/multiModule.kt @@ -4,18 +4,16 @@ // MODULE: lib -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc @Rpc -interface BoxService : RemoteService { +interface BoxService { suspend fun simple(): String } // MODULE: main(lib) import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RemoteService import kotlinx.rpc.withService import kotlinx.rpc.codegen.test.TestRpcClient 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 f45cf01a6..15de1bff3 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 @@ -1,5 +1,5 @@ FILE fqName: fileName:/simple.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RemoteService] + CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlin.Any] annotations: Rpc $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService @@ -27,25 +27,6 @@ FILE fqName: fileName:/simple.kt RETURN type=kotlin.Nothing from='private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:__rpc_client type:kotlinx.rpc.RpcClient visibility:private [final]' type=kotlinx.rpc.RpcClient origin=null receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null - PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient - FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final] - EXPRESSION_BODY - CALL 'public abstract fun provideStubContext (serviceId: kotlin.Long): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RpcClient' type=kotlin.coroutines.CoroutineContext origin=null - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub' type=.BoxService.$rpcServiceStub origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.BoxService.$rpcServiceStub) returnType:kotlin.coroutines.CoroutineContext - correspondingProperty: PROPERTY name:coroutineContext visibility:public modality:FINAL [val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in .BoxService - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.coroutines.CoroutineContext declared in .BoxService.$rpcServiceStub' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:coroutineContext type:kotlin.coroutines.CoroutineContext visibility:private [final]' type=kotlin.coroutines.CoroutineContext origin=null - receiver: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.' type=.BoxService.$rpcServiceStub origin=null CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.BoxService.$rpcServiceStub.Companion PROPERTY name:fqName visibility:public modality:FINAL [val] @@ -159,16 +140,6 @@ FILE fqName: fileName:/simple.kt $this: CALL 'private final fun (): kotlin.collections.Map.BoxService>> declared in .BoxService.$rpcServiceStub.Companion' type=kotlin.collections.Map.BoxService>> origin=GET_PROPERTY $this: GET_VAR ': .BoxService.$rpcServiceStub.Companion declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=.BoxService.$rpcServiceStub.Companion origin=null key: GET_VAR 'name: kotlin.String declared in .BoxService.$rpcServiceStub.Companion.getCallable' type=kotlin.String origin=null - FUN name:getFields visibility:public modality:OPEN <> ($this:.BoxService.$rpcServiceStub.Companion, service:.BoxService) returnType:kotlin.collections.List> - overridden: - public abstract fun getFields (service: T of kotlinx.rpc.descriptor.RpcServiceDescriptor): kotlin.collections.List> declared in kotlinx.rpc.descriptor.RpcServiceDescriptor - $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub.Companion - VALUE_PARAMETER name:service index:0 type:.BoxService - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun getFields (service: .BoxService): kotlin.collections.List> declared in .BoxService.$rpcServiceStub.Companion' - TYPE_OP type=kotlin.collections.List> origin=CAST typeOperand=kotlin.collections.List> - CALL 'public final fun emptyList (): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null - : kotlin.Any? CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass] annotations: Serializable(with = ) @@ -257,46 +228,31 @@ FILE fqName: fileName:/simple.kt $this: VALUE_PARAMETER name: type:.BoxService.$rpcServiceStub BLOCK_BODY RETURN type=kotlin.Nothing from='public open fun simple (): kotlin.String declared in .BoxService.$rpcServiceStub' - CALL 'public final fun scopedClientCall (serviceScope: kotlinx.coroutines.CoroutineScope, body: kotlin.coroutines.SuspendFunction0): T of kotlinx.rpc.internal.scopedClientCall declared in kotlinx.rpc.internal' type=kotlin.String origin=null + CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null : kotlin.String - serviceScope: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=kotlinx.coroutines.CoroutineScope origin=null - body: FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String [suspend] - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .BoxService.$rpcServiceStub.simple' - CALL 'public abstract fun call (call: kotlinx.rpc.RpcCall): T of kotlinx.rpc.RpcClient.call declared in kotlinx.rpc.RpcClient' type=kotlin.String origin=null - : kotlin.String - $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null - call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null - descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion - callableName: CONST String type=kotlin.String value="simple" - data: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass]' type=.BoxService.$rpcServiceStub.simple$rpcMethod - serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY - $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null + $this: CALL 'private final fun (): kotlinx.rpc.RpcClient declared in .BoxService.$rpcServiceStub' type=kotlinx.rpc.RpcClient origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null + call: CONSTRUCTOR_CALL 'public constructor (descriptor: kotlinx.rpc.descriptor.RpcServiceDescriptor<*>, callableName: kotlin.String, data: kotlin.Any, serviceId: kotlin.Long) declared in kotlinx.rpc.RpcCall' type=kotlinx.rpc.RpcCall origin=null + descriptor: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.FirRpcServiceStubCompanionObject] OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlinx.rpc.descriptor.RpcServiceDescriptor<.BoxService>]' type=.BoxService.$rpcServiceStub.Companion + callableName: CONST String type=kotlin.String value="simple" + data: GET_OBJECT 'CLASS GENERATED[kotlinx.rpc.codegen.RpcGeneratedRpcMethodClassKey] OBJECT name:simple$rpcMethod modality:FINAL visibility:public superTypes:[kotlin.Any; kotlinx.rpc.internal.RpcMethodClass]' type=.BoxService.$rpcServiceStub.simple$rpcMethod + serviceId: CALL 'private final fun (): kotlin.Long declared in .BoxService.$rpcServiceStub' type=kotlin.Long origin=GET_PROPERTY + $this: GET_VAR ': .BoxService.$rpcServiceStub declared in .BoxService.$rpcServiceStub.simple' type=.BoxService.$rpcServiceStub origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlinx.rpc.RemoteService + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any VALUE_PARAMETER name:other index:0 type:kotlin.Any? FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] overridden: - public open fun hashCode (): kotlin.Int declared in kotlinx.rpc.RemoteService + public open fun hashCode (): kotlin.Int declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] overridden: - public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService + public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any FUN name:simple visibility:public modality:ABSTRACT <> ($this:.BoxService) returnType:kotlin.String [suspend] $this: VALUE_PARAMETER name: type:.BoxService - PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract coroutineContext: kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RemoteService) returnType:kotlin.coroutines.CoroutineContext [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] - overridden: - public abstract fun (): kotlin.coroutines.CoroutineContext declared in kotlinx.rpc.RemoteService - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RemoteService FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' diff --git a/tests/compiler-plugin-tests/src/testData/box/simple.fir.txt b/tests/compiler-plugin-tests/src/testData/box/simple.fir.txt index dd09bd08f..51cb78524 100644 --- a/tests/compiler-plugin-tests/src/testData/box/simple.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/simple.fir.txt @@ -1,5 +1,5 @@ FILE: simple.kt - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlin/Any| { public abstract suspend fun simple(): R|kotlin/String| public final class $rpcServiceStub : R|kotlin/Any| { diff --git a/tests/compiler-plugin-tests/src/testData/box/simple.kt b/tests/compiler-plugin-tests/src/testData/box/simple.kt index 637ba9990..88e9769cd 100644 --- a/tests/compiler-plugin-tests/src/testData/box/simple.kt +++ b/tests/compiler-plugin-tests/src/testData/box/simple.kt @@ -3,13 +3,12 @@ */ import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RemoteService import kotlinx.rpc.withService import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient @Rpc -interface BoxService : RemoteService { +interface BoxService { suspend fun simple(): String } diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.fir.txt b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.fir.txt index 67db05178..9c77a3020 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.fir.txt @@ -1,6 +1,6 @@ FILE: rpcChecked.kt @FILE:R|kotlin/OptIn|(markerClass = vararg((Q|kotlinx/rpc/internal/utils/ExperimentalRpcApi|))) - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any| { public final class $rpcServiceStub : R|kotlin/Any| { public final companion object Companion : R|kotlin/Any| { } @@ -9,44 +9,28 @@ FILE: rpcChecked.kt } public final class NotAService : R|kotlin/Any| { - public constructor(coroutineContext: R|kotlin/coroutines/CoroutineContext|): R|NotAService| { + public constructor(): R|NotAService| { super() } - public final val coroutineContext: R|kotlin/coroutines/CoroutineContext| = R|/coroutineContext| - public get(): R|kotlin/coroutines/CoroutineContext| - } public final class MyServiceImpl : R|MyService| { - public constructor(coroutineContext: R|kotlin/coroutines/CoroutineContext|): R|MyServiceImpl| { + public constructor(): R|MyServiceImpl| { super() } - public open override val coroutineContext: R|kotlin/coroutines/CoroutineContext| = R|/coroutineContext| - public get(): R|kotlin/coroutines/CoroutineContext| - } public final inline suspend fun <@R|kotlinx/rpc/annotations/Rpc|() reified T : R|kotlin/Any|> ok(client: R|kotlinx/rpc/RpcClient|, server: R|kotlinx/rpc/RpcServer|, impl: R|T|, myServiceImpl: R|MyService|): R|kotlin/Unit| { R|/client|.R|kotlinx/rpc/withService|() R|/client|.R|kotlinx/rpc/withService|() - R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (it: R|kotlin/coroutines/CoroutineContext|): R|MyService| { - ^ R|/MyServiceImpl.MyServiceImpl|(R|/it|) + R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (): R|MyService| { + ^ R|/MyServiceImpl.MyServiceImpl|() } ) - R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (it: R|kotlin/coroutines/CoroutineContext|): R|T| { + R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (): R|T| { ^ R|/impl| } ) - R|/myServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|() - R|/myServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|( = awaitFieldInitialization@fun R|MyService|.(): R|kotlin/Int| { - ^ Int(1) - } - ) - R|/impl|.R|kotlinx/rpc/awaitFieldInitialization|() - R|/impl|.R|kotlinx/rpc/awaitFieldInitialization|( = awaitFieldInitialization@fun R|T|.(): R|kotlin/Int| { - ^ Int(1) - } - ) R|kotlinx/rpc/descriptor/serviceDescriptorOf|() R|kotlinx/rpc/descriptor/serviceDescriptorOf|() } @@ -54,33 +38,18 @@ FILE: rpcChecked.kt R|/client|.R|kotlinx/rpc/withService|() R|/client|.R|kotlinx/rpc/withService|() R|/client|.R|kotlinx/rpc/withService|() - R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (it: R|kotlin/coroutines/CoroutineContext|): R|MyServiceImpl| { - ^ R|/MyServiceImpl.MyServiceImpl|(R|/it|) + R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (): R|MyServiceImpl| { + ^ R|/MyServiceImpl.MyServiceImpl|() } ) - R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (it: R|kotlin/coroutines/CoroutineContext|): R|NotAService| { - ^ R|/NotAService.NotAService|(R|/it|) + R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (): R|NotAService| { + ^ R|/NotAService.NotAService|() } ) - R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (it: R|kotlin/coroutines/CoroutineContext|): R|T| { + R|/server|.R|kotlinx/rpc/registerService|( = registerService@fun (): R|T| { ^ R|/impl| } ) - R|/myServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|() - R|/myServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|( = awaitFieldInitialization@fun R|MyServiceImpl|.(): R|kotlin/Int| { - ^ Int(1) - } - ) - R|/notAServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|() - R|/notAServiceImpl|.R|kotlinx/rpc/awaitFieldInitialization|( = awaitFieldInitialization@fun R|NotAService|.(): R|kotlin/Int| { - ^ Int(1) - } - ) - R|/impl|.R|kotlinx/rpc/awaitFieldInitialization|() - R|/impl|.R|kotlinx/rpc/awaitFieldInitialization|( = awaitFieldInitialization@fun R|T|.(): R|kotlin/Int| { - ^ Int(1) - } - ) R|kotlinx/rpc/descriptor/serviceDescriptorOf|() R|kotlinx/rpc/descriptor/serviceDescriptorOf|() R|kotlinx/rpc/descriptor/serviceDescriptorOf|() diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.kt b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.kt index 08770caae..c0a9c9ddd 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.kt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcChecked.kt @@ -12,29 +12,22 @@ import kotlinx.rpc.RpcClient import kotlinx.rpc.RpcServer import kotlinx.rpc.registerService import kotlinx.rpc.descriptor.serviceDescriptorOf -import kotlinx.rpc.awaitFieldInitialization import kotlinx.rpc.internal.utils.ExperimentalRpcApi @Rpc interface MyService -class NotAService(val coroutineContext: CoroutineContext) +class NotAService -class MyServiceImpl(override val coroutineContext: CoroutineContext) : MyService +class MyServiceImpl : MyService inline suspend fun <@Rpc reified T : Any> ok(client: RpcClient, server: RpcServer, impl: T, myServiceImpl: MyService) { client.withService() client.withService() - server.registerService { MyServiceImpl(it) } + server.registerService { MyServiceImpl() } server.registerService { impl } - myServiceImpl.awaitFieldInitialization() - myServiceImpl.awaitFieldInitialization { 1 } - - impl.awaitFieldInitialization() - impl.awaitFieldInitialization { 1 } - serviceDescriptorOf() serviceDescriptorOf() } @@ -44,19 +37,10 @@ inline suspend fun fail(client: RpcClient, server: RpcServer, client.withService<NotAService>() client.withService<T>() - server.registerService<MyServiceImpl> { MyServiceImpl(it) } - server.registerService<NotAService> { NotAService(it) } + server.registerService<MyServiceImpl> { MyServiceImpl() } + server.registerService<NotAService> { NotAService() } server.registerService<T> { impl } - myServiceImpl.awaitFieldInitialization<MyServiceImpl>() - myServiceImpl.awaitFieldInitialization<MyServiceImpl, Int> { 1 } - - notAServiceImpl.awaitFieldInitialization<NotAService>() - notAServiceImpl.awaitFieldInitialization<NotAService, Int> { 1 } - - impl.awaitFieldInitialization<T>() - impl.awaitFieldInitialization<T, Int> { 1 } - serviceDescriptorOf<MyServiceImpl>() serviceDescriptorOf<NotAService>() serviceDescriptorOf<T>() diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt index 36f04f509..808bf3735 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt @@ -1,6 +1,6 @@ FILE: rpcService.kt @FILE:R|kotlin/OptIn|(markerClass = vararg((Q|kotlinx/rpc/internal/utils/ExperimentalRpcApi|))) - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any| { public abstract fun hello(): R|kotlin/Unit| public abstract suspend fun generic(a: R|T|): R|kotlin/Unit| @@ -110,7 +110,7 @@ FILE: rpcService.kt } } - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT : R|kotlin/Any| { public final class $rpcServiceStub : R|kotlin/Any| { public final companion object Companion : R|kotlin/Any| { } @@ -118,7 +118,7 @@ FILE: rpcService.kt } } - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT2 : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT2 : R|kotlin/Any| { public final class $rpcServiceStub : R|kotlin/Any| { public final companion object Companion : R|kotlin/Any| { } diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt index 8ad72ddb2..02c13640d 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt @@ -10,10 +10,6 @@ import kotlinx.coroutines.flow.* import kotlinx.serialization.Serializable import kotlinx.serialization.Contextual import kotlinx.rpc.annotations.Rpc -import kotlinx.rpc.krpc.streamScoped -import kotlinx.rpc.krpc.withStreamScope -import kotlinx.rpc.krpc.StreamScope -import kotlinx.rpc.krpc.invokeOnStreamScopeCompletion import kotlinx.rpc.internal.utils.ExperimentalRpcApi @Rpc 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 6fd3db61b..cf4fea132 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.fir.txt @@ -1,49 +1,3 @@ -Module: none -FILE: a.kt - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceWithStateFlow : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { - public abstract suspend fun hello(flow: R|kotlinx/coroutines/flow/StateFlow|): R|kotlin/Unit| - - public final class $rpcServiceStub : R|kotlin/Any| { - @R|kotlinx/serialization/Serializable|() public final class hello$rpcMethod : R|kotlin/Any| { - @R|kotlinx/serialization/Contextual|() public final val flow: R|kotlinx/coroutines/flow/StateFlow| - public get(): R|kotlinx/coroutines/flow/StateFlow| - - public constructor(flow: R|kotlinx/coroutines/flow/StateFlow|): R|MyServiceWithStateFlow.$rpcServiceStub.hello$rpcMethod| - - public final companion object Companion : R|kotlin/Any| { - public final fun serializer(): R|kotlinx/serialization/KSerializer| - - private constructor(): R|MyServiceWithStateFlow.$rpcServiceStub.hello$rpcMethod.Companion| { - super() - } - - } - - @R|kotlin/Deprecated|(message = String(This synthesized declaration should not be used directly), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.HIDDEN|) public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer| { - public final override fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|MyServiceWithStateFlow.$rpcServiceStub.hello$rpcMethod|): R|kotlin/Unit| - - public final override fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|MyServiceWithStateFlow.$rpcServiceStub.hello$rpcMethod| - - public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor| - public get(): R|kotlinx/serialization/descriptors/SerialDescriptor| - - public final override fun childSerializers(): R|kotlin/Array>| - - private constructor(): R|MyServiceWithStateFlow.$rpcServiceStub.hello$rpcMethod.$serializer| { - super() - } - - } - - } - - public final companion object Companion : R|kotlin/Any| { - } - - } - - } -Module: main FILE: b.kt @FILE:R|kotlin/OptIn|(markerClass = vararg((Q|kotlinx/rpc/internal/utils/ExperimentalRpcApi|))) @R|kotlinx/serialization/Serializable|() public final data class InnerFlow : R|kotlin/Any| { @@ -174,7 +128,7 @@ FILE: b.kt } } - @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyService : R|kotlin/Any| { public abstract val flow: R|kotlinx/coroutines/flow/Flow| public get(): R|kotlinx/coroutines/flow/Flow| @@ -744,21 +698,3 @@ FILE: b.kt } } - public final fun main(): R|kotlin/Unit| { - ^main R|kotlinx/coroutines/runBlocking|( = runBlocking@fun R|kotlinx/coroutines/CoroutineScope|.(): R|kotlin/Unit| { - R|kotlinx/rpc/krpc/streamScoped|( = streamScoped@fun R|kotlinx/coroutines/CoroutineScope|.(): R|kotlin/Unit| { - ^@streamScoped Unit - } - ) - lval scope: R|kotlinx/rpc/krpc/StreamScope| = R|kotlinx/rpc/krpc/StreamScope|(R|kotlinx/coroutines/Job|()) - R|kotlinx/rpc/krpc/withStreamScope|(R|/scope|, = withStreamScope@fun R|kotlinx/coroutines/CoroutineScope|.(): R|kotlin/Unit| { - ^@withStreamScope Unit - } - ) - R|kotlinx/rpc/krpc/invokeOnStreamScopeCompletion|( = invokeOnStreamScopeCompletion@fun (it: R|kotlin/Throwable?|): R|kotlin/Unit| { - ^@invokeOnStreamScopeCompletion Unit - } - ) - } - ) - } diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt index 72baaaca6..4b747e00b 100644 --- a/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/strictMode.kt @@ -2,21 +2,7 @@ * Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ -// MODULE: none -// RPC_STRICT_MODE: none -// FILE: a.kt - -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import kotlinx.rpc.annotations.Rpc - -@Rpc -interface MyServiceWithStateFlow { - suspend fun hello(flow: StateFlow) -} - // MODULE: main -// RPC_STRICT_MODE: warning // FILE: b.kt @file:OptIn(ExperimentalRpcApi::class) @@ -27,10 +13,6 @@ import kotlinx.coroutines.flow.* import kotlinx.serialization.Serializable import kotlinx.serialization.Contextual import kotlinx.rpc.annotations.Rpc -import kotlinx.rpc.krpc.streamScoped -import kotlinx.rpc.krpc.withStreamScope -import kotlinx.rpc.krpc.StreamScope -import kotlinx.rpc.krpc.invokeOnStreamScopeCompletion import kotlinx.rpc.internal.utils.ExperimentalRpcApi @Serializable @@ -79,10 +61,3 @@ interface MyService { fun nonSuspendNoFlow() fun nonSuspendNoFlowString(): String } - -fun main(): Unit = runBlocking { - streamScoped {} - val scope = StreamScope(Job()) - withStreamScope(scope) {} - invokeOnStreamScopeCompletion {} -} diff --git a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Bar.kt b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Bar.kt index 69afa0f28..549d176a1 100644 --- a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Bar.kt +++ b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Bar.kt @@ -4,17 +4,15 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc -import kotlin.coroutines.CoroutineContext @Rpc -interface BarInterface : RemoteService { +interface BarInterface { suspend fun get(): Unit suspend fun get2(): Unit } -class BarInterfaceImpl(override val coroutineContext: CoroutineContext) : BarInterface { +class BarInterfaceImpl : BarInterface { override suspend fun get() {} override suspend fun get2() {} diff --git a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Baz.kt b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Baz.kt index 1e201d0c6..53d05e542 100644 --- a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Baz.kt +++ b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Baz.kt @@ -4,19 +4,17 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext @Serializable data class Baz(val field: String, val field2: String = "") @Rpc -interface BazInterface : RemoteService { +interface BazInterface { suspend fun get(): Baz } -class BazInterfaceImpl(override val coroutineContext: CoroutineContext) : BazInterface { +class BazInterfaceImpl : BazInterface { override suspend fun get(): Baz = Baz("asd", "def") } diff --git a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Foo.kt b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Foo.kt index 2e5fa75d0..32fc5c698 100644 --- a/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Foo.kt +++ b/tests/krpc-compatibility-tests/src/newApi/kotlin/interfaces/Foo.kt @@ -4,20 +4,18 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext @Serializable data class Foo(val field: String, val field2: String? = null) @Rpc -interface FooInterface : RemoteService { +interface FooInterface { suspend fun get(): Foo } -class FooInterfaceImpl(override val coroutineContext: CoroutineContext) : FooInterface { +class FooInterfaceImpl : FooInterface { override suspend fun get(): Foo { return Foo("", "") } diff --git a/tests/krpc-compatibility-tests/src/newApi/kotlin/tests/ApiServer.kt b/tests/krpc-compatibility-tests/src/newApi/kotlin/tests/ApiServer.kt index f6ef49a9e..e1059e1a6 100644 --- a/tests/krpc-compatibility-tests/src/newApi/kotlin/tests/ApiServer.kt +++ b/tests/krpc-compatibility-tests/src/newApi/kotlin/tests/ApiServer.kt @@ -18,9 +18,9 @@ import kotlinx.rpc.registerService class ApiServer : TestApiServer { override fun serveAllInterfaces(rpcServer: RpcServer) { rpcServer.apply { - registerService { FooInterfaceImpl(it) } - registerService { BarInterfaceImpl(it) } - registerService { BazInterfaceImpl(it) } + registerService { FooInterfaceImpl() } + registerService { BarInterfaceImpl() } + registerService { BazInterfaceImpl() } } } } diff --git a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Bar.kt b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Bar.kt index 99bb03569..927628123 100644 --- a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Bar.kt +++ b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Bar.kt @@ -4,15 +4,13 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc -import kotlin.coroutines.CoroutineContext @Rpc -interface BarInterface : RemoteService { +interface BarInterface { suspend fun get() } -class BarInterfaceImpl(override val coroutineContext: CoroutineContext) : BarInterface { +class BarInterfaceImpl() : BarInterface { override suspend fun get() {} } diff --git a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Baz.kt b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Baz.kt index cee355f01..58a5424e0 100644 --- a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Baz.kt +++ b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Baz.kt @@ -4,19 +4,17 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext @Serializable data class Baz(val field: String) @Rpc -interface BazInterface : RemoteService { +interface BazInterface { suspend fun get(): Baz } -class BazInterfaceImpl(override val coroutineContext: CoroutineContext) : BazInterface { +class BazInterfaceImpl : BazInterface { override suspend fun get(): Baz = Baz("asd") } diff --git a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Foo.kt b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Foo.kt index 6ca38219d..bafee94df 100644 --- a/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Foo.kt +++ b/tests/krpc-compatibility-tests/src/oldApi/kotlin/interfaces/Foo.kt @@ -4,20 +4,18 @@ package interfaces -import kotlinx.rpc.RemoteService import kotlinx.rpc.annotations.Rpc import kotlinx.serialization.Serializable -import kotlin.coroutines.CoroutineContext @Serializable data class Foo(val field: String) @Rpc -interface FooInterface : RemoteService { +interface FooInterface { suspend fun get(): Foo } -class FooInterfaceImpl(override val coroutineContext: CoroutineContext) : FooInterface { +class FooInterfaceImpl : FooInterface { override suspend fun get(): Foo { return Foo("") } diff --git a/tests/krpc-compatibility-tests/src/oldApi/kotlin/tests/ApiServer.kt b/tests/krpc-compatibility-tests/src/oldApi/kotlin/tests/ApiServer.kt index f6ef49a9e..e1059e1a6 100644 --- a/tests/krpc-compatibility-tests/src/oldApi/kotlin/tests/ApiServer.kt +++ b/tests/krpc-compatibility-tests/src/oldApi/kotlin/tests/ApiServer.kt @@ -18,9 +18,9 @@ import kotlinx.rpc.registerService class ApiServer : TestApiServer { override fun serveAllInterfaces(rpcServer: RpcServer) { rpcServer.apply { - registerService { FooInterfaceImpl(it) } - registerService { BarInterfaceImpl(it) } - registerService { BazInterfaceImpl(it) } + registerService { FooInterfaceImpl() } + registerService { BarInterfaceImpl() } + registerService { BazInterfaceImpl() } } } } diff --git a/tests/krpc-compatibility-tests/src/test/kotlin/kotlinx/rpc/krpc/compatibility/LocalTransport.kt b/tests/krpc-compatibility-tests/src/test/kotlin/kotlinx/rpc/krpc/compatibility/LocalTransport.kt index 9739e2234..58aad8f0e 100644 --- a/tests/krpc-compatibility-tests/src/test/kotlin/kotlinx/rpc/krpc/compatibility/LocalTransport.kt +++ b/tests/krpc-compatibility-tests/src/test/kotlin/kotlinx/rpc/krpc/compatibility/LocalTransport.kt @@ -12,7 +12,7 @@ import kotlinx.coroutines.job import kotlinx.rpc.krpc.KrpcConfig import kotlinx.rpc.krpc.KrpcTransport import kotlinx.rpc.krpc.KrpcTransportMessage -import kotlinx.rpc.krpc.client.KrpcClient +import kotlinx.rpc.krpc.client.InitializedKrpcClient import kotlinx.rpc.krpc.server.KrpcServer import kotlin.coroutines.CoroutineContext @@ -24,7 +24,7 @@ class KrpcTestServer( class KrpcTestClient( config: KrpcConfig.Client, transport: KrpcTransport, -) : KrpcClient(config, transport) +) : InitializedKrpcClient(config, transport) class LocalTransport(parentScope: CoroutineScope? = null) : CoroutineScope { override val coroutineContext = parentScope?.run { SupervisorJob(coroutineContext.job) } diff --git a/utils/build.gradle.kts b/utils/build.gradle.kts index 23b50d830..1a8f9afa9 100644 --- a/utils/build.gradle.kts +++ b/utils/build.gradle.kts @@ -18,5 +18,10 @@ kotlin { implementation(libs.coroutines.core) } } + commonTest { + dependencies { + implementation(kotlin("test")) + } + } } } diff --git a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/RpcInternalSupervisedCompletableDeferred.kt b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/RpcInternalSupervisedCompletableDeferred.kt deleted file mode 100644 index 969cb2277..000000000 --- a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/RpcInternalSupervisedCompletableDeferred.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.internal.utils - -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Job -import kotlinx.coroutines.currentCoroutineContext -import kotlinx.coroutines.job - -/** - * Cancels when parent is canceled, but not otherwise - */ -@InternalRpcApi -public class RpcInternalSupervisedCompletableDeferred( - parent: Job, -) : CompletableDeferred by CompletableDeferred() { - init { - val handle = parent.invokeOnCompletion { cause -> - if (cause != null) { - completeExceptionally(cause) - } - } - - invokeOnCompletion { - handle.dispose() - } - } -} - -@InternalRpcApi -public suspend fun RpcInternalSupervisedCompletableDeferred(): RpcInternalSupervisedCompletableDeferred { - return RpcInternalSupervisedCompletableDeferred(currentCoroutineContext().job) -} diff --git a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/RpcInternalConcurrentHashMap.kt b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/RpcInternalConcurrentHashMap.kt index 6fb7d6672..1818a1709 100644 --- a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/RpcInternalConcurrentHashMap.kt +++ b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/RpcInternalConcurrentHashMap.kt @@ -14,6 +14,8 @@ public interface RpcInternalConcurrentHashMap { put(key, value) } + public fun merge(key: K, value: V, remappingFunction: (V, V) -> V): V? + public fun computeIfAbsent(key: K, computeValue: () -> V): V public operator fun get(key: K): V? diff --git a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/SynchronizedHashMap.kt b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/SynchronizedHashMap.kt index ae588405c..502ec6e34 100644 --- a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/SynchronizedHashMap.kt +++ b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/map/SynchronizedHashMap.kt @@ -14,6 +14,18 @@ internal class SynchronizedHashMap : RpcInternalConcurrentHashM map.put(key, value) } + override fun merge(key: K, value: V, remappingFunction: (V, V) -> V): V? = synchronized(this) { + val old = map[key] + if (old == null) { + map[key] = value + value + } else { + val new = remappingFunction(old, value) + map[key] = new + new + } + } + override fun computeIfAbsent(key: K, computeValue: () -> V): V = synchronized(this) { map[key] ?: computeValue().also { map[key] = it } } diff --git a/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.kt b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.kt new file mode 100644 index 000000000..daae01153 --- /dev/null +++ b/utils/src/commonMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.kt @@ -0,0 +1,50 @@ +@file:Suppress("detekt.MatchingDeclarationName") + +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi +import kotlinx.rpc.internal.utils.map.RpcInternalConcurrentHashMap + +/** + * A cross-platform implementation of ThreadLocal for Kotlin Multiplatform. + * This class provides thread-local variables, which are variables that are local to a thread. + * Each thread that accesses a thread-local variable has its own, independently initialized copy of the variable. + */ +@InternalRpcApi +public class RpcInternalThreadLocal { + private val map = RpcInternalConcurrentHashMap() + + /** + * Returns the value of this thread-local variable for the current thread or null. + */ + public fun get(): T? { + val threadId = currentThreadId() + return map[threadId] + } + + /** + * Sets the value of this thread-local variable for the current thread. + */ + public fun set(value: T) { + val threadId = currentThreadId() + map[threadId] = value + } + + /** + * Removes the value of this thread-local variable for the current thread. + */ + public fun remove() { + val threadId = currentThreadId() + map.remove(threadId) + } +} + +/** + * Returns the current thread's ID. + * This is a platform-specific function that must be implemented for each platform. + */ +internal expect fun currentThreadId(): Long diff --git a/utils/src/commonTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalTest.kt b/utils/src/commonTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalTest.kt new file mode 100644 index 000000000..214dc6273 --- /dev/null +++ b/utils/src/commonTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalTest.kt @@ -0,0 +1,47 @@ +/* + * 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.internal.utils.thread + +import kotlin.test.Test +import kotlin.test.assertEquals + +class ThreadLocalTest { + @Test + fun testGetWithInitialValue() { + val threadLocal = RpcInternalThreadLocal() + val value = threadLocal.get() + assertEquals(null, value) + } + + @Test + fun testSetAndGet() { + val threadLocal = RpcInternalThreadLocal() + threadLocal.set(42) + val value = threadLocal.get() + assertEquals(42, value) + } + + @Test + fun testRemove() { + val threadLocal = RpcInternalThreadLocal() + threadLocal.set("value") + assertEquals("value", threadLocal.get()) + + threadLocal.remove() + assertEquals(null, threadLocal.get()) + } + + @Test + fun testMultipleThreadLocals() { + val threadLocal1 = RpcInternalThreadLocal() + val threadLocal2 = RpcInternalThreadLocal() + + threadLocal1.set("value1") + threadLocal2.set(42) + + assertEquals("value1", threadLocal1.get()) + assertEquals(42, threadLocal2.get()) + } +} diff --git a/utils/src/jsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.js.kt b/utils/src/jsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.js.kt new file mode 100644 index 000000000..ee410c840 --- /dev/null +++ b/utils/src/jsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.js.kt @@ -0,0 +1,16 @@ +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi + +/** + * JS implementation of currentThreadId. + * Since JavaScript is single-threaded (except for Web Workers), we use a global counter + * to simulate thread IDs. In a real multi-threaded environment with Web Workers, + * a more sophisticated approach would be needed. + */ +@InternalRpcApi +public actual fun currentThreadId(): Long = 1L // Always return 1 for main thread in JS diff --git a/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.jvm.kt b/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.jvm.kt index 5aa01899f..6a0e5c507 100644 --- a/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.jvm.kt +++ b/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.jvm.kt @@ -20,6 +20,10 @@ private class ConcurrentHashMapJvm(initialSize: Int) : RpcInter return map.put(key, value) } + override fun merge(key: K, value: V, remappingFunction: (V, V) -> V): V? { + return map.merge(key, value) { old, new -> remappingFunction(old, new) } + } + override fun computeIfAbsent(key: K, computeValue: () -> V): V { return map.computeIfAbsent(key) { computeValue() } } diff --git a/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.jvm.kt b/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.jvm.kt new file mode 100644 index 000000000..17c23cfd9 --- /dev/null +++ b/utils/src/jvmMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.jvm.kt @@ -0,0 +1,13 @@ +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi + +/** + * JVM implementation of currentThreadId that returns the current thread's ID. + */ +@InternalRpcApi +public actual fun currentThreadId(): Long = Thread.currentThread().id diff --git a/utils/src/jvmTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalJvmTest.kt b/utils/src/jvmTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalJvmTest.kt new file mode 100644 index 000000000..dac21693d --- /dev/null +++ b/utils/src/jvmTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalJvmTest.kt @@ -0,0 +1,71 @@ +/* + * 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.internal.utils.thread + +import kotlin.test.Test +import kotlin.test.assertEquals +import java.util.concurrent.CountDownLatch +import kotlin.concurrent.thread + +class ThreadLocalJvmTest { + @Test + fun testThreadLocalInMultipleThreads() { + val threadLocal = RpcInternalThreadLocal() + val mainThreadId = Thread.currentThread().id + + // Set a value in the main thread + threadLocal.set("main-thread-value") + + // Create a new thread and verify it has its own value + val latch = CountDownLatch(1) + var threadIdRef: Long = -1 + var threadValueRef: String? = null + + thread { + try { + // This thread should have a different thread ID + threadIdRef = Thread.currentThread().id + + // The thread local should return the default value since we haven't set it in this thread + threadValueRef = threadLocal.get() + + // Now set a different value in this thread + threadLocal.set("worker-thread-value") + } finally { + latch.countDown() + } + } + + // Wait for the thread to complete + latch.await() + + // Verify the main thread's value is still intact + assertEquals("main-thread-value", threadLocal.get()) + + // Verify the worker thread had a different ID + assert(threadIdRef != mainThreadId) { "Worker thread should have a different ID" } + + // Verify the worker thread initially got the default value + assertEquals(null, threadValueRef) + + // Create another thread to verify the worker thread's value + val latch2 = CountDownLatch(1) + var threadValue2Ref: String? = null + + thread { + try { + // This should be a new thread with its own value + threadValue2Ref = threadLocal.get() + } finally { + latch2.countDown() + } + } + + latch2.await() + + // Verify the second thread got its own default value + assertEquals(null, threadValue2Ref) + } +} diff --git a/utils/src/nativeMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.native.kt b/utils/src/nativeMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.native.kt new file mode 100644 index 000000000..466541114 --- /dev/null +++ b/utils/src/nativeMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.native.kt @@ -0,0 +1,17 @@ +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi +import kotlin.native.concurrent.ObsoleteWorkersApi +import kotlin.native.concurrent.Worker + +/** + * Native implementation of currentThreadId that returns the current worker's ID. + * In Kotlin/Native, we use Worker.current.id as a thread identifier. + */ +@OptIn(ObsoleteWorkersApi::class) +@InternalRpcApi +public actual fun currentThreadId(): Long = Worker.current.id.toLong() diff --git a/utils/src/nativeTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalNativeTest.kt b/utils/src/nativeTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalNativeTest.kt new file mode 100644 index 000000000..51bd8d21b --- /dev/null +++ b/utils/src/nativeTest/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocalNativeTest.kt @@ -0,0 +1,106 @@ +/* + * 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.internal.utils.thread + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.native.concurrent.ObsoleteWorkersApi +import kotlin.native.concurrent.Worker +import kotlin.native.concurrent.TransferMode +import kotlin.experimental.ExperimentalNativeApi + +class ThreadLocalNativeTest { + @OptIn(ObsoleteWorkersApi::class, ExperimentalNativeApi::class) + @Test + fun testThreadLocalInWorkers() { + val threadLocal = RpcInternalThreadLocal() + val mainWorkerId = Worker.current.id.toLong() + + // Set a value in the main worker + threadLocal.set("main-worker-value") + + // Create a new worker and verify it has its own value + val worker = Worker.start() + + // Execute a task in the worker + val future = worker.execute(TransferMode.SAFE, { threadLocal }) { tl -> + // Get the worker's ID + val workerId = Worker.current.id.toLong() + + // Get the initial value (should be null since we haven't set it in this worker) + val initialValue = tl.get() + + // Set a new value in this worker + tl.set("worker-value") + + // Return the worker ID and initial value + Pair(workerId, initialValue) + } + + // Wait for the worker to complete and get the results + val (workerId, workerInitialValue) = future.result + + // Verify the worker had a different ID + assert(workerId != mainWorkerId) { "Worker should have a different ID" } + + // Verify the worker initially got null (default value) + assertEquals(null, workerInitialValue) + + // Verify the main worker's value is still intact + assertEquals("main-worker-value", threadLocal.get()) + + // Create another worker to verify isolation + val worker2 = Worker.start() + + val future2 = worker2.execute(TransferMode.SAFE, { threadLocal }) { tl -> + // This should be a new worker with its own value + tl.get() + } + + // Verify the second worker got null (default value) + assertEquals(null, future2.result) + + // Clean up + worker.requestTermination().result + worker2.requestTermination().result + } + + @OptIn(ObsoleteWorkersApi::class, ExperimentalNativeApi::class) + @Test + fun testMultipleThreadLocalsInWorkers() { + val threadLocal1 = RpcInternalThreadLocal() + val threadLocal2 = RpcInternalThreadLocal() + + // Set values in the main worker + threadLocal1.set("main-value") + threadLocal2.set(42) + + // Create a worker and set different values + val worker = Worker.start() + + val future = worker.execute(TransferMode.SAFE, { Pair(threadLocal1, threadLocal2) }) { (tl1, tl2) -> + // Set different values in the worker + tl1.set("worker-value") + tl2.set(99) + + // Return the values + Pair(tl1.get(), tl2.get()) + } + + // Get the worker's values + val (workerValue1, workerValue2) = future.result + + // Verify the worker's values + assertEquals("worker-value", workerValue1) + assertEquals(99, workerValue2) + + // Verify the main worker's values are unchanged + assertEquals("main-value", threadLocal1.get()) + assertEquals(42, threadLocal2.get()) + + // Clean up + worker.requestTermination().result + } +} diff --git a/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasm.kt b/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasm.kt new file mode 100644 index 000000000..417186aac --- /dev/null +++ b/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasm.kt @@ -0,0 +1,14 @@ +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi + +/** + * WASM JS implementation of currentThreadId. + * Since WASM JS is single-threaded (similar to regular JS), we return a constant value. + */ +@InternalRpcApi +public actual fun currentThreadId(): Long = 1L // Always return 1 for main thread in WASM JS diff --git a/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasi.kt b/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasi.kt new file mode 100644 index 000000000..3a4b6bbcd --- /dev/null +++ b/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/thread/ThreadLocal.wasi.kt @@ -0,0 +1,14 @@ +/* + * 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.internal.utils.thread + +import kotlinx.rpc.internal.utils.InternalRpcApi + +/** + * WASM WASI implementation of currentThreadId. + * Since WASM WASI is single-threaded in the current implementation, we return a constant value. + */ +@InternalRpcApi +public actual fun currentThreadId(): Long = 1L // Always return 1 for main thread in WASM WASI