diff --git a/README.md b/README.md index fc95c9d1f..fd28c8942 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,13 @@ Build your RPC with already known language constructs and nothing more! ## Quick start -First, create your `RPC` service and define some methods: +First, create your RPC service and define some methods: ```kotlin -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService +import kotlinx.rpc.annotations.Rpc -interface AwesomeService : RPC { +@Rpc +interface AwesomeService : RemoteService { suspend fun getNews(city: String): Flow } ``` 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 8597a8f95..b67314b44 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 @@ -94,8 +94,8 @@ internal object RPCDeclarationScanner { private fun unsupportedDeclaration(service: IrClass, declaration: IrDeclaration, logger: MessageCollector): Nothing? { logger.report( - severity = CompilerMessageSeverity.WARNING, - message = "Unsupported declaration in RPC interface ${service.name}: ${declaration.dumpKotlinLike()}", + severity = CompilerMessageSeverity.LOGGING, + message = "Unsupported declaration in RemoteService 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 64858b722..ca2ac1b0e 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 @@ -77,10 +77,6 @@ internal class RPCIrContext( getIrClassSymbol("kotlin", "Pair") } - val rpc by lazy { - getRpcIrClassSymbol("RPC") - } - val rpcClient by lazy { getRpcIrClassSymbol("RPCClient") } diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrServiceProcessor.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrServiceProcessor.kt index f1c618ee5..e450eb7fd 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrServiceProcessor.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrServiceProcessor.kt @@ -4,24 +4,23 @@ package kotlinx.rpc.codegen.extension +import kotlinx.rpc.codegen.common.RpcClassId import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.types.defaultType -import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.visitors.IrElementTransformer internal class RPCIrServiceProcessor( @Suppress("unused") private val logger: MessageCollector, ) : IrElementTransformer { - @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") - override fun visitClass(declaration: IrClass, context: RPCIrContext): IrStatement { - if (declaration.isInterface && declaration.superTypes.contains(context.rpc.defaultType)) { - processService(declaration, context) + override fun visitClass(declaration: IrClass, data: RPCIrContext): IrStatement { + if (declaration.hasAnnotation(RpcClassId.rpcAnnotation)) { + processService(declaration, data) } - return super.visitClass(declaration, context) + return super.visitClass(declaration, data) } private fun processService(service: IrClass, context: RPCIrContext) { 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 e30fa0605..a70483aa1 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 @@ -196,7 +196,7 @@ internal class RPCStubGenerator( private var coroutineContextProperty: IrProperty by Delegates.notNull() /** - * `coroutineContext` property from `RPC` interface + * `coroutineContext` property from `RemoteService` interface * * ```kotlin * final override val coroutineContext: CoroutineContext = __rpc_client.provideStubContext(__rpc_stub_id) 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 5f725c7ea..aa7010119 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 @@ -34,5 +34,5 @@ fun CompilerPluginRegistrar.ExtensionStorage.registerRpcExtensions(configuration VersionSpecificApi.INSTANCE = VersionSpecificApiImpl IrGenerationExtension.registerExtension(RPCIrExtension(configuration)) - FirExtensionRegistrarAdapter.registerExtension(FirRPCExtensionRegistrar(configuration)) + FirExtensionRegistrarAdapter.registerExtension(FirRpcExtensionRegistrar(configuration)) } 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 f31121112..5c83460ec 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 @@ -8,8 +8,9 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -object ClassDeclarations { - val rpcInterface = ClassId(FqName("kotlinx.rpc"), Name.identifier("RPC")) +object RpcClassId { + val remoteServiceInterface = ClassId(FqName("kotlinx.rpc"), Name.identifier("RemoteService")) + val rpcAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("Rpc")) val serializableAnnotation = ClassId(FqName("kotlinx.serialization"), Name.identifier("Serializable")) val contextualAnnotation = ClassId(FqName("kotlinx.serialization"), Name.identifier("Contextual")) diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCExtensionRegistrar.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCExtensionRegistrar.kt index 40de0b364..07c07447d 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCExtensionRegistrar.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCExtensionRegistrar.kt @@ -8,12 +8,16 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar +import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension.Factory as CFactory import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension.Factory as GFactory +import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension.Factory as SFactory -class FirRPCExtensionRegistrar(private val configuration: CompilerConfiguration) : FirExtensionRegistrar() { +class FirRpcExtensionRegistrar(private val configuration: CompilerConfiguration) : FirExtensionRegistrar() { override fun ExtensionRegistrarContext.configurePlugin() { val logger = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) - +GFactory { FirRPCServiceGenerator(it, logger) } + +CFactory { FirRpcCheckers(it) } + +GFactory { FirRpcServiceGenerator(it, logger) } + +SFactory { FirRpcSupertypeGenerator(it, logger) } } } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCServiceGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCServiceGenerator.kt index 136a0709f..70ff68d27 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCServiceGenerator.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRPCServiceGenerator.kt @@ -4,7 +4,7 @@ package kotlinx.rpc.codegen -import kotlinx.rpc.codegen.common.ClassDeclarations +import kotlinx.rpc.codegen.common.RpcClassId import kotlinx.rpc.codegen.common.RpcNames import kotlinx.rpc.codegen.common.rpcMethodClassName import kotlinx.rpc.codegen.common.rpcMethodName @@ -19,9 +19,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.declarations.utils.visibility -import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension -import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext -import org.jetbrains.kotlin.fir.extensions.NestedClassGenerationContext +import org.jetbrains.kotlin.fir.extensions.* import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.plugin.* import org.jetbrains.kotlin.fir.symbols.SymbolInternals @@ -44,22 +42,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage * * ## General idea * - * [getNestedClassifiersNames] should return a set of [Name]s to generate for. - * For these names [generateNestedClassLikeDeclaration] can generate some nested classes, - * which is what we need. - * - * But the catch is that we cannot say for sure, if we need to generate a class - * while in [getNestedClassifiersNames], but if we do not return anything - * [generateNestedClassLikeDeclaration] will not be called. - * We need to generate a class if only the current declaration is an RPC interface - * (inherits kotlinx.rpc.RPC). There is no resolved supertypes in [getNestedClassifiersNames], - * But, if the potentially generated class is not referenced anywhere, - * then [generateNestedClassLikeDeclaration] will already have supertypes resolved, - * so we can use this info to check the actual supertypes for RPC interface. - * - * So we always return a class name that may be generated. - * And then, in [generateNestedClassLikeDeclaration] we do the actual check with the resolved supertypes - * and generate a class if needed, otherwise returning null. + * Detect `@Rpc` annotation - generate stub classes. * * ## Usage of kotlinx.serialization plugin * @@ -68,7 +51,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage * We generate classes that are marked `@Serializable`. * In that case, the serialization plugin will not be able to pick up those classes and process them accordingly. * - * That's why we have an instance of this plugin, which we call only on our generated classes - [serializationExtension] + * That is why we have an instance of this plugin, which we call only on our generated classes - [serializationExtension] * * Not all the methods that we would like to call are public, so we access them via reflection: * - [generateCompanionDeclaration] @@ -76,7 +59,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage * * This is basically copying the behavior of the actual plugin but isolated only for our generated classes. */ -class FirRPCServiceGenerator( +class FirRpcServiceGenerator( session: FirSession, @Suppress("unused") private val logger: MessageCollector, @@ -84,22 +67,22 @@ class FirRPCServiceGenerator( private val serializationExtension = SerializationFirResolveExtension(session) private val isJvmOrMetadata = !session.moduleData.platform.run { isJs() || isWasm() || isNative() } + override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(FirRpcPredicates.rpc) + } + /** * Generates nested classifiers. * * They can be of three kinds: * - Nested Service Stub class. * In that case [classSymbol] will not have any RPC-generated [FirClassSymbol.origin]. - * Rge only check we do - is we check that the declaration is an interface, - * and return [RpcNames.SERVICE_STUB_NAME]. - * We cannot be sure if the declaration is actually an RPC service, - * because superTypes are not resolved during that stage. - * We postpone this check until [generateNestedClassLikeDeclaration]. + * The only check we do - presence of the `@Rpc` annotation and return [RpcNames.SERVICE_STUB_NAME]. * * - Companion object of the service stub and method classes. * If we generate this companion object, we will have [FirClassSymbol.origin] * of [classSymbol] be set to [RPCGeneratedStubKey], - * because we are inside the previously generated service stub class. + * because we're inside the previously generated service stub class. * The same goes for method classes too. * So we return [SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT] * and a list of method class names. @@ -141,7 +124,7 @@ class FirRPCServiceGenerator( SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT } - classSymbol.isInterface -> { + classSymbol.isInterface && session.predicateBasedProvider.matches(FirRpcPredicates.rpc, classSymbol) -> { setOf(RpcNames.SERVICE_STUB_NAME) } @@ -158,7 +141,7 @@ class FirRPCServiceGenerator( override fun generateNestedClassLikeDeclaration( owner: FirClassSymbol<*>, name: Name, - context: NestedClassGenerationContext + context: NestedClassGenerationContext, ): FirClassLikeSymbol<*>? { val rpcServiceStubKey = owner.generatedRpcServiceStubKey return when { @@ -214,7 +197,7 @@ class FirRPCServiceGenerator( modality = Modality.FINAL } - rpcMethodClass.addAnnotation(ClassDeclarations.serializableAnnotation, session) + rpcMethodClass.addAnnotation(RpcClassId.serializableAnnotation, session) /** * Required to pass isSerializableObjectAndNeedsFactory check @@ -264,18 +247,10 @@ class FirRPCServiceGenerator( } /** - * Checks whether the [owner] class is actually an RPC service - * (the supertypes are resolved at this stage, - * as the [RpcNames.SERVICE_STUB_NAME] is not references anywhere) - * - * If the [owner] is an RPC service - generates its service stub. + * Generates [owner]'s service stub. * Scrapes the functions from the [owner] to generate method classes. */ private fun generateRpcServiceStubClass(owner: FirClassSymbol<*>): FirRegularClassSymbol? { - owner.resolvedSuperTypes.find { - it.classId == ClassDeclarations.rpcInterface - } ?: return null - @OptIn(SymbolInternals::class) val functions = owner.fir.declarations .filterIsInstance() @@ -306,7 +281,7 @@ class FirRPCServiceGenerator( } /** - * If the method does not have any parameters, it is an object, + * If the method doesn't have any parameters, it is an object, * and its only callable names are constructor, and the ones provided by the [serializationExtension]. * Otherwise, the callable names are the names of the method parameters and the constructor. */ @@ -322,7 +297,7 @@ class FirRPCServiceGenerator( rpcMethodClassKey.rpcMethod.valueParameterSymbols.map { it.name }.toSet() } + SpecialNames.INIT - // ^ init is necessary either way, as serialization does not add it for a serializable object + // ^ init is necessary either way, as serialization doesn't add it for a serializable object } override fun generateConstructors(context: MemberGenerationContext): List { @@ -361,7 +336,7 @@ class FirRPCServiceGenerator( override fun generateProperties( callableId: CallableId, - context: MemberGenerationContext? + context: MemberGenerationContext?, ): List { context ?: return emptyList() @@ -399,14 +374,14 @@ class FirRPCServiceGenerator( returnType = valueParam.resolvedReturnType, ).apply { if (valueParam.resolvedReturnType.requiresContextual()) { - addAnnotation(ClassDeclarations.contextualAnnotation, session) + addAnnotation(RpcClassId.contextualAnnotation, session) } }.symbol.let(::listOf) } private fun ConeKotlinType.requiresContextual(): Boolean { return when (classId) { - ClassDeclarations.flow, ClassDeclarations.sharedFlow, ClassDeclarations.stateFlow -> true + RpcClassId.flow, RpcClassId.sharedFlow, RpcClassId.stateFlow -> true else -> false } } @@ -416,7 +391,7 @@ class FirRPCServiceGenerator( */ override fun generateFunctions( callableId: CallableId, - context: MemberGenerationContext? + context: MemberGenerationContext?, ): List { val owner = context?.owner ?: return emptyList() diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcCheckers.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcCheckers.kt new file mode 100644 index 000000000..4c3289e04 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcCheckers.kt @@ -0,0 +1,19 @@ +/* + * 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 kotlinx.rpc.codegen.checkers.FirRpcDeclarationCheckers +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers +import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension +import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar + +class FirRpcCheckers(session: FirSession) : FirAdditionalCheckersExtension(session) { + override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(FirRpcPredicates.rpc) + } + + override val declarationCheckers: DeclarationCheckers = FirRpcDeclarationCheckers +} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcPredicates.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcPredicates.kt new file mode 100644 index 000000000..8ec8e808c --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcPredicates.kt @@ -0,0 +1,14 @@ +/* + * 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 kotlinx.rpc.codegen.common.RpcClassId +import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate + +object FirRpcPredicates { + internal val rpc = DeclarationPredicate.create { + annotated(RpcClassId.rpcAnnotation.asSingleFqName()) // @Rpc + } +} 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 new file mode 100644 index 000000000..8dd784e49 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcSupertypeGenerator.kt @@ -0,0 +1,45 @@ +/* + * 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 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.FirClassLikeDeclaration +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.fir.types.constructClassLikeType +import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef + +class FirRpcSupertypeGenerator( + 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(FirRpcPredicates.rpc, declaration) + } + + override fun computeAdditionalSupertypes( + classLikeDeclaration: FirClassLikeDeclaration, + resolvedSupertypes: List, + typeResolver: TypeResolveService, + ): List { + if (resolvedSupertypes.any { it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) }) { + return emptyList() + } + + return listOf( + RpcClassId.remoteServiceInterface + .constructClassLikeType(emptyArray(), isNullable = false) + .toFirResolvedTypeRef() + ) + } +} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcUtils.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcUtils.kt new file mode 100644 index 000000000..04c5d0607 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/FirRpcUtils.kt @@ -0,0 +1,47 @@ +/* + * 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 kotlinx.rpc.codegen.common.RpcClassId +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +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): KtSourceElement? { + return rpcAnnotation(session)?.source +} + +fun FirBasedSymbol<*>.rpcAnnotation(session: FirSession): FirAnnotation? { + return resolvedCompilerAnnotationsWithClassIds.rpcAnnotation(session) +} + +fun List.rpcAnnotation(session: FirSession): FirAnnotation? { + return getAnnotationByClassId(RpcClassId.rpcAnnotation, session) +} + +fun FirClassSymbol<*>.remoteServiceSupertypeSource(session: FirSession): KtSourceElement? { + return remoteServiceSupertype(session)?.source +} + +fun FirClassSymbol<*>.remoteServiceSupertype(session: FirSession): FirResolvedTypeRef? { + return resolvedSuperTypeRefs.find { it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) } +} + +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/latest/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt new file mode 100644 index 000000000..b0060fc22 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt @@ -0,0 +1,45 @@ +/* + * 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.checkers + +import kotlinx.rpc.codegen.FirRpcPredicates +import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcDiagnostics +import kotlinx.rpc.codegen.isRemoteService +import kotlinx.rpc.codegen.remoteServiceSupertypeSource +import kotlinx.rpc.codegen.rpcAnnotationSource +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.utils.isInterface +import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider + +object FirRpcAnnotationChecker : FirRegularClassChecker(MppCheckerKind.Common) { + override fun check( + declaration: FirRegularClass, + context: CheckerContext, + reporter: DiagnosticReporter, + ) { + val rpcAnnotated = context.session.predicateBasedProvider.matches(FirRpcPredicates.rpc, declaration) + + if (!declaration.isInterface && rpcAnnotated) { + reporter.reportOn( + source = declaration.symbol.rpcAnnotationSource(context.session), + factory = FirRpcDiagnostics.WRONG_RPC_ANNOTATION_TARGET, + context = context, + ) + } + + if (declaration.symbol.isRemoteService(context.session) && !rpcAnnotated) { + reporter.reportOn( + source = declaration.symbol.remoteServiceSupertypeSource(context.session), + factory = FirRpcDiagnostics.MISSING_RPC_ANNOTATION, + context = context, + ) + } + } +} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcDeclarationCheckers.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcDeclarationCheckers.kt new file mode 100644 index 000000000..45c3d5742 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/FirRpcDeclarationCheckers.kt @@ -0,0 +1,14 @@ +/* + * 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.checkers + +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker + +object FirRpcDeclarationCheckers : DeclarationCheckers() { + override val regularClassCheckers: Set = setOf( + FirRpcAnnotationChecker, + ) +} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt new file mode 100644 index 000000000..2b93e2fda --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt @@ -0,0 +1,18 @@ +/* + * 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.checkers.diagnostics + +import org.jetbrains.kotlin.diagnostics.error0 +import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory +import org.jetbrains.kotlin.psi.KtAnnotationEntry + +object FirRpcDiagnostics { + val MISSING_RPC_ANNOTATION by error0() + val WRONG_RPC_ANNOTATION_TARGET by error0() + + init { + RootDiagnosticRendererFactory.registerFactory(RpcDiagnosticRendererFactory) + } +} diff --git a/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt new file mode 100644 index 000000000..fd1254044 --- /dev/null +++ b/compiler-plugin/compiler-plugin-k2/src/main/latest/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt @@ -0,0 +1,24 @@ +/* + * 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.checkers.diagnostics + +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap +import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory + +object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() { + override val MAP = KtDiagnosticFactoryToRendererMap("Rpc").apply { + 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", + ) + + put( + factory = FirRpcDiagnostics.WRONG_RPC_ANNOTATION_TARGET, + message = "@Rpc annotation is only applicable to interfaces.", + ) + } +} diff --git a/core/api/core.api b/core/api/core.api index 1e9b437b4..dba97ab59 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -1,6 +1,6 @@ public final class kotlinx/rpc/AwaitFieldInitializationKt { - public static final fun awaitFieldInitialization (Lkotlinx/rpc/RPC;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun awaitFieldInitialization (Lkotlinx/rpc/RPC;Lkotlin/reflect/KClass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun awaitFieldInitialization (Lkotlinx/rpc/RemoteService;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun awaitFieldInitialization (Lkotlinx/rpc/RemoteService;Lkotlin/reflect/KClass;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class kotlinx/rpc/RPC : kotlinx/coroutines/CoroutineScope { @@ -69,13 +69,19 @@ public abstract interface class kotlinx/rpc/RPCServer : kotlinx/coroutines/Corou public abstract fun registerService (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V } +public abstract interface class kotlinx/rpc/RemoteService : kotlinx/coroutines/CoroutineScope { +} + 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 final class kotlinx/rpc/WithServiceKt { - public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KClass;)Lkotlinx/rpc/RPC; - public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KType;)Lkotlinx/rpc/RPC; + public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KClass;)Lkotlinx/rpc/RemoteService; + public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KType;)Lkotlinx/rpc/RemoteService; +} + +public abstract interface annotation class kotlinx/rpc/annotations/Rpc : java/lang/annotation/Annotation { } diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RPCCall.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RPCCall.kt index d49749689..d2aace238 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RPCCall.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RPCCall.kt @@ -7,7 +7,7 @@ package kotlinx.rpc import kotlin.reflect.KType /** - * Represents a method or field call of the RPC interface. + * Represents a method or field call of an RPC service. * Contains all types and values information for the call, so it can be passed to a server. * * @property serviceTypeString The service type as a string. diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RPCClient.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RPCClient.kt index ee3f60274..8dd4ed0ce 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RPCClient.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RPCClient.kt @@ -63,9 +63,9 @@ public interface RPCClient : CoroutineScope { public fun registerStateFlowField(serviceScope: CoroutineScope, field: RPCField): StateFlow /** - * Provides child [CoroutineContext] for a new [RPC] service stub. + * Provides child [CoroutineContext] for a new [RemoteService] service stub. * - * This function should not be called directly. + * This function shouldn't be called directly. * * @param serviceId id of the new service. Used for service cancellation messages. */ diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RPCServer.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RPCServer.kt index 5bb7a3ba2..1aa492182 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RPCServer.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RPCServer.kt @@ -24,7 +24,7 @@ public interface RPCServer : CoroutineScope { * @param serviceKClass [KClass] of the [Service]. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. */ - public fun registerService( + public fun registerService( serviceKClass: KClass, serviceFactory: (CoroutineContext) -> Service, ) @@ -39,7 +39,7 @@ public interface RPCServer : CoroutineScope { * 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 RPCServer.registerService( +public inline fun RPCServer.registerService( noinline serviceFactory: (CoroutineContext) -> Service, ) { registerService(Service::class, serviceFactory) diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt b/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt new file mode 100644 index 000000000..ce41e270b --- /dev/null +++ b/core/src/commonMain/kotlin/kotlinx/rpc/RemoteService.kt @@ -0,0 +1,25 @@ +/* + * 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 + +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( + message = "Deprecated in favor of RemoteService. Will be removed in 0.5.0", + replaceWith = ReplaceWith("RemoteService", "kotlinx.rpc.RemoteService"), + level = DeprecationLevel.ERROR, +) +public interface RPC : CoroutineScope diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRPCFieldException.kt b/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRPCFieldException.kt index 49db36cfc..dcf42b189 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRPCFieldException.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRPCFieldException.kt @@ -7,7 +7,7 @@ package kotlinx.rpc import kotlin.reflect.KProperty /** - * Thrown when an uninitialized field of an RPC interface is accessed. + * Thrown when an uninitialized field of an RPC service is accessed. * * Use [awaitFieldInitialization] to await for the field initialization */ diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/RPC.kt b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt similarity index 53% rename from core/src/commonMain/kotlin/kotlinx/rpc/RPC.kt rename to core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt index ca79c1729..3b9dab8fe 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/RPC.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/annotations/Rpc.kt @@ -2,40 +2,42 @@ * 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 +package kotlinx.rpc.annotations -import kotlinx.coroutines.CoroutineScope +import kotlinx.rpc.RemoteService /** - * Marker interface for an RPC service. - * For each service that inherits this interface library will generate an implementation to use it on the client side. + * Every [Rpc] annotated interface will have a code generation process run on it, + * making the interface effectively usable for RPC calls. * - * [CoroutineScope] defines service lifetime. + * 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: * ```kotlin * // common code - * interface MyService : RPC { + * @Rpc + * interface MyService : RemoteService { * suspend fun sayHello(firstName: String, lastName: String, age: Int): String * } - * * // client code * val rpcClient: RPCClient * val myService = rpcClient.withService() * val greetingFromServer = myService.sayHello("Alex", "Smith", 35) - * * // server code * class MyServiceImpl(override val coroutineContext: CoroutineContext) : 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) } * ``` * - * @see RPCClient - * @see RPCServer + * @see [RemoteService] */ -public interface RPC : CoroutineScope +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +public annotation class Rpc diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt b/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt index 0fd06b13a..9961247da 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt @@ -14,7 +14,8 @@ import kotlin.reflect.KClass * Waits for the initialization of an RPC field in the generated client: * * ```kotlin - * interface MyService : RPC { + * @Rpc + * interface MyService : RemoteService { * val stateFlow: StateFlow * } * @@ -27,7 +28,7 @@ import kotlin.reflect.KClass * @param getter function that returns the field of the context service to wait for. * @return service filed after it was initialized. */ -public suspend fun T.awaitFieldInitialization(getter: T.() -> R): R { +public suspend fun T.awaitFieldInitialization(getter: T.() -> R): R { val field = getter() if (field is RPCDeferredField<*>) { @@ -42,7 +43,8 @@ public suspend fun T.awaitFieldInitialization(getter: T.() -> R): R * Waits for the initialization of all RPC fields in the generated client: * * ```kotlin - * interface MyService : RPC { + * @Rpc + * interface MyService : RemoteService { * val stateFlow1: StateFlow * val stateFlow2: StateFlow * } @@ -55,7 +57,7 @@ public suspend fun T.awaitFieldInitialization(getter: T.() -> R): R * @param T service type * @return specified service, after all of it's field were initialized. */ -public suspend inline fun T.awaitFieldInitialization(): T { +public suspend inline fun T.awaitFieldInitialization(): T { return awaitFieldInitialization(T::class) } @@ -63,7 +65,8 @@ public suspend inline fun T.awaitFieldInitialization(): T { * Waits for the initialization of all RPC fields in the generated client: * * ```kotlin - * interface MyService : RPC { + * @Rpc + * interface MyService : RemoteService { * val stateFlow1: StateFlow * val stateFlow2: StateFlow * } @@ -77,7 +80,7 @@ public suspend inline fun T.awaitFieldInitialization(): T { * @param kClass [KClass] of the [T] type. * @return specified service, after all of it's field were initialized. */ -public suspend fun T.awaitFieldInitialization(kClass: KClass): T { +public suspend fun T.awaitFieldInitialization(kClass: KClass): T { findRPCStubProvider>(kClass, RPCServiceFieldsProvider::class.safeCast()) .rpcFields(this) .forEach { field -> diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RPCStubObject.kt b/core/src/commonMain/kotlin/kotlinx/rpc/internal/RPCStubObject.kt index 7b9264c82..2cef230d9 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/internal/RPCStubObject.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/internal/RPCStubObject.kt @@ -4,19 +4,19 @@ package kotlinx.rpc.internal -import kotlinx.rpc.RPC import kotlinx.rpc.RPCClient +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.InternalRPCApi import kotlin.reflect.KType @InternalRPCApi -public interface RPCStubObject : +public interface RPCStubObject : RPCStubServiceProvider, RPCServiceMethodSerializationTypeProvider, RPCServiceFieldsProvider @InternalRPCApi -public interface RPCStubServiceProvider { +public interface RPCStubServiceProvider { public fun withClient(serviceId: Long, client: RPCClient) : T } @@ -26,6 +26,6 @@ public interface RPCServiceMethodSerializationTypeProvider { } @InternalRPCApi -public interface RPCServiceFieldsProvider { +public interface RPCServiceFieldsProvider { public fun rpcFields(service: T): List> } diff --git a/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt b/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt index 8a8ed47fe..10123a523 100644 --- a/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt +++ b/core/src/commonMain/kotlin/kotlinx/rpc/withService.kt @@ -20,7 +20,7 @@ import kotlin.reflect.KType * @param T the exact type of the service to be created. * @return instance of the generated service. */ -public inline fun RPCClient.withService(): T { +public inline fun RPCClient.withService(): T { return withService(T::class) } @@ -33,7 +33,7 @@ public inline fun RPCClient.withService(): T { * @param serviceKType [KType] of the service to be created. * @return instance of the generated service. */ -public fun RPCClient.withService(serviceKType: KType): T { +public fun RPCClient.withService(serviceKType: KType): T { return withService(serviceKType.kClass()) } @@ -52,7 +52,7 @@ private val SERVICE_ID = atomic(0L) * @param serviceKClass [KClass] of the service to be created. * @return instance of the generated service. */ -public fun RPCClient.withService(serviceKClass: KClass): T { +public fun RPCClient.withService(serviceKClass: KClass): T { val provider = findRPCStubProvider>( kClass = serviceKClass, resultKClass = RPCStubServiceProvider::class.safeCast(), diff --git a/core/src/jsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.js.kt b/core/src/jsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.js.kt index b3805eca4..2a40cf266 100644 --- a/core/src/jsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.js.kt +++ b/core/src/jsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.js.kt @@ -7,7 +7,7 @@ package kotlinx.rpc.internal import js.objects.Object -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.InternalRPCApi import kotlin.reflect.AssociatedObjectKey import kotlin.reflect.ExperimentalAssociatedObjects @@ -20,7 +20,7 @@ import kotlin.reflect.findAssociatedObject @Target(AnnotationTarget.CLASS) public annotation class WithRPCStubObject( @Suppress("unused") - val stub: KClass> + val stub: KClass>, ) @InternalRPCApi diff --git a/core/src/nativeMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.native.kt b/core/src/nativeMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.native.kt index 0eb4cbb0c..b7da9531f 100644 --- a/core/src/nativeMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.native.kt +++ b/core/src/nativeMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.native.kt @@ -6,7 +6,7 @@ package kotlinx.rpc.internal -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.InternalRPCApi import kotlin.reflect.AssociatedObjectKey import kotlin.reflect.ExperimentalAssociatedObjects @@ -19,7 +19,7 @@ import kotlin.reflect.findAssociatedObject @Target(AnnotationTarget.CLASS) public annotation class WithRPCStubObject( @Suppress("unused") - val stub: KClass> + val stub: KClass>, ) @InternalRPCApi diff --git a/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt index 054f9fbe4..0b03caeca 100644 --- a/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt +++ b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt @@ -6,7 +6,7 @@ package kotlinx.rpc.internal -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.InternalRPCApi import kotlin.reflect.AssociatedObjectKey import kotlin.reflect.ExperimentalAssociatedObjects @@ -19,7 +19,7 @@ import kotlin.reflect.findAssociatedObject @Target(AnnotationTarget.CLASS) public annotation class WithRPCStubObject( @Suppress("unused") - val stub: KClass> + val stub: KClass>, ) @OptIn(ExperimentalAssociatedObjects::class) diff --git a/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt index 054f9fbe4..0b03caeca 100644 --- a/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt +++ b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt @@ -6,7 +6,7 @@ package kotlinx.rpc.internal -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.InternalRPCApi import kotlin.reflect.AssociatedObjectKey import kotlin.reflect.ExperimentalAssociatedObjects @@ -19,7 +19,7 @@ import kotlin.reflect.findAssociatedObject @Target(AnnotationTarget.CLASS) public annotation class WithRPCStubObject( @Suppress("unused") - val stub: KClass> + val stub: KClass>, ) @OptIn(ExperimentalAssociatedObjects::class) diff --git a/docs/pages/kotlinx-rpc/topics/features.topic b/docs/pages/kotlinx-rpc/topics/features.topic index 6ad69c72b..9b236eae8 100644 --- a/docs/pages/kotlinx-rpc/topics/features.topic +++ b/docs/pages/kotlinx-rpc/topics/features.topic @@ -24,7 +24,8 @@ val innerFlow: StateFlow<Int> } - interface MyService : RPC { + @Rpc + interface MyService : RemoteService { suspend fun sendStream(stream: Flow<Flow<Int>>): Flow<StreamResult> } @@ -85,7 +86,8 @@

