Skip to content

Commit 671990d

Browse files
committed
Updated code to use @Rpc annotation type-safety
1 parent 1cf8305 commit 671990d

File tree

33 files changed

+101
-53
lines changed

33 files changed

+101
-53
lines changed

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcCheckers.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ import org.jetbrains.kotlin.fir.caches.firCachesFactory
1616
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
1717
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
1818

19-
class FirRpcCheckers(session: FirSession) : FirAdditionalCheckersExtension(session) {
19+
class FirRpcCheckers(session: FirSession, serializationIsPresent: Boolean) : FirAdditionalCheckersExtension(session) {
2020
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
2121
register(FirRpcPredicates.rpc)
2222
register(FirRpcPredicates.checkedAnnotationMeta)
2323
}
2424

25-
private val ctx = FirCheckersContext(session)
25+
private val ctx = FirCheckersContext(session, serializationIsPresent)
2626

2727
override val declarationCheckers: DeclarationCheckers = FirRpcDeclarationCheckers(ctx)
2828
override val expressionCheckers: ExpressionCheckers = FirRpcExpressionCheckers(ctx)
2929
}
3030

31-
class FirCheckersContext(private val session: FirSession) {
31+
class FirCheckersContext(private val session: FirSession, val serializationIsPresent: Boolean) {
3232
val typeParametersCache = session.firCachesFactory.createCache { typeParameter: FirTypeParameterSymbol ->
3333
FirCheckedAnnotationHelper.checkedAnnotations(session, typeParameter)
3434
}

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcExtensionRegistrar.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package kotlinx.rpc.codegen
66

77
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
8+
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
89
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
910
import org.jetbrains.kotlin.config.CompilerConfiguration
1011
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
@@ -16,8 +17,20 @@ class FirRpcExtensionRegistrar(private val configuration: CompilerConfiguration)
1617
override fun ExtensionRegistrarContext.configurePlugin() {
1718
val logger = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
1819

19-
+CFactory { FirRpcCheckers(it) }
20-
+GFactory { FirRpcServiceGenerator(it, logger) }
20+
val serializationIsPresent = try {
21+
Class.forName("org.jetbrains.kotlinx.serialization.compiler.fir.SerializationFirResolveExtension")
22+
+GFactory { FirRpcServiceGenerator(it, logger) }
23+
true
24+
} catch (_ : ClassNotFoundException) {
25+
logger.report(
26+
severity = CompilerMessageSeverity.INFO,
27+
message = "Serialization plugin is not found, so generated services are not available",
28+
)
29+
false
30+
}
31+
32+
+CFactory { FirRpcCheckers(it, serializationIsPresent) }
33+
2134
+SFactory { FirRpcSupertypeGenerator(it, logger) }
2235
}
2336
}

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirRpcServiceGenerator.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ class FirRpcServiceGenerator(
6767
@Suppress("unused")
6868
private val logger: MessageCollector,
6969
) : FirDeclarationGenerationExtension(session) {
70-
private val serializationExtension = SerializationFirResolveExtension(session)
70+
private val serializationExtension by lazy {
71+
SerializationFirResolveExtension(session)
72+
}
73+
7174
private val isJvmOrMetadata = !session.moduleData.platform.run { isJs() || isWasm() || isNative() }
7275

7376
override fun FirDeclarationPredicateRegistrar.registerPredicates() {

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcAnnotationChecker.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package kotlinx.rpc.codegen.checkers
66

7+
import kotlinx.rpc.codegen.FirCheckersContext
78
import kotlinx.rpc.codegen.FirRpcPredicates
89
import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcDiagnostics
910
import kotlinx.rpc.codegen.isRemoteService
@@ -18,7 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
1819
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
1920
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
2021

21-
object FirRpcAnnotationChecker : FirRegularClassChecker(MppCheckerKind.Common) {
22+
class FirRpcAnnotationChecker(private val ctx: FirCheckersContext) : FirRegularClassChecker(MppCheckerKind.Common) {
2223
override fun check(
2324
declaration: FirRegularClass,
2425
context: CheckerContext,
@@ -41,5 +42,13 @@ object FirRpcAnnotationChecker : FirRegularClassChecker(MppCheckerKind.Common) {
4142
context = context,
4243
)
4344
}
45+
46+
if (rpcAnnotated && !ctx.serializationIsPresent) {
47+
reporter.reportOn(
48+
source = declaration.symbol.rpcAnnotationSource(context.session),
49+
factory = FirRpcDiagnostics.MISSING_SERIALIZATION_MODULE,
50+
context = context,
51+
)
52+
}
4453
}
4554
}

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirRpcDeclarationCheckers.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChec
1515

1616
class FirRpcDeclarationCheckers(ctx: FirCheckersContext) : DeclarationCheckers() {
1717
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
18-
FirRpcAnnotationChecker,
18+
FirRpcAnnotationChecker(ctx),
1919
)
2020

2121
override val classCheckers: Set<FirClassChecker> = setOf(

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ package kotlinx.rpc.codegen.checkers.diagnostics
77
import org.jetbrains.kotlin.diagnostics.error0
88
import org.jetbrains.kotlin.diagnostics.error1
99
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
10+
import org.jetbrains.kotlin.diagnostics.warning0
1011
import org.jetbrains.kotlin.fir.types.ConeKotlinType
1112
import org.jetbrains.kotlin.psi.KtAnnotationEntry
1213

1314
object FirRpcDiagnostics {
1415
val MISSING_RPC_ANNOTATION by error0<KtAnnotationEntry>()
16+
val MISSING_SERIALIZATION_MODULE by warning0<KtAnnotationEntry>()
1517
val WRONG_RPC_ANNOTATION_TARGET by error0<KtAnnotationEntry>()
1618
val CHECKED_ANNOTATION_VIOLATION by error1<KtAnnotationEntry, ConeKotlinType>()
1719

compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() {
1717
"must be annotated with kotlinx.rpc.annotations.Rpc",
1818
)
1919

20+
put(
21+
factory = FirRpcDiagnostics.MISSING_SERIALIZATION_MODULE,
22+
message = "Missing kotlinx.serialization plugin in the module. " +
23+
"Service generation will not be available. " +
24+
"Add kotlin(\"plugin.serialization\") to your build.gradle.kts plugins section."
25+
)
26+
2027
put(
2128
factory = FirRpcDiagnostics.WRONG_RPC_ANNOTATION_TARGET,
2229
message = "@Rpc annotation is only applicable to interfaces.",

core/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import util.applyAtomicfuPlugin
77
plugins {
88
alias(libs.plugins.conventions.kmp)
99
alias(libs.plugins.serialization)
10+
alias(libs.plugins.kotlinx.rpc)
1011
}
1112

1213
applyAtomicfuPlugin()

core/src/commonMain/kotlin/kotlinx/rpc/RpcServer.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package kotlinx.rpc
66

77
import kotlinx.coroutines.CoroutineScope
8+
import kotlinx.rpc.annotations.Rpc
89
import kotlin.coroutines.CoroutineContext
910
import kotlin.reflect.KClass
1011

@@ -27,7 +28,7 @@ public interface RpcServer : CoroutineScope {
2728
* @param serviceKClass [KClass] of the [Service].
2829
* @param serviceFactory function that produces the actual implementation of the service that will handle the calls.
2930
*/
30-
public fun <Service : RemoteService> registerService(
31+
public fun <@Rpc Service : Any> registerService(
3132
serviceKClass: KClass<Service>,
3233
serviceFactory: (CoroutineContext) -> Service,
3334
)
@@ -42,7 +43,7 @@ public interface RpcServer : CoroutineScope {
4243
* type `MyService` should be specified explicitly.
4344
* @param serviceFactory function that produces the actual implementation of the service that will handle the calls.
4445
*/
45-
public inline fun <reified Service : RemoteService> RpcServer.registerService(
46+
public inline fun <@Rpc reified Service : Any> RpcServer.registerService(
4647
noinline serviceFactory: (CoroutineContext) -> Service,
4748
) {
4849
registerService(Service::class, serviceFactory)

core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package kotlinx.rpc
66

7+
import kotlinx.rpc.annotations.Rpc
78
import kotlinx.rpc.descriptor.serviceDescriptorOf
89
import kotlinx.rpc.internal.RpcDeferredField
910
import kotlin.reflect.KClass
@@ -26,7 +27,7 @@ import kotlin.reflect.KClass
2627
* @param getter function that returns the field of the context service to wait for.
2728
* @return service filed after it was initialized.
2829
*/
29-
public suspend fun <T : RemoteService, R> T.awaitFieldInitialization(getter: T.() -> R): R {
30+
public suspend fun <@Rpc T : Any, R> T.awaitFieldInitialization(getter: T.() -> R): R {
3031
val field = getter()
3132

3233
if (field is RpcDeferredField<*>) {
@@ -55,7 +56,7 @@ public suspend fun <T : RemoteService, R> T.awaitFieldInitialization(getter: T.(
5556
* @param T service type
5657
* @return specified service, after all of it's field were initialized.
5758
*/
58-
public suspend inline fun <reified T : RemoteService> T.awaitFieldInitialization(): T {
59+
public suspend inline fun <@Rpc reified T : Any> T.awaitFieldInitialization(): T {
5960
return awaitFieldInitialization(T::class)
6061
}
6162

@@ -78,7 +79,7 @@ public suspend inline fun <reified T : RemoteService> T.awaitFieldInitialization
7879
* @param kClass [KClass] of the [T] type.
7980
* @return specified service, after all of it's field were initialized.
8081
*/
81-
public suspend fun <T : RemoteService> T.awaitFieldInitialization(kClass: KClass<T>): T {
82+
public suspend fun <@Rpc T : Any> T.awaitFieldInitialization(kClass: KClass<T>): T {
8283
serviceDescriptorOf(kClass)
8384
.getFields(this)
8485
.forEach { field ->

0 commit comments

Comments
 (0)