From 909f8a2aa6958e675ae4aea7822b374e330d1621 Mon Sep 17 00:00:00 2001 From: Alexander Sysoev Date: Wed, 4 Dec 2024 14:29:29 +0100 Subject: [PATCH] Added compiler tests for generic checks --- .../rpc/codegen/FirRpcServiceGenerator.kt | 5 +- .../test/runners/DiagnosticTestGenerated.java | 6 + .../testData/diagnostics/rpcService.fir.txt | 128 ++++++++++++++++++ .../src/testData/diagnostics/rpcService.kt | 44 ++++++ 4 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt create mode 100644 tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcServiceGenerator.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcServiceGenerator.kt index 1482183d..3dcdd998 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcServiceGenerator.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcServiceGenerator.kt @@ -187,9 +187,10 @@ class FirRpcServiceGenerator( owner: FirClassSymbol<*>, name: Name, rpcServiceStubKey: RpcGeneratedStubKey, - ): FirClassLikeSymbol<*> { + ): FirClassLikeSymbol<*>? { val methodName = name.rpcMethodName - val rpcMethod = rpcServiceStubKey.functions.single { it.name == methodName } + val rpcMethod = rpcServiceStubKey.functions.singleOrNull { it.name == methodName } + ?: return null val rpcMethodClassKey = RpcGeneratedRpcMethodClassKey(rpcMethod) val classKind = if (rpcMethodClassKey.isObject) ClassKind.OBJECT else ClassKind.CLASS diff --git a/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/DiagnosticTestGenerated.java b/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/DiagnosticTestGenerated.java index 5d0bedf4..995639c6 100644 --- a/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/DiagnosticTestGenerated.java +++ b/tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/DiagnosticTestGenerated.java @@ -36,6 +36,12 @@ public void testRpcChecked() { runTest("src/testData/diagnostics/rpcChecked.kt"); } + @Test + @TestMetadata("rpcService.kt") + public void testRpcService() { + runTest("src/testData/diagnostics/rpcService.kt"); + } + @Test @TestMetadata("strictMode.kt") public void testStrictMode() { diff --git a/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt new file mode 100644 index 00000000..36f04f50 --- /dev/null +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.fir.txt @@ -0,0 +1,128 @@ +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| { + public abstract fun hello(): R|kotlin/Unit| + + public abstract suspend fun generic(a: R|T|): R|kotlin/Unit| + + public abstract suspend fun |> generic2(a: R|T|, b: R|kotlin/Int|, c: R|T4|, t2: R|T2|): R|T3| + + public abstract suspend fun sameName(): R|kotlin/Unit| + + public abstract suspend fun sameName(a: R|kotlin/Int|): R|kotlin/Unit| + + public abstract suspend fun sameName(a: R|kotlin/Int|, b: R|kotlin/Int|): R|kotlin/Unit| + + public abstract suspend fun sameName(a: R|kotlin/Int|, b: R|kotlin/Int|, c: R|kotlin/Int|): R|kotlin/Unit| + + public abstract suspend fun sameName2(): R|kotlin/Unit| + + public abstract suspend fun sameName2(a: R|kotlin/Int|): R|kotlin/Unit| + + public final class $rpcServiceStub : R|kotlin/Any| { + @R|kotlinx/serialization/Serializable|() public final object hello$rpcMethod : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|MyService.$rpcServiceStub.hello$rpcMethod| { + super() + } + + } + + @R|kotlinx/serialization/Serializable|() public final class generic$rpcMethod : R|kotlin/Any| { + public final val a: R|T| + public get(): R|T| + + public constructor(a: R|T|): R|MyService.$rpcServiceStub.generic$rpcMethod| + + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|MyService.$rpcServiceStub.generic$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|MyService.$rpcServiceStub.generic$rpcMethod|): R|kotlin/Unit| + + public final override fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|MyService.$rpcServiceStub.generic$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|MyService.$rpcServiceStub.generic$rpcMethod.$serializer| { + super() + } + + } + + } + + @R|kotlinx/serialization/Serializable|() public final class generic2$rpcMethod : R|kotlin/Any| { + public final val a: R|T| + public get(): R|T| + + public final val b: R|kotlin/Int| + public get(): R|kotlin/Int| + + public final val c: R|T4| + public get(): R|T4| + + public final val t2: R|T2| + public get(): R|T2| + + public constructor(a: R|T|, b: R|kotlin/Int|, c: R|T4|, t2: R|T2|): R|MyService.$rpcServiceStub.generic2$rpcMethod| + + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|MyService.$rpcServiceStub.generic2$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|MyService.$rpcServiceStub.generic2$rpcMethod|): R|kotlin/Unit| + + public final override fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|MyService.$rpcServiceStub.generic2$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|MyService.$rpcServiceStub.generic2$rpcMethod.$serializer| { + super() + } + + } + + } + + public final companion object Companion : R|kotlin/Any| { + } + + } + + } + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + public final class $rpcServiceStub : R|kotlin/Any| { + public final companion object Companion : R|kotlin/Any| { + } + + } + + } + @R|kotlinx/rpc/annotations/Rpc|() public abstract interface MyServiceT2 : R|kotlin/Any|, R|kotlinx/rpc/RemoteService| { + 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 new file mode 100644 index 00000000..deca0222 --- /dev/null +++ b/tests/compiler-plugin-tests/src/testData/diagnostics/rpcService.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:OptIn(ExperimentalRpcApi::class) + +import kotlin.coroutines.* +import kotlinx.coroutines.* +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 +interface MyService { + fun hello() + + suspend fun generic(a: T) + + suspend fun > generic2(a: T, b: Int, c: T4, t2: T2): T3 + + suspend fun sameName() + + suspend fun sameName(a: Int) + + suspend fun sameName(a: Int, b: Int) + + suspend fun sameName(a: Int, b: Int, c: Int) + + suspend fun sameName2() + + suspend fun sameName2(a: Int) +} + +@Rpc +interface MyServiceT + +@Rpc +interface MyServiceT2