Our protocol provides you with an ability to declare service fields:

- interface MyService : RPC { + @Rpc + interface MyService : RemoteService { val plainFlow: Flow<Int> val sharedFlow: SharedFlow<Int> val stateFlow: StateFlow<Int> @@ -142,7 +144,8 @@

- interface MyService : RPC { + @Rpc + interface MyService : RemoteService { val flow: StateFlow<Int> } @@ -163,7 +166,8 @@ (when withService method is called):

- interface MyService : RPC { + @Rpc + interface MyService : RemoteService { val lazyFlow: Flow<Int> // initialized on first access @RPCEagerField @@ -171,4 +175,4 @@ } - \ No newline at end of file + diff --git a/docs/pages/kotlinx-rpc/topics/services.topic b/docs/pages/kotlinx-rpc/topics/services.topic index 0c34097a8..a2840eb18 100644 --- a/docs/pages/kotlinx-rpc/topics/services.topic +++ b/docs/pages/kotlinx-rpc/topics/services.topic @@ -15,7 +15,8 @@ A simple service can be declared as follows:

- interface MyService : RPC { + @Rpc + interface MyService : RemoteService { suspend fun hello(name: String): String } @@ -41,4 +42,4 @@ }

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

- \ No newline at end of file + diff --git a/docs/pages/kotlinx-rpc/topics/transport.topic b/docs/pages/kotlinx-rpc/topics/transport.topic index cf8d16915..a89f193db 100644 --- a/docs/pages/kotlinx-rpc/topics/transport.topic +++ b/docs/pages/kotlinx-rpc/topics/transport.topic @@ -86,7 +86,8 @@ val numberOfDogs: Int ) - interface ImageService : RPC { + @Rpc + interface ImageService : RemoteService { suspend fun processImage(url: Srting): ProcessedImage } @@ -147,4 +148,4 @@ You can provide your own transport and even your own fully implemented protocols, while the library will take care of code generation.

- \ No newline at end of file + diff --git a/krpc/krpc-client/api/krpc-client.api b/krpc/krpc-client/api/krpc-client.api index 084717c78..d62feabc2 100644 --- a/krpc/krpc-client/api/krpc-client.api +++ b/krpc/krpc-client/api/krpc-client.api @@ -10,8 +10,3 @@ public abstract class kotlinx/rpc/krpc/client/KRPCClient : kotlinx/rpc/krpc/inte public final fun registerStateFlowField (Lkotlinx/coroutines/CoroutineScope;Lkotlinx/rpc/RPCField;)Lkotlinx/coroutines/flow/StateFlow; } -public final class kotlinx/rpc/krpc/client/RPCClientUtilsKt { - public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KClass;)Lkotlinx/rpc/RPC; - public static final fun withService (Lkotlinx/rpc/RPCClient;Lkotlin/reflect/KType;)Lkotlinx/rpc/RPC; -} - diff --git a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/RPCClientUtils.kt b/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/RPCClientUtils.kt deleted file mode 100644 index 99e3b99a8..000000000 --- a/krpc/krpc-client/src/commonMain/kotlin/kotlinx/rpc/krpc/client/RPCClientUtils.kt +++ /dev/null @@ -1,38 +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.client - -import kotlinx.rpc.RPC -import kotlinx.rpc.RPCClient -import kotlinx.rpc.withService -import kotlin.reflect.KClass -import kotlin.reflect.KType - -@Deprecated( - message = "withService was moved to kotlinx-rpc-core, to kotlinx.rpc package", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith("withService()", "kotlinx.rpc.withService") -) -public inline fun RPCClient.withService(): T { - return withService() -} - -@Deprecated( - message = "withService was moved to kotlinx-rpc-core, to kotlinx.rpc package", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith("withService(serviceKType)", "kotlinx.rpc.withService") -) -public fun RPCClient.withService(serviceKType: KType): T { - return withService(serviceKType) -} - -@Deprecated( - message = "withService was moved to kotlinx-rpc-core, to kotlinx.rpc package", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith("withService(serviceKClass)", "kotlinx.rpc.withService") -) -public fun RPCClient.withService(serviceKClass: KClass): T { - return withService(serviceKClass) -} 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 574a7bd09..5e9d4eb80 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 @@ -9,7 +9,8 @@ package kotlinx.rpc.krpc.ktor import io.ktor.server.application.* import io.ktor.server.testing.* import kotlinx.coroutines.cancel -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.krpc.ktor.client.installRPC import kotlinx.rpc.krpc.ktor.client.rpc import kotlinx.rpc.krpc.ktor.client.rpcConfig @@ -21,7 +22,8 @@ import org.junit.Assert.assertEquals import kotlin.coroutines.CoroutineContext import kotlin.test.Test -interface NewService : RPC { +@Rpc +interface NewService : RemoteService { suspend fun echo(value: String): String } diff --git a/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/RPCRoute.kt b/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/RPCRoute.kt index 41647e2b8..2fb71d0d1 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/RPCRoute.kt +++ b/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/RPCRoute.kt @@ -5,8 +5,8 @@ package kotlinx.rpc.krpc.ktor.server import io.ktor.server.websocket.* -import kotlinx.rpc.RPC import kotlinx.rpc.RPCServer +import kotlinx.rpc.RemoteService import kotlinx.rpc.krpc.RPCConfigBuilder import kotlin.coroutines.CoroutineContext import kotlin.reflect.KClass @@ -42,7 +42,7 @@ public class RPCRoute( * @param serviceKClass [KClass] of the [Service]. * @param serviceFactory function that produces the actual implementation of the service that will handle the calls. */ - public fun registerService( + public fun registerService( serviceKClass: KClass, serviceFactory: (CoroutineContext) -> Service, ) { @@ -60,7 +60,7 @@ public class RPCRoute( * 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 registerService( + public inline fun registerService( noinline serviceFactory: (CoroutineContext) -> Service, ) { registerService(Service::class, serviceFactory) diff --git a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServiceUtils.kt b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServiceUtils.kt index 2c8661e5b..ed0d380fd 100644 --- a/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServiceUtils.kt +++ b/krpc/krpc-server/src/commonMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServiceUtils.kt @@ -4,7 +4,7 @@ package kotlinx.rpc.krpc.server.internal -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.RPCServiceMethodSerializationTypeProvider import kotlinx.rpc.internal.findRPCStubProvider import kotlinx.rpc.internal.kClass @@ -16,7 +16,7 @@ import kotlin.reflect.KType * Utility method that returns [KType] for the class which is used to serialize method request with the [methodName] */ @InternalRPCApi -public inline fun rpcServiceMethodSerializationTypeOf(methodName: String): KType? { +public inline fun rpcServiceMethodSerializationTypeOf(methodName: String): KType? { return rpcServiceMethodSerializationTypeOf(T::class, methodName) } diff --git a/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/KRPCServer.kt b/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/KRPCServer.kt index b986afc03..ed5706736 100644 --- a/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/KRPCServer.kt +++ b/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/KRPCServer.kt @@ -5,8 +5,8 @@ package kotlinx.rpc.krpc.server import kotlinx.coroutines.* -import kotlinx.rpc.RPC import kotlinx.rpc.RPCServer +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.qualifiedClassName import kotlinx.rpc.internal.utils.InternalRPCApi import kotlinx.rpc.internal.utils.map.ConcurrentHashMap @@ -99,7 +99,7 @@ public abstract class KRPCServer( } } - final override fun registerService( + final override fun registerService( serviceKClass: KClass, serviceFactory: (CoroutineContext) -> Service, ) { @@ -122,7 +122,7 @@ public abstract class KRPCServer( } } - private fun createNewServiceInstance( + private fun createNewServiceInstance( serviceKClass: KClass, serviceFactory: (CoroutineContext) -> Service, ): RPCServerService { diff --git a/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServerService.kt b/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServerService.kt index b19e11db8..ed68e0ef8 100644 --- a/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServerService.kt +++ b/krpc/krpc-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/server/internal/RPCServerService.kt @@ -5,7 +5,7 @@ package kotlinx.rpc.krpc.server.internal import kotlinx.coroutines.* -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.RPCMethodClassArguments import kotlinx.rpc.internal.qualifiedClassName import kotlinx.rpc.internal.utils.map.ConcurrentHashMap @@ -24,7 +24,7 @@ import kotlin.reflect.KClass import kotlin.reflect.KProperty import kotlin.reflect.full.callSuspend -internal class RPCServerService( +internal class RPCServerService( private val service: T, private val serviceKClass: KClass, override val config: RPCConfig.Server, diff --git a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KRPCTestService.kt b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KRPCTestService.kt index 60a03d617..ddd6ca0dd 100644 --- a/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KRPCTestService.kt +++ b/krpc/krpc-test/src/jvmMain/kotlin/kotlinx/rpc/krpc/test/KRPCTestService.kt @@ -7,10 +7,12 @@ package kotlinx.rpc.krpc.test import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService +import kotlinx.rpc.annotations.Rpc @Suppress("detekt.TooManyFunctions") -interface KRPCTestService : RPC { +@Rpc +interface KRPCTestService : RemoteService { suspend fun empty() suspend fun returnType(): String suspend fun simpleWithParams(name: String): String diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt index cebe69a4c..02e67ad2d 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/ProtocolTestBase.kt @@ -9,7 +9,8 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.job import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.test.TestScope -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.internal.utils.hex.hexToReadableBinary import kotlinx.rpc.krpc.RPCConfig import kotlinx.rpc.krpc.client.KRPCClient @@ -90,7 +91,8 @@ abstract class ProtocolTestBase { } } -interface ProtocolTestService : RPC { +@Rpc +interface ProtocolTestService : RemoteService { suspend fun sendRequest() } diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt index 54f3a416d..998e87975 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/SamplingService.kt @@ -9,7 +9,8 @@ package org.jetbrains.krpc.test.api.util import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import kotlinx.rpc.RPC +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 @@ -21,7 +22,8 @@ data class SamplingData( val data: String, ) -interface SamplingService : RPC { +@Rpc +interface SamplingService : RemoteService { suspend fun echo(arg1: String, data: SamplingData): SamplingData suspend fun clientStream(flow: Flow): List diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt index 0e0dedaab..ed44cd4f5 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/TransportTest.kt @@ -7,6 +7,7 @@ package kotlinx.rpc.krpc.test import junit.framework.TestCase.assertEquals import kotlinx.coroutines.* import kotlinx.rpc.* +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.krpc.RPCConfigBuilder import kotlinx.rpc.krpc.rpcClientConfig import kotlinx.rpc.krpc.rpcServerConfig @@ -18,11 +19,13 @@ import kotlin.test.Test import kotlin.test.assertFailsWith import kotlin.test.assertTrue -interface Echo : RPC { +@Rpc +interface Echo : RemoteService { suspend fun echo(message: String): String } -interface Second : RPC { +@Rpc +interface Second : RemoteService { suspend fun second(message: String): String } @@ -232,7 +235,7 @@ class TransportTest { assertTrue(echoServices.single().coroutineContext.job.isCancelled) } - private inline fun RPCServer.registerServiceAndReturn( + private inline fun RPCServer.registerServiceAndReturn( crossinline body: (CoroutineContext) -> Impl, ): List { val instances = mutableListOf() 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 d71934dd5..5ed99e372 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 @@ -11,7 +11,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.internal.utils.hex.hexToByteArrayInternal import kotlinx.rpc.internal.utils.hex.hexToReadableBinary import kotlinx.rpc.krpc.RPCTransportMessage @@ -246,7 +246,7 @@ private class WireToolkit(scope: CoroutineScope, format: SamplingFormat, val log DumpLoggerContainer.set(dumpLogger) } - private inline fun Service.withConsistentServiceId(): Service = apply { + private inline fun Service.withConsistentServiceId(): Service = apply { val clazz = this::class.java val prop = clazz .declaredFields diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt index 37c168e25..dcd83bb7c 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/cancellation/CancellationService.kt @@ -7,13 +7,15 @@ package kotlinx.rpc.krpc.test.cancellation import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.rpc.RPC +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 -interface CancellationService : RPC { +@Rpc +interface CancellationService : RemoteService { suspend fun longRequest() suspend fun serverDelay(millis: Long) diff --git a/ksp-plugin/src/main/kotlin/kotlinx/rpc/codegen/ACodeGenerationException.kt b/ksp-plugin/src/main/kotlin/kotlinx/rpc/codegen/ACodeGenerationException.kt index 3eddf7e41..72814052e 100644 --- a/ksp-plugin/src/main/kotlin/kotlinx/rpc/codegen/ACodeGenerationException.kt +++ b/ksp-plugin/src/main/kotlin/kotlinx/rpc/codegen/ACodeGenerationException.kt @@ -29,7 +29,7 @@ class FieldExtensionReceiverCodeGenerationException(declaration: KSDeclaration? ACodeGenerationException("RPC Service field can not have extension receiver", declaration) class ForbiddenFieldTypeCodeGenerationException(declaration: KSDeclaration? = null) : ACodeGenerationException( - initMessage = "Only Flow, SharedFlow and StateFlow fields are allowed in RPC Service interfaces", + initMessage = "Only Flow, SharedFlow and StateFlow fields are allowed in a RemoteService", declaration = declaration ) 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 07d5368b1..4616c7425 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,9 @@ 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.RPC] + 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 @@ -1060,16 +1062,16 @@ FILE fqName: fileName:/customParameterTypes.kt : kotlin.String 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.RPC + 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.RPC + 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.RPC + public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService $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 @@ -1080,11 +1082,11 @@ FILE fqName: fileName:/customParameterTypes.kt PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] overridden: public abstract coroutineContext: kotlin.coroutines.CoroutineContext - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RPC) returnType:kotlin.coroutines.CoroutineContext [fake_override] + 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.RPC - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RPC + 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 16083527f..8f4220e9c 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 } } - public abstract interface BoxService : R|kotlinx/rpc/RPC| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { 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 4bda56322..e8f0b5472 100644 --- a/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt +++ b/tests/compiler-plugin-tests/src/testData/box/customParameterTypes.kt @@ -5,14 +5,16 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking import kotlinx.serialization.Serializable -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.withService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient @Serializable data class TestData(val value: String) -interface BoxService : RPC { +@Rpc +interface BoxService : RemoteService { 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 index 4746e26ad..dc3e1a5a7 100644 --- a/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/fields.fir.ir.txt @@ -1,5 +1,7 @@ FILE fqName: fileName:/fields.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RPC] + 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 @@ -244,25 +246,25 @@ FILE fqName: fileName:/fields.kt $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.RPC + 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.RPC + 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.RPC + 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 - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RPC) returnType:kotlin.coroutines.CoroutineContext [fake_override] + 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.RPC - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RPC + 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] diff --git a/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt b/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt index 4fd39dbf1..ec381714c 100644 --- a/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt +++ b/tests/compiler-plugin-tests/src/testData/box/fields.fir.txt @@ -1,5 +1,5 @@ FILE: fields.kt - public abstract interface BoxService : R|kotlinx/rpc/RPC| { + @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| diff --git a/tests/compiler-plugin-tests/src/testData/box/fields.kt b/tests/compiler-plugin-tests/src/testData/box/fields.kt index 1c35cdc9a..0b08d6759 100644 --- a/tests/compiler-plugin-tests/src/testData/box/fields.kt +++ b/tests/compiler-plugin-tests/src/testData/box/fields.kt @@ -4,11 +4,13 @@ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.withService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient -interface BoxService : RPC { +@Rpc +interface BoxService : RemoteService { val plainFlow: Flow val sharedFlow: SharedFlow 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 761e44206..e5748a0e8 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,7 @@ FILE fqName: fileName:/flowParameter.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RPC] + 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 @@ -477,16 +479,16 @@ FILE fqName: fileName:/flowParameter.kt : kotlin.String 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.RPC + 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.RPC + 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.RPC + public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService $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 @@ -494,11 +496,11 @@ FILE fqName: fileName:/flowParameter.kt PROPERTY FAKE_OVERRIDE name:coroutineContext visibility:public modality:ABSTRACT [fake_override,val] overridden: public abstract coroutineContext: kotlin.coroutines.CoroutineContext - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RPC) returnType:kotlin.coroutines.CoroutineContext [fake_override] + 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.RPC - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RPC + 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 bb9b6aa26..bbcf6fbd8 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 - public abstract interface BoxService : R|kotlinx/rpc/RPC| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { 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 06362e391..bf1be1abf 100644 --- a/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt +++ b/tests/compiler-plugin-tests/src/testData/box/flowParameter.kt @@ -4,11 +4,13 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.withService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient -interface BoxService : RPC { +@Rpc +interface BoxService : RemoteService { // 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 df3fa624e..765920175 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,8 @@ Module: lib FILE fqName: fileName:/module_lib_multiModule.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RPC] + 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 @@ -228,27 +230,27 @@ FILE fqName: fileName:/module_lib_multiModule.kt : kotlin.String 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.RPC + 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.RPC + 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.RPC + public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService $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 - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RPC) returnType:kotlin.coroutines.CoroutineContext [fake_override] + 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.RPC - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RPC + 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 28244d13f..92835fc84 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 - public abstract interface BoxService : R|kotlinx/rpc/RPC| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { 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 6d89cfb3b..a575bb86d 100644 --- a/tests/compiler-plugin-tests/src/testData/box/multiModule.kt +++ b/tests/compiler-plugin-tests/src/testData/box/multiModule.kt @@ -4,16 +4,18 @@ // MODULE: lib -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService +import kotlinx.rpc.annotations.Rpc -interface BoxService : RPC { +@Rpc +interface BoxService : RemoteService { suspend fun simple(): String } // MODULE: main(lib) import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RPC +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 e994089be..8f07a49d4 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,7 @@ FILE fqName: fileName:/simple.kt - CLASS INTERFACE name:BoxService modality:ABSTRACT visibility:public superTypes:[kotlinx.rpc.RPC] + 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 @@ -227,27 +229,27 @@ FILE fqName: fileName:/simple.kt : kotlin.String 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.RPC + 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.RPC + 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.RPC + public open fun toString (): kotlin.String declared in kotlinx.rpc.RemoteService $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 - FUN FAKE_OVERRIDE name: visibility:public modality:ABSTRACT <> ($this:kotlinx.rpc.RPC) returnType:kotlin.coroutines.CoroutineContext [fake_override] + 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.RPC - $this: VALUE_PARAMETER name: type:kotlinx.rpc.RPC + 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 44770b129..dd09bd08f 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 - public abstract interface BoxService : R|kotlinx/rpc/RPC| { + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface BoxService : R|kotlinx/rpc/RemoteService| { 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 67a2488c1..637ba9990 100644 --- a/tests/compiler-plugin-tests/src/testData/box/simple.kt +++ b/tests/compiler-plugin-tests/src/testData/box/simple.kt @@ -3,11 +3,13 @@ */ import kotlinx.coroutines.runBlocking -import kotlinx.rpc.RPC +import kotlinx.rpc.RemoteService import kotlinx.rpc.withService +import kotlinx.rpc.annotations.Rpc import kotlinx.rpc.codegen.test.TestRpcClient -interface BoxService : RPC { +@Rpc +interface BoxService : RemoteService { suspend fun simple(): String }