44
55package kotlinx.rpc.codegen
66
7- import kotlinx.rpc.codegen.common.ClassDeclarations
7+ import kotlinx.rpc.codegen.common.RpcClassId
88import kotlinx.rpc.codegen.common.RpcNames
99import kotlinx.rpc.codegen.common.rpcMethodClassName
1010import kotlinx.rpc.codegen.common.rpcMethodName
@@ -19,9 +19,7 @@ import org.jetbrains.kotlin.fir.FirSession
1919import org.jetbrains.kotlin.fir.declarations.FirFunction
2020import org.jetbrains.kotlin.fir.declarations.utils.isInterface
2121import org.jetbrains.kotlin.fir.declarations.utils.visibility
22- import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
23- import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
24- import org.jetbrains.kotlin.fir.extensions.NestedClassGenerationContext
22+ import org.jetbrains.kotlin.fir.extensions.*
2523import org.jetbrains.kotlin.fir.moduleData
2624import org.jetbrains.kotlin.fir.plugin.*
2725import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -44,22 +42,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage
4442 *
4543 * ## General idea
4644 *
47- * [getNestedClassifiersNames] should return a set of [Name]s to generate for.
48- * For these names [generateNestedClassLikeDeclaration] can generate some nested classes,
49- * which is what we need.
50- *
51- * But the catch is that we cannot say for sure, if we need to generate a class
52- * while in [getNestedClassifiersNames], but if we do not return anything
53- * [generateNestedClassLikeDeclaration] will not be called.
54- * We need to generate a class if only the current declaration is an RPC interface
55- * (inherits kotlinx.rpc.RPC). There is no resolved supertypes in [getNestedClassifiersNames],
56- * But, if the potentially generated class is not referenced anywhere,
57- * then [generateNestedClassLikeDeclaration] will already have supertypes resolved,
58- * so we can use this info to check the actual supertypes for RPC interface.
59- *
60- * So we always return a class name that may be generated.
61- * And then, in [generateNestedClassLikeDeclaration] we do the actual check with the resolved supertypes
62- * and generate a class if needed, otherwise returning null.
45+ * Detect `@Rpc` annotation - generate stub classes.
6346 *
6447 * ## Usage of kotlinx.serialization plugin
6548 *
@@ -68,38 +51,38 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackage
6851 * We generate classes that are marked `@Serializable`.
6952 * In that case, the serialization plugin will not be able to pick up those classes and process them accordingly.
7053 *
71- * That's why we have an instance of this plugin, which we call only on our generated classes - [serializationExtension]
54+ * That is why we have an instance of this plugin, which we call only on our generated classes - [serializationExtension]
7255 *
7356 * Not all the methods that we would like to call are public, so we access them via reflection:
7457 * - [generateCompanionDeclaration]
7558 * - [generateSerializerImplClass]
7659 *
7760 * This is basically copying the behavior of the actual plugin but isolated only for our generated classes.
7861 */
79- class FirRPCServiceGenerator (
62+ class FirRpcServiceGenerator (
8063 session : FirSession ,
8164 @Suppress(" unused" )
8265 private val logger : MessageCollector ,
8366) : FirDeclarationGenerationExtension(session) {
8467 private val serializationExtension = SerializationFirResolveExtension (session)
8568 private val isJvmOrMetadata = ! session.moduleData.platform.run { isJs() || isWasm() || isNative() }
8669
70+ override fun FirDeclarationPredicateRegistrar.registerPredicates () {
71+ register(FirRpcPredicates .rpc)
72+ }
73+
8774 /* *
8875 * Generates nested classifiers.
8976 *
9077 * They can be of three kinds:
9178 * - Nested Service Stub class.
9279 * In that case [classSymbol] will not have any RPC-generated [FirClassSymbol.origin].
93- * Rge only check we do - is we check that the declaration is an interface,
94- * and return [RpcNames.SERVICE_STUB_NAME].
95- * We cannot be sure if the declaration is actually an RPC service,
96- * because superTypes are not resolved during that stage.
97- * We postpone this check until [generateNestedClassLikeDeclaration].
80+ * The only check we do - presence of the `@Rpc` annotation and return [RpcNames.SERVICE_STUB_NAME].
9881 *
9982 * - Companion object of the service stub and method classes.
10083 * If we generate this companion object, we will have [FirClassSymbol.origin]
10184 * of [classSymbol] be set to [RPCGeneratedStubKey],
102- * because we are inside the previously generated service stub class.
85+ * because we're inside the previously generated service stub class.
10386 * The same goes for method classes too.
10487 * So we return [SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT]
10588 * and a list of method class names.
@@ -141,7 +124,7 @@ class FirRPCServiceGenerator(
141124 SpecialNames .DEFAULT_NAME_FOR_COMPANION_OBJECT
142125 }
143126
144- classSymbol.isInterface -> {
127+ classSymbol.isInterface && session.predicateBasedProvider.matches( FirRpcPredicates .rpc, classSymbol) -> {
145128 setOf (RpcNames .SERVICE_STUB_NAME )
146129 }
147130
@@ -158,7 +141,7 @@ class FirRPCServiceGenerator(
158141 override fun generateNestedClassLikeDeclaration (
159142 owner : FirClassSymbol <* >,
160143 name : Name ,
161- context : NestedClassGenerationContext
144+ context : NestedClassGenerationContext ,
162145 ): FirClassLikeSymbol <* >? {
163146 val rpcServiceStubKey = owner.generatedRpcServiceStubKey
164147 return when {
@@ -214,7 +197,7 @@ class FirRPCServiceGenerator(
214197 modality = Modality .FINAL
215198 }
216199
217- rpcMethodClass.addAnnotation(ClassDeclarations .serializableAnnotation, session)
200+ rpcMethodClass.addAnnotation(RpcClassId .serializableAnnotation, session)
218201
219202 /* *
220203 * Required to pass isSerializableObjectAndNeedsFactory check
@@ -264,18 +247,10 @@ class FirRPCServiceGenerator(
264247 }
265248
266249 /* *
267- * Checks whether the [owner] class is actually an RPC service
268- * (the supertypes are resolved at this stage,
269- * as the [RpcNames.SERVICE_STUB_NAME] is not references anywhere)
270- *
271- * If the [owner] is an RPC service - generates its service stub.
250+ * Generates [owner]'s service stub.
272251 * Scrapes the functions from the [owner] to generate method classes.
273252 */
274253 private fun generateRpcServiceStubClass (owner : FirClassSymbol <* >): FirRegularClassSymbol ? {
275- owner.resolvedSuperTypes.find {
276- it.classId == ClassDeclarations .rpcInterface
277- } ? : return null
278-
279254 @OptIn(SymbolInternals ::class )
280255 val functions = owner.fir.declarations
281256 .filterIsInstance<FirFunction >()
@@ -306,7 +281,7 @@ class FirRPCServiceGenerator(
306281 }
307282
308283 /* *
309- * If the method does not have any parameters, it is an object,
284+ * If the method doesn't have any parameters, it is an object,
310285 * and its only callable names are constructor, and the ones provided by the [serializationExtension].
311286 * Otherwise, the callable names are the names of the method parameters and the constructor.
312287 */
@@ -322,7 +297,7 @@ class FirRPCServiceGenerator(
322297 rpcMethodClassKey.rpcMethod.valueParameterSymbols.map { it.name }.toSet()
323298 } + SpecialNames .INIT
324299
325- // ^ init is necessary either way, as serialization does not add it for a serializable object
300+ // ^ init is necessary either way, as serialization doesn't add it for a serializable object
326301 }
327302
328303 override fun generateConstructors (context : MemberGenerationContext ): List <FirConstructorSymbol > {
@@ -361,7 +336,7 @@ class FirRPCServiceGenerator(
361336
362337 override fun generateProperties (
363338 callableId : CallableId ,
364- context : MemberGenerationContext ?
339+ context : MemberGenerationContext ? ,
365340 ): List <FirPropertySymbol > {
366341 context ? : return emptyList()
367342
@@ -399,14 +374,14 @@ class FirRPCServiceGenerator(
399374 returnType = valueParam.resolvedReturnType,
400375 ).apply {
401376 if (valueParam.resolvedReturnType.requiresContextual()) {
402- addAnnotation(ClassDeclarations .contextualAnnotation, session)
377+ addAnnotation(RpcClassId .contextualAnnotation, session)
403378 }
404379 }.symbol.let (::listOf)
405380 }
406381
407382 private fun ConeKotlinType.requiresContextual (): Boolean {
408383 return when (classId) {
409- ClassDeclarations .flow, ClassDeclarations .sharedFlow, ClassDeclarations .stateFlow -> true
384+ RpcClassId .flow, RpcClassId .sharedFlow, RpcClassId .stateFlow -> true
410385 else -> false
411386 }
412387 }
@@ -416,7 +391,7 @@ class FirRPCServiceGenerator(
416391 */
417392 override fun generateFunctions (
418393 callableId : CallableId ,
419- context : MemberGenerationContext ?
394+ context : MemberGenerationContext ? ,
420395 ): List <FirNamedFunctionSymbol > {
421396 val owner = context?.owner ? : return emptyList()
422397
0 commit comments