From cc0581cfa5cf3f140013ba75b7804200bbc9e309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Fri, 22 Sep 2023 16:03:59 +0200 Subject: [PATCH 01/17] K2 support --- buildSrc/src/main/kotlin/Config.kt | 6 +- packages/cinterop/build.gradle.kts | 1 + .../kotlin/internal/interop/RealmInterop.kt | 2 +- packages/library-base/build.gradle.kts | 11 +- .../io/realm/kotlin/compiler/Identifiers.kt | 3 + .../io/realm/kotlin/compiler/IrUtils.kt | 36 ++++-- .../RealmModelSyntheticMethodsExtension.kt | 8 +- .../io/realm/kotlin/compiler/Registrar.kt | 7 ++ .../compiler/k2/model/CompanionAugmenter.kt | 112 ++++++++++++++++++ .../compiler/k2/model/ModelObjectAugmenter.kt | 88 ++++++++++++++ .../compiler/k2/model/RealmApiAugumenter.kt | 39 ++++++ .../compiler/k2/model/RealmApiGeneratorKey.kt | 28 +++++ .../compiler/GenerationExtensionTest.kt | 1 + 13 files changed, 325 insertions(+), 17 deletions(-) create mode 100644 packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt create mode 100644 packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt create mode 100644 packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt create mode 100644 packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 3402f0e318..01617e49d8 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -119,14 +119,14 @@ object Versions { const val coroutines = "1.7.0" // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core const val datetime = "0.4.0" // https://github.com/Kotlin/kotlinx-datetime const val detektPlugin = "1.22.0-RC2" // https://github.com/detekt/detekt - const val dokka = "1.6.0" // https://github.com/Kotlin/dokka + const val dokka = "1.9.0" // https://github.com/Kotlin/dokka const val gradlePluginPublishPlugin = "0.15.0" // https://plugins.gradle.org/plugin/com.gradle.plugin-publish const val jmh = "1.34" // https://github.com/openjdk/jmh const val jmhPlugin = "0.6.6" // https://github.com/melix/jmh-gradle-plugin const val junit = "4.13.2" // https://mvnrepository.com/artifact/junit/junit const val kbson = "0.3.0" // https://github.com/mongodb/kbson // When updating the Kotlin version, also remember to update /examples/min-android-sample/build.gradle.kts - const val kotlin = "1.8.21" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details + const val kotlin = "1.9.10" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details const val kotlinJvmTarget = "1.8" // Which JVM bytecode version is kotlin compiled to. const val latestKotlin = "1.9.20-Beta" // https://kotlinlang.org/docs/eap.html#build-details const val kotlinCompileTesting = "1.5.0" // https://github.com/tschuchortdev/kotlin-compile-testing @@ -136,7 +136,7 @@ object Versions { const val nexusPublishPlugin = "1.1.0" // https://github.com/gradle-nexus/publish-plugin const val okio = "3.2.0" // https://square.github.io/okio/#releases const val relinker = "1.4.5" // https://github.com/KeepSafe/ReLinker - const val serialization = "1.4.0" // https://kotlinlang.org/docs/releases.html#release-details + const val serialization = "1.6.0" // https://kotlinlang.org/docs/releases.html#release-details const val shadowJar = "6.1.0" // https://mvnrepository.com/artifact/com.github.johnrengelman.shadow/com.github.johnrengelman.shadow.gradle.plugin?repo=gradle-plugins val sourceCompatibilityVersion = JavaVersion.VERSION_1_8 // Language level of any Java source code. val targetCompatibilityVersion = JavaVersion.VERSION_1_8 // Version of generated JVM bytecode from Java files. diff --git a/packages/cinterop/build.gradle.kts b/packages/cinterop/build.gradle.kts index 8cbeb83f8e..93cdb46e9e 100644 --- a/packages/cinterop/build.gradle.kts +++ b/packages/cinterop/build.gradle.kts @@ -271,6 +271,7 @@ kotlin { compilations.all { kotlinOptions { freeCompilerArgs += listOf("-opt-in=kotlin.ExperimentalUnsignedTypes") + freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") } } } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 46facf20d2..121bf7b4eb 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -1967,7 +1967,7 @@ actual object RealmInterop { realm_wrapper.realm_app_get_all_users( app.cptr(), null, - 0, + 0.toULong(), capacityCount.ptr ) ) diff --git a/packages/library-base/build.gradle.kts b/packages/library-base/build.gradle.kts index d5ca3b5ffc..6f0f4d97e8 100644 --- a/packages/library-base/build.gradle.kts +++ b/packages/library-base/build.gradle.kts @@ -44,6 +44,14 @@ kotlin { macosX64() macosArm64() + targets.all { + compilations.all { + kotlinOptions { + freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") + } + } + } + sourceSets { val commonMain by getting { dependencies { @@ -128,7 +136,8 @@ kotlin { // name and build type variant as a suffix, this default behaviour can cause mismatch at runtime https://github.com/realm/realm-kotlin/issues/621 tasks.withType().configureEach { kotlinOptions { - freeCompilerArgs = listOf("-module-name", "io.realm.kotlin.library") + freeCompilerArgs += listOf("-module-name", "io.realm.kotlin.library") + freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") } } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt index c4d1a87176..5536dc3441 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt @@ -40,6 +40,9 @@ internal object Names { Name.identifier("${REALM_SYNTHETIC_PROPERTY_PREFIX}schema") val REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD = Name.identifier("${REALM_SYNTHETIC_PROPERTY_PREFIX}newInstance") + val REALM_OBJECT_TO_STRING_METHOD = Name.identifier("toString") + val REALM_OBJECT_EQUALS = Name.identifier("equals") + val REALM_OBJECT_HASH_CODE = Name.identifier("hashCode") val SET = Name.special("") diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index 7c5d1f5f13..b868743ccc 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -33,6 +33,11 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirUserTypeRef +import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder import org.jetbrains.kotlin.ir.builders.IrBlockBuilder @@ -141,10 +146,9 @@ val anyRealmObjectInterfacesFqNames = realmObjectInterfaceFqNames + realmEmbedde fun IrType.classIdOrFail(): ClassId = getClass()?.classId ?: error("Can't get classId of ${render()}") -inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean { - // Using PSI to find super types to avoid cyclic reference (see https://github.com/realm/realm-kotlin/issues/339) +inline fun PsiElement.hasInterface(interfaces: Set): Boolean { var hasRealmObjectAsSuperType = false - this.findPsi()?.acceptChildren(object : PsiElementVisitor() { + this.acceptChildren(object : PsiElementVisitor() { override fun visitElement(element: PsiElement) { if (element.node.elementType == SUPER_TYPE_LIST) { // Check supertypes for classes with Embbeded/RealmObject as generics and remove @@ -156,11 +160,11 @@ inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean { .split(",") // Split by commas .filter { !( - it.contains("") || - it.contains("") || - it.contains("") || - it.contains("") - ) + it.contains("") || + it.contains("") || + it.contains("") || + it.contains("") + ) }.joinToString(",") // Re-sanitize again hasRealmObjectAsSuperType = elementNodeText.findAnyOf(interfaces) != null } @@ -169,6 +173,10 @@ inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean { return hasRealmObjectAsSuperType } +inline fun ClassDescriptor.hasInterfacePsi(interfaces: Set): Boolean { + // Using PSI to find super types to avoid cyclic reference (see https://github.com/realm/realm-kotlin/issues/339) + return this.findPsi()?.hasInterface(interfaces) ?: false +} // Do to the way PSI works, it can be a bit tricky to uniquely identify when the Realm Kotlin // RealmObject interface is used. For that reason, once we have determined a match for RealmObject, @@ -186,6 +194,18 @@ val ClassDescriptor.isEmbeddedRealmObject: Boolean val ClassDescriptor.isBaseRealmObject: Boolean get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames + asymmetricRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames) +// FIXME Cannot disregard Java's constructor invocation for RealmObject() +@OptIn(SymbolInternals::class) +val FirClassSymbol<*>.isBaseRealmObject: Boolean + get() = this.fir.superTypeRefs.any { + // In SUPERTYPES stage + it is FirUserTypeRef && it.qualifier.last().name in realmObjectTypes + // After SUPERTYPES stage + || it is FirResolvedTypeRef && it.type.classId in realmObjectTypes.map { name -> ClassId(FqName("io.realm.kotlin.types"), name) } + } + +val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) + // JetBrains already have a method `fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol)` // It is unclear exactly what the difference is and how to get a ClassSymbol from a ClassId, // so for now just work around it. diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticMethodsExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticMethodsExtension.kt index 5342091838..c9dc1af6a8 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticMethodsExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticMethodsExtension.kt @@ -51,8 +51,8 @@ class RealmModelSyntheticMethodsExtension : SyntheticResolveExtension { !isNestedInRealmModelClass(thisDescriptor) && /* do not override nested class methods */ result.isEmpty() /* = no method has been declared in the current class */ ) { - when (name.identifier) { - "toString" -> { + when (name) { + Names.REALM_OBJECT_TO_STRING_METHOD -> { result.add( createMethod( classDescriptor = thisDescriptor, @@ -62,7 +62,7 @@ class RealmModelSyntheticMethodsExtension : SyntheticResolveExtension { ) ) } - "equals" -> { + Names.REALM_OBJECT_EQUALS -> { result.add( createMethod( classDescriptor = thisDescriptor, @@ -72,7 +72,7 @@ class RealmModelSyntheticMethodsExtension : SyntheticResolveExtension { ) ) } - "hashCode" -> { + Names.REALM_OBJECT_HASH_CODE -> { result.add( createMethod( classDescriptor = thisDescriptor, diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt index ed03b01688..ff047a0c45 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt @@ -17,6 +17,7 @@ package io.realm.kotlin.compiler import com.google.auto.service.AutoService +import io.realm.kotlin.compiler.k2.model.RealmApiAugmenter import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.com.intellij.openapi.extensions.LoadingOrder import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension /** @@ -76,6 +78,11 @@ class Registrar : ComponentRegistrar { LoadingOrder.LAST, project ) + + // K2: Register extension that modifies the API similarly to the above two + // SyntheticResolveExtensions + FirExtensionRegistrarAdapter.registerExtension(project, RealmApiAugmenter()) + // Adds RealmObjectInternal properties, rewires accessors and adds static companion // properties and methods getExtensionPoint(IrGenerationExtension.extensionPointName).registerExtension( diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt new file mode 100644 index 0000000000..de22aabb8f --- /dev/null +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2023 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.kotlin.compiler.k2.model + +import io.realm.kotlin.compiler.Names +import io.realm.kotlin.compiler.isBaseRealmObject +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.declarations.utils.isCompanion +import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension +import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext +import org.jetbrains.kotlin.fir.extensions.NestedClassGenerationContext +import org.jetbrains.kotlin.fir.plugin.createCompanionObject +import org.jetbrains.kotlin.fir.plugin.createDefaultPrivateConstructor +import org.jetbrains.kotlin.fir.plugin.createMemberFunction +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames + +class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtension(session) { + override fun getNestedClassifiersNames( + classSymbol: FirClassSymbol<*>, + context: NestedClassGenerationContext + ): Set { + val isRealmObject = classSymbol.isBaseRealmObject + return if (isRealmObject) { + setOf(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) + } else { + emptySet() + } + } + + override fun generateNestedClassLikeDeclaration( + owner: FirClassSymbol<*>, + name: Name, + context: NestedClassGenerationContext + ): FirClassLikeSymbol<*>? { + // Only generate new companion if class does not have on already + val companion = (owner as? FirRegularClassSymbol)?.companionObjectSymbol + return if (companion == null && owner.isBaseRealmObject) { + createCompanionObject(owner, RealmApiGeneratorKey).symbol + } else { null } + } + + override fun getCallableNamesForClass( + classSymbol: FirClassSymbol<*>, + context: MemberGenerationContext + ): Set { + if (classSymbol.isCompanion && (classSymbol.getContainingClassSymbol(session) as? FirClassSymbol<*>)?.isBaseRealmObject == true) { + return setOf( + Names.REALM_OBJECT_COMPANION_SCHEMA_METHOD, + Names.REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD, + SpecialNames.INIT, // If from out own plugin remember to generate a default constructor + ) + } + return emptySet() + } + + override fun generateFunctions( + callableId: CallableId, + context: MemberGenerationContext? + ): List { + val owner = context?.owner ?: return emptyList() + return when (callableId.callableName) { + Names.REALM_OBJECT_COMPANION_SCHEMA_METHOD -> + listOf( + createMemberFunction( + owner, + RealmApiGeneratorKey, + callableId.callableName, + session.builtinTypes.anyType.type, + ).symbol + ) + + Names.REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD -> + listOf( + createMemberFunction( + owner, + RealmApiGeneratorKey, + callableId.callableName, + session.builtinTypes.anyType.type + ).symbol + ) + + else -> emptyList() + } + } + + override fun generateConstructors(context: MemberGenerationContext): List { + val constructor = createDefaultPrivateConstructor(context.owner, RealmApiGeneratorKey) + return listOf(constructor.symbol) + } +} diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt new file mode 100644 index 0000000000..47c5f2a6be --- /dev/null +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2023 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.kotlin.compiler.k2.model + +import io.realm.kotlin.compiler.Names +import io.realm.kotlin.compiler.isBaseRealmObject +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension +import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext +import org.jetbrains.kotlin.fir.plugin.createMemberFunction +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns + +/** + * Fir extension that adds `toString`, `equals` and `hashCode` to RealmObject-classes. + */ +class ModelObjectAugmenter(session: FirSession) : FirDeclarationGenerationExtension(session) { + override fun getCallableNamesForClass( + classSymbol: FirClassSymbol<*>, + context: MemberGenerationContext + ): Set { + return if (classSymbol.isBaseRealmObject) { + setOf( + Names.REALM_OBJECT_TO_STRING_METHOD, + Names.REALM_OBJECT_EQUALS, + Names.REALM_OBJECT_HASH_CODE, + ) + } else { + emptySet() + } + } + + override fun generateFunctions( + callableId: CallableId, + context: MemberGenerationContext? + ): List { + val owner = context?.owner ?: return emptyList() + return when (callableId.callableName) { + Names.REALM_OBJECT_TO_STRING_METHOD -> + listOf( + createMemberFunction( + owner, + RealmApiGeneratorKey, + callableId.callableName, + session.builtinTypes.stringType.type, + ).symbol + ) + Names.REALM_OBJECT_EQUALS -> + listOf( + createMemberFunction( + owner, + RealmApiGeneratorKey, + callableId.callableName, + session.builtinTypes.booleanType.type, + ) { + valueParameter(Name.identifier("other"), session.builtinTypes.nullableAnyType.type) + }.symbol + ) + Names.REALM_OBJECT_HASH_CODE -> + listOf( + createMemberFunction( + owner, + RealmApiGeneratorKey, + callableId.callableName, + session.builtinTypes.intType.type, + ).symbol + ) + else -> emptyList() + } + } +} diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt new file mode 100644 index 0000000000..55fb28343a --- /dev/null +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.realm.kotlin.compiler.k2.model + +import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar + +/** + * Fir extension that modifies the Realm object API. + * + * This consists of: + * - A [CompanionAugmenter] that adds a (or updates existing) companion object to + * RealmObject-classes and modifies it to implement the [RealmObjectCompanion] interface and its + * methods. + * - A [ModelObjectAugmenter] that adds `toString`, `equals` and `hashCode` methods to + * RealmObject-classes. + * + * All API modifications should be tagged with the [RealmApiGeneratorKey] to make it recognizable + * in other compiler plugin phases. + */ +class RealmApiAugmenter : FirExtensionRegistrar() { + override fun ExtensionRegistrarContext.configurePlugin() { + +::CompanionAugmenter + +::ModelObjectAugmenter + } +} + diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt new file mode 100644 index 0000000000..e27feac162 --- /dev/null +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.kotlin.compiler.k2.model + +import org.jetbrains.kotlin.GeneratedDeclarationKey + +/** + * Key to mark all additions made by out compile plugin. + */ +object RealmApiGeneratorKey : GeneratedDeclarationKey() { + override fun toString(): String { + return "RealmApiGenerator" + } +} diff --git a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt index b6f0f9bd15..18ba86a658 100644 --- a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt +++ b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt @@ -400,6 +400,7 @@ class GenerationExtensionTest { useIR = true messageOutputStream = System.out componentRegistrars = plugins + useK2 = true inheritClassPath = true kotlincArguments = listOf( "-Xjvm-default=all-compatibility", From c2cc7f31155a21363888671af326b22b85934a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Tue, 26 Sep 2023 11:40:52 +0200 Subject: [PATCH 02/17] Build test and perform compiler tests with K2 support --- packages/gradle.properties | 1 + .../io/realm/kotlin/compiler/Identifiers.kt | 2 +- .../io/realm/kotlin/compiler/IrUtils.kt | 31 +++++++++------ .../io/realm/kotlin/compiler/Registrar.kt | 4 +- .../RealmPluginGeneratorKey.kt} | 4 +- .../model/CompanionExtension.kt} | 13 ++++--- .../model/ObjectExtension.kt} | 39 ++++++++++++------- .../model/RealmModelRegistrar.kt} | 17 ++++---- packages/test-base/gradle.properties | 17 ++++++++ .../kotlin/entities/SerializableSample.kt | 5 +++ .../kotlin/test/common/RealmSchemaTests.kt | 2 +- .../realm/kotlin/test/common/SampleTests.kt | 6 ++- .../io/realm/kotlin/test/util/Compiler.kt | 2 + packages/test-sync/build.gradle.kts | 1 + packages/test-sync/gradle.properties | 17 ++++++++ .../test/mongodb/common/FunctionsTests.kt | 5 +++ 16 files changed, 119 insertions(+), 47 deletions(-) rename packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/{k2/model/RealmApiGeneratorKey.kt => fir/RealmPluginGeneratorKey.kt} (88%) rename packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/{k2/model/CompanionAugmenter.kt => fir/model/CompanionExtension.kt} (92%) rename packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/{k2/model/ModelObjectAugmenter.kt => fir/model/ObjectExtension.kt} (70%) rename packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/{k2/model/RealmApiAugumenter.kt => fir/model/RealmModelRegistrar.kt} (66%) create mode 100644 packages/test-base/gradle.properties create mode 100644 packages/test-sync/gradle.properties diff --git a/packages/gradle.properties b/packages/gradle.properties index 46f68050af..4c5f18cb06 100644 --- a/packages/gradle.properties +++ b/packages/gradle.properties @@ -49,3 +49,4 @@ syncTestLoginPassword=password # syncTestLoginPublicApiKey=replace-with-value # synctestLoginPrivateApiKey=replace-with-value # syncTestClusterName=replace-with-value + diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt index 5536dc3441..67197eba0b 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt @@ -163,5 +163,5 @@ object ClassIds { val APP_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppImpl")) val APP_CONFIGURATION = ClassId(PACKAGE_MONGODB, Name.identifier("AppConfiguration")) val APP_CONFIGURATION_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppConfigurationImpl")) - val APP_CONFIGURATION_BUILDER = ClassId(FqName("io.realm.kotlin.mongodb.AppConfiguration"), FqName("Builder"), true) + val APP_CONFIGURATION_BUILDER = ClassId(FqName("io.realm.kotlin.mongodb"), FqName("AppConfiguration.Builder"), false) } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index b868743ccc..226b225abb 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor @@ -160,11 +161,11 @@ inline fun PsiElement.hasInterface(interfaces: Set): Boolean { .split(",") // Split by commas .filter { !( - it.contains("") || - it.contains("") || - it.contains("") || - it.contains("") - ) + it.contains("") || + it.contains("") || + it.contains("") || + it.contains("") + ) }.joinToString(",") // Re-sanitize again hasRealmObjectAsSuperType = elementNodeText.findAnyOf(interfaces) != null } @@ -197,12 +198,20 @@ val ClassDescriptor.isBaseRealmObject: Boolean // FIXME Cannot disregard Java's constructor invocation for RealmObject() @OptIn(SymbolInternals::class) val FirClassSymbol<*>.isBaseRealmObject: Boolean - get() = this.fir.superTypeRefs.any { - // In SUPERTYPES stage - it is FirUserTypeRef && it.qualifier.last().name in realmObjectTypes - // After SUPERTYPES stage - || it is FirResolvedTypeRef && it.type.classId in realmObjectTypes.map { name -> ClassId(FqName("io.realm.kotlin.types"), name) } - } + get() = this.classKind == ClassKind.CLASS && + this.fir.superTypeRefs.any { + // In SUPERTYPES stage + it is FirUserTypeRef && ( + it.qualifier.last().name in realmObjectTypes + ) || + // After SUPERTYPES stage + it is FirResolvedTypeRef && it.type.classId in realmObjectTypes.map { name -> + ClassId( + FqName("io.realm.kotlin.types"), + name + ) + } + } val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt index ff047a0c45..388d647a8e 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Registrar.kt @@ -17,7 +17,7 @@ package io.realm.kotlin.compiler import com.google.auto.service.AutoService -import io.realm.kotlin.compiler.k2.model.RealmApiAugmenter +import io.realm.kotlin.compiler.fir.model.RealmModelRegistrar import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -81,7 +81,7 @@ class Registrar : ComponentRegistrar { // K2: Register extension that modifies the API similarly to the above two // SyntheticResolveExtensions - FirExtensionRegistrarAdapter.registerExtension(project, RealmApiAugmenter()) + FirExtensionRegistrarAdapter.registerExtension(project, RealmModelRegistrar()) // Adds RealmObjectInternal properties, rewires accessors and adds static companion // properties and methods diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt similarity index 88% rename from packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt rename to packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt index e27feac162..7caddda2b8 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiGeneratorKey.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package io.realm.kotlin.compiler.k2.model +package io.realm.kotlin.compiler.fir import org.jetbrains.kotlin.GeneratedDeclarationKey /** * Key to mark all additions made by out compile plugin. */ -object RealmApiGeneratorKey : GeneratedDeclarationKey() { +object RealmPluginGeneratorKey : GeneratedDeclarationKey() { override fun toString(): String { return "RealmApiGenerator" } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt similarity index 92% rename from packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt rename to packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt index de22aabb8f..a98f4ec275 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/CompanionAugmenter.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt @@ -14,9 +14,10 @@ * limitations under the License. */ -package io.realm.kotlin.compiler.k2.model +package io.realm.kotlin.compiler.fir.model import io.realm.kotlin.compiler.Names +import io.realm.kotlin.compiler.fir.RealmPluginGeneratorKey import io.realm.kotlin.compiler.isBaseRealmObject import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol @@ -36,7 +37,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames -class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtension(session) { +class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { override fun getNestedClassifiersNames( classSymbol: FirClassSymbol<*>, context: NestedClassGenerationContext @@ -57,7 +58,7 @@ class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtensio // Only generate new companion if class does not have on already val companion = (owner as? FirRegularClassSymbol)?.companionObjectSymbol return if (companion == null && owner.isBaseRealmObject) { - createCompanionObject(owner, RealmApiGeneratorKey).symbol + createCompanionObject(owner, RealmPluginGeneratorKey).symbol } else { null } } @@ -85,7 +86,7 @@ class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtensio listOf( createMemberFunction( owner, - RealmApiGeneratorKey, + RealmPluginGeneratorKey, callableId.callableName, session.builtinTypes.anyType.type, ).symbol @@ -95,7 +96,7 @@ class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtensio listOf( createMemberFunction( owner, - RealmApiGeneratorKey, + RealmPluginGeneratorKey, callableId.callableName, session.builtinTypes.anyType.type ).symbol @@ -106,7 +107,7 @@ class CompanionAugmenter(session: FirSession) : FirDeclarationGenerationExtensio } override fun generateConstructors(context: MemberGenerationContext): List { - val constructor = createDefaultPrivateConstructor(context.owner, RealmApiGeneratorKey) + val constructor = createDefaultPrivateConstructor(context.owner, RealmPluginGeneratorKey) return listOf(constructor.symbol) } } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt similarity index 70% rename from packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt rename to packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt index 47c5f2a6be..5ba60e8833 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/ModelObjectAugmenter.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt @@ -14,10 +14,12 @@ * limitations under the License. */ -package io.realm.kotlin.compiler.k2.model +package io.realm.kotlin.compiler.fir.model import io.realm.kotlin.compiler.Names +import io.realm.kotlin.compiler.fir.RealmPluginGeneratorKey import io.realm.kotlin.compiler.isBaseRealmObject +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext @@ -26,22 +28,28 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns + +/** + * Name of methods for which we will generate default implementations for if the users have not + * defined their own. + */ +private val realmObjectDefaultMethods = setOf( + Names.REALM_OBJECT_TO_STRING_METHOD, + Names.REALM_OBJECT_EQUALS, + Names.REALM_OBJECT_HASH_CODE, +) /** * Fir extension that adds `toString`, `equals` and `hashCode` to RealmObject-classes. */ -class ModelObjectAugmenter(session: FirSession) : FirDeclarationGenerationExtension(session) { +class ObjectExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { override fun getCallableNamesForClass( classSymbol: FirClassSymbol<*>, context: MemberGenerationContext ): Set { return if (classSymbol.isBaseRealmObject) { - setOf( - Names.REALM_OBJECT_TO_STRING_METHOD, - Names.REALM_OBJECT_EQUALS, - Names.REALM_OBJECT_HASH_CODE, - ) + val methodNames: List = classSymbol.declarationSymbols.filterIsInstance().map { it.name } + realmObjectDefaultMethods.filter { !methodNames.contains(it) }.toSet() } else { emptySet() } @@ -57,19 +65,22 @@ class ModelObjectAugmenter(session: FirSession) : FirDeclarationGenerationExtens listOf( createMemberFunction( owner, - RealmApiGeneratorKey, + RealmPluginGeneratorKey, callableId.callableName, session.builtinTypes.stringType.type, - ).symbol + ) { + modality = Modality.OPEN + }.symbol ) Names.REALM_OBJECT_EQUALS -> listOf( createMemberFunction( owner, - RealmApiGeneratorKey, + RealmPluginGeneratorKey, callableId.callableName, session.builtinTypes.booleanType.type, ) { + modality = Modality.OPEN valueParameter(Name.identifier("other"), session.builtinTypes.nullableAnyType.type) }.symbol ) @@ -77,10 +88,12 @@ class ModelObjectAugmenter(session: FirSession) : FirDeclarationGenerationExtens listOf( createMemberFunction( owner, - RealmApiGeneratorKey, + RealmPluginGeneratorKey, callableId.callableName, session.builtinTypes.intType.type, - ).symbol + ) { + modality = Modality.OPEN + }.symbol ) else -> emptyList() } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt similarity index 66% rename from packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt rename to packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt index 55fb28343a..393517f232 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/k2/model/RealmApiAugumenter.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt @@ -13,27 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.realm.kotlin.compiler.k2.model +package io.realm.kotlin.compiler.fir.model import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar /** - * Fir extension that modifies the Realm object API. + * Fir extension registrar that adds extensions to modify the Realm object API. * * This consists of: - * - A [CompanionAugmenter] that adds a (or updates existing) companion object to + * - A [CompanionExtension] that adds a (or updates existing) companion object to * RealmObject-classes and modifies it to implement the [RealmObjectCompanion] interface and its * methods. - * - A [ModelObjectAugmenter] that adds `toString`, `equals` and `hashCode` methods to + * - A [ObjectExtension] that adds `toString`, `equals` and `hashCode` methods to * RealmObject-classes. * - * All API modifications should be tagged with the [RealmApiGeneratorKey] to make it recognizable + * All API modifications should be tagged with the [RealmPluginGeneratorKey] to make it recognizable * in other compiler plugin phases. */ -class RealmApiAugmenter : FirExtensionRegistrar() { +class RealmModelRegistrar : FirExtensionRegistrar() { override fun ExtensionRegistrarContext.configurePlugin() { - +::CompanionAugmenter - +::ModelObjectAugmenter + +::CompanionExtension + +::ObjectExtension } } - diff --git a/packages/test-base/gradle.properties b/packages/test-base/gradle.properties new file mode 100644 index 0000000000..47c3ee5ab1 --- /dev/null +++ b/packages/test-base/gradle.properties @@ -0,0 +1,17 @@ +# +# Copyright 2023 Realm Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +kotlin.experimental.tryK2=true diff --git a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt index 9e6b939bf7..f5995a3ba4 100644 --- a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt +++ b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt @@ -351,4 +351,9 @@ class SerializableSample : RealmObject { @Serializable class SerializableEmbeddedObject : EmbeddedRealmObject { var name: String = "hello world" + + // Supplying custom companion object to work around that multiple K2 FIR extension clashes if + // they both generate a Companion. + // FIXME Issue reference + companion object } diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSchemaTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSchemaTests.kt index 7f5debbd7e..5bb4e0f5a6 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSchemaTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmSchemaTests.kt @@ -211,7 +211,7 @@ class RealmSchemaTests { @Suppress("NestedBlockDepth") fun schema_optionCoverage() { // Property options - @Suppress("invisible_member") + @Suppress("invisible_member", "invisible_reference") val propertyTypeMap = RealmPropertyType.subTypes.map { it to RealmStorageType.values().toMutableSet() } .toMap().toMutableMap() diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SampleTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SampleTests.kt index 3931202124..e79ee1732c 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SampleTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/SampleTests.kt @@ -27,7 +27,6 @@ import io.realm.kotlin.ext.query import io.realm.kotlin.ext.realmListOf import io.realm.kotlin.ext.toRealmList import io.realm.kotlin.internal.RealmObjectCompanion -import io.realm.kotlin.internal.platform.realmObjectCompanionOrThrow import io.realm.kotlin.internal.realmObjectCompanionOrThrow import io.realm.kotlin.query.find import io.realm.kotlin.test.platform.PlatformUtils @@ -69,7 +68,10 @@ class SampleTests { @Test fun realmObjectCompanion() { assertIs(Sample::class.realmObjectCompanionOrThrow()) - assertIs(realmObjectCompanionOrThrow(Sample::class)) + // K2 backend cannot handle multiple imports of the same reference so use fully qualified + // name + // assertIs(realmObjectCompanionOrThrow(Sample::class)) + assertIs(io.realm.kotlin.internal.platform.realmObjectCompanionOrThrow(Sample::class)) } @Test diff --git a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt index 2375417402..bc75edac84 100644 --- a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt +++ b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt @@ -31,6 +31,8 @@ object Compiler { KotlinCompilation().apply { sources = listOf(source) useIR = true + // TODO Find a way to differentiate to test both K1 and K2 support + useK2 = true messageOutputStream = System.out componentRegistrars = plugins inheritClassPath = true diff --git a/packages/test-sync/build.gradle.kts b/packages/test-sync/build.gradle.kts index d04f38661f..9b05d4edbd 100644 --- a/packages/test-sync/build.gradle.kts +++ b/packages/test-sync/build.gradle.kts @@ -123,6 +123,7 @@ kotlin { // JVM specific KotlinCompilation tasks tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java).all { kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + kotlinOptions.freeCompilerArgs += "-opt-in=org.mongodb.kbson.ExperimentalKBsonSerializerApi" } } diff --git a/packages/test-sync/gradle.properties b/packages/test-sync/gradle.properties new file mode 100644 index 0000000000..47c3ee5ab1 --- /dev/null +++ b/packages/test-sync/gradle.properties @@ -0,0 +1,17 @@ +# +# Copyright 2023 Realm Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +kotlin.experimental.tryK2=true diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt index 354bc859ac..7f01cb4fed 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt @@ -139,6 +139,11 @@ val BSON_DOCUMENT_VALUE = BsonDocument( class SerializablePerson : RealmObject { var firstName: String = "FIRST NAME" var lastName: String = "LAST NAME" + + // Supplying custom companion object to work around that multiple K2 FIR extension clashes if + // they both generate a Companion. + // FIXME Issue reference + companion object } class FunctionsTests { From bfb8a9511adf59c81dcbfc72ed833ee4db0a4b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Fri, 13 Oct 2023 16:12:52 +0200 Subject: [PATCH 03/17] Add CI test of K2 support --- CHANGELOG.md | 3 +- Jenkinsfile | 2 ++ buildSrc/src/main/kotlin/Config.kt | 2 +- .../mongodb/internal/RealmSyncInitializer.kt | 2 +- .../io/realm/kotlin/compiler/IrUtils.kt | 29 ++++++++++--------- .../compiler/fir/RealmPluginGeneratorKey.kt | 2 +- .../compiler/fir/model/CompanionExtension.kt | 4 +-- .../compiler/fir/model/ObjectExtension.kt | 2 +- .../compiler/fir/model/RealmModelRegistrar.kt | 2 +- .../compiler/GenerationExtensionTest.kt | 1 - packages/test-base/gradle.properties | 2 +- .../kotlin/entities/SerializableSample.kt | 2 +- .../io/realm/kotlin/test/util/Compiler.kt | 2 -- packages/test-sync/gradle.properties | 2 +- .../test/mongodb/common/FunctionsTests.kt | 2 +- 15 files changed, 30 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c990aa834e..b7a5116416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements * Realm will no longer set the JVM bytecode to 1.8 when applying the Realm plugin. ([#1513](https://github.com/realm/realm-kotlin/issues/1513)) +* Support for experimental K2 compilation. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) ### Fixed * `Realm.close()` is now idempotent. @@ -20,7 +21,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * File format: Generates Realms with file format v23. * Realm Studio 13.0.0 or above is required to open Realms created by this version. * This release is compatible with the following Kotlin releases: - * Kotlin 1.8.0 and above. The K2 compiler is not supported yet. + * Kotlin 1.9.0 and above. Support for experimental K2 compilation with `kotlin.experimental.tryK2=true`. * Ktor 2.1.2 and above. * Coroutines 1.7.0 and above. * AtomicFu 0.18.3 and above. diff --git a/Jenkinsfile b/Jenkinsfile index c3ff69b098..af83a48421 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -247,6 +247,7 @@ pipeline { when { expression { runTests } } steps { testAndCollect("integration-tests/gradle-plugin-test", "integrationTest") + testAndCollect("integration-tests/gradle-plugin-test", "-Pkotlin.experimental.tryK2=true integrationTest") } } stage('Tests Android Sample App') { @@ -268,6 +269,7 @@ pipeline { when { expression { runTests } } steps { testAndCollect("examples/realm-java-compatibility", "connectedAndroidTest") + testAndCollect("examples/realm-java-compatibility", "-Pkotlin.experimental.tryK2=true connectedAndroidTest") } } stage('Track build metrics') { diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 01617e49d8..e4a07f6f59 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -126,7 +126,7 @@ object Versions { const val junit = "4.13.2" // https://mvnrepository.com/artifact/junit/junit const val kbson = "0.3.0" // https://github.com/mongodb/kbson // When updating the Kotlin version, also remember to update /examples/min-android-sample/build.gradle.kts - const val kotlin = "1.9.10" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details + const val kotlin = "1.9.0" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details const val kotlinJvmTarget = "1.8" // Which JVM bytecode version is kotlin compiled to. const val latestKotlin = "1.9.20-Beta" // https://kotlinlang.org/docs/eap.html#build-details const val kotlinCompileTesting = "1.5.0" // https://github.com/tschuchortdev/kotlin-compile-testing diff --git a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt index f5bed0c72c..fabe9f7461 100644 --- a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt +++ b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt @@ -35,7 +35,7 @@ import io.realm.kotlin.log.RealmLog * An **initializer** for Sync specific functionality that does not fit into the `RealmInitializer` * in cinterop.o allow Realm to access context properties. */ -class RealmSyncInitializer : Initializer { +internal class RealmSyncInitializer : Initializer { companion object { @Suppress("DEPRECATION") // Should only be called below API 21 diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index 226b225abb..bb7b7fc2df 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -195,25 +195,26 @@ val ClassDescriptor.isEmbeddedRealmObject: Boolean val ClassDescriptor.isBaseRealmObject: Boolean get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames + asymmetricRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames) -// FIXME Cannot disregard Java's constructor invocation for RealmObject() +val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) +val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(FqName("io.realm.kotlin.types"), name) } + @OptIn(SymbolInternals::class) val FirClassSymbol<*>.isBaseRealmObject: Boolean get() = this.classKind == ClassKind.CLASS && - this.fir.superTypeRefs.any { - // In SUPERTYPES stage - it is FirUserTypeRef && ( - it.qualifier.last().name in realmObjectTypes - ) || - // After SUPERTYPES stage - it is FirResolvedTypeRef && it.type.classId in realmObjectTypes.map { name -> - ClassId( - FqName("io.realm.kotlin.types"), - name - ) + this.fir.superTypeRefs.any { + when (it) { + // In SUPERTYPES stage + is FirUserTypeRef -> { + it.qualifier.last().name in realmObjectTypes && + // Disregard constructor invocations as that means that it is a Realm Java class + !(it.source?.let { it.treeStructure.getParent(it.lighterASTNode) }?.tokenType?.let { it.debugName == "CONSTRUCTOR_CALLEE"} ?: false) + } + // After SUPERTYPES stage + is FirResolvedTypeRef -> it.type.classId in realmObjectClassIds + else -> false + } } - } -val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) // JetBrains already have a method `fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol)` // It is unclear exactly what the difference is and how to get a ClassSymbol from a ClassId, diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt index 7caddda2b8..7e39509fc6 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/RealmPluginGeneratorKey.kt @@ -19,7 +19,7 @@ package io.realm.kotlin.compiler.fir import org.jetbrains.kotlin.GeneratedDeclarationKey /** - * Key to mark all additions made by out compile plugin. + * Key to mark all additions made by our compile plugin. */ object RealmPluginGeneratorKey : GeneratedDeclarationKey() { override fun toString(): String { diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt index a98f4ec275..0ec41e8eb7 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/CompanionExtension.kt @@ -55,7 +55,7 @@ class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtensio name: Name, context: NestedClassGenerationContext ): FirClassLikeSymbol<*>? { - // Only generate new companion if class does not have on already + // Only generate new companion if class does not have one already val companion = (owner as? FirRegularClassSymbol)?.companionObjectSymbol return if (companion == null && owner.isBaseRealmObject) { createCompanionObject(owner, RealmPluginGeneratorKey).symbol @@ -70,7 +70,7 @@ class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtensio return setOf( Names.REALM_OBJECT_COMPANION_SCHEMA_METHOD, Names.REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD, - SpecialNames.INIT, // If from out own plugin remember to generate a default constructor + SpecialNames.INIT, // If from our own plugin remember to generate a default constructor ) } return emptySet() diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt index 5ba60e8833..6869c6243f 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/ObjectExtension.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.Name /** - * Name of methods for which we will generate default implementations for if the users have not + * Name of methods for which we will generate default implementations if the users have not * defined their own. */ private val realmObjectDefaultMethods = setOf( diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt index 393517f232..b0897ddaf6 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/fir/model/RealmModelRegistrar.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar * - A [CompanionExtension] that adds a (or updates existing) companion object to * RealmObject-classes and modifies it to implement the [RealmObjectCompanion] interface and its * methods. - * - A [ObjectExtension] that adds `toString`, `equals` and `hashCode` methods to + * - An [ObjectExtension] that adds `toString`, `equals` and `hashCode` methods to * RealmObject-classes. * * All API modifications should be tagged with the [RealmPluginGeneratorKey] to make it recognizable diff --git a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt index 18ba86a658..b6f0f9bd15 100644 --- a/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt +++ b/packages/plugin-compiler/src/test/kotlin/io/realm/kotlin/compiler/GenerationExtensionTest.kt @@ -400,7 +400,6 @@ class GenerationExtensionTest { useIR = true messageOutputStream = System.out componentRegistrars = plugins - useK2 = true inheritClassPath = true kotlincArguments = listOf( "-Xjvm-default=all-compatibility", diff --git a/packages/test-base/gradle.properties b/packages/test-base/gradle.properties index 47c3ee5ab1..c259017766 100644 --- a/packages/test-base/gradle.properties +++ b/packages/test-base/gradle.properties @@ -14,4 +14,4 @@ # limitations under the License. # -kotlin.experimental.tryK2=true +#kotlin.experimental.tryK2=true diff --git a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt index f5995a3ba4..6a15ef617d 100644 --- a/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt +++ b/packages/test-base/src/commonMain/kotlin/io/realm/kotlin/entities/SerializableSample.kt @@ -354,6 +354,6 @@ class SerializableEmbeddedObject : EmbeddedRealmObject { // Supplying custom companion object to work around that multiple K2 FIR extension clashes if // they both generate a Companion. - // FIXME Issue reference + // https://youtrack.jetbrains.com/issue/KT-62194/K2-Two-compiler-plugins-interference-in-generated-companion-object companion object } diff --git a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt index bc75edac84..2375417402 100644 --- a/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt +++ b/packages/test-base/src/jvmMain/kotlin/io/realm/kotlin/test/util/Compiler.kt @@ -31,8 +31,6 @@ object Compiler { KotlinCompilation().apply { sources = listOf(source) useIR = true - // TODO Find a way to differentiate to test both K1 and K2 support - useK2 = true messageOutputStream = System.out componentRegistrars = plugins inheritClassPath = true diff --git a/packages/test-sync/gradle.properties b/packages/test-sync/gradle.properties index 47c3ee5ab1..c259017766 100644 --- a/packages/test-sync/gradle.properties +++ b/packages/test-sync/gradle.properties @@ -14,4 +14,4 @@ # limitations under the License. # -kotlin.experimental.tryK2=true +#kotlin.experimental.tryK2=true diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt index 7f01cb4fed..cfd87265a1 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FunctionsTests.kt @@ -142,7 +142,7 @@ class SerializablePerson : RealmObject { // Supplying custom companion object to work around that multiple K2 FIR extension clashes if // they both generate a Companion. - // FIXME Issue reference + // https://youtrack.jetbrains.com/issue/KT-62194/K2-Two-compiler-plugins-interference-in-generated-companion-object companion object } From 52ad21eaf44a433a1b1f582307c7e2acc3bbae3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Fri, 13 Oct 2023 16:25:59 +0200 Subject: [PATCH 04/17] Linting and opt ins --- .../util/platform/PlatformUtils.kt | 3 +++ .../io/realm/kotlin/compiler/IrUtils.kt | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/integration-tests/gradle-plugin-test/multi-platform/src/nativeTest/kotlin/io/realm/test/multiplatform/util/platform/PlatformUtils.kt b/integration-tests/gradle-plugin-test/multi-platform/src/nativeTest/kotlin/io/realm/test/multiplatform/util/platform/PlatformUtils.kt index 26b1dabdab..9b5b5b4fca 100644 --- a/integration-tests/gradle-plugin-test/multi-platform/src/nativeTest/kotlin/io/realm/test/multiplatform/util/platform/PlatformUtils.kt +++ b/integration-tests/gradle-plugin-test/multi-platform/src/nativeTest/kotlin/io/realm/test/multiplatform/util/platform/PlatformUtils.kt @@ -15,8 +15,11 @@ * limitations under the License. */ +@file:OptIn(ExperimentalForeignApi::class) + package io.realm.test.multiplatform.util.platform +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.cstr actual object PlatformUtils { diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index bb7b7fc2df..cf4ae2666e 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -198,23 +198,26 @@ val ClassDescriptor.isBaseRealmObject: Boolean val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(FqName("io.realm.kotlin.types"), name) } +// This is the K2 equivalent of our PSI hack to determine if a symbol has a RealmObject base class. +// There is currently no way to determine this within the resolved type system and there is +// probably no such option around the corner. +// https://kotlinlang.slack.com/archives/C03PK0PE257/p1694599154558669 @OptIn(SymbolInternals::class) val FirClassSymbol<*>.isBaseRealmObject: Boolean get() = this.classKind == ClassKind.CLASS && - this.fir.superTypeRefs.any { - when (it) { - // In SUPERTYPES stage - is FirUserTypeRef -> { - it.qualifier.last().name in realmObjectTypes && + this.fir.superTypeRefs.any { + when (it) { + // In SUPERTYPES stage + is FirUserTypeRef -> { + it.qualifier.last().name in realmObjectTypes && // Disregard constructor invocations as that means that it is a Realm Java class - !(it.source?.let { it.treeStructure.getParent(it.lighterASTNode) }?.tokenType?.let { it.debugName == "CONSTRUCTOR_CALLEE"} ?: false) - } - // After SUPERTYPES stage - is FirResolvedTypeRef -> it.type.classId in realmObjectClassIds - else -> false + !(it.source?.let { it.treeStructure.getParent(it.lighterASTNode) }?.tokenType?.let { it.debugName == "CONSTRUCTOR_CALLEE" } ?: false) } + // After SUPERTYPES stage + is FirResolvedTypeRef -> it.type.classId in realmObjectClassIds + else -> false } - + } // JetBrains already have a method `fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol)` // It is unclear exactly what the difference is and how to get a ClassSymbol from a ClassId, From 4304e0caca9f275bbad4156a4c34529cdf456a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Fri, 13 Oct 2023 18:34:57 +0200 Subject: [PATCH 05/17] Another round for linting --- examples/kmm-sample/shared/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/kmm-sample/shared/build.gradle.kts b/examples/kmm-sample/shared/build.gradle.kts index 64fae846d6..97dfb9dbfc 100644 --- a/examples/kmm-sample/shared/build.gradle.kts +++ b/examples/kmm-sample/shared/build.gradle.kts @@ -64,7 +64,7 @@ kotlin { implementation("com.google.android.material:material:1.2.0") } } - val androidTest by getting { + val androidInstrumentedTest by getting { dependencies { implementation(kotlin("test-junit")) implementation("junit:junit:4.12") From 3f47a0a604406ef4825cdce4d3bbffbefa3bf23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Sat, 14 Oct 2023 09:15:01 +0200 Subject: [PATCH 06/17] Fix native conversion to ulong --- .../kotlin/io/realm/kotlin/test/CinteropTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt index 01fd6fec06..c45cd50448 100644 --- a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt +++ b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt @@ -119,7 +119,7 @@ class CinteropTest { realm_config_set_path(config, "c_api_test.realm") realm_config_set_schema(config, realmSchemaNew) realm_config_set_schema_mode(config, realm_schema_mode_e.RLM_SCHEMA_MODE_AUTOMATIC) - realm_config_set_schema_version(config, 1) + realm_config_set_schema_version(config, 1.toULong()) val realm: CPointer? = realm_open(config) assertEquals(1U, realm_get_num_classes(realm)) From 7d9a97d24cbbdfef37f3497b0c7d7573040ddeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Sat, 14 Oct 2023 09:37:44 +0200 Subject: [PATCH 07/17] More ExperimentalForeignApi optins --- .../kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt | 3 +++ .../kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt index 25c99d0556..876c2183d0 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt @@ -14,8 +14,11 @@ * limitations under the License. */ +@file:OptIn(ExperimentalForeignApi::class) + package io.realm.kotlin.test.platform +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.ULongVar import kotlinx.cinterop.alloc import kotlinx.cinterop.cValue diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt index c45640c5e7..6839137e6e 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt @@ -14,8 +14,11 @@ * limitations under the License. */ +@file:OptIn(ExperimentalForeignApi::class) + package io.realm.kotlin.test.platform +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope From 61077832ac1790a95087ebf7d67dca179f9dc86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Sat, 14 Oct 2023 09:54:28 +0200 Subject: [PATCH 08/17] More native optins and fixes --- .../main/kotlin/io/realm/kotlin/compiler/IrUtils.kt | 10 +++++----- .../io/realm/kotlin/test/darwin/CoroutineTests.kt | 2 +- .../io/realm/kotlin/test/darwin/InstrumentedTests.kt | 3 +++ .../kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt | 7 +++++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index cf4ae2666e..791518d6a4 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -205,16 +205,16 @@ val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(FqName("io.real @OptIn(SymbolInternals::class) val FirClassSymbol<*>.isBaseRealmObject: Boolean get() = this.classKind == ClassKind.CLASS && - this.fir.superTypeRefs.any { - when (it) { + this.fir.superTypeRefs.any { typeRef -> + when (typeRef) { // In SUPERTYPES stage is FirUserTypeRef -> { - it.qualifier.last().name in realmObjectTypes && + typeRef.qualifier.last().name in realmObjectTypes && // Disregard constructor invocations as that means that it is a Realm Java class - !(it.source?.let { it.treeStructure.getParent(it.lighterASTNode) }?.tokenType?.let { it.debugName == "CONSTRUCTOR_CALLEE" } ?: false) + !(typeRef.source?.run { treeStructure.getParent(lighterASTNode) }?.tokenType?.run { debugName == "CONSTRUCTOR_CALLEE" } ?: false) } // After SUPERTYPES stage - is FirResolvedTypeRef -> it.type.classId in realmObjectClassIds + is FirResolvedTypeRef -> typeRef.type.classId in realmObjectClassIds else -> false } } diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt index 2b7dfd654b..11c4d61f71 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt @@ -67,7 +67,7 @@ class CoroutineTests { @Test @Ignore fun dispatchQueueScheduler() { - val queue = dispatch_get_global_queue(NSNumber(DISPATCH_QUEUE_PRIORITY_BACKGROUND).integerValue, 0) + val queue = dispatch_get_global_queue(NSNumber(DISPATCH_QUEUE_PRIORITY_BACKGROUND).integerValue, 0.toULong()) val dispatcher = NsQueueDispatcher(queue) CoroutineScope(dispatcher).async { printlntid("async") diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt index 668a184a99..faa4c94390 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalForeignApi::class) + package io.realm.kotlin.test.darwin // FIXME API-CLEANUP Do we actually want to expose this. Test should probably just be reeavluated @@ -40,6 +42,7 @@ import io.realm.kotlin.types.TypedRealmObject import kotlinx.cinterop.COpaquePointerVar import kotlinx.cinterop.CPointed import kotlinx.cinterop.CPointer +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt index d2ea4d483d..806ec9e7d3 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalForeignApi::class) + package io.realm.kotlin.test.darwin import io.realm.kotlin.Realm @@ -24,6 +26,7 @@ import io.realm.kotlin.test.platform.PlatformUtils.createTempDir import io.realm.kotlin.test.platform.PlatformUtils.deleteTempDir import io.realm.kotlin.test.platform.PlatformUtils.triggerGC import kotlinx.cinterop.CPointer +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.refTo import kotlinx.cinterop.toKString import platform.posix.FILE @@ -101,7 +104,7 @@ class MemoryTests { referenceHolder.clear() triggerGC() - platform.posix.sleep(1 * 5) // give chance to the Collector Thread to process references + platform.posix.sleep((1 * 5).toUInt()) // give chance to the Collector Thread to process references // We should find a way to just meassure the increase over these tests. Referencing // NSProcessInfo.Companion.processInfo().operatingSystemVersionString @@ -148,7 +151,7 @@ class MemoryTests { }() triggerGC() - platform.posix.sleep(1 * 5) // give chance to the Collector Thread to process out of scope references + platform.posix.sleep((1 * 5).toUInt()) // give chance to the Collector Thread to process out of scope references // Referencing things like // NSProcessInfo.Companion.processInfo().operatingSystemVersionString From 1b7a6788caf4cfa1ab1e634e35c08d9b2198c64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 23 Oct 2023 14:01:45 +0200 Subject: [PATCH 09/17] Update R8 to support Kotlin 1.9 metadata --- buildSrc/src/main/kotlin/Config.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index e4a07f6f59..1973712d49 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -103,7 +103,7 @@ object Versions { const val buildToolsVersion = "33.0.0" const val buildTools = "7.3.1" // https://maven.google.com/web/index.html?q=gradle#com.android.tools.build:gradle const val ndkVersion = "23.2.8568313" - const val r8 = "4.0.48" // See https://developer.android.com/build/kotlin-support + const val r8 = "8.0.34" // See https://developer.android.com/build/kotlin-support } const val androidxBenchmarkPlugin = "1.2.0-alpha12" // https://maven.google.com/web/index.html#androidx.benchmark:androidx.benchmark.gradle.plugin const val androidxStartup = "1.1.1" // https://maven.google.com/web/index.html?q=startup#androidx.startup:startup-runtime From 4a391bea8c04a7bd569a3cb4ea7fcb81d471a602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 23 Oct 2023 14:11:00 +0200 Subject: [PATCH 10/17] Add minimum R8 compatible version --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d224794037..a7efef5b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * Minimum Gradle version: 6.8.3. * Minimum Android Gradle Plugin version: 4.1.3. * Minimum Android SDK: 16. +* Minimum R8 version: 8.0.27. ### Internal * None. From e9e63092d98a04d1413128a756be232a8b03139e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 23 Oct 2023 16:18:44 +0200 Subject: [PATCH 11/17] Revert minimum kotlin version --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7efef5b6b..b376c5aebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,7 @@ ### Enhancements * Realm will no longer set the JVM bytecode to 1.8 when applying the Realm plugin. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) * The Realm Gradle Plugin no longer has a dependency on KAPT. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) -* Realm will no longer set the JVM bytecode to 1.8 when applying the Realm plugin. ([#1513](https://github.com/realm/realm-kotlin/issues/1513)) -* Support for experimental K2 compilation. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) +* Support for Kotlin 1.9's experimental K2 compilation. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) ### Fixed * `Realm.close()` is now idempotent. @@ -23,7 +22,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * File format: Generates Realms with file format v23. * Realm Studio 13.0.0 or above is required to open Realms created by this version. * This release is compatible with the following Kotlin releases: - * Kotlin 1.9.0 and above. Support for experimental K2 compilation with `kotlin.experimental.tryK2=true`. + * Kotlin 1.8.20 and above. Support for experimental K2 compilation from Kotlin 1.9.0 with `kotlin.experimental.tryK2=true`. * Ktor 2.1.2 and above. * Coroutines 1.7.0 and above. * AtomicFu 0.18.3 and above. @@ -32,7 +31,6 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * Minimum Gradle version: 6.8.3. * Minimum Android Gradle Plugin version: 4.1.3. * Minimum Android SDK: 16. -* Minimum R8 version: 8.0.27. ### Internal * None. From 8ce75cae5237f0465d00fea3b95b09c65c60786d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 23 Oct 2023 18:31:33 +0200 Subject: [PATCH 12/17] Rework opt ins and update changelog --- CHANGELOG.md | 4 ++-- packages/gradle.properties | 1 - packages/library-base/build.gradle.kts | 12 ++++-------- packages/test-base/build.gradle.kts | 6 ++++++ .../io/realm/kotlin/test/platform/PlatformUtils.kt | 3 --- .../io/realm/kotlin/test/platform/RunLoopThread.kt | 3 --- .../io/realm/kotlin/test/darwin/InstrumentedTests.kt | 3 --- .../io/realm/kotlin/test/darwin/MemoryTests.kt | 3 --- packages/test-sync/build.gradle.kts | 1 - 9 files changed, 12 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa613090d..311bacccf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This release upgrades the Sync metadata in a way that is not compatible with old ### Enhancements * Realm will no longer set the JVM bytecode to 1.8 when applying the Realm plugin. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) * The Realm Gradle Plugin no longer has a dependency on KAPT. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) -* Support for Kotlin 1.9's experimental K2 compilation. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) +* Support for Kotlin 1.9's experimental K2 compilation with `kotlin.experimental.tryK2=true`. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) ### Fixed * `Realm.close()` is now idempotent. @@ -24,7 +24,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * File format: Generates Realms with file format v23. * Realm Studio 13.0.0 or above is required to open Realms created by this version. * This release is compatible with the following Kotlin releases: - * Kotlin 1.8.20 and above. Support for experimental K2 compilation from Kotlin 1.9.0 with `kotlin.experimental.tryK2=true`. + * Kotlin 1.8.0 and above. Support for experimental K2 compilation from Kotlin 1.9.0 with `kotlin.experimental.tryK2=true`. * Ktor 2.1.2 and above. * Coroutines 1.7.0 and above. * AtomicFu 0.18.3 and above. diff --git a/packages/gradle.properties b/packages/gradle.properties index 4c5f18cb06..46f68050af 100644 --- a/packages/gradle.properties +++ b/packages/gradle.properties @@ -49,4 +49,3 @@ syncTestLoginPassword=password # syncTestLoginPublicApiKey=replace-with-value # synctestLoginPrivateApiKey=replace-with-value # syncTestClusterName=replace-with-value - diff --git a/packages/library-base/build.gradle.kts b/packages/library-base/build.gradle.kts index 6f0f4d97e8..1a75c1b893 100644 --- a/packages/library-base/build.gradle.kts +++ b/packages/library-base/build.gradle.kts @@ -44,14 +44,6 @@ kotlin { macosX64() macosArm64() - targets.all { - compilations.all { - kotlinOptions { - freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") - } - } - } - sourceSets { val commonMain by getting { dependencies { @@ -137,6 +129,10 @@ kotlin { tasks.withType().configureEach { kotlinOptions { freeCompilerArgs += listOf("-module-name", "io.realm.kotlin.library") + } +} +tasks.withType().all { + kotlinOptions { freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") } } diff --git a/packages/test-base/build.gradle.kts b/packages/test-base/build.gradle.kts index 8976c4f7c8..e56161f7d7 100644 --- a/packages/test-base/build.gradle.kts +++ b/packages/test-base/build.gradle.kts @@ -271,6 +271,12 @@ kotlin { } } +tasks.withType().all { + kotlinOptions { + freeCompilerArgs += listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi") + } +} + // Rules for getting Kotlin Native resource test files in place for locating it with the `assetFile` // configuration. For JVM platforms the files are placed in // `src/jvmTest/resources`(non-Android JVM) and `src/androidTest/assets` (Android). diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt index 876c2183d0..25c99d0556 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/PlatformUtils.kt @@ -14,11 +14,8 @@ * limitations under the License. */ -@file:OptIn(ExperimentalForeignApi::class) - package io.realm.kotlin.test.platform -import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.ULongVar import kotlinx.cinterop.alloc import kotlinx.cinterop.cValue diff --git a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt index 6839137e6e..c45640c5e7 100644 --- a/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt +++ b/packages/test-base/src/nativeDarwin/kotlin/io/realm/kotlin/test/platform/RunLoopThread.kt @@ -14,11 +14,8 @@ * limitations under the License. */ -@file:OptIn(ExperimentalForeignApi::class) - package io.realm.kotlin.test.platform -import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt index faa4c94390..668a184a99 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/InstrumentedTests.kt @@ -14,8 +14,6 @@ * limitations under the License. */ -@file:OptIn(ExperimentalForeignApi::class) - package io.realm.kotlin.test.darwin // FIXME API-CLEANUP Do we actually want to expose this. Test should probably just be reeavluated @@ -42,7 +40,6 @@ import io.realm.kotlin.types.TypedRealmObject import kotlinx.cinterop.COpaquePointerVar import kotlinx.cinterop.CPointed import kotlinx.cinterop.CPointer -import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.alloc import kotlinx.cinterop.memScoped import kotlinx.cinterop.ptr diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt index 806ec9e7d3..578227de62 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt @@ -14,8 +14,6 @@ * limitations under the License. */ -@file:OptIn(ExperimentalForeignApi::class) - package io.realm.kotlin.test.darwin import io.realm.kotlin.Realm @@ -26,7 +24,6 @@ import io.realm.kotlin.test.platform.PlatformUtils.createTempDir import io.realm.kotlin.test.platform.PlatformUtils.deleteTempDir import io.realm.kotlin.test.platform.PlatformUtils.triggerGC import kotlinx.cinterop.CPointer -import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.refTo import kotlinx.cinterop.toKString import platform.posix.FILE diff --git a/packages/test-sync/build.gradle.kts b/packages/test-sync/build.gradle.kts index 9b05d4edbd..d04f38661f 100644 --- a/packages/test-sync/build.gradle.kts +++ b/packages/test-sync/build.gradle.kts @@ -123,7 +123,6 @@ kotlin { // JVM specific KotlinCompilation tasks tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java).all { kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" - kotlinOptions.freeCompilerArgs += "-opt-in=org.mongodb.kbson.ExperimentalKBsonSerializerApi" } } From 52b2099cb23b75a1a0729eb76fc185a0b50e476a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 30 Oct 2023 14:10:26 +0100 Subject: [PATCH 13/17] Update minimum required Kotlin version. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 311bacccf1..6476f53f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This release upgrades the Sync metadata in a way that is not compatible with old ### Enhancements * Realm will no longer set the JVM bytecode to 1.8 when applying the Realm plugin. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) * The Realm Gradle Plugin no longer has a dependency on KAPT. (Issue [#1513](https://github.com/realm/realm-kotlin/issues/1513)) -* Support for Kotlin 1.9's experimental K2 compilation with `kotlin.experimental.tryK2=true`. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) +* Support for experimental K2-compilation with `kotlin.experimental.tryK2=true`. (Issue [#1483](https://github.com/realm/realm-kotlin/issues/1483)) ### Fixed * `Realm.close()` is now idempotent. @@ -24,7 +24,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * File format: Generates Realms with file format v23. * Realm Studio 13.0.0 or above is required to open Realms created by this version. * This release is compatible with the following Kotlin releases: - * Kotlin 1.8.0 and above. Support for experimental K2 compilation from Kotlin 1.9.0 with `kotlin.experimental.tryK2=true`. + * Kotlin 1.9.0 and above. Support for experimental K2-compilation with `kotlin.experimental.tryK2=true`. * Ktor 2.1.2 and above. * Coroutines 1.7.0 and above. * AtomicFu 0.18.3 and above. From 23197be0e963914f16d16f566338a59ec85c4872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 30 Oct 2023 15:08:57 +0100 Subject: [PATCH 14/17] Add minimum version required for R8 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6476f53f8a..ef0291f2de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517)) * Minimum Gradle version: 6.8.3. * Minimum Android Gradle Plugin version: 4.1.3. * Minimum Android SDK: 16. +* Minimum R8: 8.0.27. ### Internal * Updated to Realm Core 13.23.1, commit 3618b2e9d679cd2880be8df17b79d4cc6d71ff76. From 311f2ae8588f4a48d0b55c4355d0692431046da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 13 Nov 2023 13:16:25 +0100 Subject: [PATCH 15/17] Updated according to review comments --- .../kotlin/internal/interop/RealmInterop.kt | 2 +- .../kotlin/io/realm/kotlin/test/CinteropTest.kt | 8 ++++---- .../io/realm/kotlin/compiler/Identifiers.kt | 9 +++++++-- .../kotlin/io/realm/kotlin/compiler/IrUtils.kt | 15 ++++++++++++--- packages/test-base/gradle.properties | 17 ----------------- .../realm/kotlin/test/darwin/CoroutineTests.kt | 2 +- .../io/realm/kotlin/test/darwin/MemoryTests.kt | 4 ++-- packages/test-sync/gradle.properties | 17 ----------------- 8 files changed, 27 insertions(+), 47 deletions(-) delete mode 100644 packages/test-base/gradle.properties delete mode 100644 packages/test-sync/gradle.properties diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 9bfa2ba86c..213be632f4 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -1985,7 +1985,7 @@ actual object RealmInterop { realm_wrapper.realm_app_get_all_users( app.cptr(), null, - 0.toULong(), + 0UL, capacityCount.ptr ) ) diff --git a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt index 8cb96e2425..b2733215a0 100644 --- a/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt +++ b/packages/cinterop/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/CinteropTest.kt @@ -136,14 +136,14 @@ class CinteropTest { classes[0].apply { name = "foo".cstr.ptr primary_key = "".cstr.ptr - num_properties = 1.toULong() - num_computed_properties = 0.toULong() + num_properties = 1UL + num_computed_properties = 0UL flags = RLM_CLASS_NORMAL.toInt() } val classProperties: CPointer>> = cValuesOf(prop_1_1.ptr).ptr - val realmSchemaNew = realm_schema_new(classes, 1.toULong(), classProperties) + val realmSchemaNew = realm_schema_new(classes, 1UL, classProperties) assertNoError() assertTrue( @@ -157,7 +157,7 @@ class CinteropTest { realm_config_set_path(config, "c_api_test.realm") realm_config_set_schema(config, realmSchemaNew) realm_config_set_schema_mode(config, realm_schema_mode_e.RLM_SCHEMA_MODE_AUTOMATIC) - realm_config_set_schema_version(config, 1.toULong()) + realm_config_set_schema_version(config, 1UL) val realm: CPointer? = realm_open(config) assertEquals(1U, realm_get_num_classes(realm)) diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt index 67197eba0b..ce6afd3774 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/Identifiers.kt @@ -26,6 +26,10 @@ import org.jetbrains.kotlin.name.Name internal object Names { const val REALM_SYNTHETIC_PROPERTY_PREFIX = "io_realm_kotlin_" + val REALM_OBJECT: Name = Name.identifier("RealmObject") + val EMBEDDED_REALM_OBJECT: Name = Name.identifier("EmbeddedRealmObject") + val ASYMMETRIC_REALM_OBJECT: Name = Name.identifier("AsymmetricRealmObject") + val REALM_OBJECT_COMPANION_CLASS_MEMBER: Name = Name.identifier("${REALM_SYNTHETIC_PROPERTY_PREFIX}class") val REALM_OBJECT_COMPANION_CLASS_NAME_MEMBER: Name = @@ -93,11 +97,12 @@ internal object FqNames { val PACKAGE_KBSON = FqName("org.mongodb.kbson") val PACKAGE_KOTLIN_COLLECTIONS = FqName("kotlin.collections") val PACKAGE_KOTLIN_REFLECT = FqName("kotlin.reflect") - val PACKAGE_TYPES = FqName("io.realm.kotlin.types") + val PACKAGE_TYPES: FqName = FqName("io.realm.kotlin.types") val PACKAGE_REALM_INTEROP = FqName("io.realm.kotlin.internal.interop") val PACKAGE_REALM_INTERNAL = FqName("io.realm.kotlin.internal") val PACKAGE_MONGODB = FqName("io.realm.kotlin.mongodb") val PACKAGE_MONGODB_INTERNAL = FqName("io.realm.kotlin.mongodb.internal") + val APP_CONFIGURATION_BUILDER = FqName("AppConfiguration.Builder") } object ClassIds { @@ -163,5 +168,5 @@ object ClassIds { val APP_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppImpl")) val APP_CONFIGURATION = ClassId(PACKAGE_MONGODB, Name.identifier("AppConfiguration")) val APP_CONFIGURATION_IMPL = ClassId(PACKAGE_MONGODB_INTERNAL, Name.identifier("AppConfigurationImpl")) - val APP_CONFIGURATION_BUILDER = ClassId(FqName("io.realm.kotlin.mongodb"), FqName("AppConfiguration.Builder"), false) + val APP_CONFIGURATION_BUILDER = ClassId(PACKAGE_MONGODB, FqNames.APP_CONFIGURATION_BUILDER, false) } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index 791518d6a4..65912d84cb 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -22,6 +22,10 @@ import io.realm.kotlin.compiler.ClassIds.EMBEDDED_OBJECT_INTERFACE import io.realm.kotlin.compiler.ClassIds.KOTLIN_COLLECTIONS_LISTOF import io.realm.kotlin.compiler.ClassIds.PERSISTED_NAME_ANNOTATION import io.realm.kotlin.compiler.ClassIds.REALM_OBJECT_INTERFACE +import io.realm.kotlin.compiler.FqNames.PACKAGE_TYPES +import io.realm.kotlin.compiler.Names.ASYMMETRIC_REALM_OBJECT +import io.realm.kotlin.compiler.Names.EMBEDDED_REALM_OBJECT +import io.realm.kotlin.compiler.Names.REALM_OBJECT import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocationWithRange @@ -111,6 +115,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_LIST import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.KotlinType @@ -195,8 +200,8 @@ val ClassDescriptor.isEmbeddedRealmObject: Boolean val ClassDescriptor.isBaseRealmObject: Boolean get() = this.hasInterfacePsi(realmObjectPsiNames + embeddedRealmObjectPsiNames + asymmetricRealmObjectPsiNames) && !this.hasInterfacePsi(realmJavaObjectPsiNames) -val realmObjectTypes = setOf(Name.identifier("RealmObject"), Name.identifier("EmbeddedRealmObject"), Name.identifier("AsymmetricRealmObject")) -val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(FqName("io.realm.kotlin.types"), name) } +val realmObjectTypes: Set = setOf(REALM_OBJECT, EMBEDDED_REALM_OBJECT, ASYMMETRIC_REALM_OBJECT) +val realmObjectClassIds = realmObjectTypes.map { name -> ClassId(PACKAGE_TYPES, name) } // This is the K2 equivalent of our PSI hack to determine if a symbol has a RealmObject base class. // There is currently no way to determine this within the resolved type system and there is @@ -211,7 +216,11 @@ val FirClassSymbol<*>.isBaseRealmObject: Boolean is FirUserTypeRef -> { typeRef.qualifier.last().name in realmObjectTypes && // Disregard constructor invocations as that means that it is a Realm Java class - !(typeRef.source?.run { treeStructure.getParent(lighterASTNode) }?.tokenType?.run { debugName == "CONSTRUCTOR_CALLEE" } ?: false) + !( + typeRef.source?.run { treeStructure.getParent(lighterASTNode) } + ?.let { it == KtStubElementTypes.CONSTRUCTOR_CALLEE } + ?: false + ) } // After SUPERTYPES stage is FirResolvedTypeRef -> typeRef.type.classId in realmObjectClassIds diff --git a/packages/test-base/gradle.properties b/packages/test-base/gradle.properties deleted file mode 100644 index c259017766..0000000000 --- a/packages/test-base/gradle.properties +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright 2023 Realm Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -#kotlin.experimental.tryK2=true diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt index 11c4d61f71..3822f03a71 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/CoroutineTests.kt @@ -67,7 +67,7 @@ class CoroutineTests { @Test @Ignore fun dispatchQueueScheduler() { - val queue = dispatch_get_global_queue(NSNumber(DISPATCH_QUEUE_PRIORITY_BACKGROUND).integerValue, 0.toULong()) + val queue = dispatch_get_global_queue(NSNumber(DISPATCH_QUEUE_PRIORITY_BACKGROUND).integerValue, 0UL) val dispatcher = NsQueueDispatcher(queue) CoroutineScope(dispatcher).async { printlntid("async") diff --git a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt index b59ade0814..f6493591c6 100644 --- a/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt +++ b/packages/test-base/src/nativeDarwinTest/kotlin/io/realm/kotlin/test/darwin/MemoryTests.kt @@ -101,7 +101,7 @@ class MemoryTests { referenceHolder.clear() triggerGC() - platform.posix.sleep((1 * 5).toUInt()) // give chance to the Collector Thread to process references + platform.posix.sleep(1U * 5U) // give chance to the Collector Thread to process references // We should find a way to just meassure the increase over these tests. Referencing // NSProcessInfo.Companion.processInfo().operatingSystemVersionString @@ -157,7 +157,7 @@ class MemoryTests { }() triggerGC() - platform.posix.sleep((1 * 5).toUInt()) // give chance to the Collector Thread to process out of scope references + platform.posix.sleep(1U * 5U) // give chance to the Collector Thread to process out of scope references val allocation = parseSizeString(runSystemCommand(amountOfMemoryMappedInProcessCMD)) assertEquals(initialAllocation, allocation, "mmap allocation exceeds expectations: initial=$initialAllocation current=$allocation") diff --git a/packages/test-sync/gradle.properties b/packages/test-sync/gradle.properties deleted file mode 100644 index c259017766..0000000000 --- a/packages/test-sync/gradle.properties +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright 2023 Realm Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -#kotlin.experimental.tryK2=true From 4662be153ecf97962ff8d09b99a30d08de210725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 13 Nov 2023 13:18:29 +0100 Subject: [PATCH 16/17] Fix r8 requirement in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d61c81f1d6..0c0f679753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ * Minimum Gradle version: 6.8.3. * Minimum Android Gradle Plugin version: 4.1.3. * Minimum Android SDK: 16. -* Minimum R8: 8.0.27. +* Minimum R8: 8.0.34. ### Internal * None. From 23e4b12d7d9eb5572158675f65187f449e6388df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20R=C3=B8rbech?= Date: Mon, 13 Nov 2023 18:20:09 +0100 Subject: [PATCH 17/17] Fix java compatibility sample --- .../realm/kotlin/mongodb/internal/MutableSubscriptionSetImpl.kt | 2 +- .../kotlin/io/realm/kotlin/mongodb/internal/SubscriptionImpl.kt | 2 +- .../io/realm/kotlin/mongodb/internal/SyncConfigurationImpl.kt | 2 +- .../kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt | 2 +- .../src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MutableSubscriptionSetImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MutableSubscriptionSetImpl.kt index b4059ffa1f..ac56ccd5f3 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MutableSubscriptionSetImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/MutableSubscriptionSetImpl.kt @@ -87,7 +87,7 @@ internal class MutableSubscriptionSetImpl( return result } - @Suppress("invisible_member") + @Suppress("invisible_member", "invisible_reference") override fun removeAll(type: KClass): Boolean { var result = false val objectType = io.realm.kotlin.internal.platform.realmObjectCompanionOrThrow(type).`io_realm_kotlin_className` diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SubscriptionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SubscriptionImpl.kt index d908305357..8d8b9f609d 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SubscriptionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SubscriptionImpl.kt @@ -42,7 +42,7 @@ internal class SubscriptionImpl( // Trim the query to match the output of RealmQuery.description() override val queryDescription: String = RealmInterop.realm_sync_subscription_query_string(nativePointer).trim() - @Suppress("invisible_member") + @Suppress("invisible_member", "invisible_reference") override fun asQuery(type: KClass): RealmQuery { // TODO Check for invalid combinations of Realm and type once we properly support // DynamicRealm diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncConfigurationImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncConfigurationImpl.kt index 23d689a20d..1a06d2a32f 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncConfigurationImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncConfigurationImpl.kt @@ -222,7 +222,7 @@ internal class SyncConfigurationImpl( initializerHelper.onSyncError(session, frozenAppPointer, error) } } catch (ex: Exception) { - @Suppress("invisible_member") + @Suppress("invisible_member", "invisible_reference") RealmLog.error("Error thrown and ignored in `onManualResetFallback`: $ex") } } else { diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt index 6ce5e305c6..7a9d3416f6 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt @@ -139,7 +139,7 @@ internal open class SyncSessionImpl( } } - @Suppress("invisible_member") // To be able to use RealmImpl.scopedFlow from library-base + @Suppress("invisible_member", "invisible_reference") // To be able to use RealmImpl.scopedFlow from library-base override fun connectionStateAsFlow(): Flow = realm.scopedFlow { callbackFlow { val token: AtomicRef = kotlinx.atomicfu.atomic(NO_OP_NOTIFICATION_TOKEN) diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt index 65912d84cb..01953e72c7 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/IrUtils.kt @@ -218,7 +218,7 @@ val FirClassSymbol<*>.isBaseRealmObject: Boolean // Disregard constructor invocations as that means that it is a Realm Java class !( typeRef.source?.run { treeStructure.getParent(lighterASTNode) } - ?.let { it == KtStubElementTypes.CONSTRUCTOR_CALLEE } + ?.tokenType?.let { it == KtStubElementTypes.CONSTRUCTOR_CALLEE } ?: false ) }