Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {
alias(libs.plugins.conventions.kover)
alias(libs.plugins.conventions.gradle.doctor)
alias(libs.plugins.atomicfu)
id("build-util")
}

configureProjectReport()
Expand Down
1 change: 1 addition & 0 deletions compiler-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import util.whenForIde

plugins {
alias(libs.plugins.conventions.gradle.doctor)
id("build-util")
}

val rpcVersion: String = libs.versions.kotlinx.rpc.get()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.name.Name
object RpcClassId {
val remoteServiceInterface = ClassId(FqName("kotlinx.rpc"), Name.identifier("RemoteService"))
val rpcAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("Rpc"))
val checkedTypeAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("CheckedTypeAnnotation"))

val serializableAnnotation = ClassId(FqName("kotlinx.serialization"), Name.identifier("Serializable"))
val contextualAnnotation = ClassId(FqName("kotlinx.serialization"), Name.identifier("Contextual"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,32 @@

package kotlinx.rpc.codegen

import kotlinx.rpc.codegen.checkers.FirCheckedAnnotationHelper
import kotlinx.rpc.codegen.checkers.FirRpcDeclarationCheckers
import kotlinx.rpc.codegen.checkers.FirRpcExpressionCheckers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol

class FirRpcCheckers(session: FirSession) : FirAdditionalCheckersExtension(session) {
class FirRpcCheckers(session: FirSession, serializationIsPresent: Boolean) : FirAdditionalCheckersExtension(session) {
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
register(FirRpcPredicates.rpc)
register(FirRpcPredicates.checkedAnnotationMeta)
}

override val declarationCheckers: DeclarationCheckers = FirRpcDeclarationCheckers
private val ctx = FirCheckersContext(session, serializationIsPresent)

override val declarationCheckers: DeclarationCheckers = FirRpcDeclarationCheckers(ctx)
override val expressionCheckers: ExpressionCheckers = FirRpcExpressionCheckers(ctx)
}

class FirCheckersContext(private val session: FirSession, val serializationIsPresent: Boolean) {
val typeParametersCache = session.firCachesFactory.createCache { typeParameter: FirTypeParameterSymbol ->
FirCheckedAnnotationHelper.checkedAnnotations(session, typeParameter)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package kotlinx.rpc.codegen

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

+CFactory { FirRpcCheckers(it) }
+GFactory { FirRpcServiceGenerator(it, logger) }
val serializationIsPresent = try {
Class.forName("org.jetbrains.kotlinx.serialization.compiler.fir.SerializationFirResolveExtension")
+GFactory { FirRpcServiceGenerator(it, logger) }
true
} catch (_ : ClassNotFoundException) {
logger.report(
severity = CompilerMessageSeverity.INFO,
message = "Serialization plugin is not found, so generated services are not available",
)
false
}

+CFactory { FirRpcCheckers(it, serializationIsPresent) }

+SFactory { FirRpcSupertypeGenerator(it, logger) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ object FirRpcPredicates {
internal val rpc = DeclarationPredicate.create {
annotated(RpcClassId.rpcAnnotation.asSingleFqName()) // @Rpc
}

internal val checkedAnnotationMeta = DeclarationPredicate.create {
metaAnnotated(RpcClassId.checkedTypeAnnotation.asSingleFqName(), includeItself = false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ class FirRpcServiceGenerator(
@Suppress("unused")
private val logger: MessageCollector,
) : FirDeclarationGenerationExtension(session) {
private val serializationExtension = SerializationFirResolveExtension(session)
private val serializationExtension by lazy {
SerializationFirResolveExtension(session)
}

private val isJvmOrMetadata = !session.moduleData.platform.run { isJs() || isWasm() || isNative() }

override fun FirDeclarationPredicateRegistrar.registerPredicates() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package kotlinx.rpc.codegen

import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
Expand All @@ -16,10 +18,20 @@ interface FirVersionSpecificApi {
delegatedTypeRef: FirTypeRef? = null,
): FirResolvedTypeRef

fun ConeKotlinType.toClassSymbolVS(
session: FirSession,
): FirClassSymbol<*>?

var FirResolvedTypeRefBuilder.coneTypeVS: ConeKotlinType
}

fun <T> vsApi(body: FirVersionSpecificApi.() -> T) : T {
val klass = Class.forName("kotlinx.rpc.codegen.FirVersionSpecificApiImpl")
return (klass.kotlin.objectInstance as FirVersionSpecificApi).body()
val vsApiClass by lazy {
runCatching {
Class.forName("kotlinx.rpc.codegen.FirVersionSpecificApiImpl")
}.getOrNull()
}

inline fun <T> vsApi(body: FirVersionSpecificApi.() -> T): T {
val kClass = vsApiClass?.kotlin ?: error("FirVersionSpecificApi is not present")
return (kClass.objectInstance as FirVersionSpecificApi).body()
}
Loading