diff --git a/.directory b/.directory new file mode 100644 index 0000000000..5c63501398 --- /dev/null +++ b/.directory @@ -0,0 +1,7 @@ +[Dolphin] +Timestamp=2025,1,23,9,58,31.491 +Version=4 +ViewMode=1 + +[Settings] +HiddenFilesShown=true diff --git a/.gitmodules b/.gitmodules index 47da7742a4..e22b4175e1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ -[submodule "external/core"] +[submodule "packages/external/core"] path = packages/external/core url = https://github.com/realm/realm-core.git - branch = su/c-api diff --git a/CHANGELOG.md b/CHANGELOG.md index 19f4386c27..3f968a9e44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +## 3.2.2 + +* set Android targetSDK to 35 +* included the publishing scripts from @PavelFedoseev https://github.com/realm/realm-kotlin/issues/1857#issuecomment-2621494944 + +## 3.2.1 + +* fixed local publishing errors (for jvm and Android) + +## 3.2.0 + +* changed project structure to make Intellij IDE work, buildSrc is moved out of scope io.realm +* gradlew should be run in the root directory rather than packages +* testing are on dev versions, not supporting testing maven artifacts yet +* updated a few dependencies + +## 3.1.0 + +* updated to work with Kotlin 2.1.0 +* Coroutines tested with 1.10.1 +* Gradle version 8.12 +* Android Gradle Plugin version 8.7.3 +* Minimum Android SDK: 21 +* R8 version 8.7.18 + ## 3.0.0-SNAPSHOT (YYYY-MM-DD) ### Breaking Changes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0cd3db7f53..70953fec40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,7 @@ The repository can be built on Windows, although only for the JVM and Android ta ### Linux support -This repository does currently not support building on Linux from the source code. +This repository can now be built in the same way as on the Mac. ### Building and running tests @@ -45,19 +45,17 @@ be developed and tested as a single project. For details on publishing and runni Maven artifacts see the [Running tests against Maven artifacts](#running-tests-against-maven-artifacts)-section. The tests are triggered from the IDE or by triggering the specific test tasks across the various -platforms with: +platforms with (in the root directory): ```sh -cd packages -./gradlew :test-base:jvmTest :test-base:connectedAndroidTest :test-base:macosTest :test-base:iosTest +./gradlew :packages:test-base:jvmTest :packages:test-base:connectedAndroidTest :packages:test-base:macosTest :packages:test-base:iosTest # Note that running the test-sync suite requires running a local server # (see `tools/sync_test_server/start_local_server.sh` and `tools/sync_test_server/stop_local_server.sh`) -./gradlew :test-sync:jvmTest :test-sync:connectedAndroidTest :test-sync:macosTest :test-sync:iosTest +./gradlew :packages:test-sync:jvmTest :packages:test-sync:connectedAndroidTest :packages:test-sync:macosTest :packages:test-sync:iosTest ``` You can also the test across all modules on the various platforms with ```sh -cd packages ./gradlew jvmTest connectedAndroidTest macosTest iosTest ``` But this will also trigger tests in the SDK modules. @@ -91,7 +89,6 @@ repository in a local folder using the default local and test against these usin commands: ```sh -cd packages ./gradlew publishAllPublicationsToTestRepository ./gradlew -PincludeSdkModules=false jvmTest connectedAndroidTest macosTest iosTest ``` diff --git a/README.md b/README.md index 83478678f9..58301aa0cf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,32 @@ +### This fork of Realm Kotlin SDK is to make it compatible with Kotlin 2.1.0 while updating various dependencies + +JVM has been tested to work the same as with builds with Kotlin 2.0.x. Android is being tested. Testing iOS and MacOS will depend on other contributors. + +Unlike the forked repo, this one can be built from source on Linux. + +Project structure is changed to make Intellij IDE work. gradlew needs to be run from the root directory rather than packages. + +Testing are performed on the dev versions. Maven artifacts can be published (tested locally), but can not be tested upon yet. + +#### This project is rebranded for publishing on maven central, and is no longer maintained. The new project is [here](https://github.com/XilinJia/krdb) + +------------------------------------ + +> [!WARNING] +> We announced the deprecation of Atlas Device Sync + Realm SDKs in September 2024. For more information please see: +> - [SDK Deprecation](https://www.mongodb.com/docs/atlas/device-sdks/deprecation/) +> - [Device Sync Deprecation](https://www.mongodb.com/docs/atlas/app-services/sync/device-sync-deprecation/) +> +> For a version of Realm Kotlin without sync features, install version `3.0.0+` or see the `community` git branch. + + realm by MongoDB -[![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/io/realm/kotlin/io.realm.kotlin.gradle.plugin/maven-metadata.xml.svg?colorB=ff6b00&label=Gradle%20Plugin%20Portal)](https://plugins.gradle.org/plugin/io.realm.kotlin) -[![Maven Central](https://img.shields.io/maven-central/v/io.realm.kotlin/gradle-plugin?colorB=4dc427&label=Maven%20Central)](https://search.maven.org/artifact/io.realm.kotlin/gradle-plugin) +[![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/io/realm/kotlin/io.realm.kotlin.gradle.plugin/maven-metadata.xml.svg?colorB=ff6b00&label=Gradle%20Plugin%20Portal&versionPrefix=2)](https://plugins.gradle.org/plugin/io.realm.kotlin) +[![Maven Central](https://img.shields.io/maven-central/v/io.realm.kotlin/gradle-plugin/2.3.0?colorB=4dc427&label=Maven%20Central)](https://search.maven.org/artifact/io.realm.kotlin/gradle-plugin) [![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-blue.svg?logo=kotlin)](http://kotlinlang.org) [![License](https://img.shields.io/badge/License-Apache-blue.svg)](https://github.com/realm/realm-kotlin/blob/master/LICENSE) diff --git a/benchmarks/gradle/wrapper/gradle-wrapper.properties b/benchmarks/gradle/wrapper/gradle-wrapper.properties index f42e62f372..d6e308a637 100644 --- a/benchmarks/gradle/wrapper/gradle-wrapper.properties +++ b/benchmarks/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/benchmarks/jvmApp/build.gradle.kts b/benchmarks/jvmApp/build.gradle.kts index 3244a5ee05..1e2369533b 100644 --- a/benchmarks/jvmApp/build.gradle.kts +++ b/benchmarks/jvmApp/build.gradle.kts @@ -20,5 +20,5 @@ jmh { } tasks.withType { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "1.8" } diff --git a/build.gradle.kts b/build.gradle.kts index 5637bdb1d0..5a3f204d61 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.Companion.fromTarget + /* * Copyright 2020 Realm Inc. * @@ -19,6 +22,9 @@ buildscript { repositories { jcenter() } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0") + } } // Find property in either System environment or Gradle properties. @@ -64,8 +70,19 @@ fun copyProperties(action: GradleBuild) { } } -tasks { +//allprojects { +// version = Realm.version +// group = Realm.group +// +// // Define JVM bytecode target for all Kotlin targets +// tasks.withType { +// compilerOptions { +// jvmTarget.set(fromTarget(Versions.kotlinJvmTarget)) +// } +// } +//} +tasks { register("ktlintCheck") { description = "Runs ktlintCheck on all projects." group = "Verification" @@ -112,8 +129,8 @@ tasks { // TODO Verify we can actually use these debug symbols val archiveDebugSymbols by register("archiveDebugSymbols", Zip::class) { - archiveName = "realm-kotlin-jni-libs-unstripped-${currentVersion}.zip" - destinationDir = releaseMetaDataDir +// archiveName = "realm-kotlin-jni-libs-unstripped-${currentVersion}.zip" +// destinationDir = releaseMetaDataDir from("${rootDir}/packages/cinterop/build/intermediates/merged_native_libs/release/out/lib") { include("**/*.so") } @@ -175,4 +192,119 @@ tasks { description = "Upload release metadata to S3 (Native debug symbols, version files)" dependsOn.addAll(listOf(uploadDebugSymbols, updateS3VersionFile)) } + + register("publishCIPackages") { + group = "Publishing" + description = "Publish packages that has been configured for this CI node. See `gradle.properties`." + + // Figure out which targets are configured. This will impact which sub modules will be published + val availableTargets = setOf( + "iosArm64", + "iosX64", + "jvm", + "macosX64", + "macosArm64", + "android", + "metadata", + "compilerPlugin", + "gradlePlugin" + ) + + val mainHostTarget: Set = setOf("metadata") // "kotlinMultiplatform" + + val isMainHost: Boolean = project.properties["realm.kotlin.mainHost"]?.let { it == "true" } ?: false + + // Find user configured platforms (if any) + val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?) + ?.split(",") + ?.map { it.trim() } + ?.filter { it.isNotEmpty() } + ?.toSet() + + userTargets?.forEach { + if (!availableTargets.contains(it)) { + project.logger.error("Unknown publication: $it") + throw IllegalArgumentException("Unknown publication: $it") + } + } + + // Configure which platforms publications we do want to publish + val publicationTargets = (userTargets ?: availableTargets).let { + when (isMainHost) { + true -> it + mainHostTarget + false -> it - mainHostTarget + } + } + + publicationTargets.forEach { target: String -> + when (target) { + "iosArm64" -> { + dependsOn( + ":packages:cinterop:publishIosArm64PublicationToTestRepository", + ":packages:cinterop:publishIosSimulatorArm64PublicationToTestRepository", + ":packages:library-base:publishIosArm64PublicationToTestRepository", + ":packages:library-base:publishIosSimulatorArm64PublicationToTestRepository", + ":packages:library-sync:publishIosArm64PublicationToTestRepository", + ":packages:library-sync:publishIosSimulatorArm64PublicationToTestRepository", + ) + } + "iosX64" -> { + dependsOn( + ":packages:cinterop:publishIosX64PublicationToTestRepository", + ":packages:library-base:publishIosX64PublicationToTestRepository", + ":packages:library-sync:publishIosX64PublicationToTestRepository", + ) + } + "jvm" -> { + dependsOn( + ":packages:jni-swig-stub:publishAllPublicationsToTestRepository", + ":packages:cinterop:publishJvmPublicationToTestRepository", + ":packages:library-base:publishJvmPublicationToTestRepository", + ":packages:library-sync:publishJvmPublicationToTestRepository", + ) + } + "macosX64" -> { + dependsOn( + ":packages:cinterop:publishMacosX64PublicationToTestRepository", + ":packages:library-base:publishMacosX64PublicationToTestRepository", + ":packages:library-sync:publishMacosX64PublicationToTestRepository", + ) + } + "macosArm64" -> { + dependsOn( + ":packages:cinterop:publishMacosArm64PublicationToTestRepository", + ":packages:library-base:publishMacosArm64PublicationToTestRepository", + ":packages:library-sync:publishMacosArm64PublicationToTestRepository", + ) + } + "android" -> { + dependsOn( + ":packages:jni-swig-stub:publishAllPublicationsToTestRepository", + ":packages:cinterop:publishAndroidReleasePublicationToTestRepository", + ":packages:library-base:publishAndroidReleasePublicationToTestRepository", + ":packages:library-sync:publishAndroidReleasePublicationToTestRepository", + ) + } + "metadata" -> { + dependsOn( + ":packages:cinterop:publishKotlinMultiplatformPublicationToTestRepository", + ":packages:library-base:publishKotlinMultiplatformPublicationToTestRepository", + ":packages:library-sync:publishKotlinMultiplatformPublicationToTestRepository", + ) + } + "compilerPlugin" -> { + dependsOn( + ":packages:plugin-compiler:publishAllPublicationsToTestRepository", + ":packages:plugin-compiler-shaded:publishAllPublicationsToTestRepository" + ) + } + "gradlePlugin" -> { + dependsOn(":packages:gradle-plugin:publishAllPublicationsToTestRepository") + } + else -> { + throw IllegalArgumentException("Unsupported target: $target") + } + } + } + } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 9989e916f2..a16eb27b2d 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,14 +18,19 @@ plugins { `kotlin-dsl` `kotlin-dsl-precompiled-script-plugins` + kotlin("jvm") version Versions.kotlin } gradlePlugin { plugins { register("realm-publisher") { id = "realm-publisher" - implementationClass = "io.realm.kotlin.RealmPublishPlugin" + implementationClass = "org.realm.kotlin.RealmPublishPlugin" } +// create("realm-compiler") { // Plugin name (used internally) +// id = "io.realm.kotlin.plugin-compiler" // Plugin ID (used to apply) +// implementationClass = "io.realm.kotlin.compiler.Registrar" +// } } } @@ -44,6 +49,7 @@ repositories { buildscript { dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}") + classpath("org.jetbrains.dokka:dokka-gradle-plugin:${Versions.dokka}") // Use the latest version } } @@ -51,9 +57,13 @@ buildscript { // These seem to propagate to all projects including the buildSrc/ directory, which also means // they are not allowed to set the version. It can only be set from here. dependencies { + implementation(kotlin("gradle-plugin", version = Versions.kotlin)) implementation("io.github.gradle-nexus:publish-plugin:${Versions.nexusPublishPlugin}") implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:${Versions.detektPlugin}") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}") + implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") + implementation("org.gradle.kotlin:gradle-kotlin-dsl-plugins:5.1.2") + implementation("org.jetbrains.dokka:dokka-gradle-plugin:${Versions.dokka}") implementation("com.android.tools:r8:${Versions.Android.r8}") implementation("com.android.tools.build:gradle:${Versions.Android.buildTools}") implementation(kotlin("script-runtime")) diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index efa281582d..58d765de8d 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -62,7 +62,7 @@ val HOST_OS: OperatingSystem = findHostOs() object Realm { val ciBuild = (System.getenv("CI") != null) - const val version = "3.0.0-SNAPSHOT" + const val version = "3.2.1-SNAPSHOT" const val group = "io.realm.kotlin" const val projectUrl = "https://realm.io" const val pluginPortalId = "io.realm.kotlin" @@ -97,47 +97,49 @@ object Realm { object Versions { object Android { - const val minSdk = 16 - const val targetSdk = 33 - const val compileSdkVersion = 33 - 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 = "8.3.37" // See https://developer.android.com/build/kotlin-support + const val minSdk = 21 + const val targetSdk = 35 + const val compileSdkVersion = 35 + const val buildToolsVersion = "35.0.0" + const val buildTools = "8.7.3" // https://maven.google.com/web/index.html?q=gradle#com.android.tools.build:gradle + const val ndkVersion = "27.0.12077973" + const val r8 = "8.7.18" // 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 - const val androidxJunit = "1.1.3" // https://maven.google.com/web/index.html#androidx.test.ext:junit - const val androidxTest = "1.4.0" // https://maven.google.com/web/index.html#androidx.test:rules + const val androidxBenchmarkPlugin = "1.3.3" // https://maven.google.com/web/index.html#androidx.benchmark:androidx.benchmark.gradle.plugin + const val androidxStartup = "1.2.0" // https://maven.google.com/web/index.html?q=startup#androidx.startup:startup-runtime + const val androidxJunit = "1.2.1" // https://maven.google.com/web/index.html#androidx.test.ext:junit + const val androidxTest = "1.6.1" // https://maven.google.com/web/index.html#androidx.test:rules + // Must be built with same (major.minor!?) kotlin version as 'kotlin' variable below, to be binary compatible with kotlin - const val atomicfu = "0.18.5" // https://github.com/Kotlin/kotlinx.atomicfu + const val atomicfu = "0.26.1" // https://github.com/Kotlin/kotlinx.atomicfu + const val atomicfuPlugin = "0.27.0" // https://github.com/Kotlin/kotlinx.atomicfu const val autoService = "1.0" // https://mvnrepository.com/artifact/com.google.auto.service/auto-service const val buildkonfig = "0.13.3" // https://github.com/yshrsmz/BuildKonfig - 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 coroutines = "1.10.1" // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core + const val datetime = "0.6.1" // https://github.com/Kotlin/kotlinx-datetime const val detektPlugin = "1.23.6" // https://github.com/detekt/detekt - const val dokka = "1.9.0" // https://github.com/Kotlin/dokka + const val dokka = "2.0.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.4.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 = "2.0.20" // 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 = "2.0.20" // https://kotlinlang.org/docs/eap.html#build-details - const val kotlinCompileTesting = "0.5.1" // https://github.com/zacsweers/kotlin-compile-testing - const val ktlint = "0.45.2" // https://github.com/pinterest/ktlint + const val kotlin = "2.1.0" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details + const val kotlinJvmTarget = "17" // Which JVM bytecode version is kotlin compiled to. + const val latestKotlin = "2.1.0" // https://kotlinlang.org/docs/eap.html#build-details + const val kotlinCompileTesting = "0.7.0" // https://github.com/zacsweers/kotlin-compile-testing + const val ktlint = "1.5.0" // https://github.com/pinterest/ktlint const val ktor = "2.3.12" // https://github.com/ktorio/ktor const val multidex = "2.0.1" // https://developer.android.com/jetpack/androidx/releases/multidex const val nexusPublishPlugin = "1.3.0" // https://github.com/gradle-nexus/publish-plugin - const val okio = "3.9.0" // https://square.github.io/okio/#releases + const val okio = "3.10.2" // https://square.github.io/okio/#releases const val relinker = "1.4.5" // https://github.com/KeepSafe/ReLinker - const val serialization = "1.7.1" // 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 + const val serialization = "1.8.0" // https://kotlinlang.org/docs/releases.html#release-details + const val shadowJar = "8.1.0" // https://mvnrepository.com/artifact/com.github.johnrengelman.shadow/com.github.johnrengelman.shadow.gradle.plugin?repo=gradle-plugins const val snakeYaml = "1.33" // https://github.com/snakeyaml/snakeyaml - 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. + val sourceCompatibilityVersion = JavaVersion.VERSION_17 // Language level of any Java source code. + val targetCompatibilityVersion = JavaVersion.VERSION_17 // Version of generated JVM bytecode from Java files. } // Could be actual Dependency objects diff --git a/buildSrc/src/main/kotlin/io/realm/RealmPublishPlugin.kt b/buildSrc/src/main/kotlin/org/realm/kotlin/RealmPublishPlugin.kt similarity index 99% rename from buildSrc/src/main/kotlin/io/realm/RealmPublishPlugin.kt rename to buildSrc/src/main/kotlin/org/realm/kotlin/RealmPublishPlugin.kt index 3c8de8c3e4..94f58cc06b 100644 --- a/buildSrc/src/main/kotlin/io/realm/RealmPublishPlugin.kt +++ b/buildSrc/src/main/kotlin/org/realm/kotlin/RealmPublishPlugin.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package io.realm.kotlin +package org.realm.kotlin import Realm import io.github.gradlenexus.publishplugin.NexusPublishExtension diff --git a/examples/kmm-sample/gradle/wrapper/gradle-wrapper.properties b/examples/kmm-sample/gradle/wrapper/gradle-wrapper.properties index f42e62f372..d6e308a637 100644 --- a/examples/kmm-sample/gradle/wrapper/gradle-wrapper.properties +++ b/examples/kmm-sample/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/examples/min-android-sample/build.gradle.kts b/examples/min-android-sample/build.gradle.kts index a5bacf7088..69baecb838 100644 --- a/examples/min-android-sample/build.gradle.kts +++ b/examples/min-android-sample/build.gradle.kts @@ -15,8 +15,8 @@ buildscript { maven(url = "https://oss.sonatype.org/content/repositories/snapshots") } dependencies { - classpath("com.android.tools.build:gradle:7.1.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20") + classpath("com.android.tools.build:gradle:8.7.3") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0") classpath("io.realm.kotlin:gradle-plugin:${rootProject.extra["realmVersion"]}") } } diff --git a/examples/min-android-sample/gradle/wrapper/gradle-wrapper.properties b/examples/min-android-sample/gradle/wrapper/gradle-wrapper.properties index a0f7639f7d..d6e308a637 100644 --- a/examples/min-android-sample/gradle/wrapper/gradle-wrapper.properties +++ b/examples/min-android-sample/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/examples/realm-java-compatibility/app/build.gradle b/examples/realm-java-compatibility/app/build.gradle index da72b4e451..fad3802631 100644 --- a/examples/realm-java-compatibility/app/build.gradle +++ b/examples/realm-java-compatibility/app/build.gradle @@ -24,7 +24,7 @@ plugins { apply plugin: "realm-android" android { - compileSdkVersion = 31 + compileSdkVersion = 35 defaultConfig { applicationId "io.realm.kotlin.demo.javacompatibility" diff --git a/examples/realm-java-compatibility/gradle/wrapper/gradle-wrapper.properties b/examples/realm-java-compatibility/gradle/wrapper/gradle-wrapper.properties index f42e62f372..d6e308a637 100644 --- a/examples/realm-java-compatibility/gradle/wrapper/gradle-wrapper.properties +++ b/examples/realm-java-compatibility/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..d94cac9b2f --- /dev/null +++ b/gradle.properties @@ -0,0 +1,100 @@ +# +# Copyright 2020 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. +# + +org.gradle.jvmargs=-Xms512m -Xmx2048m +kotlin.mpp.stability.nowarn=true + +kotlin.code.style=official +android.useAndroidX=true + +# See https://kotlinlang.org/docs/whatsnew18.html#configuration-and-setup +kotlin.mpp.androidSourceSetLayoutVersion=2 + +# Realm Kotlin build options +# +# See https://kotlinlang.org/docs/multiplatform-publish-lib.html +# The main host is responsible for publishing the KMP metadata needed to lookup platform specific +# artifacts. During a publishing process, one host is _required_ to be the main host. +# +# If this property is commented out, the build will publish all publications regardless of what +# `realm.kotlin.targets` is. +realm.kotlin.mainHost=true + +# Which publications to publish. Allowed values are: +# - iosArm64 +# - iosSimulatorArm64 +# - iosX64 +# - jvm +# - macos +# - macosArm64 +# - android +# - gradlePlugin +# - compilerPlugin +# +# If not set, all publications will be published. `metadata` is also a publication but +# is controlled independently by the `realm.kotlin.mainHost` property. +# +# realm.kotlin.targets= + +# Whether or not to build Realm Core on the platform running the build. +# This can be used to prevent certain targets transentively starting a +# native build, which can easily take 30+ minutes. This is e.g. relevant +# when only building docs or compiler/gradle plugins. +realm.kotlin.buildRealmCore=true + +# Comma-seperated list of pre-built JVM native files that should be copied into place, making them +# ready to run or package into the final JVM JARs. +# +# If the list is empty, no files are copied, and must instead be built locally. +# +# The following options are allowed and will copy the prebuilt file if it is placed in the defined location. +# If a platform is enabled, but the file doesn't exist, then the build will crash. +# +# - macos: /packages/cinterop/build/realmMacOsBuild/librealmc.dylib +# - linux: /packages/cinterop/build/realmWindowsBuild/librealmc.so +# - windows: /packages/cinterop/build/realmWindowsBuild/Release/realmc.dll +realm.kotlin.copyNativeJvmLibs= + +# See https://kotlinlang.org/docs/mpp-publish-lib.html#publish-an-android-library +# Allow the default dependency name to match the client debug build type. Otherwise the client project has to +# explicitly specify the debug variant (ex: implementation("io.realm.kotlin:library-base-debug:0.8.0")) +kotlin.android.buildTypeAttribute.keep=false + +# Project setup - See './CONTRIBUTING.md' for description of the project structure and various options. +# includeSdkModules=true +# includeTestModules=true +# Test repository path must be a relative path to the `packages` folder and defined with Linux line seperators. +testRepository=build/m2-buildrepo/ +# Must either be `debug` or `debugMinified` +testBuildType=debug + +# Properties controlling which test server to run sync tests against. Default is a local +# test server that has been started by calling `/tools/sync_test_server/start_local_server.sh` +syncTestUrl=http://localhost:9090 +syncTestAppNamePrefix=test-app +syncTestLoginEmail=unique_user@domain.com +syncTestLoginPassword=password + +# If the public/private apiKey is set, it will take precedence when logging into the Admin API that controls the app +# syncTestUrl=https://realm-qa.mongodb.com +# syncTestLoginPublicApiKey=replace-with-value +# synctestLoginPrivateApiKey=replace-with-value +# syncTestClusterName=replace-with-value + +# The option 'android.disableAutomaticComponentCreation' is deprecated. +# It was removed in version 8.0 of the Android Gradle plugin. +#android.disableAutomaticComponentCreation=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f42e62f372..d6e308a637 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/integration-tests/README.md b/integration-tests/README.md index 6c332e0f83..9d51aa84c7 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -10,3 +10,5 @@ This folder holds the various integration test projects. There are various project with specific Gradle versions that has been proven troublesome with regards to collecting analytics data and a `current` project that will use the versions used to build the SDK. + +# TODO: will configure later \ No newline at end of file diff --git a/integration-tests/gradle/current/gradle/wrapper/gradle-wrapper.properties b/integration-tests/gradle/current/gradle/wrapper/gradle-wrapper.properties index f42e62f372..d6e308a637 100644 --- a/integration-tests/gradle/current/gradle/wrapper/gradle-wrapper.properties +++ b/integration-tests/gradle/current/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/integration-tests/gradle/gradle85-test/single-platform/build.gradle.kts b/integration-tests/gradle/gradle85-test/single-platform/build.gradle.kts index 70fdfc5a71..2defadac36 100644 --- a/integration-tests/gradle/gradle85-test/single-platform/build.gradle.kts +++ b/integration-tests/gradle/gradle85-test/single-platform/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } android { - compileSdk = 33 + compileSdk = 35 namespace = "io.realm.test.singleplatform" diff --git a/packages/build.gradle.kts b/packages/build.gradle.kts deleted file mode 100644 index 3af7043487..0000000000 --- a/packages/build.gradle.kts +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2020 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. - */ -import io.realm.kotlin.getPropertyValue -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -plugins { - id("com.android.library") apply false - id("realm-lint") - `java-gradle-plugin` - id("realm-publisher") - id("org.jetbrains.dokka") version Versions.dokka -} - -allprojects { - version = Realm.version - group = Realm.group - - // Define JVM bytecode target for all Kotlin targets - tasks.withType { - compilerOptions { - jvmTarget.set(JvmTarget.fromTarget(Versions.kotlinJvmTarget)) - } - } -} - -/** - * Task that will build and publish the defined packages to /packages/build/m2-buildrepo`. - * This is mostly suited for CI jobs that wants to build select publications on specific runners. - * - * - * See `gradle.properties` for specific configuration options available to this task. - * - * For local development, using: - * - * ``` - * > ./gradlew publishAllPublicationsToTestRepository - * ``` - * - * will build and publish all targets available to the builder platform. - */ -tasks.register("publishCIPackages") { - group = "Publishing" - description = "Publish packages that has been configured for this CI node. See `gradle.properties`." - - // Figure out which targets are configured. This will impact which sub modules will be published - val availableTargets = setOf( - "iosArm64", - "iosX64", - "jvm", - "macosX64", - "macosArm64", - "android", - "metadata", - "compilerPlugin", - "gradlePlugin" - ) - - val mainHostTarget: Set = setOf("metadata") // "kotlinMultiplatform" - - val isMainHost: Boolean = project.properties["realm.kotlin.mainHost"]?.let { it == "true" } ?: false - - // Find user configured platforms (if any) - val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?) - ?.split(",") - ?.map { it.trim() } - ?.filter { it.isNotEmpty() } - ?.toSet() - - userTargets?.forEach { - if (!availableTargets.contains(it)) { - project.logger.error("Unknown publication: $it") - throw IllegalArgumentException("Unknown publication: $it") - } - } - - // Configure which platforms publications we do want to publish - val publicationTargets = (userTargets ?: availableTargets).let { - when (isMainHost) { - true -> it + mainHostTarget - false -> it - mainHostTarget - } - } - - publicationTargets.forEach { target: String -> - when(target) { - "iosArm64" -> { - dependsOn( - ":cinterop:publishIosArm64PublicationToTestRepository", - ":cinterop:publishIosSimulatorArm64PublicationToTestRepository", - ":library-base:publishIosArm64PublicationToTestRepository", - ":library-base:publishIosSimulatorArm64PublicationToTestRepository", - ":library-sync:publishIosArm64PublicationToTestRepository", - ":library-sync:publishIosSimulatorArm64PublicationToTestRepository", - ) - } - "iosX64" -> { - dependsOn( - ":cinterop:publishIosX64PublicationToTestRepository", - ":library-base:publishIosX64PublicationToTestRepository", - ":library-sync:publishIosX64PublicationToTestRepository", - ) - } - "jvm" -> { - dependsOn( - ":jni-swig-stub:publishAllPublicationsToTestRepository", - ":cinterop:publishJvmPublicationToTestRepository", - ":library-base:publishJvmPublicationToTestRepository", - ":library-sync:publishJvmPublicationToTestRepository", - ) - } - "macosX64" -> { - dependsOn( - ":cinterop:publishMacosX64PublicationToTestRepository", - ":library-base:publishMacosX64PublicationToTestRepository", - ":library-sync:publishMacosX64PublicationToTestRepository", - ) - } - "macosArm64" -> { - dependsOn( - ":cinterop:publishMacosArm64PublicationToTestRepository", - ":library-base:publishMacosArm64PublicationToTestRepository", - ":library-sync:publishMacosArm64PublicationToTestRepository", - ) - } - "android" -> { - dependsOn( - ":jni-swig-stub:publishAllPublicationsToTestRepository", - ":cinterop:publishAndroidReleasePublicationToTestRepository", - ":library-base:publishAndroidReleasePublicationToTestRepository", - ":library-sync:publishAndroidReleasePublicationToTestRepository", - ) - } - "metadata" -> { - dependsOn( - ":cinterop:publishKotlinMultiplatformPublicationToTestRepository", - ":library-base:publishKotlinMultiplatformPublicationToTestRepository", - ":library-sync:publishKotlinMultiplatformPublicationToTestRepository", - ) - } - "compilerPlugin" -> { - dependsOn( - ":plugin-compiler:publishAllPublicationsToTestRepository", - ":plugin-compiler-shaded:publishAllPublicationsToTestRepository" - ) - } - "gradlePlugin" -> { - dependsOn(":gradle-plugin:publishAllPublicationsToTestRepository") - } - else -> { - throw IllegalArgumentException("Unsupported target: $target") - } - } - } -} - -tasks.register("uploadDokka") { - dependsOn("dokkaHtmlMultiModule") - group = "Release" - description = "Upload SDK docs to S3" - doLast { - val awsAccessKey = getPropertyValue(this.project, "SDK_DOCS_AWS_ACCESS_KEY") - val awsSecretKey = getPropertyValue(this.project, "SDK_DOCS_AWS_SECRET_KEY") - - // Failsafe check, ensuring that we catch if the path ever changes, which it might since it is an - // implementation detail of the Kotlin Gradle Plugin - val dokkaDir = File("$rootDir/build/dokka/htmlMultiModule/") - if (!dokkaDir.exists() || !dokkaDir.isDirectory || dokkaDir.listFiles().isEmpty()) { - throw GradleException("Could not locate dir with dokka files in: ${dokkaDir.path}") - } - - // Upload two copies, to 'latest' and a versioned folder for posterity. - // Symlinks would have been safer and faster, but this is not supported by S3. - listOf(Realm.version, "latest").forEach { version: String -> - exec { - commandLine = listOf( - "s3cmd", - "put", - "--no-mime-magic", - "--guess-mime-type", - "--recursive", - "--acl-public", - "--access_key=$awsAccessKey", - "--secret_key=$awsSecretKey", - "${dokkaDir.absolutePath}/", // Add / to only upload content of the folder, not the folder itself. - "s3://realm-sdks/docs/realm-sdks/kotlin/$version/" - ) - } - } - } -} diff --git a/packages/cinterop/build.gradle.kts b/packages/cinterop/build.gradle.kts index 32a61dd7ca..df62540026 100644 --- a/packages/cinterop/build.gradle.kts +++ b/packages/cinterop/build.gradle.kts @@ -23,15 +23,9 @@ plugins { id("org.jetbrains.kotlin.multiplatform") id("com.android.library") id("realm-publisher") + id("org.jetbrains.kotlinx.atomicfu") version Versions.atomicfuPlugin } -buildscript { - dependencies { - classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${Versions.atomicfu}") - } -} - -apply(plugin = "kotlinx-atomicfu") // AtomicFu cannot transform JVM code. Throws // ClassCastException: org.objectweb.asm.tree.InsnList cannot be cast to java.lang.Iterable project.extensions.configure(kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtension::class) { @@ -71,7 +65,7 @@ fun checkIfBuildingNativeLibs(task: Task, action: Task.() -> Unit) { } val corePath = "external/core" -val absoluteCorePath = "$rootDir/$corePath" +val absoluteCorePath = "$rootDir/packages/$corePath" val jvmJniPath = "src/jvmMain/resources/jni" fun includeBinaries(binaries: List): List { @@ -236,7 +230,7 @@ kotlin { val jvm by creating { dependsOn(commonMain) dependencies { - api(project(":jni-swig-stub")) + api(project(":packages:jni-swig-stub")) } } val jvmMain by getting { @@ -426,7 +420,8 @@ val buildJVMSharedLibs: TaskProvider by tasks.registering { } else if (HOST_OS.isWindows()) { buildSharedLibrariesForJVMWindows() } else { - throw IllegalStateException("Building JVM libraries on this platform is not supported: $HOST_OS") + buildSharedLibrariesForJVMLinux() +// throw IllegalStateException("Building JVM libraries on this platform is not supported: $HOST_OS") } } @@ -540,6 +535,42 @@ fun Task.buildSharedLibrariesForJVMMacOs() { outputs.file(project.file("$jvmJniPath/macos/librealmc.dylib")) } +fun Task.buildSharedLibrariesForJVMLinux() { + group = "Build" + description = "Compile dynamic libraries loaded by the JVM fat jar for supported platforms." + val directory = "$buildDir/realmLinuxBuild" + + doLast { + exec { + commandLine("mkdir", "-p", directory) + } + exec { + workingDir(project.file(directory)) + commandLine( + "cmake", + *getSharedCMakeFlags(BuildType.RELEASE), + "-DCPACK_PACKAGE_DIRECTORY=..", + project.file("src/jvm/") + ) + } + exec { + workingDir(project.file(directory)) + commandLine("cmake", "--build", ".", "-j8") + } + + // copy files (macos) + exec { + commandLine("mkdir", "-p", project.file("$jvmJniPath/linux")) + } + File("$directory/librealmc.so") + .copyTo(project.file("$jvmJniPath/linux/librealmc.so"), overwrite = true) + } + + inputs.dir(project.file("src/jvm")) + inputs.dir(project.file("$absoluteCorePath/src")) + outputs.file(project.file("$jvmJniPath/linux/librealmc.so")) +} + fun Task.buildSharedLibrariesForJVMWindows() { group = "Build" description = "Compile dynamic libraries loaded by the JVM fat jar for supported platforms." @@ -709,10 +740,10 @@ afterEvaluate { // the cpp file as it somehow processes the CMakeList.txt-file, but haven't dug up the // actuals tasks.named("generateJsonModelDebug") { - inputs.files(tasks.getByPath(":jni-swig-stub:realmWrapperJvm").outputs) + inputs.files(tasks.getByPath(":packages:jni-swig-stub:realmWrapperJvm").outputs) } tasks.named("generateJsonModelRelease") { - inputs.files(tasks.getByPath(":jni-swig-stub:realmWrapperJvm").outputs) + inputs.files(tasks.getByPath(":packages:jni-swig-stub:realmWrapperJvm").outputs) } } @@ -817,4 +848,10 @@ abstract class CmakeVersionProvider : ValueSource { 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 8c8d6d617b..9663faa9c9 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 @@ -226,7 +226,7 @@ val FirClassSymbol<*>.isBaseRealmObject: Boolean ) } // After SUPERTYPES stage - is FirResolvedTypeRef -> typeRef.type.classId in realmObjectClassIds + is FirResolvedTypeRef -> typeRef.coneType.classId in realmObjectClassIds else -> false } } @@ -424,7 +424,7 @@ data class SchemaProperty( companion object { fun getPersistedName(declaration: IrProperty): String { @Suppress("UNCHECKED_CAST") - return (declaration.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value + return (declaration.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value?.toString() ?: "" } } } @@ -446,22 +446,22 @@ internal fun buildOf( type = containerType.typeWith(elementType), symbol = function, typeArgumentsCount = 1, - valueArgumentsCount = 1, +// valueArgumentsCount = 1, origin = null, - superQualifierSymbol = null - ).apply { - putTypeArgument(index = 0, type = elementType) - putValueArgument( - index = 0, - valueArgument = IrVarargImpl( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - context.irBuiltIns.arrayClass.typeWith(elementType), - type, - args.toList() + superQualifierSymbol = null) + .apply { + putTypeArgument(index = 0, type = elementType) + putValueArgument( + index = 0, + valueArgument = IrVarargImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + context.irBuiltIns.arrayClass.typeWith(elementType), + type, + args.toList() + ) ) - ) - } + } } internal fun buildSetOf( @@ -593,11 +593,16 @@ fun IrBlockBuilder.createSafeCallConstruction( statements += receiverVariable statements += IrWhenImpl(startOffset, endOffset, resultType).apply { val condition = IrCallImpl( - startOffset, endOffset, context.irBuiltIns.booleanType, - context.irBuiltIns.eqeqSymbol, - valueArgumentsCount = 2, + startOffset = startOffset, endOffset = endOffset, + type = context.irBuiltIns.booleanType, + symbol = context.irBuiltIns.eqeqSymbol, typeArgumentsCount = 0, origin = IrStatementOrigin.EQEQ +// startOffset, endOffset, context.irBuiltIns.booleanType, +// context.irBuiltIns.eqeqSymbol, +// valueArgumentsCount = 2, +// typeArgumentsCount = 0, +// origin = IrStatementOrigin.EQEQ ).apply { putValueArgument(0, IrGetValueImpl(startOffset, endOffset, receiverVariableSymbol)) putValueArgument( @@ -684,7 +689,7 @@ fun getLinkingObjectPropertyName(backingField: IrField): String { fun getSchemaClassName(clazz: IrClass): String { return if (clazz.hasAnnotation(PERSISTED_NAME_ANNOTATION)) { @Suppress("UNCHECKED_CAST") - return (clazz.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value + return (clazz.getAnnotation(PERSISTED_NAME_ANNOTATION.asSingleFqName()).getValueArgument(0)!! as IrConstImpl).value?.toString() ?: "" } else { clazz.name.identifier } diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt index 71b741a572..9ed91f828c 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelDefaultMethodGeneration.kt @@ -76,7 +76,7 @@ class RealmModelDefaultMethodGeneration(private val pluginContext: IrPluginConte type = pluginContext.irBuiltIns.booleanType, symbol = realmEquals.symbol, typeArgumentsCount = 0, - valueArgumentsCount = 2 +// valueArgumentsCount = 2 ).apply { dispatchReceiver = irGetObject(realmObjectHelper.symbol) putValueArgument(0, irGet(function.dispatchReceiverParameter!!.type, function.dispatchReceiverParameter!!.symbol)) @@ -96,7 +96,7 @@ class RealmModelDefaultMethodGeneration(private val pluginContext: IrPluginConte type = pluginContext.irBuiltIns.intType, symbol = realmHashCode.symbol, typeArgumentsCount = 0, - valueArgumentsCount = 1 +// valueArgumentsCount = 1 ).apply { dispatchReceiver = irGetObject(realmObjectHelper.symbol) putValueArgument(0, irGet(function.dispatchReceiverParameter!!.type, function.dispatchReceiverParameter!!.symbol)) @@ -115,7 +115,7 @@ class RealmModelDefaultMethodGeneration(private val pluginContext: IrPluginConte type = pluginContext.irBuiltIns.stringType, symbol = realmToString.symbol, typeArgumentsCount = 0, - valueArgumentsCount = 1 +// valueArgumentsCount = 1 ).apply { dispatchReceiver = irGetObject(realmObjectHelper.symbol) putValueArgument(0, irGet(function.dispatchReceiverParameter!!.type, function.dispatchReceiverParameter!!.symbol)) diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt index 91e726f159..6aa453e61e 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelLoweringExtension.kt @@ -32,10 +32,13 @@ import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.starProjectedType +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isAnonymousObject @@ -118,11 +121,14 @@ private class RealmModelLowering(private val pluginContext: IrPluginContext) : C // able to resolve the companion object during runtime due to absence of // kotlin.reflect.full.companionObjectInstance if (pluginContext.platform.isNative()) { + val type = modelObjectAnnotationClass.defaultType as? IrType ?: throw IllegalStateException("defaultType is not an IrType") + val primaryConstructor = modelObjectAnnotationClass.primaryConstructor ?: throw IllegalStateException("primaryConstructor is null") + val constructorSymbol = primaryConstructor.symbol as? IrConstructorSymbol ?: throw IllegalStateException("symbol is not an IrConstructorSymbol") val modelObjectAnnotation = IrConstructorCallImpl.fromSymbolOwner( startOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET, - type = modelObjectAnnotationClass.defaultType, - constructorSymbol = modelObjectAnnotationClass.primaryConstructor!!.symbol + type = type, + constructorSymbol = constructorSymbol ).apply { putValueArgument( 0, diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt index 0ce7399497..e922bda1ae 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/RealmModelSyntheticPropertiesGeneration.kt @@ -92,6 +92,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrPropertyReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType @@ -303,7 +304,7 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi type = companionFieldsType, symbol = mapOf, typeArgumentsCount = 2, - valueArgumentsCount = 1, +// valueArgumentsCount = 1, origin = null, superQualifierSymbol = null ).apply { @@ -333,15 +334,14 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi symbol = propertyElementType.classOrNull!!, classType = propertyElementType.classOrNull!!.defaultType, ) - val objectPropertyType = if (it.value.isComputed) realmObjectPropertyType else - realmObjectMutablePropertyType + val objectPropertyType = if (it.value.isComputed) realmObjectPropertyType else realmObjectMutablePropertyType val elementType = pairClass.typeWith(pluginContext.irBuiltIns.kClassClass.typeWith(), objectPropertyType) // Pair>>() IrConstructorCallImpl.fromSymbolOwner( startOffset = startOffset, endOffset = endOffset, - type = elementType, - constructorSymbol = pairCtor + type = elementType as IrType, + constructorSymbol = pairCtor as org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol ).apply { putTypeArgument(0, pluginContext.irBuiltIns.stringType) putTypeArgument(1, elementType) @@ -359,8 +359,8 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi IrConstructorCallImpl.fromSymbolOwner( startOffset = startOffset, endOffset = endOffset, - type = elementType, - constructorSymbol = pairCtor + type = elementType as IrType, + constructorSymbol = pairCtor as org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol ).apply { putTypeArgument( 0, @@ -507,7 +507,7 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi type = classInfoClass.defaultType, symbol = classInfoCreateMethod.symbol, typeArgumentsCount = 0, - valueArgumentsCount = 5 +// valueArgumentsCount = 5 ).apply { dispatchReceiver = irGetObject(classInfoClass.companionObject()!!.symbol) var arg = 0 @@ -714,7 +714,7 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi } ?: irNull(pluginContext.irBuiltIns.kClassClass.typeWith(typedRealmObjectInterface.defaultType).makeNullable()) // Define the link target. Empty string if there is none. - val linkPropertyName: IrConst = if (type == linkingObjectType) { + val linkPropertyName: IrConst = if (type == linkingObjectType) { val targetPropertyName = getLinkingObjectPropertyName(backingField) irString(targetPropertyName) } else { @@ -727,7 +727,7 @@ class RealmModelSyntheticPropertiesGeneration(private val pluginContext: IrPlugi type = propertyClass.defaultType, symbol = propertyCreateMethod, typeArgumentsCount = 0, - valueArgumentsCount = 10 +// valueArgumentsCount = 10 ).apply { var arg = 0 // Persisted name diff --git a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt index d5a11767f2..fa95ccbe1e 100644 --- a/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt +++ b/packages/plugin-compiler/src/main/kotlin/io/realm/kotlin/compiler/SyncLoweringExtension.kt @@ -140,7 +140,7 @@ private class SyncLowering(private val pluginContext: IrPluginContext, private v type = expression.type, symbol = target.symbol, typeArgumentsCount = 0, - valueArgumentsCount = target.valueParameters.size, +// valueArgumentsCount = target.valueParameters.size, origin = null, superQualifierSymbol = null ).apply { 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 0ec41e8eb7..0e5b672285 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 @@ -66,7 +66,7 @@ class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtensio classSymbol: FirClassSymbol<*>, context: MemberGenerationContext ): Set { - if (classSymbol.isCompanion && (classSymbol.getContainingClassSymbol(session) as? FirClassSymbol<*>)?.isBaseRealmObject == true) { + if (classSymbol.isCompanion && (classSymbol.getContainingClassSymbol() as? FirClassSymbol<*>)?.isBaseRealmObject == true) { return setOf( Names.REALM_OBJECT_COMPANION_SCHEMA_METHOD, Names.REALM_OBJECT_COMPANION_NEW_INSTANCE_METHOD, @@ -88,7 +88,7 @@ class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtensio owner, RealmPluginGeneratorKey, callableId.callableName, - session.builtinTypes.anyType.type, + session.builtinTypes.anyType.coneType, ).symbol ) @@ -98,7 +98,7 @@ class CompanionExtension(session: FirSession) : FirDeclarationGenerationExtensio owner, RealmPluginGeneratorKey, callableId.callableName, - session.builtinTypes.anyType.type + session.builtinTypes.anyType.coneType ).symbol ) 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 6869c6243f..358b8bcfda 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 @@ -67,7 +67,7 @@ class ObjectExtension(session: FirSession) : FirDeclarationGenerationExtension(s owner, RealmPluginGeneratorKey, callableId.callableName, - session.builtinTypes.stringType.type, + session.builtinTypes.stringType.coneType, ) { modality = Modality.OPEN }.symbol @@ -78,10 +78,10 @@ class ObjectExtension(session: FirSession) : FirDeclarationGenerationExtension(s owner, RealmPluginGeneratorKey, callableId.callableName, - session.builtinTypes.booleanType.type, + session.builtinTypes.booleanType.coneType, ) { modality = Modality.OPEN - valueParameter(Name.identifier("other"), session.builtinTypes.nullableAnyType.type) + valueParameter(Name.identifier("other"), session.builtinTypes.nullableAnyType.coneType) }.symbol ) Names.REALM_OBJECT_HASH_CODE -> @@ -90,7 +90,7 @@ class ObjectExtension(session: FirSession) : FirDeclarationGenerationExtension(s owner, RealmPluginGeneratorKey, callableId.callableName, - session.builtinTypes.intType.type, + session.builtinTypes.intType.coneType, ) { modality = Modality.OPEN }.symbol diff --git a/packages/settings.gradle.kts b/packages/settings.gradle.kts index 6ea6605fde..e95bc1544e 100644 --- a/packages/settings.gradle.kts +++ b/packages/settings.gradle.kts @@ -35,20 +35,20 @@ fun getPropertyValue(propertyName: String): String? { return systemValue } -(getPropertyValue("includeSdkModules")?.let { it.toBoolean() } ?: true).let { - if (it) { - include(":gradle-plugin") - include(":plugin-compiler") - include(":plugin-compiler-shaded") - include(":library-base") - include(":library-sync") - include(":cinterop") - include(":jni-swig-stub") - } -} -(getPropertyValue("includeTestModules")?.let { it.toBoolean() } ?: true).let { - if (it) { - include(":test-base") - include(":test-sync") - } -} +//(getPropertyValue("includeSdkModules")?.let { it.toBoolean() } ?: true).let { +// if (it) { +// include(":gradle-plugin") +// include(":plugin-compiler") +// include(":plugin-compiler-shaded") +// include(":library-base") +// include(":library-sync") +// include(":cinterop") +// include(":jni-swig-stub") +// } +//} +//(getPropertyValue("includeTestModules")?.let { it.toBoolean() } ?: true).let { +// if (it) { +// include(":test-base") +// include(":test-sync") +// } +//} diff --git a/packages/test-base/build.gradle.kts b/packages/test-base/build.gradle.kts index 3fc4722ce4..4f884fd129 100644 --- a/packages/test-base/build.gradle.kts +++ b/packages/test-base/build.gradle.kts @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTests import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile -import kotlin.math.min plugins { id("org.jetbrains.kotlin.multiplatform") @@ -32,7 +31,9 @@ plugins { // Test relies on the compiler plugin, but we cannot apply our full plugin from within the same // gradle run, so we just apply the compiler plugin directly dependencies { - kotlinCompilerPluginClasspath("io.realm.kotlin:plugin-compiler:${Realm.version}") + implementation(project(":packages:library-base")) +// kotlinCompilerPluginClasspath("io.realm.kotlin:plugin-compiler:${Realm.version}") + kotlinCompilerPluginClasspath(project(":packages:plugin-compiler")) kotlinNativeCompilerPluginClasspath("io.realm.kotlin:plugin-compiler-shaded:${Realm.version}") kotlinCompilerClasspath("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") kotlinCompilerClasspath("org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:${Versions.kotlin}") @@ -43,10 +44,10 @@ dependencies { configurations.all { resolutionStrategy.dependencySubstitution { rootProject.allprojects - .filter { it != project && it != rootProject } + .filter { it != project && it != rootProject && it.name != "packages"} .forEach { subproject: Project -> substitute(module("io.realm.kotlin:${subproject.name}:${Realm.version}")).using( - project(":${subproject.name}") + if (subproject.name != "packages") project(":packages:${subproject.name}") else project(":${subproject.name}") ) } } @@ -81,13 +82,13 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}") // FIXME AUTO-SETUP Removed automatic dependency injection to ensure observability of // requirements for now - implementation("io.realm.kotlin:library-base:${Realm.version}") + implementation(project(":packages:library-base")) // FIXME API-SCHEMA We currently have some tests that verified injection of // interfaces, uses internal representation for property meta data, etc. Can // probably be replaced when schema information is exposed in the public API // Our current compiler plugin tests only runs on JVM, so makes sense to keep them // for now, but ideally they should go to the compiler plugin tests. - implementation("io.realm.kotlin:cinterop:${Realm.version}") + implementation(project(":packages:cinterop")) implementation("org.jetbrains.kotlinx:atomicfu:${Versions.atomicfu}") implementation("com.squareup.okio:okio:${Versions.okio}") implementation("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.datetime}") @@ -100,7 +101,9 @@ kotlin { dependencies { // TODO AtomicFu doesn't work on the test project due to // https://github.com/Kotlin/kotlinx.atomicfu/issues/90#issuecomment-597872907 - implementation("co.touchlab:stately-concurrency:1.2.0") + + implementation("co.touchlab:stately-concurrency:2.1.0") + implementation(kotlin("test")) implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.coroutines}") @@ -188,6 +191,7 @@ kotlin { // Realm dependencies must be converted to -jvm variants here. // This is currently done using dependency substitution in `build.gradle`. // See https://kotlinlang.slack.com/archives/C19FD9681/p1685089661499199 + implementation(kotlin("test")) } } val androidInstrumentedTest by getting { @@ -215,7 +219,8 @@ kotlin { dependencies { // TODO AtomicFu doesn't work on the test project due to // https://github.com/Kotlin/kotlinx.atomicfu/issues/90#issuecomment-597872907 - implementation("co.touchlab:stately-concurrency:1.2.0") + implementation("co.touchlab:stately-concurrency:2.1.0") + implementation(kotlin("test")) implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.coroutines}") @@ -229,7 +234,7 @@ kotlin { sourceSets { val jvmMain by getting { dependencies { - implementation("io.realm.kotlin:plugin-compiler:${Realm.version}") + implementation(project(":packages:plugin-compiler")) implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${Versions.kotlin}") implementation("dev.zacsweers.kctfork:core:${Versions.kotlinCompileTesting}") } diff --git a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/BacklinksTests.kt b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/BacklinksTests.kt index 04e299fe5b..ae92a16f99 100644 --- a/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/BacklinksTests.kt +++ b/packages/test-base/src/jvmTest/kotlin/io/realm/kotlin/test/compiler/BacklinksTests.kt @@ -42,11 +42,15 @@ class BacklinksTests { fun `unsupported types`() { unsupportedTypes.forEach { entry -> val (type, value) = entry + println("Testing type: $type, value: $value") val result = createFileAndCompile( "unsupportedTypes.kt", TARGET_INVALID_TYPE.format(type, value) ) + println("Exit code: ${result.exitCode}") + println("Messages: ${result.messages}") + assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode) assertContains( result.messages, diff --git a/packages/test-sync/build.gradle.kts b/packages/test-sync/build.gradle.kts0 similarity index 100% rename from packages/test-sync/build.gradle.kts rename to packages/test-sync/build.gradle.kts0 diff --git a/settings.gradle.kts b/settings.gradle.kts index de30f48a8e..14610f20bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,3 +17,38 @@ rootProject.name = "realm-kotlin-root" +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } + resolutionStrategy { + eachPlugin { +// if (requested.id.id.startsWith("org.example.buildsrc")) { +// useModule("org.example:buildSrc:${pluginManagement.version}") +// } + if (requested.id.id == "kotlinx-atomicfu") { + useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.27.0") + } + } + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +include(":packages:gradle-plugin") +include(":packages:plugin-compiler") +include(":packages:plugin-compiler-shaded") +include(":packages:library-base") +include(":packages:library-sync") +include(":packages:cinterop") +include(":packages:jni-swig-stub") + +include(":packages:test-base") +include(":packages:test-sync") diff --git a/widgets.qss b/widgets.qss new file mode 100644 index 0000000000..9af680993f --- /dev/null +++ b/widgets.qss @@ -0,0 +1,604 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Megan Conkle + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/******************************************************************************/ +/* Scrollbars */ +/******************************************************************************/ + +ghostwriter--MarkdownEditor QAbstractScrollArea::corner, +ghostwriter--HtmlPreview QAbstractScrollArea::corner, +ghostwriter--Sidebar QAbstractScrollArea::corner { + background: transparent; +} + +ghostwriter--MarkdownEditor QAbstractScrollArea, +ghostwriter--HtmlPreview QAbstractScrollArea, +ghostwriter--Sidebar QAbstractScrollArea { + padding: 3px 3px 0px 3px; + margin: 0 +} + +ghostwriter--Sidebar MarkdownEditor::horizontal, +ghostwriter--Sidebar HtmlPreview::horizontal, +ghostwriter--Sidebar QScrollBar::horizontal { + height: 16px; + margin: 5px; + border: 0; + background: transparent; +} + +ghostwriter--MarkdownEditor QScrollBar::vertical, +ghostwriter--HtmlPreview QScrollBar::vertical, +ghostwriter--Sidebar QScrollBar::vertical { + width: 16px; + margin: 5px; + border: 0; + background: transparent; +} + + +ghostwriter--MarkdownEditor QScrollBar::horizontal:hover, +ghostwriter--HtmlPreview QScrollBar::horizontal:hover, +ghostwriter--Sidebar QScrollBar::horizontal:hover { + background-color: #202325; + border-radius: 3px; +} + +ghostwriter--MarkdownEditor QScrollBar::vertical:hover, +ghostwriter--HtmlPreview QScrollBar::vertical:hover, +ghostwriter--Sidebar QScrollBar::vertical:hover { + background-color: #202325; + border-radius: 3px; +} + +ghostwriter--MarkdownEditor QScrollBar::handle:horizontal, +ghostwriter--HtmlPreview QScrollBar::handle:horizontal, +ghostwriter--Sidebar QScrollBar::handle:horizontal { + min-width: 50px; + border: 0; + background: #444749; + border-radius: 3px; + +} + +ghostwriter--MarkdownEditor QScrollBar::handle:horizontal, +ghostwriter--HtmlPreview QScrollBar::handle:horizontal, +ghostwriter--Sidebar QScrollBar::handle:horizontal { + min-width: 50px; + border: 0; + background: #444749; + border-radius: 3px; +} + +ghostwriter--MarkdownEditor QScrollBar::handle:vertical, +ghostwriter--HtmlPreview QScrollBar::handle:vertical, +ghostwriter--Sidebar QScrollBar::handle:vertical { + min-height: 50px; + border: 0; + background: #444749; + border-radius: 3px; +} + +ghostwriter--MarkdownEditor QScrollBar::handle:horizontal:hover, +ghostwriter--HtmlPreview QScrollBar::handle:horizontal:hover, +ghostwriter--Sidebar QScrollBar::handle:horizontal:hover { + background: #3daee9; +} + +ghostwriter--MarkdownEditor QScrollBar::handle:vertical:hover, +ghostwriter--HtmlPreview QScrollBar::handle:vertical:hover, +ghostwriter--Sidebar QScrollBar::handle:vertical:hover { + background: #3daee9; +} + +ghostwriter--MarkdownEditor QScrollBar::add-line, +ghostwriter--HtmlPreview QScrollBar::add-line, +ghostwriter--Sidebar QScrollBar::add-line, +ghostwriter--MarkdownEditor QScrollBar::sub-line, +ghostwriter--HtmlPreview QScrollBar::sub-line, +ghostwriter--Sidebar QScrollBar::sub-line, +ghostwriter--MarkdownEditor QScrollBar::add-page, +ghostwriter--HtmlPreview QScrollBar::add-page, +ghostwriter--Sidebar QScrollBar::add-page, +ghostwriter--MarkdownEditor QScrollBar::sub-page, +ghostwriter--HtmlPreview QScrollBar::sub-page, +ghostwriter--Sidebar QScrollBar::sub-page, +ghostwriter--MarkdownEditor QScrollBar::down-arrow, +ghostwriter--HtmlPreview QScrollBar::down-arrow, +ghostwriter--Sidebar QScrollBar::down-arrow, +ghostwriter--MarkdownEditor QScrollBar::right-arrow, +ghostwriter--HtmlPreview QScrollBar::right-arrow, +ghostwriter--Sidebar QScrollBar::right-arrow { + background: transparent; + border: 0 +} + +/******************************************************************************/ +/* Menu Bar */ +/******************************************************************************/ + +QMainWindow QMenuBar { + color: #bdc3c7; + background-color: #151719; + font-size: 10pt; + spacing: 2px; + border: 0px; + border-bottom: 1px; + border-color: #2c2f31; + border-style: solid; + padding: 1px 0px 1px 0px; +} + +QMainWindow QMenuBar::item { + padding: 2px 7px 2px 7px; + border: 0px; + margin: 2px; + border-radius: 5px; +} + +QMainWindow QMenuBar::item:selected { + background-color: #25282c; +} + +QMainWindow QMenuBar::item:hover { + background-color: #373d42; +} + +QMainWindow QMenuBar::item:pressed { + background-color: #1f2225; +} + +/******************************************************************************/ +/* Popup menus */ +/******************************************************************************/ + +QMainWindow QMenu, +QMenuBar QMenu { + color: #bdc3c7; + background-color: #1a1d1f; + border: 0px; + padding: 7px 0px 7px 0px; +} + +QMainWindow QMenu::item, +QMenuBar QMenu::item { + background-color: transparent; + padding: 5px 10px 5px 10px; + margin: 0px 0px 0px 0px; +} + +QMainWindow QMenu::indicator, +QMenuBar QMenu::indicator { + width: 16px; + height: 16px; + background-color: #25282c; + padding: 0px 5px 0px 5px; + margin: 0px 5px 0px 5px; +} + +QMainWindow QMenu::indicator::unchecked, +QMenuBar QMenu::indicator::unchecked { + width: 16px; + height: 16px; + background-color: #25282c; + border-radius: 2px; + border-style: solid; + border-width: 1px; + border-color: #bdc3c7; + margin: 0px 5px 0px 5px; +} + +QMainWindow QMenu::indicator::checked, +QMenuBar QMenu::indicator::checked { + width: 16px; + height: 16px; + background-color: #074051; + border-radius: 2px; + border-style: solid; + border-width: 1px; + border-color: #bdc3c7; + margin: 0px 5px 0px 5px; +} + +QMainWindow QMenu::item:selected, +QMenuBar QMenu::item::selected { + background-color: #074051; + color: #bdc3c7; +} + +QMainWindow QMenu::icon, +QMenuBar QMenu::icon { + border-radius: 2px; + border-width: 0px; + padding: 1px 3px 1px 3px; + margin: 0px 3px 0px 3px; +} + +QMainWindow QMenu::icon::checked, +QMenuBar QMenu::icon::checked { + background-color: #373d42; +} + +/******************************************************************************/ +/* Editor */ +/******************************************************************************/ + +QMainWindow QPlainTextEdit { + border: 0; + margin: 0; + padding: 5px; + background-color: #151719; + color: #bdc3c7; + selection-color: #bdc3c7; + selection-background-color: #074051; + font-family: Noto Sans Mono; + font-size: 16pt; +} + +QMainWindow QSplitter::handle { + border: 0; + padding: 0; + margin: 0; + background-color: #2c2f31; +} + +QMainWindow QSplitter::handle:vertical { + height: 1px; +} + +QMainWindow QSplitter::handle:horizontal { + width: 1px; +} + +/******************************************************************************/ +/* Sidebar and Activity Bar */ +/******************************************************************************/ + +/* Sidebar */ +QMainWindow ghostwriter--Sidebar, +QSplitter ghostwriter--Sidebar { + border: 0; + margin: 0; + padding: 0; + background-color: #151719; +} + +ghostwriter--Sidebar QStackedWidget { + border: 0; + padding: 1; + margin: 0; + background-color: #151719; + border-width: 0px; +} + +/* Activity bar tabs */ +ghostwriter--Sidebar QPushButton[checkable="true"] { + icon-size: 22px; + min-width: 40px; + max-width: 40px; + height: 40px; + outline: none; + margin: 0; + padding: 0; + border: 0; + background-color: transparent; + color: #8b8f92; + border-width: 0px; + border-left-width: 3px; + border-style: solid; + border-color: transparent; + border-radius: 0px; +} + +ghostwriter--Sidebar QPushButton:checked { + border-color: #3daee9; + color: #bdc3c7; + background-color: #202325; +} + +ghostwriter--Sidebar QPushButton:hover { + background-color: #202325; +} + +ghostwriter--Sidebar QPushButton:checked:hover { + border-color: #3daee9; + color: #bdc3c7; + background-color: #202325; +} + +/* Activity bar buttons */ +ghostwriter--Sidebar QPushButton[checkable="false"] { + icon-size: 22px; + padding: 0; + margin: 0; + border: 0; + border-radius: 5px; + background-color: transparent; + color: #8b8f92; + width: 40px; + height: 40px; +} + +ghostwriter--Sidebar QPushButton[checkable="false"]:hover { + color: #bdc3c7; + background-color: #202325; +} + +ghostwriter--Sidebar QPushButton[checkable="false"]:pressed { + color: #bdc3c7; + background-color: transparent; +} + +/* Stacked widgets inside sidebar pane */ + +ghostwriter--Sidebar QListWidget { + outline: none; + border: 0; + padding: 1; + background-color: #151719; + color: #bdc3c7; + font-size: 11pt; + font-weight: normal +} + +ghostwriter--Sidebar QListWidget::item { + border: 0; + padding: 1 0 1 0; + margin: 0; + background-color: #151719; + color: #bdc3c7; + font-weight: normal +} + +ghostwriter--Sidebar QListWidget::item:selected { + border-radius: 0px; + color: #bdc3c7; + background-color: #074051; +} + +ghostwriter--Sidebar QLabel { + border: 0; + padding: 0; + margin: 0; + background-color: transparent; + font-size: 11pt; + color: #bdc3c7; +} + +/******************************************************************************/ +/* Status bar */ +/******************************************************************************/ + +QStatusBar { + margin: 0; + padding: 0; + border-top: 1px solid #2c2f31; + border-left: 0; + border-right: 0; + border-bottom: 0; + background: #151719; + color: #8b8f92; +} + +QStatusBar QLabel { + font-size: 11pt; + margin: 0px; + padding: 5px; + border: 0; + background: transparent; + color: #8b8f92; +} + +QStatusBar QToolButton { + padding: 5 5 5 5; + margin: 0; + border: 0; + border-radius: 5px; + color: #8b8f92; + background-color: transparent; + font-size: 16px; + width: 32px; + height: 16px; +} + +QStatusBar QToolButton:hover, +QStatusBar QToolButton:checked:hover { + background-color: #373d42; +} + +QStatusBar QToolButton:pressed, +QStatusBar QToolButton:checked:pressed { + color: #73777a; + background-color: #1f2225; +} + +QStatusBar QToolButton:flat, +QStatusBar QToolButton:checked { + background-color: #25282c; +} + +QStatusBar QComboBox { + height: 22px; + border: 0px; + margin: 0; + padding: 0; + color: #8b8f92; + background-color: #151719; + font-size: 11pt; +} + +QStatusBar QComboBox:hover { + border-bottom: 2px solid #3daee9; +} + +QStatusBar QListView { + padding: 7px 0px 7px 0px; + margin: 0px; + color: #bdc3c7; + background-color: #151719; +} + +QStatusBar QListView::item { + background-color: transparent; + padding: 5px 10px 5px 10px; + margin: 0px; +} + +QStatusBar QListView::item:selected { + background-color: #074051; + color: #bdc3c7; +} + +QStatusBar QComboBox::drop-down { + border: 0; + margin: 0; + padding: 0; + height: 20px; + width: 20px; +} + +QStatusBar QComboBox::down-arrow { + border: 0; + margin: 0; + padding: 0; + height: 14px; + width: 14px; + image: url(/tmp/KbaWnf.png) +} + +QStatusBar QComboBox::drop-down:hover { + border-radius: 10px; + background-color: #373d42; +} + +QStatusBar #leftStatusBarWidget, +QStatusBar #midStatusBarWidget, +QStatusBar #rightStatusBarWidget { + border: 0; + margin: 0; + padding: 0; +} + +/******************************************************************************/ +/* Find and Replace Pane */ +/******************************************************************************/ + +ghostwriter--FindReplace QLabel { + font-size: 11pt; + margin: 0px; + padding: 5px; + border: 0; + background: transparent; + color: #8b8f92; +} + +ghostwriter--FindReplace QPushButton { + font-size: 16px; + padding: 5 5 5 5; + margin: 0; + border: 0; + border-radius: 5px; + color: #8b8f92; + background-color: transparent; + min-width: 16px; +} + +ghostwriter--FindReplace QPushButton:pressed { + color: #9da2a6; + background-color: transparent; +} + +ghostwriter--FindReplace QPushButton:hover { + color: #ffffff; + background-color: transparent; +} + +ghostwriter--FindReplace QPushButton:disabled { + color: #adb3b6; + background-color: transparent; +} + +ghostwriter--FindReplace QPushButton[checkable="true"] { + color: #8b8f92; + background-color: transparent; + min-width: 32px; + height: 16px; +} + +ghostwriter--FindReplace QPushButton[checkable="true"]:disabled, +ghostwriter--FindReplace QPushButton:flat:disabled { + color: #adb3b6; + background-color: #272a2e; +} + +ghostwriter--FindReplace QPushButton[checkable="true"]:hover, +ghostwriter--FindReplace QPushButton:checked:hover { + background-color: #d0d7db; + background-color: #373d42; +} + +ghostwriter--FindReplace QPushButton[checkable="true"]:pressed, +ghostwriter--FindReplace QPushButton:checked:pressed { + color: #73777a; + background-color: #1f2225; +} + +ghostwriter--FindReplace QPushButton:checked { + background-color: #25282c; +} + +ghostwriter--FindReplace QPushButton:flat { + color: #8b8f92; + background-color: #25282c; + font-weight: bold; +} + +ghostwriter--FindReplace QPushButton:flat:hover { + color: #d0d7db; + background-color: #373d42; +} + +ghostwriter--FindReplace QPushButton:flat:pressed { + color: #73777a; + background-color: #1f2225; +} + +ghostwriter--FindReplace QPushButton:flat:disabled { + color: #adb3b6; + background-color: #272a2e; +} + +ghostwriter--FindReplace QPushButton#matchCaseButton, +ghostwriter--FindReplace QPushButton#regexButton { + font-size: 16px; + font-family: default; + font-weight: bold; +} + +ghostwriter--FindReplace QPushButton#replaceButton, +ghostwriter--FindReplace QPushButton#replaceAllButton { + font-size: 11pt; + font-family: default; +} + +ghostwriter--FindReplace QPushButton#findReplaceCloseButton { + padding: 0; + margin: 0; + icon-size: 16px; +} + +ghostwriter--FindReplace QLineEdit { + color: #bdc3c7; + background-color: #202325; + border: 0px; + border-radius: 3px; + selection-color: #bdc3c7; + selection-background-color: #074051; +} + +ghostwriter--FindReplace QLineEdit:focus { + border: 1px solid #1d2022; +}