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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.codegen.extension
Expand All @@ -9,14 +9,15 @@ 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.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer

internal class RpcIrServiceProcessor(
@Suppress("unused")
private val logger: MessageCollector,
) : IrElementTransformer<RpcIrContext> {
override fun visitClass(declaration: IrClass, data: RpcIrContext): IrStatement {
if (declaration.hasAnnotation(RpcClassId.rpcAnnotation)) {
if (declaration.hasAnnotation(RpcClassId.rpcAnnotation) && declaration.isInterface) {
processService(declaration, data)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 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.FirClass
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
Expand All @@ -23,7 +25,10 @@ abstract class FirRpcSupertypeGeneratorAbstract(
}

override fun needTransformSupertypes(declaration: FirClassLikeDeclaration): Boolean {
return session.predicateBasedProvider.matches(FirRpcPredicates.rpc, declaration)
return session.predicateBasedProvider.matches(
predicate = FirRpcPredicates.rpc,
declaration = declaration,
) && declaration is FirClass && declaration.isInterface
}

protected fun computeAdditionalSupertypesAbstract(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 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.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.UnresolvedExpressionTypeAccess
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
Expand All @@ -23,16 +26,31 @@ fun FirClassSymbol<*>.isRemoteService(session: FirSession): Boolean = resolvedSu
it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface)
}

fun FirBasedSymbol<*>.rpcAnnotationSource(session: FirSession): KtSourceElement? {
return rpcAnnotation(session)?.source
fun FirBasedSymbol<*>.rpcAnnotationSource(
session: FirSession,
predicate: DeclarationPredicate,
classId: ClassId?,
): KtSourceElement? {
return rpcAnnotation(session, predicate, classId)?.source
}

fun FirBasedSymbol<*>.rpcAnnotation(session: FirSession): FirAnnotation? {
return resolvedCompilerAnnotationsWithClassIds.rpcAnnotation(session)
fun FirBasedSymbol<*>.rpcAnnotation(
session: FirSession,
predicate: DeclarationPredicate,
classId: ClassId?,
): FirAnnotation? {
return resolvedCompilerAnnotationsWithClassIds.rpcAnnotation(session, predicate, classId)
}

fun List<FirAnnotation>.rpcAnnotation(session: FirSession): FirAnnotation? {
return getAnnotationByClassId(RpcClassId.rpcAnnotation, session)
@OptIn(UnresolvedExpressionTypeAccess::class)
fun List<FirAnnotation>.rpcAnnotation(session: FirSession, predicate: DeclarationPredicate, classId: ClassId?): FirAnnotation? {
return find {
vsApi {
it.coneTypeOrNull?.toClassSymbolVS(session)?.let { declaration ->
session.predicateBasedProvider.matches(predicate, declaration)
} == true || (classId != null && it.toAnnotationClassId(session) == classId)
}
}
}

fun FirClassSymbol<*>.remoteServiceSupertypeSource(session: FirSession): KtSourceElement? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package kotlinx.rpc.codegen.checkers
import kotlinx.rpc.codegen.FirCheckersContext
import kotlinx.rpc.codegen.FirRpcPredicates
import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcDiagnostics
import kotlinx.rpc.codegen.common.RpcClassId
import kotlinx.rpc.codegen.isRemoteService
import kotlinx.rpc.codegen.remoteServiceSupertypeSource
import kotlinx.rpc.codegen.rpcAnnotation
Expand All @@ -31,12 +32,22 @@ class FirRpcAnnotationChecker(private val ctx: FirCheckersContext) : FirRegularC
val rpcAnnotated = context.session.predicateBasedProvider.matches(FirRpcPredicates.rpc, declaration)
val rpcMetaAnnotated = context.session.predicateBasedProvider.matches(FirRpcPredicates.rpcMeta, declaration)

if (!declaration.isInterface && declaration.classKind != ClassKind.ANNOTATION_CLASS && rpcMetaAnnotated) {
val isMetaAnnotated = declaration.classKind != ClassKind.ANNOTATION_CLASS

if (!declaration.isInterface && isMetaAnnotated && rpcMetaAnnotated) {
reporter.reportOn(
source = declaration.symbol.rpcAnnotationSource(context.session),
source = declaration.symbol.rpcAnnotationSource(
session = context.session,
predicate = FirRpcPredicates.rpcMeta,
classId = RpcClassId.rpcAnnotation,
),
factory = FirRpcDiagnostics.WRONG_RPC_ANNOTATION_TARGET,
context = context,
a = declaration.symbol.rpcAnnotation(context.session)?.resolvedType
a = declaration.symbol.rpcAnnotation(
session = context.session,
predicate = FirRpcPredicates.rpc,
classId = RpcClassId.rpcAnnotation,
)?.resolvedType
?: error("Unexpected unresolved annotation type for declaration: ${declaration.symbol.classId.asSingleFqName()}"),
)
}
Expand All @@ -49,9 +60,13 @@ class FirRpcAnnotationChecker(private val ctx: FirCheckersContext) : FirRegularC
)
}

if (rpcAnnotated && !ctx.serializationIsPresent) {
if (rpcAnnotated && !ctx.serializationIsPresent && isMetaAnnotated) {
reporter.reportOn(
source = declaration.symbol.rpcAnnotationSource(context.session),
source = declaration.symbol.rpcAnnotationSource(
session = context.session,
predicate = FirRpcPredicates.rpcMeta,
classId = RpcClassId.rpcAnnotation,
),
factory = FirRpcDiagnostics.MISSING_SERIALIZATION_MODULE,
context = context,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import org.jetbrains.kotlin.diagnostics.error0
import org.jetbrains.kotlin.diagnostics.error1
import org.jetbrains.kotlin.diagnostics.error2
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.warning0
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry

object FirRpcDiagnostics {
val MISSING_RPC_ANNOTATION by error0<KtAnnotationEntry>()
val MISSING_SERIALIZATION_MODULE by warning0<KtAnnotationEntry>()
val MISSING_SERIALIZATION_MODULE by error0<KtAnnotationEntry>()
val WRONG_RPC_ANNOTATION_TARGET by error1<KtAnnotationEntry, ConeKotlinType>()
val CHECKED_ANNOTATION_VIOLATION by error1<KtAnnotationEntry, ConeKotlinType>()
val NON_SUSPENDING_REQUEST_WITHOUT_STREAMING_RETURN_TYPE by error0<PsiElement>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.internal
Expand All @@ -13,8 +13,12 @@ private const val RPC_SERVICE_STUB_SIMPLE_NAME = "\$rpcServiceStub"
internal actual fun <@Rpc T : Any> internalServiceDescriptorOf(kClass: KClass<T>): Any? {
val className = "${kClass.qualifiedName}\$$RPC_SERVICE_STUB_SIMPLE_NAME"

return kClass.java.classLoader
.loadClass(className)
?.kotlin
?.companionObjectInstance
return try {
return kClass.java.classLoader
.loadClass(className)
?.kotlin
?.companionObjectInstance
} catch (_: ClassNotFoundException) {
null
}
}
5 changes: 0 additions & 5 deletions krpc/krpc-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ kotlin {
dependencies {
api(projects.krpc.krpcCore)

// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
implementation(projects.core)
implementation(projects.utils)
implementation(projects.krpc.krpcSerialization.krpcSerializationCore)

implementation(libs.serialization.core)
implementation(libs.kotlin.reflect)

Expand Down
3 changes: 0 additions & 3 deletions krpc/krpc-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ kotlin {
api(projects.krpc.krpcSerialization.krpcSerializationCore)
implementation(projects.krpc.krpcLogging)

// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
implementation(projects.utils)

api(libs.coroutines.core)
implementation(libs.serialization.core)
implementation(libs.kotlin.reflect)
Expand Down
4 changes: 0 additions & 4 deletions krpc/krpc-ktor/krpc-ktor-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ kotlin {
api(projects.krpc.krpcClient)
api(projects.krpc.krpcKtor.krpcKtorCore)

// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
implementation(projects.krpc.krpcCore)
implementation(projects.core)

api(libs.ktor.client.core)
api(libs.ktor.client.websockets)

Expand Down
4 changes: 0 additions & 4 deletions krpc/krpc-ktor/krpc-ktor-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ kotlin {
dependencies {
api(projects.krpc.krpcCore)

// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
implementation(projects.core)
implementation(projects.utils)

implementation(libs.ktor.websockets)
implementation(libs.coroutines.core)
implementation(libs.serialization.core)
Expand Down
5 changes: 0 additions & 5 deletions krpc/krpc-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ kotlin {
dependencies {
api(projects.krpc.krpcCore)

// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
implementation(projects.core)
implementation(projects.utils)
implementation(projects.krpc.krpcSerialization.krpcSerializationCore)

implementation(projects.krpc.krpcLogging)

implementation(libs.serialization.core)
Expand Down
6 changes: 3 additions & 3 deletions publishLocal.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/bin/bash

#
# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
# Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
#

set -euxo pipefail

./gradlew publishAllPublicationsToBuildRepoRepository
./gradlew -p compiler-plugin publishAllPublicationsToBuildRepoRepository
./gradlew -p gradle-plugin publishAllPublicationsToBuildRepoRepository
./gradlew -p compiler-plugin publishAllPublicationsToBuildRepoRepository --no-configuration-cache
./gradlew -p gradle-plugin publishAllPublicationsToBuildRepoRepository --no-configuration-cache
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.Ignore;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.File;
Expand All @@ -21,7 +19,6 @@
@SuppressWarnings("all")
@TestMetadata("src/testData/box")
@TestDataPath("$PROJECT_ROOT")
@Disabled("KRPC-137")
public class BoxTestGenerated extends AbstractBoxTest {
@Test
public void testAllFilesPresentInBox() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.regex.Pattern;

/** This class is generated by {@link kotlinx.rpc.codegen.test.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("src/testData/diagnostics")
@TestDataPath("$PROJECT_ROOT")
@Disabled("KRPC-137")
public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
@Test
public void testAllFilesPresentInDiagnostics() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@

package kotlinx.rpc.codegen.test

import kotlinx.rpc.codegen.test.runners.AbstractBoxTest
import kotlinx.rpc.codegen.test.runners.AbstractDiagnosticTest
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5

fun main() {
generateTestGroupSuiteWithJUnit5 {
testGroup(testDataRoot = "src/testData", testsRoot = "src/test-gen") {
// KRPC-137 Remove temporary explicit dependencies in 2.1.10 and unmute compiler tests
// testClass<AbstractDiagnosticTest> {
// model("diagnostics")
// }
testClass<AbstractDiagnosticTest> {
model("diagnostics")
}

// testClass<AbstractBoxTest> {
// model("box")
// }
testClass<AbstractBoxTest> {
model("box")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.rpc.codegen.test.services
Expand All @@ -22,12 +22,12 @@ private class RuntimeDependency(
val name: String,
) {
val filter = FilenameFilter { _, filename ->
filename.startsWith(name) && filename.endsWith(".jar")
filename.startsWith(name) && filename.endsWith(".jar") && !filename.contains("sources")
}
}

private object RpcClasspathProvider {
private val TEST_RUNTIME = RuntimeDependency("build/libs/", "compiler-plugin-test")
private val TEST_RUNTIME = RuntimeDependency("build/libs/", "compiler-plugin-tests")
private val KRPC_CORE_JVM = RuntimeDependency("$globalRootDir/krpc/krpc-core/build/libs/", "krpc-core-jvm")
private val CORE_JVM = RuntimeDependency("$globalRootDir/core/build/libs/", "core-jvm")
private val UTILS_JVM = RuntimeDependency("$globalRootDir/utils/build/libs/", "utils-jvm")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,23 @@ FILE: rpcChecked.kt
R|kotlinx/rpc/descriptor/serviceDescriptorOf|<R|NotAService|>()
R|kotlinx/rpc/descriptor/serviceDescriptorOf|<R|T|>()
}
@R|kotlinx/rpc/annotations/Rpc|() public final annotation class Grpc : R|kotlin/Annotation| {
public constructor(): R|Grpc| {
super<R|kotlin/Any|>()
}

}
@R|Grpc|() public abstract interface MyGrpcService : R|kotlin/Any| {
}
@R|Grpc|() public final class WrongGrpcTarget : R|kotlin/Any| {
public constructor(): R|WrongGrpcTarget| {
super<R|kotlin/Any|>()
}

}
@R|kotlinx/rpc/annotations/Rpc|() public final class WrongRpcTarget : R|kotlin/Any| {
public constructor(): R|WrongRpcTarget| {
super<R|kotlin/Any|>()
}

}
Loading