From 48b313f85aa83016a4cd94cfaffd9c3d49b0257e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 9 Jun 2026 13:25:56 +0200 Subject: [PATCH 1/4] chore: Phase 0 toolchain upgrade for spm4Kmp migration Prerequisite toolchain bump that unblocks the planned CocoaPods -> spm4Kmp internal Apple build migration, with no public API/ABI change. - Bump Kotlin 2.2.21, Gradle 8.13, AGP 8.7.3, compileSdk 35; plugins (vanniktech-publish 0.30.0, kover 0.9.1, detekt 1.23.8, dokka 1.9.20, buildkonfig 0.17.1, spotless 7.0.2), serialization 1.7.3, coroutines 1.9.0, Compose 1.9.0 - Migrate vanniktech publish DSL, kover 0.9 DSL, AGP 8 namespace, and kotlinOptions -> compilerOptions (SDK + plugin + samples) - ktlint 1.x reformat via spotlessApply + .editorconfig; regenerate detekt baseline - Fix no-op stub target test wiring, Cocoa log-level cinterop type, and tv/watch/macOS test wrappers under Kotlin 2.2.21 - Add SPM4KMP_MIGRATION.md tracking doc (Phase 0 verified green: SDK + plugin build/tests, apiCheck, detekt, and Apple samples incl. CocoaPods xcodebuild) Co-Authored-By: Claude Opus 4.8 Co-authored-by: Cursor --- .editorconfig | 8 + build.gradle.kts | 104 +- buildSrc/src/main/java/Config.kt | 26 +- buildSrc/src/main/java/Publication.kt | 50 +- config/detekt/baseline.xml | 27 + gradle.properties | 7 + gradle/wrapper/gradle-wrapper.properties | 2 +- kotlin-js-store/yarn.lock | 2168 +++++++++++++++++ .../build.gradle.kts | 13 +- .../gradle.properties | 3 + .../gradle/libs.versions.toml | 12 +- .../gradle/AutoInstallExtension.kt | 36 +- .../gradle/CocoaFrameworkLinker.kt | 46 +- .../gradle/CocoapodsAutoInstallExtension.kt | 42 +- .../gradle/DerivedDataPathValueSource.kt | 35 +- .../multiplatform/gradle/FrameworkLinker.kt | 37 +- .../gradle/FrameworkPathResolver.kt | 101 +- .../multiplatform/gradle/LinkerExtension.kt | 66 +- .../ManualFrameworkPathSearchValueSource.kt | 39 +- .../multiplatform/gradle/SentryExtension.kt | 28 +- .../multiplatform/gradle/SentryPlugin.kt | 60 +- .../gradle/SourceSetAutoInstallExtension.kt | 42 +- .../CocoaFrameworkLinkerIntegrationTest.kt | 45 +- .../gradle/CocoaFrameworkLinkerTest.kt | 86 +- .../gradle/CustomPathStrategyTest.kt | 15 +- .../gradle/DerivedDataPathTest.kt | 29 +- .../gradle/DerivedDataStrategyTest.kt | 59 +- .../gradle/FrameworkPathResolverTest.kt | 7 +- .../gradle/ManualSearchStrategyTest.kt | 13 +- .../gradle/SentryFrameworkArchitectureTest.kt | 72 +- .../multiplatform/gradle/SentryPluginTest.kt | 9 +- sentry-kotlin-multiplatform/build.gradle.kts | 84 +- .../sentry_kotlin_multiplatform.podspec | 2 +- .../src/androidMain/AndroidManifest.xml | 3 +- .../kotlin/multiplatform/Context.android.kt | 15 +- .../SentryPlatformInstance.android.kt | 9 +- .../SentryPlatformOptions.android.kt | 3 +- .../SentryOptionsExtensions.android.kt | 51 +- .../kotlin/multiplatform/BaseSentryTest.kt | 1 + .../multiplatform/PlatformOptions.android.kt | 25 +- .../multiplatform/SentryAndroidBridgeTest.kt | 11 +- .../kotlin/multiplatform/Attachment.apple.kt | 6 +- .../multiplatform/CocoaScopeProvider.kt | 54 +- .../multiplatform/SentryBridge.apple.kt | 65 +- .../kotlin/multiplatform/SentryEvent.apple.kt | 14 +- .../extensions/BreadcrumbExtensions.apple.kt | 38 +- .../extensions/FoundationExtensions.kt | 22 +- .../extensions/MessageExtensions.apple.kt | 11 +- .../SentryExceptionExtensions.apple.kt | 13 +- .../SentryOptionsExtensions.apple.kt | 35 +- .../extensions/UserExtensions.apple.kt | 30 +- .../log/CocoaSentryLoggerAdapter.kt | 7 +- .../log/SentryLogConverters.apple.kt | 76 +- .../multiplatform/nsexception/NSException.kt | 24 +- .../nsexception/SentryUnhandledExceptions.kt | 117 +- .../multiplatform/nsexception/Throwable.kt | 35 +- .../multiplatform/protocol/SentryId.apple.kt | 20 +- .../kotlin/multiplatform/AppleSentryIdTest.kt | 1 - .../kotlin/multiplatform/ApplyKmpEventTest.kt | 56 +- .../kotlin/multiplatform/BaseSentryTest.kt | 1 + .../multiplatform/BreadcrumbTestConverter.kt | 25 +- .../multiplatform/PlatformOptions.apple.kt | 14 +- .../SentryAttributesConversionTest.kt | 3 +- .../multiplatform/SentryBridgeTest.apple.kt | 34 +- .../multiplatform/SentryExceptionTest.kt | 37 +- .../multiplatform/SentryLevelTestConverter.kt | 4 +- .../UserFeedbackExtensionsTest.kt | 33 +- .../log/SentryLogConvertersTest.kt | 16 +- .../nsexception/InitAddressesTests.kt | 18 +- .../nsexception/ThrowableCausesTests.kt | 5 +- .../nsexception/ThrowableNameTests.kt | 1 - .../nsexception/ThrowableReasonTests.kt | 14 +- .../kotlin/multiplatform/Attachment.jvm.kt | 6 +- .../kotlin/multiplatform/JvmScopeProvider.kt | 58 +- .../multiplatform/SentryBridge.commonJvm.kt | 36 +- .../extensions/BreadcrumbExtensions.jvm.kt | 36 +- .../extensions/MessageExtensions.jvm.kt | 24 +- .../SentryExceptionExtensions.jvm.kt | 13 +- .../extensions/SentryLevelExtensions.jvm.kt | 10 +- .../extensions/SentryOptionsExtensions.jvm.kt | 11 +- .../extensions/UserExtensions.jvm.kt | 38 +- .../log/JvmSentryLoggerAdapter.kt | 7 +- .../log/SentryLogConverters.jvm.kt | 69 +- .../multiplatform/protocol/SentryId.jvm.kt | 20 +- .../multiplatform/BreadcrumbTestConverter.kt | 25 +- .../kotlin/multiplatform/JvmSentryIdTest.kt | 1 - .../SentryAttributesConversionTest.kt | 3 +- .../SentryBridgeTest.commonJvm.kt | 42 +- .../multiplatform/SentryLevelTestConverter.kt | 4 +- .../sentry/kotlin/multiplatform/Attachment.kt | 1 - .../multiplatform/HttpStatusCodeRange.kt | 10 +- .../io/sentry/kotlin/multiplatform/Scope.kt | 46 +- .../multiplatform/SentryAttributeValue.kt | 18 +- .../kotlin/multiplatform/SentryAttributes.kt | 36 +- .../kotlin/multiplatform/SentryBaseEvent.kt | 7 +- .../kotlin/multiplatform/SentryBridge.kt | 19 +- .../sentry/kotlin/multiplatform/SentryKMP.kt | 45 +- .../kotlin/multiplatform/SentryLevel.kt | 16 +- .../multiplatform/SentryReplayOptions.kt | 10 +- .../multiplatform/log/BaseSentryLogger.kt | 191 +- .../log/DefaultSentryLogBuilder.kt | 14 +- .../kotlin/multiplatform/log/SentryLog.kt | 6 +- .../multiplatform/log/SentryLogBuilder.kt | 7 +- .../multiplatform/log/SentryLogLevel.kt | 2 +- .../kotlin/multiplatform/log/SentryLogger.kt | 109 +- .../multiplatform/protocol/Breadcrumb.kt | 101 +- .../kotlin/multiplatform/protocol/Message.kt | 2 +- .../multiplatform/protocol/SdkVersion.kt | 10 +- .../multiplatform/protocol/SentryException.kt | 2 +- .../kotlin/multiplatform/protocol/SentryId.kt | 5 +- .../kotlin/multiplatform/protocol/User.kt | 10 +- .../multiplatform/protocol/UserFeedback.kt | 2 +- .../multiplatform/Attachment.commonStub.kt | 1 - .../kotlin/multiplatform/NoOpSentryLogger.kt | 109 +- .../multiplatform/SentryBridge.commonStub.kt | 41 +- .../protocol/SentryId.commonStub.kt | 4 +- .../kotlin/multiplatform/AttachmentTest.kt | 1 - .../multiplatform/BaseSentryScopeTest.kt | 1 - .../kotlin/multiplatform/BaseSentryTest.kt | 2 + .../BeforeBreadcrumbIntegrationTest.kt | 125 +- .../BeforeSendIntegrationTest.kt | 222 +- .../kotlin/multiplatform/BeforeSendTest.kt | 34 +- .../multiplatform/BreadcrumbConfigurator.kt | 2 + .../kotlin/multiplatform/BreadcrumbTest.kt | 1 - .../multiplatform/BreadcrumbTestConverter.kt | 8 +- .../sentry/kotlin/multiplatform/ScopeTest.kt | 6 +- .../multiplatform/SentryAttributeValueTest.kt | 1 - .../multiplatform/SentryAttributesTest.kt | 10 +- .../kotlin/multiplatform/SentryBridgeTest.kt | 5 + .../kotlin/multiplatform/SentryE2ETest.kt | 92 +- .../multiplatform/SentryEventConfigurator.kt | 2 + .../kotlin/multiplatform/SentryEventTest.kt | 1 - .../kotlin/multiplatform/SentryIdTest.kt | 1 - .../multiplatform/SentryIntegrationTest.kt | 129 +- .../SentryLevelConversionTest.kt | 1 - .../multiplatform/SentryLevelTestConverter.kt | 1 - .../kotlin/multiplatform/SentryOptionsTest.kt | 87 +- .../kotlin/multiplatform/UserFeedbackTest.kt | 1 - .../sentry/kotlin/multiplatform/UserTest.kt | 5 +- .../multiplatform/log/BaseSentryLoggerTest.kt | 22 +- .../multiplatform/log/SentryLogBuilderTest.kt | 1 - .../multiplatform/log/SentryLogOptionsTest.kt | 3 +- .../SentryPlatformOptions.tvwatchmacos.kt | 3 +- .../PlatformOptions.tvwatchmacos.kt | 8 +- .../SentryPlatformOptions.ios.kt | 3 +- .../extensions/SentryOptionsExtensions.ios.kt | 58 +- .../multiplatform/PlatformOptions.ios.kt | 11 +- .../SentryPlatformOptions.jvm.kt | 3 +- .../kotlin/multiplatform/BaseSentryTest.kt | 1 + .../multiplatform/PlatformOptions.jvm.kt | 11 +- .../androidApp/build.gradle.kts | 1 + .../androidApp/src/main/AndroidManifest.xml | 3 +- .../kotlin/sample.kmp.app.desktop/Main.kt | 29 +- .../kmp-app-cocoapods/shared/build.gradle.kts | 1 + .../kmp-app-cocoapods/shared/shared.podspec | 2 +- .../src/androidMain/AndroidManifest.xml | 2 +- .../sample/kmp/app/SentrySetup.android.kt | 7 +- .../kotlin/sample.kmp.app/LoginImpl.kt | 50 +- .../kotlin/sample.kmp.app/SentrySetup.kt | 9 +- .../kotlin/sample.kmp.app/HttpClient.kt | 19 +- .../kotlin/sample.kmp.app/SentrySetup.ios.kt | 7 +- .../kotlin/sample/kmp/app/SentrySetup.jvm.kt | 7 +- .../kmp-app-spm/androidApp/build.gradle.kts | 1 + .../androidApp/src/main/AndroidManifest.xml | 3 +- .../kotlin/sample.kmp.app.desktop/Main.kt | 29 +- .../kmp-app-spm/shared/build.gradle.kts | 3 +- .../src/androidMain/AndroidManifest.xml | 2 +- .../kotlin/sample.kmp.app/LoginImpl.kt | 41 +- .../kotlin/sample.kmp.app/SentrySetup.kt | 9 +- .../kotlin/sample.kmp.app/HttpClient.kt | 19 +- 170 files changed, 4738 insertions(+), 1915 deletions(-) create mode 100644 .editorconfig create mode 100644 kotlin-js-store/yarn.lock diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..8cea45444 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*.{kt,kts}] +# ktlint 1.x enables stricter naming rules by default. The codebase relies on +# backtick-wrapped test function names and constant-style vals that predate +# these rules, so keep them disabled to match existing conventions. +ktlint_standard_function-naming = disabled +ktlint_standard_property-naming = disabled diff --git a/build.gradle.kts b/build.gradle.kts index 22878d0de..b3a9e802a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,5 @@ import com.diffplug.spotless.LineEnding import com.vanniktech.maven.publish.MavenPublishPlugin -import com.vanniktech.maven.publish.MavenPublishPluginExtension import io.gitlab.arturbosch.detekt.Detekt import org.jetbrains.dokka.gradle.DokkaTask import java.util.zip.ZipFile @@ -18,7 +17,8 @@ plugins { id(Config.BuildPlugins.buildConfig).version(Config.BuildPlugins.buildConfigVersion).apply(false) kotlin(Config.kotlinSerializationPlugin).version(Config.kotlinVersion).apply(false) id(Config.QualityPlugins.kover).version(Config.QualityPlugins.koverVersion).apply(false) - id(Config.QualityPlugins.binaryCompatibility).version(Config.QualityPlugins.binaryCompatibilityVersion) + id(Config.QualityPlugins.binaryCompatibility) + .version(Config.QualityPlugins.binaryCompatibilityVersion) .apply(false) } @@ -52,18 +52,17 @@ subprojects { } afterEvaluate { - val platformDists = project.tasks.filter { task -> - task.name.matches(Regex("(.*)DistZip")) - }.toTypedArray() + val platformDists = + project.tasks + .filter { task -> + task.name.matches(Regex("(.*)DistZip")) + }.toTypedArray() project.tasks.getByName("distZip").finalizedBy(*platformDists) + // signing is done when uploading files to MC + // via gpg:sign-and-deploy-file (release.kts); disabled here via + // the RELEASE_SIGNING_ENABLED Gradle property (see gradle.properties) apply() - - configure { - // signing is done when uploading files to MC - // via gpg:sign-and-deploy-file (release.kts) - releaseSigningEnabled = false - } } } } @@ -78,7 +77,11 @@ tasks.register("validateDistributions") { } private fun Project.validateKotlinMultiplatformCoreArtifacts() { - val distributionDir = project.layout.buildDirectory.dir("distributions").get().asFile + val distributionDir = + project.layout.buildDirectory + .dir("distributions") + .get() + .asFile val expectedNumOfFiles = 20 val filesList = distributionDir.listFiles() val actualNumOfFiles = filesList?.size ?: 0 @@ -90,34 +93,46 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { } val baseFileName = "sentry-kotlin-multiplatform" - val platforms = listOf( - "watchosx64", "watchossimulatorarm64", "watchosarm64", "watchosarm32", - "tvosx64", "tvossimulatorarm64", "tvosarm64", - "macosx64", "macosarm64", - "jvm", - "iosx64", "iossimulatorarm64", "iosarm64", - "android", - "js", - "wasm-js", - "linuxx64", "linuxarm64", - "mingwx64" - ) - - val artifactPaths = buildList { - add(distributionDir.resolve("$baseFileName-$version.zip")) - addAll( - platforms.map { platform -> - distributionDir.resolve("$baseFileName-$platform-$version.zip") - } + val platforms = + listOf( + "watchosx64", + "watchossimulatorarm64", + "watchosarm64", + "watchosarm32", + "tvosx64", + "tvossimulatorarm64", + "tvosarm64", + "macosx64", + "macosarm64", + "jvm", + "iosx64", + "iossimulatorarm64", + "iosarm64", + "android", + "js", + "wasm-js", + "linuxx64", + "linuxarm64", + "mingwx64", ) - } - val commonRequiredEntries = listOf( - "javadoc", - "sources", - "module", - "pom-default.xml" - ) + val artifactPaths = + buildList { + add(distributionDir.resolve("$baseFileName-$version.zip")) + addAll( + platforms.map { platform -> + distributionDir.resolve("$baseFileName-$platform-$version.zip") + }, + ) + } + + val commonRequiredEntries = + listOf( + "javadoc", + "sources", + "module", + "pom-default.xml", + ) artifactPaths.forEach { artifactFile -> if (!artifactFile.exists()) { @@ -128,7 +143,12 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { } ZipFile(artifactFile).use { zip -> - val entries = zip.entries().asSequence().map { it.name }.toList() + val entries = + zip + .entries() + .asSequence() + .map { it.name } + .toList() commonRequiredEntries.forEach { requiredEntry -> if (entries.none { it.contains(requiredEntry) }) { @@ -146,7 +166,9 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { val expectedNumOfKlibFiles = 3 val actualKlibFiles = entries.count { it.contains("klib") } if (actualKlibFiles != expectedNumOfKlibFiles) { - throw GradleException("❌ Expected $expectedNumOfKlibFiles klib files in ${artifactFile.name}, but found $actualKlibFiles") + throw GradleException( + "❌ Expected $expectedNumOfKlibFiles klib files in ${artifactFile.name}, but found $actualKlibFiles", + ) } else { println("✅ Found $expectedNumOfKlibFiles klib files in ${artifactFile.name}") } @@ -197,7 +219,7 @@ val detektBaselineFilePath = "$rootDir/config/detekt/baseline.xml" detekt { buildUponDefaultConfig = true - config = files(detektConfigFilePath) + config.setFrom(files(detektConfigFilePath)) baseline = file(detektBaselineFilePath) } diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 56749f7a7..44b1e573d 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -1,8 +1,8 @@ object Config { - val agpVersion = "7.4.2" - val kotlinVersion = "2.1.21" - val composePluginVersion = "1.8.0" - val gradleMavenPublishPluginVersion = "0.18.0" + val agpVersion = "8.7.3" + val kotlinVersion = "2.2.21" + val composePluginVersion = "1.9.0" + val gradleMavenPublishPluginVersion = "0.30.0" val multiplatform = "multiplatform" val cocoapods = "native.cocoapods" @@ -12,20 +12,20 @@ object Config { val androidGradle = "com.android.library" val kotlinSerializationPlugin = "plugin.serialization" val dokka = "org.jetbrains.dokka" - val dokkaVersion = "1.8.10" + val dokkaVersion = "1.9.20" object BuildPlugins { val buildConfig = "com.codingfeline.buildkonfig" - val buildConfigVersion = "0.13.3" + val buildConfigVersion = "0.17.1" } object QualityPlugins { val spotless = "com.diffplug.spotless" - val spotlessVersion = "6.11.0" + val spotlessVersion = "7.0.2" val kover = "org.jetbrains.kotlinx.kover" - val koverVersion = "0.7.3" + val koverVersion = "0.9.1" val detekt = "io.gitlab.arturbosch.detekt" - val detektVersion = "1.22.0" + val detektVersion = "1.23.8" val binaryCompatibility = "org.jetbrains.kotlinx.binary-compatibility-validator" val binaryCompatibilityVersion = "0.18.0" } @@ -51,9 +51,9 @@ object Config { val kotlinCommon = "org.jetbrains.kotlin:kotlin-test-common" val kotlinCommonAnnotation = "org.jetbrains.kotlin:kotlin-test-annotations-common" val kotlinJunit = "org.jetbrains.kotlin:kotlin-test-junit" - val kotlinCoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0-RC" - val kotlinCoroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.0-RC" - val kotlinxSerializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0" + val kotlinCoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0" + val kotlinCoroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0" + val kotlinxSerializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3" val ktorClientCore = "io.ktor:ktor-client-core:2.3.6" val ktorClientSerialization = "io.ktor:ktor-client-serialization:2.3.6" @@ -66,7 +66,7 @@ object Config { } object Android { - private val sdkVersion = 33 + private val sdkVersion = 35 val minSdkVersion = 21 val targetSdkVersion = sdkVersion diff --git a/buildSrc/src/main/java/Publication.kt b/buildSrc/src/main/java/Publication.kt index 96bb9f884..749024baf 100644 --- a/buildSrc/src/main/java/Publication.kt +++ b/buildSrc/src/main/java/Publication.kt @@ -5,34 +5,38 @@ import java.io.File private val sep: String = File.separator -fun DistributionContainer.configureForMultiplatform(project: Project, buildPublishDir: String) { +fun DistributionContainer.configureForMultiplatform( + project: Project, + buildPublishDir: String, +) { val version = project.property("versionName").toString() if (version.isEmpty()) { throw GradleException("DistZip: version name is empty") } val projectName = project.name - val platforms = mapOf( - "main" to projectName, - "android" to "$projectName-android", - "jvm" to "$projectName-jvm", - "iosarm64" to "$projectName-iosarm64", - "iossimulatorarm64" to "$projectName-iossimulatorarm64", - "iosx64" to "$projectName-iosx64", - "macosarm64" to "$projectName-macosarm64", - "macosx64" to "$projectName-macosx64", - "tvosarm64" to "$projectName-tvosarm64", - "tvossimulatorarm64" to "$projectName-tvossimulatorarm64", - "tvosx64" to "$projectName-tvosx64", - "watchosarm32" to "$projectName-watchosarm32", - "watchosarm64" to "$projectName-watchosarm64", - "watchossimulatorarm64" to "$projectName-watchossimulatorarm64", - "watchosx64" to "$projectName-watchosx64", - "js" to "$projectName-js", - "wasm-js" to "$projectName-wasm-js", - "mingwx64" to "$projectName-mingwx64", - "linuxarm64" to "$projectName-linuxarm64", - "linuxx64" to "$projectName-linuxx64" - ) + val platforms = + mapOf( + "main" to projectName, + "android" to "$projectName-android", + "jvm" to "$projectName-jvm", + "iosarm64" to "$projectName-iosarm64", + "iossimulatorarm64" to "$projectName-iossimulatorarm64", + "iosx64" to "$projectName-iosx64", + "macosarm64" to "$projectName-macosarm64", + "macosx64" to "$projectName-macosx64", + "tvosarm64" to "$projectName-tvosarm64", + "tvossimulatorarm64" to "$projectName-tvossimulatorarm64", + "tvosx64" to "$projectName-tvosx64", + "watchosarm32" to "$projectName-watchosarm32", + "watchosarm64" to "$projectName-watchosarm64", + "watchossimulatorarm64" to "$projectName-watchossimulatorarm64", + "watchosx64" to "$projectName-watchosx64", + "js" to "$projectName-js", + "wasm-js" to "$projectName-wasm-js", + "mingwx64" to "$projectName-mingwx64", + "linuxarm64" to "$projectName-linuxarm64", + "linuxx64" to "$projectName-linuxx64", + ) platforms.forEach { (distName, projectName) -> val distribution = maybeCreate(distName) diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index fb608a178..b1bd6b1d5 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -2,10 +2,37 @@ + MaxLineLength:ManualFrameworkPathSearchValueSource.kt$ManualFrameworkPathSearchValueSource$abstract + MaxLineLength:SentryAttributes.kt$SentryAttributes.Companion$public + MaxLineLength:SentryLogConverters.apple.kt$is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) + MaxLineLength:SentryPlatformOptions.android.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration + MaxLineLength:SentryPlatformOptions.ios.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration + MaxLineLength:SentryPlatformOptions.jvm.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration + MaxLineLength:SentryPlatformOptions.tvwatchmacos.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration SwallowedException:CocoaScopeProvider.kt$CocoaScopeProvider$e: Throwable SwallowedException:SentryLevel.kt$SentryLevel.Companion$throwable: Throwable TooGenericExceptionCaught:CocoaScopeProvider.kt$CocoaScopeProvider$e: Throwable TooGenericExceptionCaught:SentryLevel.kt$SentryLevel.Companion$throwable: Throwable TooGenericExceptionThrown:SentryKMP.kt$Sentry$throw RuntimeException("Uncaught Exception from Kotlin Multiplatform.") + UndocumentedPublicClass:Attachment.kt$Attachment$Companion + UndocumentedPublicClass:Breadcrumb.kt$Breadcrumb$Companion + UndocumentedPublicClass:HttpStatusCodeRange.kt$HttpStatusCodeRange$Companion + UndocumentedPublicClass:SentryAttributes.kt$SentryAttributes$Companion + UndocumentedPublicClass:SentryId.kt$SentryId$Companion + UndocumentedPublicProperty:SentryLevel.kt$SentryLevel$DEBUG : SentryLevel + UndocumentedPublicProperty:SentryLevel.kt$SentryLevel$ERROR : SentryLevel + UndocumentedPublicProperty:SentryLevel.kt$SentryLevel$FATAL : SentryLevel + UndocumentedPublicProperty:SentryLevel.kt$SentryLevel$INFO : SentryLevel + UndocumentedPublicProperty:SentryLevel.kt$SentryLevel$WARNING : SentryLevel + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$DEBUG + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$ERROR + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$FATAL + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$INFO + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$TRACE + UndocumentedPublicProperty:SentryLogLevel.kt$SentryLogLevel$WARN + UnusedPrivateProperty:Attachment.kt$Attachment$bytes: ByteArray + UnusedPrivateProperty:Attachment.kt$Attachment$contentType: String? + UnusedPrivateProperty:Attachment.kt$Attachment$filename: String + UnusedPrivateProperty:Attachment.kt$Attachment$pathname: String diff --git a/gradle.properties b/gradle.properties index 1068274d6..41fa62c82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,12 +10,19 @@ compose.version=1.3.1-rc01 # Release information versionName=0.27.0 +# Disable publication signing locally; signing happens at MC upload time +RELEASE_SIGNING_ENABLED=false + # Increase memory for in-process compiler execution. org.gradle.jvmargs=-Xmx6g # https://kotlinlang.org/docs/migrating-multiplatform-project-to-14.html#migrate-to-the-hierarchical-project-structure kotlin.mpp.enableCInteropCommonization=true +# Installed Xcode is newer than the version KGP was tested against; the build works, +# so suppress the (noisy) compatibility warning. +kotlin.apple.xcodeCompatibility.nowarn=true + # Publication pom properties POM_NAME=Sentry Kotlin Multiplatform SDK POM_DESCRIPTION=SDK for sentry.io diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5e6a71a53..804f20c83 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Feb 27 16:36:52 CET 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock new file mode 100644 index 000000000..37a1466d5 --- /dev/null +++ b/kotlin-js-store/yarn.lock @@ -0,0 +1,2168 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@discoveryjs/json-ext@^0.6.1": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz#f13c7c205915eb91ae54c557f5e92bddd8be0e83" + integrity sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.11.tgz#b21835cbd36db656b857c2ad02ebd413cc13a9ba" + integrity sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@types/cors@^2.8.12": + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" + integrity sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.8": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*", "@types/node@>=10.0.0": + version "25.9.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.2.tgz#fc8958e757994b71fee516f9634bdb03d1b19e9f" + integrity sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw== + dependencies: + undici-types ">=7.24.0 <7.24.7" + +"@types/ws@^8.5.12": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== + dependencies: + "@types/node" "*" + +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== + dependencies: + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== + +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== + +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== + +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== + +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" + +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== + +"@webassemblyjs/wasm-edit@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-3.0.1.tgz#76ac285b9658fa642ce238c276264589aa2b6b57" + integrity sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA== + +"@webpack-cli/info@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-3.0.1.tgz#3cff37fabb7d4ecaab6a8a4757d3826cf5888c63" + integrity sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ== + +"@webpack-cli/serve@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-3.0.1.tgz#bd8b1f824d57e30faa19eb78e4c0951056f72f00" + integrity sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-phases@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz#16eb850ba99a056cb7cbfe872ffb8972e18c8bd7" + integrity sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ== + +acorn@^8.15.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^8.0.0, ajv@^8.9.0: + version "8.20.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9" + integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +baseline-browser-mapping@^2.10.12: + version "2.10.34" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.34.tgz#dedb606362446777cfe328d30d4ee15056d06303" + integrity sha512-IMDedajPifLnHNY0X9n8hKxRTQ6/eTHwr5bDo04WnuqxyKw6LYtQywCuuqPZwhl3aBXMvQpJov42GLCwRRdQzw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +body-parser@^1.19.0: + version "1.20.5" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.5.tgz#303c8c34423d1d6fa799bc764e93c1e4dc6ebf64" + integrity sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA== + dependencies: + bytes "~3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "~1.2.0" + http-errors "~2.0.1" + iconv-lite "~0.4.24" + on-finished "~2.4.1" + qs "~6.15.1" + raw-body "~2.5.3" + type-is "~1.6.18" + unpipe "~1.0.0" + +brace-expansion@^1.1.7: + version "1.1.15" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.15.tgz#a6d90d54067236e5f42570a3b7378d594d9b7738" + integrity sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserslist@^4.24.0: + version "4.28.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2" + integrity sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg== + dependencies: + baseline-browser-mapping "^2.10.12" + caniuse-lite "^1.0.30001782" + electron-to-chromium "^1.5.328" + node-releases "^2.0.36" + update-browserslist-db "^1.2.3" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bytes@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001782: + version "1.0.30001797" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz#1332709e1439f01ff92085dd17001e0a45897ec0" + integrity sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie@~0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + +cors@~2.8.5: + version "2.8.6" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.6.tgz#ff5dd69bd95e547503820d29aba4f8faf8dfec96" + integrity sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw== + dependencies: + object-assign "^4" + vary "^1" + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== + +date-format@^4.0.14: + version "4.0.14" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" + integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.3.4, debug@^4.3.5, debug@~4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +depd@2.0.0, depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== + +diff@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-7.0.0.tgz#3fb34d387cd76d803f6eebea67b921dab0182a9a" + integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== + +dom-serialize@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.5.328: + version "1.5.370" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.370.tgz#47dbc6565e5f13991a483e10cddff4bf0933de96" + integrity sha512-D5tSHJReAb/Kf3Hu9F/GO4lJuSWzEWHwvQ/kKSUP7pimNgvxkSKj+gUQhHpKKACwrin7rS3byU7IxreF56rl5g== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +engine.io@~6.6.0: + version "6.6.8" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.6.8.tgz#52c43629964fb9d84bf991e0e34e3c28d4e0d3e0" + integrity sha512-2agL3ueZhqxoVrfmntO8yuVj+uNSlIOnhykYHk3Cq0ShYPdUjjUiSJrQvXjq01I9jAuI0Zl2YO8Evv5Mqytm5g== + dependencies: + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + "@types/ws" "^8.5.12" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.7.2" + cors "~2.8.5" + debug "~4.4.1" + engine.io-parser "~5.2.1" + ws "~8.20.1" + +enhanced-resolve@^5.17.2: + version "5.23.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.23.0.tgz#dfdf8d1c9065e4b52f8a598356138931c07305f9" + integrity sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.3" + +ent@~2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.2.tgz#22a5ed2fd7ce0cbcff1d1474cf4909a44bdb6e85" + integrity sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + punycode "^1.4.1" + safe-regex-test "^1.1.0" + +envinfo@^7.14.0: + version "7.21.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.21.0.tgz#04a251be79f92548541f37d13c8b6f22940c3bae" + integrity sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.2.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz#a2d0b373205724dfa525d23b0c3e1b1ca582c99b" + integrity sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw== + dependencies: + es-errors "^1.3.0" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-uri@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.2.tgz#8af3d4fc9d3e71b11572cc2673b514a7d1a8c8ec" + integrity sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.7: + version "3.4.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== + +follow-redirects@^1.0.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +format-util@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" + integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^10.4.5: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3, glob@^7.1.7: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2, hasown@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +http-errors@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" + integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== + dependencies: + depd "~2.0.0" + inherits "~2.0.4" + setprototypeof "~1.2.0" + statuses "~2.0.2" + toidentifier "~1.0.1" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +iconv-lite@~0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.16.1: + version "2.16.2" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.2.tgz#3e07450a8080ebce3fbf0cac494f4d2ab324e082" + integrity sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA== + dependencies: + hasown "^2.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isbinaryfile@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" + integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-yaml@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.2.0.tgz#2bd9e85682dd91bd469afb809d816043b3d49524" + integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw== + dependencies: + argparse "^2.0.1" + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +karma-chrome-launcher@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" + integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== + dependencies: + which "^1.2.1" + +karma-mocha@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" + integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== + dependencies: + minimist "^1.2.3" + +karma-sourcemap-loader@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz#b01d73f8f688f533bcc8f5d273d43458e13b5488" + integrity sha512-xCRL3/pmhAYF3I6qOrcn0uhbQevitc2DERMPH82FMnG+4WReoGcGFZb1pURf2a5apyrOHRdvD+O6K7NljqKHyA== + dependencies: + graceful-fs "^4.2.10" + +karma-webpack@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.1.tgz#4eafd31bbe684a747a6e8f3e4ad373e53979ced4" + integrity sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ== + dependencies: + glob "^7.1.3" + minimatch "^9.0.3" + webpack-merge "^4.1.5" + +karma@6.4.4: + version "6.4.4" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.4.tgz#dfa5a426cf5a8b53b43cd54ef0d0d09742351492" + integrity sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w== + dependencies: + "@colors/colors" "1.5.0" + body-parser "^1.19.0" + braces "^3.0.2" + chokidar "^3.5.1" + connect "^3.7.0" + di "^0.0.1" + dom-serialize "^2.2.1" + glob "^7.1.7" + graceful-fs "^4.2.6" + http-proxy "^1.18.1" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" + minimatch "^3.0.4" + mkdirp "^0.5.5" + qjobs "^1.2.0" + range-parser "^1.2.1" + rimraf "^3.0.2" + socket.io "^4.7.2" + source-map "^0.6.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kotlin-web-helpers@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/kotlin-web-helpers/-/kotlin-web-helpers-2.1.0.tgz#6cd4b0f0dc3baea163929c8638155b8d19c55a74" + integrity sha512-NAJhiNB84tnvJ5EQx7iER3GWw7rsTZkX9HVHZpe7E3dDBD/dhTzqgSwNU3MfQjniy2rB04bP24WM9Z32ntUWRg== + dependencies: + format-util "^1.0.5" + +loader-runner@^4.2.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.2.tgz#9913d3a15971f8f635915e601fb5c9d495d918e9" + integrity sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.15, lodash@^4.17.21: + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log4js@^6.4.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" + integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + flatted "^3.2.7" + rfdc "^1.3.0" + streamroller "^3.1.5" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.3, minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + dependencies: + brace-expansion "^2.0.2" + +minimist@^1.2.3, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" + integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== + +mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mocha@11.7.1: + version "11.7.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.7.1.tgz#91948fecd624fb4bd154ed260b7e1ad3910d7c7a" + integrity sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^7.0.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^9.0.5" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^9.2.0" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^2.0.36: + version "2.0.47" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.47.tgz#521bb2786da8eb140b748841c0b3b3a75334ffc4" + integrity sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-finished@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +qjobs@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== + +qs@~6.15.1: + version "6.15.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9" + integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw== + dependencies: + side-channel "^1.1.0" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@~2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.3.tgz#11c6650ee770a7de1b494f197927de0c923822e2" + integrity sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA== + dependencies: + bytes "~3.1.2" + http-errors "~2.0.1" + iconv-lite "~0.4.24" + unpipe "~1.0.0" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.20.0: + version "1.22.12" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" + integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== + dependencies: + es-errors "^1.3.0" + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +rfdc@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^4.3.0, schema-utils@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46" + integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +setprototypeof@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel-list@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" + integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.4" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab" + integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.4" + side-channel-list "^1.0.1" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +socket.io-adapter@~2.5.2: + version "2.5.7" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.7.tgz#463428625f55be6f2f784a4501013b71454c0761" + integrity sha512-e0LyK91f3cUxTmv95/KzoLg47+zF+s/sbxRGDNsyG4dmIP8ZSX8ax6byOxfJXeNNtS/8AZlfD+uP7gBeR7DLlg== + dependencies: + debug "~4.4.1" + ws "~8.20.1" + +socket.io-parser@~4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.6.tgz#19156bf179af3931abd05260cfb1491822578a6f" + integrity sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + +socket.io@^4.7.2: + version "4.8.3" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.3.tgz#ca6ba1431c69532e1e0a6f496deebeb601dbc4df" + integrity sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + cors "~2.8.5" + debug "~4.4.1" + engine.io "~6.6.0" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" + +source-map-js@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-5.0.0.tgz#f593a916e1cc54471cfc8851b905c8a845fc7e38" + integrity sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA== + dependencies: + iconv-lite "^0.6.3" + source-map-js "^1.0.2" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +statuses@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== + +streamroller@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" + integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + fs-extra "^8.1.0" + +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" + integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== + dependencies: + ansi-regex "^6.2.2" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0, supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.3.tgz#5da7c9992c46038221267985ab28421a8879f160" + integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== + +terser-webpack-plugin@^5.3.11: + version "5.6.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz#47bc41bd8b8fab8383b62ec763b7394829097e7b" + integrity sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + jest-worker "^27.4.5" + schema-utils "^4.3.0" + terser "^5.31.1" + +terser@^5.31.1: + version "5.48.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.48.0.tgz#8b391171cfbb7ac4a88f9f04ba1cfabc54f643db" + integrity sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.15.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +tmp@^0.2.1: + version "0.2.7" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.7.tgz#26f4db11d1601ce8012dcb8a798ece1c06a99059" + integrity sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +ua-parser-js@^0.7.30: + version "0.7.41" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.41.tgz#9f6dee58c389e8afababa62a4a2dc22edb69a452" + integrity sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg== + +"undici-types@>=7.24.0 <7.24.7": + version "7.24.6" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.24.6.tgz#61275b485d7fd4e9d269c7cf04ec2873c9cc0f91" + integrity sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@^1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== + +watchpack@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102" + integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-6.0.1.tgz#a1ce25da5ba077151afd73adfa12e208e5089207" + integrity sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw== + dependencies: + "@discoveryjs/json-ext" "^0.6.1" + "@webpack-cli/configtest" "^3.0.1" + "@webpack-cli/info" "^3.0.1" + "@webpack-cli/serve" "^3.0.1" + colorette "^2.0.14" + commander "^12.1.0" + cross-spawn "^7.0.3" + envinfo "^7.14.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^6.0.1" + +webpack-merge@^4.1.5: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + +webpack-merge@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-6.0.1.tgz#50c776868e080574725abc5869bd6e4ef0a16c6a" + integrity sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.1" + +webpack-sources@^3.3.3: + version "3.5.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.5.0.tgz#87bf7f5801a4e985b1f1c92b64b9620a02f76d08" + integrity sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ== + +webpack@5.100.2: + version "5.100.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.100.2.tgz#e2341facf9f7de1d702147c91bcb65b693adf9e8" + integrity sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw== + dependencies: + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.8" + "@types/json-schema" "^7.0.15" + "@webassemblyjs/ast" "^1.14.1" + "@webassemblyjs/wasm-edit" "^1.14.1" + "@webassemblyjs/wasm-parser" "^1.14.1" + acorn "^8.15.0" + acorn-import-phases "^1.0.3" + browserslist "^4.24.0" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.2" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^4.3.2" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.11" + watchpack "^2.4.1" + webpack-sources "^3.3.3" + +which@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +workerpool@^9.2.0: + version "9.3.4" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41" + integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@~8.20.1: + version "8.20.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.1.tgz#91a9ae2b312ccf98e0a85ec499b48cef45ab0ddb" + integrity sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts b/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts index 7d5db4b9c..41aea54be 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts +++ b/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts @@ -1,5 +1,5 @@ -import com.vanniktech.maven.publish.MavenPublishPluginExtension import io.gitlab.arturbosch.detekt.Detekt +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -37,7 +37,7 @@ java { targetCompatibility = JavaVersion.VERSION_11 } -tasks.withType { kotlinOptions { jvmTarget = JavaVersion.VERSION_11.toString() } } +tasks.withType().configureEach { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } gradlePlugin { plugins { @@ -48,10 +48,9 @@ gradlePlugin { } } -val publish = extensions.getByType(MavenPublishPluginExtension::class.java) // signing is done when uploading files to MC -// via gpg:sign-and-deploy-file (release.kts) -publish.releaseSigningEnabled = false +// via gpg:sign-and-deploy-file (release.kts); disabled here via +// the RELEASE_SIGNING_ENABLED Gradle property (see gradle.properties) tasks.named("distZip") { dependsOn("publishToMavenLocal") @@ -94,12 +93,12 @@ buildConfig { buildConfigField( "String", "SentryCocoaVersion", - provider { "\"${project.property("sentryCocoaVersion")}\"" } + provider { "\"${project.property("sentryCocoaVersion")}\"" }, ) buildConfigField( "String", "SentryKmpVersion", - provider { "\"${project.property("versionName")}\"" } + provider { "\"${project.property("versionName")}\"" }, ) } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/gradle.properties b/sentry-kotlin-multiplatform-gradle-plugin/gradle.properties index 00a677c47..f3c3687ad 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/gradle.properties +++ b/sentry-kotlin-multiplatform-gradle-plugin/gradle.properties @@ -4,6 +4,9 @@ versionName=0.27.0 group=io.sentry sentryCocoaVersion=8.58.2 +# Disable publication signing locally; signing happens at MC upload time +RELEASE_SIGNING_ENABLED=false + # publication pom properties POM_NAME=Sentry Kotlin Multiplatform Gradle Plugin POM_DESCRIPTION=Sentry Kotlin Multiplatform Gradle Plugin diff --git a/sentry-kotlin-multiplatform-gradle-plugin/gradle/libs.versions.toml b/sentry-kotlin-multiplatform-gradle-plugin/gradle/libs.versions.toml index cd9ac9966..d1c79ffe5 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/gradle/libs.versions.toml +++ b/sentry-kotlin-multiplatform-gradle-plugin/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -detekt = "1.23.6" -kotlin = "1.9.23" -pluginPublish = "1.2.1" -buildConfig = "5.3.5" -vanniktechPublish = "0.18.0" -kover = "0.7.3" +detekt = "1.23.8" +kotlin = "2.2.21" +pluginPublish = "1.3.1" +buildConfig = "5.5.1" +vanniktechPublish = "0.30.0" +kover = "0.9.1" [plugins] detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt"} diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt index 9132450cb..e0ec94b3b 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt @@ -5,22 +5,26 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class AutoInstallExtension @Inject constructor(project: Project) { - private val objects = project.objects +abstract class AutoInstallExtension + @Inject + constructor( + project: Project, + ) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry dependencies through [CocoapodsAutoInstallExtension] - * and [SourceSetAutoInstallExtension]. - * - * Disabling this will prevent the plugin from auto installing any dependency. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry dependencies through [CocoapodsAutoInstallExtension] + * and [SourceSetAutoInstallExtension]. + * + * Disabling this will prevent the plugin from auto installing any dependency. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - val cocoapods: CocoapodsAutoInstallExtension = - objects.newInstance(CocoapodsAutoInstallExtension::class.java, project) + val cocoapods: CocoapodsAutoInstallExtension = + objects.newInstance(CocoapodsAutoInstallExtension::class.java, project) - val commonMain: SourceSetAutoInstallExtension = - objects.newInstance(SourceSetAutoInstallExtension::class.java, project) -} + val commonMain: SourceSetAutoInstallExtension = + objects.newInstance(SourceSetAutoInstallExtension::class.java, project) + } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt index ee47e83fe..68908d635 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt @@ -13,13 +13,13 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget class CocoaFrameworkLinker( private val logger: Logger, private val pathResolver: FrameworkPathResolver, - private val binaryLinker: FrameworkLinker + private val binaryLinker: FrameworkLinker, ) { fun configure(appleTargets: List) { appleTargets.forEach { target -> try { logger.info( - "Start resolving Sentry Cocoa framework paths for target: ${target.name}" + "Start resolving Sentry Cocoa framework paths for target: ${target.name}", ) processTarget(target) logger.lifecycle("Successfully configured Sentry Cocoa framework linking for target: ${target.name}") @@ -42,7 +42,7 @@ class CocoaFrameworkLinker( internal class FrameworkLinkingException( message: String, - cause: Throwable? = null + cause: Throwable? = null, ) : GradleException(message, cause) /** @@ -56,17 +56,18 @@ internal class FrameworkLinkingException( * @return Set of possible architecture folder names for the given target. * Returns empty set if target is not supported. */ -internal fun KotlinNativeTarget.toSentryFrameworkArchitecture(): Set = buildSet { - when (name) { - "iosSimulatorArm64", "iosX64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_SIMULATOR_AND_X64) - "iosArm64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_ARM64) - "macosArm64", "macosX64" -> addAll(SentryCocoaFrameworkArchitectures.MACOS_ARM64_AND_X64) - "tvosSimulatorArm64", "tvosX64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_SIMULATOR_AND_X64) - "tvosArm64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_ARM64) - "watchosArm32", "watchosArm64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_ARM) - "watchosSimulatorArm64", "watchosX64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_SIMULATOR_AND_X64) +internal fun KotlinNativeTarget.toSentryFrameworkArchitecture(): Set = + buildSet { + when (name) { + "iosSimulatorArm64", "iosX64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_SIMULATOR_AND_X64) + "iosArm64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_ARM64) + "macosArm64", "macosX64" -> addAll(SentryCocoaFrameworkArchitectures.MACOS_ARM64_AND_X64) + "tvosSimulatorArm64", "tvosX64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_SIMULATOR_AND_X64) + "tvosArm64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_ARM64) + "watchosArm32", "watchosArm64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_ARM) + "watchosSimulatorArm64", "watchosX64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_SIMULATOR_AND_X64) + } } -} internal object SentryCocoaFrameworkArchitectures { val IOS_SIMULATOR_AND_X64 = setOf("ios-arm64_x86_64-simulator") @@ -78,15 +79,16 @@ internal object SentryCocoaFrameworkArchitectures { val WATCHOS_SIMULATOR_AND_X64 = setOf("watchos-arm64_i386_x86_64-simulator") // Used for tests - val all = setOf( - IOS_SIMULATOR_AND_X64, - IOS_ARM64, - MACOS_ARM64_AND_X64, - TVOS_SIMULATOR_AND_X64, - TVOS_ARM64, - WATCHOS_ARM, - WATCHOS_SIMULATOR_AND_X64 - ) + val all = + setOf( + IOS_SIMULATOR_AND_X64, + IOS_ARM64, + MACOS_ARM64_AND_X64, + TVOS_SIMULATOR_AND_X64, + TVOS_ARM64, + WATCHOS_ARM, + WATCHOS_SIMULATOR_AND_X64, + ) } internal fun KotlinMultiplatformExtension.appleTargets() = diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt index e38772113..3021782ff 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt @@ -6,24 +6,28 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class CocoapodsAutoInstallExtension @Inject constructor(project: Project) { - private val objects = project.objects +abstract class CocoapodsAutoInstallExtension + @Inject + constructor( + project: Project, + ) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry Cocoa SDK pod. - * - * If the cocoapods plugin is applied and no existing Sentry pod configuration exists, the - * Sentry-Cocoa SDK pod will be installed. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry Cocoa SDK pod. + * + * If the cocoapods plugin is applied and no existing Sentry pod configuration exists, the + * Sentry-Cocoa SDK pod will be installed. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - /** - * Overrides default Sentry Cocoa version. - * - * Defaults to the version used in the latest KMP SDK. - */ - val sentryCocoaVersion: Property = - objects.property(String::class.java).convention("~> ${BuildConfig.SentryCocoaVersion}") -} + /** + * Overrides default Sentry Cocoa version. + * + * Defaults to the version used in the latest KMP SDK. + */ + val sentryCocoaVersion: Property = + objects.property(String::class.java).convention("~> ${BuildConfig.SentryCocoaVersion}") + } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt index 7b3adf427..c680088d9 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt @@ -14,8 +14,7 @@ import javax.inject.Inject * * e.g /Users/theusername/Library/Developer/Xcode/DerivedData/iosApp-ddefikekigqzzgcnpfkkdallksmlfpln/ */ -abstract class DerivedDataPathValueSource : - ValueSource { +abstract class DerivedDataPathValueSource : ValueSource { interface Parameters : ValueSourceParameters { @get:Input val xcodeprojPath: Property @@ -32,17 +31,19 @@ abstract class DerivedDataPathValueSource : val buildDirOutput = ByteArrayOutputStream() val errOutput = ByteArrayOutputStream() - val execOperations = execOperations.exec { - it.commandLine = listOf( - "xcodebuild", - "-project", - parameters.xcodeprojPath.get(), - "-showBuildSettings" - ) - it.standardOutput = buildDirOutput - it.errorOutput = errOutput - it.isIgnoreExitValue = true - } + val execOperations = + execOperations.exec { + it.commandLine = + listOf( + "xcodebuild", + "-project", + parameters.xcodeprojPath.get(), + "-showBuildSettings", + ) + it.standardOutput = buildDirOutput + it.errorOutput = errOutput + it.isIgnoreExitValue = true + } if (execOperations.exitValue == 0) { val buildSettings = buildDirOutput.toString("UTF-8") @@ -55,10 +56,10 @@ abstract class DerivedDataPathValueSource : } else { logger.warn( "Failed to retrieve derived data path. xcodebuild command failed. Error output: ${ - errOutput.toString( - Charsets.UTF_8 - ) - }" + errOutput.toString( + Charsets.UTF_8, + ) + }", ) return null } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkLinker.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkLinker.kt index 135f077e7..9d2d6de0e 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkLinker.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkLinker.kt @@ -10,12 +10,12 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable * This involves configuring and linking binaries to the Sentry Cocoa framework. */ class FrameworkLinker( - private val logger: Logger + private val logger: Logger, ) { fun configureBinaries( binaries: KotlinNativeBinaryContainer, dynamicPath: String?, - staticPath: String? + staticPath: String?, ) { binaries.all { binary -> when (binary) { @@ -26,27 +26,38 @@ class FrameworkLinker( } } - private fun chooseTestPath(dynamic: String?, static: String?) = when { + private fun chooseTestPath( + dynamic: String?, + static: String?, + ) = when { dynamic != null -> dynamic static != null -> static else -> throw FrameworkLinkingException("No valid framework path found for tests") } - private fun linkTestBinary(binary: TestExecutable, path: String) { + private fun linkTestBinary( + binary: TestExecutable, + path: String, + ) { // Linking in test binaries works with both dynamic and static framework binary.linkerOpts("-rpath", path, "-F$path") logger.info("Linked Sentry Cocoa framework to test binary ${binary.name}") } - private fun linkFrameworkBinary(binary: Framework, dynamicPath: String?, staticPath: String?) { - val (path, type) = when { - binary.isStatic && staticPath != null -> staticPath to "static" - !binary.isStatic && dynamicPath != null -> dynamicPath to "dynamic" - else -> throw FrameworkLinkingException( - "Framework mismatch for ${binary.name}. " + - "Required ${if (binary.isStatic) "static" else "dynamic"} Sentry Cocoa framework not found." - ) - } + private fun linkFrameworkBinary( + binary: Framework, + dynamicPath: String?, + staticPath: String?, + ) { + val (path, type) = + when { + binary.isStatic && staticPath != null -> staticPath to "static" + !binary.isStatic && dynamicPath != null -> dynamicPath to "dynamic" + else -> throw FrameworkLinkingException( + "Framework mismatch for ${binary.name}. " + + "Required ${if (binary.isStatic) "static" else "dynamic"} Sentry Cocoa framework not found.", + ) + } binary.linkerOpts("-F$path") logger.info("Linked $type Sentry Cocoa framework to ${binary.name}") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt index ec405e7cf..1ee4064de 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt @@ -11,12 +11,12 @@ import kotlin.io.path.absolutePathString enum class FrameworkType { STATIC, - DYNAMIC + DYNAMIC, } data class FrameworkPaths( val dynamic: String? = null, - val static: String? = null + val static: String? = null, ) { companion object { val NONE = FrameworkPaths(null, null) @@ -25,15 +25,17 @@ data class FrameworkPaths( dynamicBasePath: String? = null, staticBasePath: String? = null, architectures: Set, - pathExists: (String) -> Boolean = { path -> File(path).exists() } + pathExists: (String) -> Boolean = { path -> File(path).exists() }, ): FrameworkPaths { - val dynamicPath = dynamicBasePath?.let { basePath -> - architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } - } + val dynamicPath = + dynamicBasePath?.let { basePath -> + architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } + } - val staticPath = staticBasePath?.let { basePath -> - architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } - } + val staticPath = + staticBasePath?.let { basePath -> + architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } + } return when { dynamicPath != null && staticPath != null -> @@ -61,32 +63,35 @@ interface FrameworkResolutionStrategy { * This should generally be executed first. */ class CustomPathStrategy( - private val project: Project + private val project: Project, ) : FrameworkResolutionStrategy { private val linker: LinkerExtension = project.extensions.getByType(LinkerExtension::class.java) // In this function we don't distinguish between static and dynamic frameworks // We trust that the user knows the distinction if they purposefully override the framework path override fun resolvePaths(architectures: Set): FrameworkPaths { - val result = linker.frameworkPath.orNull?.takeIf { it.isNotEmpty() }?.let { basePath -> - when { - basePath.endsWith("Sentry.xcframework") -> FrameworkPaths.createValidated( - staticBasePath = basePath, - architectures = architectures - ) + val result = + linker.frameworkPath.orNull?.takeIf { it.isNotEmpty() }?.let { basePath -> + when { + basePath.endsWith("Sentry.xcframework") -> + FrameworkPaths.createValidated( + staticBasePath = basePath, + architectures = architectures, + ) - basePath.endsWith("Sentry-Dynamic.xcframework") -> FrameworkPaths.createValidated( - dynamicBasePath = basePath, - architectures = architectures - ) + basePath.endsWith("Sentry-Dynamic.xcframework") -> + FrameworkPaths.createValidated( + dynamicBasePath = basePath, + architectures = architectures, + ) - else -> FrameworkPaths.NONE - } - } ?: FrameworkPaths.NONE + else -> FrameworkPaths.NONE + } + } ?: FrameworkPaths.NONE if (linker.frameworkPath.orNull != null && result == FrameworkPaths.NONE) { project.logger.warn( "Custom framework path has been set manually but could not be found. " + - "Trying to resolve framework paths using other strategies." + "Trying to resolve framework paths using other strategies.", ) } return result @@ -103,10 +108,11 @@ class CustomPathStrategy( class DerivedDataStrategy( private val project: Project, private val derivedDataProvider: (String) -> String? = { xcodeprojPath -> - project.providers.of(DerivedDataPathValueSource::class.java) { - it.parameters.xcodeprojPath.set(xcodeprojPath) - }.orNull - } + project.providers + .of(DerivedDataPathValueSource::class.java) { + it.parameters.xcodeprojPath.set(xcodeprojPath) + }.orNull + }, ) : FrameworkResolutionStrategy { private val linker: LinkerExtension = project.extensions.getByType(LinkerExtension::class.java) @@ -126,7 +132,7 @@ class DerivedDataStrategy( return FrameworkPaths.createValidated( dynamicBasePath = dynamicBasePath, staticBasePath = staticBasePath, - architectures = architectures + architectures = architectures, ) } @@ -143,9 +149,9 @@ class DerivedDataStrategy( object : SimpleFileVisitor() { override fun preVisitDirectory( dir: Path, - attrs: BasicFileAttributes - ): FileVisitResult { - return when { + attrs: BasicFileAttributes, + ): FileVisitResult = + when { // Check if current directory is a xcodeproj before checking ignored dirs dir.toString().endsWith(".xcodeproj") -> { foundXcodeprojPath = dir.absolutePathString() @@ -155,8 +161,7 @@ class DerivedDataStrategy( ignoredDirectories.contains(dir.fileName.toString()) -> FileVisitResult.SKIP_SUBTREE else -> FileVisitResult.CONTINUE } - } - } + }, ) if (foundXcodeprojPath != null) { @@ -179,7 +184,7 @@ class DerivedDataStrategy( */ class ManualSearchStrategy( private val project: Project, - private val basePathToSearch: String? = null + private val basePathToSearch: String? = null, ) : FrameworkResolutionStrategy { // TODO: currently the search doesnt differentiate between Cocoa versions // we can improve this by checking the info.plist and prefer the ones that are the version we are looking for @@ -202,28 +207,26 @@ class ManualSearchStrategy( return FrameworkPaths.createValidated( dynamicBasePath = dynamicValueSource.orNull, staticBasePath = staticValueSource.orNull, - architectures = architectures + architectures = architectures, ) } } class FrameworkPathResolver( private val project: Project, - private val strategies: List = defaultStrategies(project) + private val strategies: List = defaultStrategies(project), ) { - fun resolvePaths( - architectures: Set - ): FrameworkPaths { + fun resolvePaths(architectures: Set): FrameworkPaths { strategies.forEach { strategy -> try { project.logger.info( - "Attempt to resolve Sentry Cocoa framework paths using ${strategy::class.simpleName}" + "Attempt to resolve Sentry Cocoa framework paths using ${strategy::class.simpleName}", ) val result = strategy.resolvePaths(architectures) if (result != FrameworkPaths.NONE) { val path = result.dynamic ?: result.static project.logger.lifecycle( - "Found Sentry Cocoa framework path using ${strategy::class.simpleName} at $path" + "Found Sentry Cocoa framework path using ${strategy::class.simpleName} at $path", ) return result } else { @@ -231,7 +234,7 @@ class FrameworkPathResolver( } } catch (e: FrameworkLinkingException) { project.logger.warn( - "Strategy ${strategy::class.simpleName} failed due to error: ${e.message}" + "Strategy ${strategy::class.simpleName} failed due to error: ${e.message}", ) } } @@ -240,7 +243,8 @@ class FrameworkPathResolver( throw FrameworkLinkingException(frameworkNotFoundMessage) } - private val frameworkNotFoundMessage = """ + private val frameworkNotFoundMessage = + """ Failed to find Sentry Cocoa framework. Steps to resolve: 1. Install Sentry Cocoa via SPM in Xcode @@ -254,7 +258,7 @@ class FrameworkPathResolver( frameworkPath.set("path/to/Sentry.xcframework") } } - """.trimIndent() + """.trimIndent() companion object { /** @@ -264,14 +268,13 @@ class FrameworkPathResolver( * resolved by the first successful strategy. Specifically here Custom Path will be checked first, * if that fails then it is followed by the Derived Data strategy etc... */ - fun defaultStrategies(project: Project): List { - return listOf( + fun defaultStrategies(project: Project): List = + listOf( CustomPathStrategy(project), DerivedDataStrategy(project), - ManualSearchStrategy(project) + ManualSearchStrategy(project), // TODO: add DownloadStrategy -> downloads the framework and stores it in build dir // this is especially useful for users who dont have a monorepo setup ) - } } } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt index f9f0114e5..1d1951520 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt @@ -5,36 +5,40 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class LinkerExtension @Inject constructor(project: Project) { - private val objects = project.objects +abstract class LinkerExtension + @Inject + constructor( + project: Project, + ) { + private val objects = project.objects - /** - * Path to the Xcode project that will be used to link the framework. - * This is used to find the derived data path in which the framework is stored for SPM. - */ - val xcodeprojPath: Property = objects.property(String::class.java) + /** + * Path to the Xcode project that will be used to link the framework. + * This is used to find the derived data path in which the framework is stored for SPM. + */ + val xcodeprojPath: Property = objects.property(String::class.java) - /** - * Path to the framework that will be linked. - * Takes precedence over [xcodeprojPath] if both are set. - * - * The path must: - * 1. Point directly to the .xcframework folder - * 2. The .xcframework folder needs to be either `Sentry.xcframework` or `Sentry-Dynamic.xcframework` - * - * ### Usage Example: - * ```kotlin - * sentryKmp { - * frameworkPath.set( - * "path/to/Sentry.xcframework" // Static framework - * // or - * "path/to/Sentry-Dynamic.xcframework" // Dynamic framework - * ) - * } - * ``` - * - * ### Typical Locations: - * `~/Library/Developer/Xcode/DerivedData/{PROJECT}/SourcePackages/artifacts/sentry-cocoa` - */ - val frameworkPath: Property = objects.property(String::class.java) -} + /** + * Path to the framework that will be linked. + * Takes precedence over [xcodeprojPath] if both are set. + * + * The path must: + * 1. Point directly to the .xcframework folder + * 2. The .xcframework folder needs to be either `Sentry.xcframework` or `Sentry-Dynamic.xcframework` + * + * ### Usage Example: + * ```kotlin + * sentryKmp { + * frameworkPath.set( + * "path/to/Sentry.xcframework" // Static framework + * // or + * "path/to/Sentry-Dynamic.xcframework" // Dynamic framework + * ) + * } + * ``` + * + * ### Typical Locations: + * `~/Library/Developer/Xcode/DerivedData/{PROJECT}/SourcePackages/artifacts/sentry-cocoa` + */ + val frameworkPath: Property = objects.property(String::class.java) + } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt index 06f92471f..d05a2d428 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt @@ -7,8 +7,7 @@ import org.gradle.api.provider.ValueSourceParameters import org.gradle.process.ExecOperations import java.io.ByteArrayOutputStream -abstract class ManualFrameworkPathSearchValueSource : - ValueSource { +abstract class ManualFrameworkPathSearchValueSource : ValueSource { interface Parameters : ValueSourceParameters { val frameworkType: Property val basePathToSearch: Property @@ -31,40 +30,42 @@ abstract class ManualFrameworkPathSearchValueSource : */ private fun findFrameworkWithFindCommand( frameworkType: FrameworkType, - basePathToSearch: String + basePathToSearch: String, ): String? { val stdOutput = ByteArrayOutputStream() val errOutput = ByteArrayOutputStream() val xcFrameworkName = if (frameworkType == FrameworkType.STATIC) "Sentry.xcframework" else "Sentry-Dynamic.xcframework" - val execResult = execOperations.exec { - it.commandLine( - "bash", - "-c", - "find $basePathToSearch " + - "-name $xcFrameworkName " + - "-exec stat -f \"%m %N\" {} \\; | " + - "sort -nr | " + - "cut -d' ' -f2-" - ) - it.standardOutput = stdOutput - it.errorOutput = errOutput - it.isIgnoreExitValue = true - } + val execResult = + execOperations.exec { + it.commandLine( + "bash", + "-c", + "find $basePathToSearch " + + "-name $xcFrameworkName " + + "-exec stat -f \"%m %N\" {} \\; | " + + "sort -nr | " + + "cut -d' ' -f2-", + ) + it.standardOutput = stdOutput + it.errorOutput = errOutput + it.isIgnoreExitValue = true + } val stringOutput = stdOutput.toString("UTF-8") return if (execResult.exitValue == 0) { if (stringOutput.lineSequence().firstOrNull().isNullOrEmpty()) { null } else { - stringOutput.lineSequence() + stringOutput + .lineSequence() .first() } } else { logger.warn( "Manual search failed to find $xcFrameworkName in $basePathToSearch. " + - "Error output: ${errOutput.toString(Charsets.UTF_8)}" + "Error output: ${errOutput.toString(Charsets.UTF_8)}", ) null } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryExtension.kt index 38baf8749..616628c62 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryExtension.kt @@ -4,17 +4,21 @@ import org.gradle.api.Project import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class SentryExtension @Inject constructor(project: Project) { - private val objects = project.objects +abstract class SentryExtension + @Inject + constructor( + project: Project, + ) { + private val objects = project.objects - /** - * Linker configuration. - * - * If you use SPM this configuration is necessary for setting up linking the framework and test - * executable. - */ - val linker: LinkerExtension = objects.newInstance(LinkerExtension::class.java, project) + /** + * Linker configuration. + * + * If you use SPM this configuration is necessary for setting up linking the framework and test + * executable. + */ + val linker: LinkerExtension = objects.newInstance(LinkerExtension::class.java, project) - val autoInstall: AutoInstallExtension = - objects.newInstance(AutoInstallExtension::class.java, project) -} + val autoInstall: AutoInstallExtension = + objects.newInstance(AutoInstallExtension::class.java, project) + } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt index 0aaa1367d..da337b3bd 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt @@ -27,17 +27,17 @@ class SentryPlugin : Plugin { project.extensions.create( SENTRY_EXTENSION_NAME, SentryExtension::class.java, - project + project, ) project.extensions.add(LINKER_EXTENSION_NAME, sentryExtension.linker) project.extensions.add(AUTO_INSTALL_EXTENSION_NAME, sentryExtension.autoInstall) project.extensions.add( COCOAPODS_AUTO_INSTALL_EXTENSION_NAME, - sentryExtension.autoInstall.cocoapods + sentryExtension.autoInstall.cocoapods, ) project.extensions.add( COMMON_MAIN_AUTO_INSTALL_EXTENSION_NAME, - sentryExtension.autoInstall.commonMain + sentryExtension.autoInstall.commonMain, ) afterEvaluate { @@ -47,7 +47,7 @@ class SentryPlugin : Plugin { internal fun executeConfiguration( project: Project, - hostIsMac: Boolean = HostManager.hostIsMac + hostIsMac: Boolean = HostManager.hostIsMac, ) { val sentryExtension = project.extensions.getByType(SentryExtension::class.java) val hasCocoapodsPlugin = @@ -78,7 +78,7 @@ class SentryPlugin : Plugin { private fun maybeLinkCocoaFramework( project: Project, hasCocoapods: Boolean, - hostIsMac: Boolean + hostIsMac: Boolean, ) { if (hostIsMac && !hasCocoapods) { // Register a task graph listener so that we only configure Cocoa framework linking @@ -104,7 +104,7 @@ private fun maybeLinkCocoaFramework( if (activeTargets.isEmpty()) { project.logger.lifecycle( "No Apple compile task scheduled for this build " + - "- skipping Sentry Cocoa framework linking" + "- skipping Sentry Cocoa framework linking", ) return@whenReady } @@ -114,7 +114,7 @@ private fun maybeLinkCocoaFramework( CocoaFrameworkLinker( logger = project.logger, pathResolver = FrameworkPathResolver(project), - binaryLinker = FrameworkLinker(project.logger) + binaryLinker = FrameworkLinker(project.logger), ).configure(appleTargets = activeTargets) } } @@ -123,26 +123,27 @@ private fun maybeLinkCocoaFramework( private fun getActiveTargets( project: Project, appleTargets: List, - graph: TaskExecutionGraph -): List = appleTargets.filter { target -> - val targetName = target.name.replaceFirstChar { - it.uppercase() - } - val path = if (project.path == ":") { - ":compileKotlin$targetName" - } else { - "${project.path}:compileKotlin$targetName" - } - try { - graph.hasTask(path) - } catch (_: Exception) { - false + graph: TaskExecutionGraph, +): List = + appleTargets.filter { target -> + val targetName = + target.name.replaceFirstChar { + it.uppercase() + } + val path = + if (project.path == ":") { + ":compileKotlin$targetName" + } else { + "${project.path}:compileKotlin$targetName" + } + try { + graph.hasTask(path) + } catch (_: Exception) { + false + } } -} -internal fun Project.installSentryForKmp( - commonMainAutoInstallExtension: SourceSetAutoInstallExtension -) { +internal fun Project.installSentryForKmp(commonMainAutoInstallExtension: SourceSetAutoInstallExtension) { val kmpExtension = extensions.findByName(KOTLIN_EXTENSION_NAME) if (kmpExtension !is KotlinMultiplatformExtension) { logger.info("Kotlin Multiplatform plugin not found. Skipping Sentry installation.") @@ -156,7 +157,7 @@ internal fun Project.installSentryForKmp( "Unsupported target: ${target.name}. " + "Cannot auto install in commonMain. " + "Please create an intermediate sourceSet with targets that the Sentry SDK " + - "supports and add the dependency manually." + "supports and add the dependency manually.", ) } } @@ -167,17 +168,14 @@ internal fun Project.installSentryForKmp( commonMain?.dependencies { api("io.sentry:sentry-kotlin-multiplatform:$sentryVersion") } } -internal fun Project.installSentryForCocoapods( - cocoapodsAutoInstallExtension: CocoapodsAutoInstallExtension -) { +internal fun Project.installSentryForCocoapods(cocoapodsAutoInstallExtension: CocoapodsAutoInstallExtension) { val kmpExtension = extensions.findByName(KOTLIN_EXTENSION_NAME) if (kmpExtension !is KotlinMultiplatformExtension || kmpExtension.targets.isEmpty() || !HostManager.hostIsMac) { logger.info("Skipping Cocoapods installation.") return } - (kmpExtension as ExtensionAware).extensions.configure(CocoapodsExtension::class.java) { cocoapods - -> + (kmpExtension as ExtensionAware).extensions.configure(CocoapodsExtension::class.java) { cocoapods -> val podName = "Sentry" val sentryPod = cocoapods.pods.findByName(podName) if (sentryPod == null) { diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt index 6e4ec17c2..3e4f0eede 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt @@ -6,24 +6,28 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class SourceSetAutoInstallExtension @Inject constructor(project: Project) { - private val objects = project.objects +abstract class SourceSetAutoInstallExtension + @Inject + constructor( + project: Project, + ) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry Kotlin Multiplatform SDK dependency in the commonMain - * source set. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry Kotlin Multiplatform SDK dependency in the commonMain + * source set. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - /** - * Overrides the default Sentry Kotlin Multiplatform SDK dependency version. - * - * Defaults to the version of this plugin which is synchronized with the KMP SDK version. - */ - val sentryKmpVersion: Property = - objects - .property(String::class.java) - .convention(BuildConfig.SentryKmpVersion) -} + /** + * Overrides the default Sentry Kotlin Multiplatform SDK dependency version. + * + * Defaults to the version of this plugin which is synchronized with the KMP SDK version. + */ + val sentryKmpVersion: Property = + objects + .property(String::class.java) + .convention(BuildConfig.SentryKmpVersion) + } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt index d67263cbf..32349df25 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt @@ -19,7 +19,9 @@ class CocoaFrameworkLinkerIntegrationTest { * contains only non-Apple targets. */ @Test - fun `linker is not configured when only non-Apple tasks are requested`(@TempDir projectDir: File) { + fun `linker is not configured when only non-Apple tasks are requested`( + @TempDir projectDir: File, + ) { writeBuildFiles(projectDir) val output = ByteArrayOutputStream() @@ -36,7 +38,9 @@ class CocoaFrameworkLinkerIntegrationTest { * task is present in the task graph. */ @Test - fun `linker is configured when an Apple task is requested`(@TempDir projectDir: File) { + fun `linker is configured when an Apple task is requested`( + @TempDir projectDir: File, + ) { writeBuildFiles(projectDir) val output = ByteArrayOutputStream() @@ -60,18 +64,20 @@ class CocoaFrameworkLinkerIntegrationTest { // can resolve a valid framework path even on CI machines where SPM // (and hence DerivedData) is not available. // ----------------------------------------------------------------- - val fakeFrameworkDir = File(dir, "Sentry-Dynamic.xcframework").apply { - // Create minimal structure that satisfies path validation logic - val archDirName = "ios-arm64_x86_64-simulator" // architecture used for iosSimulatorArm64 - val archDir = File(this, archDirName) - archDir.mkdirs() - } + val fakeFrameworkDir = + File(dir, "Sentry-Dynamic.xcframework").apply { + // Create minimal structure that satisfies path validation logic + val archDirName = "ios-arm64_x86_64-simulator" // architecture used for iosSimulatorArm64 + val archDir = File(this, archDirName) + archDir.mkdirs() + } File(dir, "settings.gradle").writeText("""rootProject.name = "fixture"""") - val pluginClasspath = PluginUnderTestMetadataReading - .readImplementationClasspath() - .joinToString(", ") { "\"${it.absolutePath.replace('\\', '/')}\"" } + val pluginClasspath = + PluginUnderTestMetadataReading + .readImplementationClasspath() + .joinToString(", ") { "\"${it.absolutePath.replace('\\', '/')}\"" } File(dir, "build.gradle").writeText( """ @@ -110,17 +116,24 @@ class CocoaFrameworkLinkerIntegrationTest { frameworkPath.set("${fakeFrameworkDir.absolutePath.replace('\\', '/')}") } } - """.trimIndent() + """.trimIndent(), ) } /** Returns a pre-configured [GradleRunner] that logs into [out]. */ - private fun defaultRunner(projectDir: File, out: ByteArrayOutputStream): GradleRunner = - GradleRunner.create() + private fun defaultRunner( + projectDir: File, + out: ByteArrayOutputStream, + ): GradleRunner = + GradleRunner + .create() .withProjectDir(projectDir) .withPluginClasspath() - .withGradleVersion(org.gradle.util.GradleVersion.current().version) - .forwardStdOutput(OutputStreamWriter(SynchronizedOutputStream(out))) + .withGradleVersion( + org.gradle.util.GradleVersion + .current() + .version, + ).forwardStdOutput(OutputStreamWriter(SynchronizedOutputStream(out))) .forwardStdError(OutputStreamWriter(SynchronizedOutputStream(out))) .withArguments("--stacktrace") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt index 473456295..de4f3bb76 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt @@ -23,18 +23,19 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for static Framework binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64() - ) + val appleTargets = + listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64(), + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -55,18 +56,19 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for dynamic Framework binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64() - ) + val appleTargets = + listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64(), + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -87,18 +89,19 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for TestExecutable binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64() - ) + val appleTargets = + listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64(), + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -129,22 +132,19 @@ class CocoaFrameworkLinkerTest { } } - fun getSut(): CocoaFrameworkLinker { - return CocoaFrameworkLinker( + fun getSut(): CocoaFrameworkLinker = + CocoaFrameworkLinker( project.logger, FrameworkPathResolver(project, strategies = listOf(FakeStrategy())), - FrameworkLinker(project.logger) + FrameworkLinker(project.logger), ) - } } } // We don't really care what the strategy exactly does in this test // The strategies themselves are tested independently private class FakeStrategy : FrameworkResolutionStrategy { - override fun resolvePaths(architectures: Set): FrameworkPaths { - return FrameworkPaths(static = staticPath, dynamic = dynamicPath) - } + override fun resolvePaths(architectures: Set): FrameworkPaths = FrameworkPaths(static = staticPath, dynamic = dynamicPath) } private const val staticPath = "/path/to/static/Sentry.xcframework" diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt index 8876beb6c..f748c8c4d 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt @@ -25,7 +25,7 @@ class CustomPathStrategyTest { @MethodSource("architectureMappingProvider") fun `should return static path when framework is Sentry xcframework`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { val xcframeworkPath = dir.resolve("Sentry.xcframework") Files.createDirectory(xcframeworkPath) @@ -42,7 +42,7 @@ class CustomPathStrategyTest { @MethodSource("architectureMappingProvider") fun `should return dynamic path when framework is Sentry xcframework`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { val xcframeworkPath = dir.resolve("Sentry-Dynamic.xcframework") Files.createDirectory(xcframeworkPath) @@ -72,7 +72,9 @@ class CustomPathStrategyTest { } @Test - fun `should return NONE when framework has invalid name`(@TempDir dir: Path) { + fun `should return NONE when framework has invalid name`( + @TempDir dir: Path, + ) { val xcframeworkPath = dir.resolve("Invalid.xcframework") val sut = fixture.getSut(xcframeworkPath.absolutePathString()) @@ -83,9 +85,10 @@ class CustomPathStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = + SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt index 99c2cab5b..61300b5cb 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt @@ -22,24 +22,26 @@ class DerivedDataPathTest { execOperations = mockk() parameters = mockk() - valueSource = object : DerivedDataPathValueSource() { - override val execOperations: ExecOperations = this@DerivedDataPathTest.execOperations - override fun getParameters(): Parameters { - return this@DerivedDataPathTest.parameters + valueSource = + object : DerivedDataPathValueSource() { + override val execOperations: ExecOperations = this@DerivedDataPathTest.execOperations + + override fun getParameters(): Parameters = this@DerivedDataPathTest.parameters } - } } @Test fun `obtain should return correct derived data path`() { - val xcodebuildOutput = """ + val xcodebuildOutput = + """ Build settings for action build and target MyTarget: BUILD_DIR = /DerivedData/Example/Build/Products - """.trimIndent() + """.trimIndent() - every { parameters.xcodeprojPath } returns mockk { - every { get() } returns "/path/to/project.xcodeproj" - } + every { parameters.xcodeprojPath } returns + mockk { + every { get() } returns "/path/to/project.xcodeproj" + } every { execOperations.exec(any()) } answers { val execSpecLambda = it.invocation.args[0] as Action @@ -73,9 +75,10 @@ class DerivedDataPathTest { fun `obtain should return null when BUILD_DIR is not found`() { val xcodebuildOutput = "Some output without BUILD_DIR" - every { parameters.xcodeprojPath } returns mockk { - every { get() } returns "/path/to/project.xcodeproj" - } + every { parameters.xcodeprojPath } returns + mockk { + every { get() } returns "/path/to/project.xcodeproj" + } every { execOperations.exec(any()) } answers { val execSpecLambda = it.invocation.args[0] as Action diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt index 93f1a2749..62c1ddd6d 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt @@ -26,7 +26,7 @@ class DerivedDataStrategyTest { @MethodSource("architectureMappingProvider") fun `if xcodeproj is null and find xcode project successfully then resolve static path`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { Files.createDirectory(dir.resolve("project.xcodeproj")) val xcframeworkPath = @@ -35,9 +35,10 @@ class DerivedDataStrategyTest { val archDirectory = Files.createDirectory(xcframeworkDirectory.resolve(expectedArchitecture.first())) - val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = + fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(expectedArchitecture) assertEquals(archDirectory.absolutePathString(), paths.static) @@ -48,7 +49,7 @@ class DerivedDataStrategyTest { @MethodSource("architectureMappingProvider") fun `if xcodeproj is null and find xcode project successfully then resolve dynamic path`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { Files.createDirectory(dir.resolve("project.xcodeproj")) val xcframeworkPath = @@ -57,9 +58,10 @@ class DerivedDataStrategyTest { val archDirectory = Files.createDirectory(xcframeworkDirectory.resolve(expectedArchitecture.first())) - val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = + fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(expectedArchitecture) assertEquals(archDirectory.absolutePathString(), paths.dynamic) @@ -68,11 +70,12 @@ class DerivedDataStrategyTest { @Test fun `if xcodeproj is null and find xcode project is not successful then return NONE`( - @TempDir dir: Path + @TempDir dir: Path, ) { - val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = + fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(setOf("doesnt matter")) assertEquals(FrameworkPaths.NONE, paths) @@ -80,14 +83,15 @@ class DerivedDataStrategyTest { @Test fun `if xcodeproj is not null and find xcode project is not successful then return NONE`( - @TempDir dir: Path + @TempDir dir: Path, ) { - val sut = fixture.getSut( - "some invalid path", - rootDirPath = dir.toFile().absolutePath - ) { _: String -> - dir.toFile().absolutePath - } + val sut = + fixture.getSut( + "some invalid path", + rootDirPath = dir.toFile().absolutePath, + ) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(setOf("doesnt matter")) assertEquals(FrameworkPaths.NONE, paths) @@ -95,20 +99,23 @@ class DerivedDataStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = + SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { fun getSut( xcodeprojPath: String?, rootDirPath: String, - derivedDataProvider: (String) -> String? + derivedDataProvider: (String) -> String?, ): DerivedDataStrategy { - val project = ProjectBuilder.builder() - .withProjectDir(File(rootDirPath)) - .build() + val project = + ProjectBuilder + .builder() + .withProjectDir(File(rootDirPath)) + .build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt index e32839ef8..c1f178f49 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt @@ -23,9 +23,10 @@ class FrameworkPathResolverTest { @Test fun `does not execute subsequent strategies after first success`() { - val strategy1 = mockk { - every { resolvePaths(any()) } returns FrameworkPaths(dynamic = "dyn") - } + val strategy1 = + mockk { + every { resolvePaths(any()) } returns FrameworkPaths(dynamic = "dyn") + } val strategy2 = mockk() val sut = fixture.getSut(listOf(strategy1, strategy2)) diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt index 347c3e1c2..578f5a47e 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt @@ -27,7 +27,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return static path when framework exists`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { val xcframeworkPath = dir.resolve("somewhere/hidden/Sentry.xcframework").createDirectories() val archDirectory = Files.createDirectory(xcframeworkPath.resolve(expectedArchitecture.first())) @@ -43,7 +43,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return dynamic path when framework exists`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { val xcframeworkPath = dir.resolve("somewhere/hidden/Sentry-Dynamic.xcframework").createDirectories() val archDirectory = Files.createDirectory(xcframeworkPath.resolve(expectedArchitecture.first())) @@ -59,7 +59,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return most recently used path when multiple framework exists`( expectedArchitecture: Set, - @TempDir dir: Path + @TempDir dir: Path, ) { val xcframeworkPath1 = dir.resolve("somewhere/hidden/Sentry.xcframework").createDirectories() Files.createDirectory(xcframeworkPath1.resolve(expectedArchitecture.first())) @@ -88,9 +88,10 @@ class ManualSearchStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = + SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt index 38a4b8354..37c84b896 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt @@ -18,20 +18,19 @@ import java.util.zip.ZipFile class SentryFrameworkArchitectureTest { companion object { @JvmStatic - fun cocoaVersions(): List = listOf( - Arguments.of("8.37.0"), - Arguments.of("8.38.0"), - Arguments.of("8.58.2") + fun cocoaVersions(): List = + listOf( + Arguments.of("8.37.0"), + Arguments.of("8.38.0"), + Arguments.of("8.58.2"), // Arguments.of("latest"), - // TODO: Latest is already v9 which is currently failing - let's fix this when we bump to v9 - ) + // TODO: Latest is already v9 which is currently failing - let's fix this when we bump to v9 + ) } @ParameterizedTest(name = "Test architecture name compatibility with Cocoa Version {0} in static framework") @MethodSource("cocoaVersions") - fun `finds arch folders in static framework`( - cocoaVersion: String - ) { + fun `finds arch folders in static framework`(cocoaVersion: String) { val project = ProjectBuilder.builder().build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") @@ -51,7 +50,7 @@ class SentryFrameworkArchitectureTest { watchosSimulatorArm64(), tvosX64(), tvosArm64(), - tvosSimulatorArm64() + tvosSimulatorArm64(), ).forEach { it.binaries.framework { baseName = "shared" @@ -67,14 +66,15 @@ class SentryFrameworkArchitectureTest { kmpExtension.appleTargets().forEach { val mappedArchNames = it.toSentryFrameworkArchitecture() - val foundMatch = mappedArchNames.any { mappedArchName -> - downloadedArchNames.contains(mappedArchName) - } + val foundMatch = + mappedArchNames.any { mappedArchName -> + downloadedArchNames.contains(mappedArchName) + } assert(foundMatch) { "Expected to find one of $mappedArchNames in $xcFramework for target ${it.name}.\nFound instead: ${ - xcFramework.listFiles() - ?.map { file -> file.name } + xcFramework.listFiles() + ?.map { file -> file.name } }" } } @@ -82,9 +82,7 @@ class SentryFrameworkArchitectureTest { @ParameterizedTest(name = "Test architecture name compatibility with Cocoa Version {0} in dynamic framework") @MethodSource("cocoaVersions") - fun `finds arch folders in dynamic framework`( - cocoaVersion: String - ) { + fun `finds arch folders in dynamic framework`(cocoaVersion: String) { val project = ProjectBuilder.builder().build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") @@ -104,7 +102,7 @@ class SentryFrameworkArchitectureTest { watchosSimulatorArm64(), tvosX64(), tvosArm64(), - tvosSimulatorArm64() + tvosSimulatorArm64(), ).forEach { it.binaries.framework { baseName = "shared" @@ -120,14 +118,15 @@ class SentryFrameworkArchitectureTest { kmpExtension.appleTargets().forEach { val mappedArchNames = it.toSentryFrameworkArchitecture() - val foundMatch = mappedArchNames.any { mappedArchName -> - downloadedArchNames.contains(mappedArchName) - } + val foundMatch = + mappedArchNames.any { mappedArchName -> + downloadedArchNames.contains(mappedArchName) + } assert(foundMatch) { "Expected to find one of $mappedArchNames in $xcFramework for target ${it.name}.\nFound instead: ${ - xcFramework.listFiles() - ?.map { file -> file.name } + xcFramework.listFiles() + ?.map { file -> file.name } }" } } @@ -137,18 +136,23 @@ class SentryFrameworkArchitectureTest { fun `returns empty list if target is unsupported`() { val unsupportedTarget = mockk() every { unsupportedTarget.name } returns "unsupported" - every { unsupportedTarget.konanTarget } returns mockk { - every { family } returns mockk { - every { isAppleFamily } returns true + every { unsupportedTarget.konanTarget } returns + mockk { + every { family } returns + mockk { + every { isAppleFamily } returns true + } } - } assert(unsupportedTarget.toSentryFrameworkArchitecture().isEmpty()) { "Expected empty list for unsupported target" } } - private fun downloadAndUnzip(cocoaVersion: String, isStatic: Boolean): File { + private fun downloadAndUnzip( + cocoaVersion: String, + isStatic: Boolean, + ): File { val tempDir = Files.createTempDirectory("sentry-cocoa-test").toFile() tempDir.deleteOnExit() @@ -157,13 +161,19 @@ class SentryFrameworkArchitectureTest { // Download val xcFrameworkZip = if (isStatic) "Sentry.xcframework.zip" else "Sentry-Dynamic.xcframework.zip" val downloadLink = - if (cocoaVersion == "latest") "https://github.com/getsentry/sentry-cocoa/releases/latest/download/$xcFrameworkZip" else "https://github.com/getsentry/sentry-cocoa/releases/download/$cocoaVersion/$xcFrameworkZip" + if (cocoaVersion == + "latest" + ) { + "https://github.com/getsentry/sentry-cocoa/releases/latest/download/$xcFrameworkZip" + } else { + "https://github.com/getsentry/sentry-cocoa/releases/download/$cocoaVersion/$xcFrameworkZip" + } val url = URL(downloadLink) url.openStream().use { input -> Files.copy( input, targetFile.toPath(), - StandardCopyOption.REPLACE_EXISTING + StandardCopyOption.REPLACE_EXISTING, ) } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt index 5af06837e..052634e5f 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt @@ -136,10 +136,11 @@ class SentryPluginTest { project.installSentryForKmp(project.extensions.getByName("commonMain") as SourceSetAutoInstallExtension) - val sentryDependencies = project.configurations - .flatMap { it.dependencies } - .filter { it.group == "io.sentry" && it.name == "sentry-kotlin-multiplatform" } - .toList() + val sentryDependencies = + project.configurations + .flatMap { it.dependencies } + .filter { it.group == "io.sentry" && it.name == "sentry-kotlin-multiplatform" } + .toList() assertTrue(sentryDependencies.isNotEmpty()) diff --git a/sentry-kotlin-multiplatform/build.gradle.kts b/sentry-kotlin-multiplatform/build.gradle.kts index a4951ec13..52de40bd6 100644 --- a/sentry-kotlin-multiplatform/build.gradle.kts +++ b/sentry-kotlin-multiplatform/build.gradle.kts @@ -3,6 +3,7 @@ import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -18,15 +19,14 @@ plugins { `maven-publish` } -koverReport { - defaults { - // adds the contents of the reports of `release` Android build variant to default reports - mergeWith("release") - } -} - android { + namespace = "io.sentry.kotlin.multiplatform" compileSdk = Config.Android.compileSdkVersion + // AGP 8 disables BuildConfig generation by default; keep it on to preserve + // the previously published Android public API surface. + buildFeatures { + buildConfig = true + } defaultConfig { minSdk = Config.Android.minSdkVersion testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -43,8 +43,10 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -tasks.withType { - kotlinOptions.jvmTarget = "1.8" +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } } kotlin { @@ -179,7 +181,7 @@ kotlin { tvosX64(), tvosSimulatorArm64(), macosX64(), - macosArm64() + macosArm64(), ).forEach { it.compilations.getByName("main") { cinterops.create("Sentry.Internal") { @@ -190,18 +192,20 @@ kotlin { // workaround for https://youtrack.jetbrains.com/issue/KT-41709 due to having "Meta" in the class name // if we need to use this class, we'd need to find a better way to work it out - targets.withType().matching { - it.konanTarget.family.isAppleFamily - }.forEach { target -> - target.compilations["main"].cinterops["Sentry"].extraOpts( - "-compiler-option", - "-DSentryMechanismMeta=SentryMechanismMetaUnavailable", - "-compiler-option", - "-DSentryIntegrationProtocol=SentryIntegrationProtocolUnavailable", - "-compiler-option", - "-DSentryMetricsAPIDelegate=SentryMetricsAPIDelegateUnavailable" - ) - } + targets + .withType() + .matching { + it.konanTarget.family.isAppleFamily + }.forEach { target -> + target.compilations["main"].cinterops["Sentry"].extraOpts( + "-compiler-option", + "-DSentryMechanismMeta=SentryMechanismMetaUnavailable", + "-compiler-option", + "-DSentryIntegrationProtocol=SentryIntegrationProtocolUnavailable", + "-compiler-option", + "-DSentryMetricsAPIDelegate=SentryMetricsAPIDelegateUnavailable", + ) + } val commonStub by creating { dependsOn(commonMain.get()) @@ -213,6 +217,28 @@ kotlin { } } +// The js/wasmJs/linux/mingw targets ship as no-op stubs and run no tests. Kotlin +// 2.2.20's shared `web` source set wires their test compilations to commonTest, whose +// Ktor dependency has no wasm (and limited native) variants, which breaks dependency +// resolution. Exclude Ktor from those test classpaths and disable their test +// compile/run tasks so no test sources are compiled for these stub targets. +val noOpStubTargets = listOf("js", "wasmJs", "mingwX64", "linuxArm64", "linuxX64") +configurations + .matching { configuration -> + noOpStubTargets.any { configuration.name.startsWith(it) } && + configuration.name.contains("Test") + }.configureEach { + exclude(group = "io.ktor") + } +tasks + .matching { task -> + val capitalizedTargets = noOpStubTargets.map { it.replaceFirstChar(Char::uppercase) } + capitalizedTargets.any { task.name.contains(it) } && + (task.name.startsWith("compileTestKotlin") || task.name.endsWith("Test")) + }.configureEach { + enabled = false + } + buildkonfig { packageName = "io.sentry.kotlin.multiplatform" defaultConfigs { @@ -236,20 +262,12 @@ private fun KotlinMultiplatformExtension.addNoOpTargets() { js(IR) { browser() binaries.library() - compilations.remove(compilations.getByName("test")) } wasmJs { browser() binaries.library() - compilations.remove(compilations.getByName("test")) - } - mingwX64 { - compilations.remove(compilations.getByName("test")) - } - linuxArm64 { - compilations.remove(compilations.getByName("test")) - } - linuxX64 { - compilations.remove(compilations.getByName("test")) } + mingwX64() + linuxArm64() + linuxX64() } diff --git a/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec b/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec index 251872b27..7007b3cc7 100644 --- a/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec +++ b/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec @@ -54,4 +54,4 @@ Pod::Spec.new do |spec| } ] -end +end \ No newline at end of file diff --git a/sentry-kotlin-multiplatform/src/androidMain/AndroidManifest.xml b/sentry-kotlin-multiplatform/src/androidMain/AndroidManifest.xml index f0aaedea3..5d4c85bb2 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/AndroidManifest.xml +++ b/sentry-kotlin-multiplatform/src/androidMain/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> ?, selection: String?, selectionArgs: Array?, - sortOrder: String? + sortOrder: String?, ): Cursor? { error("Not allowed.") } @@ -46,11 +46,18 @@ internal class SentryContextProvider : ContentProvider() { error("Not allowed.") } - override fun insert(uri: Uri, values: ContentValues?): Uri? { + override fun insert( + uri: Uri, + values: ContentValues?, + ): Uri? { error("Not allowed.") } - override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int { + override fun delete( + uri: Uri, + selection: String?, + selectionArgs: Array?, + ): Int { error("Not allowed.") } @@ -58,7 +65,7 @@ internal class SentryContextProvider : ContentProvider() { uri: Uri, values: ContentValues?, selection: String?, - selectionArgs: Array? + selectionArgs: Array?, ): Int { error("Not allowed.") } diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt index 0cd4779d5..4126ebc56 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt @@ -4,10 +4,11 @@ import io.sentry.android.core.SentryAndroid internal actual class SentryPlatformInstance : SentryInstance { actual override fun init(configuration: PlatformOptionsConfiguration) { - val context = applicationContext ?: run { - // TODO: add logging later - return - } + val context = + applicationContext ?: run { + // TODO: add logging later + return + } SentryAndroid.init(context, configuration) } diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt index 8fa945fe5..fdbbbfc95 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt @@ -13,8 +13,7 @@ internal actual fun SentryPlatformOptions.prepareForInit() { nativeSdkName = BuildKonfig.SENTRY_KMP_NATIVE_ANDROID_SDK_NAME } -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - toAndroidSentryOptionsCallback() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toAndroidSentryOptionsCallback() internal actual fun SentryPlatformOptions.prepareForInitBridge() { prepareForInit() diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt index 910d6706d..44ade8df1 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt @@ -8,36 +8,37 @@ import io.sentry.kotlin.multiplatform.SentryOptions import io.sentry.kotlin.multiplatform.SentryReplayOptions import kotlin.collections.forEach as kForEach -internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = { androidOptions -> - val kmpOptions = this +internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = + { androidOptions -> + val kmpOptions = this - // Apply base options available to all JVM targets - androidOptions.applyJvmBaseOptions(kmpOptions) + // Apply base options available to all JVM targets + androidOptions.applyJvmBaseOptions(kmpOptions) - // Apply Android specific options - androidOptions.isAttachScreenshot = kmpOptions.attachScreenshot - androidOptions.isAttachViewHierarchy = kmpOptions.attachViewHierarchy - androidOptions.isAnrEnabled = kmpOptions.isAnrEnabled - androidOptions.anrTimeoutIntervalMillis = kmpOptions.anrTimeoutIntervalMillis + // Apply Android specific options + androidOptions.isAttachScreenshot = kmpOptions.attachScreenshot + androidOptions.isAttachViewHierarchy = kmpOptions.attachViewHierarchy + androidOptions.isAnrEnabled = kmpOptions.isAnrEnabled + androidOptions.anrTimeoutIntervalMillis = kmpOptions.anrTimeoutIntervalMillis - // Replay options - androidOptions.sessionReplay.maskAllText = - kmpOptions.sessionReplay.maskAllText - androidOptions.sessionReplay.maskAllImages = - kmpOptions.sessionReplay.maskAllImages - androidOptions.sessionReplay.sessionSampleRate = - kmpOptions.sessionReplay.sessionSampleRate - androidOptions.sessionReplay.onErrorSampleRate = - kmpOptions.sessionReplay.onErrorSampleRate - androidOptions.sessionReplay.quality = - kmpOptions.sessionReplay.quality.toAndroidSentryQuality() + // Replay options + androidOptions.sessionReplay.maskAllText = + kmpOptions.sessionReplay.maskAllText + androidOptions.sessionReplay.maskAllImages = + kmpOptions.sessionReplay.maskAllImages + androidOptions.sessionReplay.sessionSampleRate = + kmpOptions.sessionReplay.sessionSampleRate + androidOptions.sessionReplay.onErrorSampleRate = + kmpOptions.sessionReplay.onErrorSampleRate + androidOptions.sessionReplay.quality = + kmpOptions.sessionReplay.quality.toAndroidSentryQuality() - // kForEach solves an issue with linter where it thinks forEach is the Java version - // see here: https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/68897591#68897591 - this.sdk?.packages?.kForEach { sdkPackage -> - androidOptions.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + // kForEach solves an issue with linter where it thinks forEach is the Java version + // see here: https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/68897591#68897591 + this.sdk?.packages?.kForEach { sdkPackage -> + androidOptions.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + } } -} internal fun SentryReplayOptions.Quality.toAndroidSentryQuality(): JvmSentryReplayQuality { val kmpQuality = this diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index d32877340..72647c512 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -9,6 +9,7 @@ import kotlin.test.BeforeTest actual abstract class BaseSentryTest { actual val platform: String = "Android" actual val authToken: String? = System.getenv("SENTRY_AUTH_TOKEN") + actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt index 22e4774f3..089741e7a 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt @@ -17,8 +17,9 @@ actual interface PlatformOptions : CommonPlatformOptions { val sessionReplay: AndroidSentryReplayOptions } -class SentryAndroidOptionsWrapper(private val androidOptions: SentryAndroidOptions) : - PlatformOptions { +class SentryAndroidOptionsWrapper( + private val androidOptions: SentryAndroidOptions, +) : PlatformOptions { override val dsn: String? get() = androidOptions.dsn @@ -84,8 +85,7 @@ class SentryAndroidOptionsWrapper(private val androidOptions: SentryAndroidOptio } } -actual fun createPlatformOptions(): PlatformOptions = - SentryAndroidOptionsWrapper(SentryAndroidOptions()) +actual fun createPlatformOptions(): PlatformOptions = SentryAndroidOptionsWrapper(SentryAndroidOptions()) actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptions) { val androidOptions = this @@ -99,35 +99,36 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio kmpReplayOptions.maskAllText, androidOptions.sessionReplay.maskViewClasses, androidOptions.sessionReplay.unmaskViewClasses, - AndroidSentryReplayOptions.TEXT_VIEW_CLASS_NAME + AndroidSentryReplayOptions.TEXT_VIEW_CLASS_NAME, ) assertViewClassMasking( kmpReplayOptions.maskAllImages, androidOptions.sessionReplay.maskViewClasses, androidOptions.sessionReplay.unmaskViewClasses, - AndroidSentryReplayOptions.IMAGE_VIEW_CLASS_NAME + AndroidSentryReplayOptions.IMAGE_VIEW_CLASS_NAME, ) assertEquals( androidOptions.sessionReplay.onErrorSampleRate, - kmpReplayOptions.onErrorSampleRate + kmpReplayOptions.onErrorSampleRate, ) assertEquals( androidOptions.sessionReplay.sessionSampleRate, - kmpReplayOptions.sessionSampleRate + kmpReplayOptions.sessionSampleRate, ) assertEquals(androidOptions.sessionReplay.quality.name, kmpReplayOptions.quality.name) assertEquals(androidOptions.proguardUuid, kmpOptions.proguardUuid) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - it.dsn = fakeDsn -} +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + it.dsn = fakeDsn + } private fun assertViewClassMasking( kmpMaskAll: Boolean, maskViewClasses: Collection, unmaskViewClasses: Collection, - viewClassName: String + viewClassName: String, ) { if (kmpMaskAll) { assertContains(maskViewClasses, viewClassName) diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt index 49981170d..ccf7cf462 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt @@ -19,9 +19,10 @@ class SentryAndroidBridgeTest { sut.init { } - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - } + val option = + SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + } assertEquals(BuildKonfig.SENTRY_KMP_NATIVE_ANDROID_SDK_NAME, option.nativeSdkName) } @@ -30,7 +31,5 @@ class SentryAndroidBridgeTest { internal class Fixture { val sentryInstance = FakeSentryInstance() - fun getSut(): SentryBridge { - return SentryBridge(sentryInstance) - } + fun getSut(): SentryBridge = SentryBridge(sentryInstance) } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt index d69637cc4..ecd4d94d5 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt @@ -4,7 +4,6 @@ import io.sentry.kotlin.multiplatform.extensions.toByteArray import io.sentry.kotlin.multiplatform.extensions.toNSData public actual class Attachment { - internal lateinit var cocoaAttachment: CocoaAttachment public actual val filename: String @@ -20,9 +19,8 @@ public actual class Attachment { get() = cocoaAttachment.contentType public actual companion object { - public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment { - return Attachment(screenshotBytes, "screenshot.png", "image/png") - } + public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment = + Attachment(screenshotBytes, "screenshot.png", "image/png") } public actual constructor(pathname: String) { diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt index 88870d1ee..09cb37989 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt @@ -9,7 +9,9 @@ import io.sentry.kotlin.multiplatform.extensions.toMutableMap import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User -internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { +internal class CocoaScopeProvider( + private val scope: CocoaScope, +) : Scope { /* This bridge exposes private Cocoa SDK API to fetch internal properties such as user, level, etc. We need this in order to return properties because the Cocoa SDK doesn't implement getters. @@ -62,11 +64,17 @@ internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { scope.clearBreadcrumbs() } - private fun setContextForPrimitiveValues(key: String, value: Any) { + private fun setContextForPrimitiveValues( + key: String, + value: Any, + ) { scope.setContextValue(mapOf("value" to value), key) } - override fun setContext(key: String, value: Any) { + override fun setContext( + key: String, + value: Any, + ) { try { (value as? Map)?.let { scope.setContextValue(it, key) @@ -76,27 +84,45 @@ internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { } } - override fun setContext(key: String, value: String) { + override fun setContext( + key: String, + value: String, + ) { setContextForPrimitiveValues(key, value) } - override fun setContext(key: String, value: Boolean) { + override fun setContext( + key: String, + value: Boolean, + ) { setContextForPrimitiveValues(key, value) } - override fun setContext(key: String, value: Number) { + override fun setContext( + key: String, + value: Number, + ) { setContextForPrimitiveValues(key, value) } - override fun setContext(key: String, value: Char) { + override fun setContext( + key: String, + value: Char, + ) { setContextForPrimitiveValues(key, value) } - override fun setContext(key: String, value: Array<*>) { + override fun setContext( + key: String, + value: Array<*>, + ) { setContextForPrimitiveValues(key, value) } - override fun setContext(key: String, value: Collection<*>) { + override fun setContext( + key: String, + value: Collection<*>, + ) { setContextForPrimitiveValues(key, value) } @@ -104,7 +130,10 @@ internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { scope.removeContextForKey(key) } - override fun setTag(key: String, value: String) { + override fun setTag( + key: String, + value: String, + ) { scope.setTagValue(value, key) } @@ -112,7 +141,10 @@ internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { scope.removeTagForKey(key) } - override fun setExtra(key: String, value: String) { + override fun setExtra( + key: String, + value: String, + ) { scope.setExtraValue(value, key) } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt index bc02c9f24..9026e5ee3 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt @@ -47,10 +47,15 @@ internal actual fun SentryPlatformOptions.prepareForInit() { PrivateSentrySDKOnly.setSdkName(BuildKonfig.SENTRY_KMP_COCOA_SDK_NAME, BuildKonfig.VERSION_NAME) } -internal actual class SentryBridge actual constructor(private val sentryInstance: SentryInstance) { +internal actual class SentryBridge actual constructor( + private val sentryInstance: SentryInstance, +) { private val logger = CocoaSentryLoggerAdapter(SentrySDK::logger) - actual fun init(context: Context, configuration: OptionsConfiguration) { + actual fun init( + context: Context, + configuration: OptionsConfiguration, + ) { init(configuration) } @@ -74,27 +79,35 @@ internal actual class SentryBridge actual constructor(private val sentryInstance return SentryId(cocoaSentryId.toString()) } - actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { + actual fun captureMessage( + message: String, + scopeCallback: ScopeCallback, + ): SentryId { val cocoaSentryId = SentrySDK.captureMessage(message, configureScopeCallback(scopeCallback)) return SentryId(cocoaSentryId.toString()) } actual fun captureException(throwable: Throwable): SentryId { - val event = throwable.asSentryEvent( - level = kSentryLevelError, - isHandled = true, - markThreadAsCrashed = false - ) + val event = + throwable.asSentryEvent( + level = kSentryLevelError, + isHandled = true, + markThreadAsCrashed = false, + ) val cocoaSentryId = SentrySDK.captureEvent(event) return SentryId(cocoaSentryId.toString()) } - actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { - val event = throwable.asSentryEvent( - level = kSentryLevelError, - isHandled = true, - markThreadAsCrashed = false - ) + actual fun captureException( + throwable: Throwable, + scopeCallback: ScopeCallback, + ): SentryId { + val event = + throwable.asSentryEvent( + level = kSentryLevelError, + isHandled = true, + markThreadAsCrashed = false, + ) val cocoaSentryId = SentrySDK.captureEvent(event, configureScopeCallback(scopeCallback)) return SentryId(cocoaSentryId.toString()) } @@ -115,32 +128,26 @@ internal actual class SentryBridge actual constructor(private val sentryInstance SentrySDK.setUser(user?.toCocoaUser()) } - actual fun isCrashedLastRun(): Boolean { - return SentrySDK.crashedLastRun() - } + actual fun isCrashedLastRun(): Boolean = SentrySDK.crashedLastRun() - actual fun isEnabled(): Boolean { - return SentrySDK.isEnabled() - } + actual fun isEnabled(): Boolean = SentrySDK.isEnabled() actual fun close() { SentrySDK.close() } - private fun configureScopeCallback(scopeCallback: ScopeCallback): (CocoaScope?) -> Unit { - return { cocoaScope -> - val cocoaScopeProvider = cocoaScope?.let { - CocoaScopeProvider(it) - } + private fun configureScopeCallback(scopeCallback: ScopeCallback): (CocoaScope?) -> Unit = + { cocoaScope -> + val cocoaScopeProvider = + cocoaScope?.let { + CocoaScopeProvider(it) + } cocoaScopeProvider?.let { scopeCallback.invoke(it) } } - } - actual fun logger(): SentryLogger { - return logger - } + actual fun logger(): SentryLogger = logger } @Suppress("unused") diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt index 45c14ff9a..f677a9afe 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt @@ -38,14 +38,20 @@ public actual class SentryEvent actual constructor() : SentryBaseEvent() { val cocoaFingerprint = cocoaSentryEvent.fingerprint()?.toMutableList() as? MutableList val cocoaSentryExceptions = - cocoaSentryEvent.exceptions?.map { (it as CocoaSentryException).toKmpSentryException() } + cocoaSentryEvent.exceptions + ?.map { (it as CocoaSentryException).toKmpSentryException() } ?.toMutableList() val cocoaContexts = cocoaSentryEvent.context?.mapKeys { it.key as String }?.mapValues { it.value as Any } - val cocoaBreadcrumbs = cocoaSentryEvent.breadcrumbs?.mapNotNull { it as? CocoaBreadcrumb } - ?.map { it.toKmpBreadcrumb() }?.toMutableList() + val cocoaBreadcrumbs = + cocoaSentryEvent.breadcrumbs + ?.mapNotNull { it as? CocoaBreadcrumb } + ?.map { it.toKmpBreadcrumb() } + ?.toMutableList() val cocoaTags = - cocoaSentryEvent.tags?.mapKeys { it.key as String }?.mapValues { it.value as String } + cocoaSentryEvent.tags + ?.mapKeys { it.key as String } + ?.mapValues { it.value as String } ?.toMutableMap() cocoaFingerprint?.let { fingerprint = it } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt index 385d2af41..2006f121b 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt @@ -3,23 +3,25 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaBreadcrumb import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -internal fun Breadcrumb.toCocoaBreadcrumb() = CocoaBreadcrumb().apply { - val scope = this@toCocoaBreadcrumb - setMessage(scope.message) - setType(scope.type) - scope.category?.let { setCategory(it) } - scope.level?.let { setLevel(it.toCocoaSentryLevel()) } - setData(scope.getData()?.toMap()) -} +internal fun Breadcrumb.toCocoaBreadcrumb() = + CocoaBreadcrumb().apply { + val scope = this@toCocoaBreadcrumb + setMessage(scope.message) + setType(scope.type) + scope.category?.let { setCategory(it) } + scope.level?.let { setLevel(it.toCocoaSentryLevel()) } + setData(scope.getData()?.toMap()) + } -internal fun CocoaBreadcrumb.toKmpBreadcrumb() = Breadcrumb().apply { - val scope = this@toKmpBreadcrumb - message = scope.message - type = scope.type - category = scope.category - val map = scope.data as? Map - map?.let { - this.setData(it.toMutableMap()) +internal fun CocoaBreadcrumb.toKmpBreadcrumb() = + Breadcrumb().apply { + val scope = this@toKmpBreadcrumb + message = scope.message + type = scope.type + category = scope.category + val map = scope.data as? Map + map?.let { + this.setData(it.toMutableMap()) + } + level = scope.level.toKmpSentryLevel() } - level = scope.level.toKmpSentryLevel() -} diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt index 8788c4b44..f9d5fde39 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt @@ -20,15 +20,17 @@ internal fun NSMutableDictionary.toMutableMap(): MutableMap { return map } -internal fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply { - usePinned { - memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) +internal fun NSData.toByteArray(): ByteArray = + ByteArray(this@toByteArray.length.toInt()).apply { + usePinned { + memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) + } } -} -internal fun ByteArray.toNSData(): NSData = memScoped { - NSData.create( - bytes = allocArrayOf(this@toNSData), - length = this@toNSData.size.toULong().convert() - ) -} +internal fun ByteArray.toNSData(): NSData = + memScoped { + NSData.create( + bytes = allocArrayOf(this@toNSData), + length = this@toNSData.size.toULong().convert(), + ) + } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt index c605f9025..f723b6556 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt @@ -3,11 +3,12 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaMessage import io.sentry.kotlin.multiplatform.protocol.Message -internal fun CocoaMessage.toKmpMessage() = Message( - message = message, - params = params as? List, - formatted = formatted -) +internal fun CocoaMessage.toKmpMessage() = + Message( + message = message, + params = params as? List, + formatted = formatted, + ) internal fun Message.toCocoaMessage(): CocoaMessage { val scope = this@toCocoaMessage diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt index d811f745f..4dd0cac7f 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt @@ -3,9 +3,10 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaSentryException import io.sentry.kotlin.multiplatform.protocol.SentryException -internal fun CocoaSentryException.toKmpSentryException() = SentryException( - type = type, - value = value, - module = module, - threadId = threadId?.longLongValue // longLong represents a 64-bit integer like Kotlin Long -) +internal fun CocoaSentryException.toKmpSentryException() = + SentryException( + type = type, + value = value, + module = module, + threadId = threadId?.longLongValue, // longLong represents a 64-bit integer like Kotlin Long + ) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt index 40d528167..583554ed5 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt @@ -11,9 +11,10 @@ import io.sentry.kotlin.multiplatform.setEnableUnhandledCppExceptionMonitoring import kotlinx.cinterop.convert import platform.Foundation.NSNumber -internal fun SentryOptions.toCocoaOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = { - it?.applyCocoaBaseOptions(this) -} +internal fun SentryOptions.toCocoaOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = + { + it?.applyCocoaBaseOptions(this) + } /** * Applies the given options to this CocoaSentryOptions. @@ -65,9 +66,12 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(kmpOptions: SentryOptions) cocoaOptions.beforeSend = { event -> val sdk = event?.sdk?.toMutableMap() - val packages = kmpOptions.sdk?.packages?.map { - mapOf("name" to it.name, "version" to it.version) - }?.toMutableList() ?: mutableListOf() + val packages = + kmpOptions.sdk + ?.packages + ?.map { + mapOf("name" to it.name, "version" to it.version) + }?.toMutableList() ?: mutableListOf() sdk?.set("packages", packages) @@ -87,17 +91,20 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(kmpOptions: SentryOptions) if (kmpOptions.beforeBreadcrumb == null) { cocoaBreadcrumb } else { - cocoaBreadcrumb?.toKmpBreadcrumb() - ?.let { kmpOptions.beforeBreadcrumb?.invoke(it) }?.toCocoaBreadcrumb() + cocoaBreadcrumb + ?.toKmpBreadcrumb() + ?.let { kmpOptions.beforeBreadcrumb?.invoke(it) } + ?.toCocoaBreadcrumb() } } cocoaOptions.enableCaptureFailedRequests = kmpOptions.enableCaptureFailedRequests cocoaOptions.failedRequestTargets = kmpOptions.failedRequestTargets - cocoaOptions.failedRequestStatusCodes = kmpOptions.failedRequestStatusCodes.map { - SentryHttpStatusCodeRange( - min = it.min.convert(), - max = it.max.convert() - ) - } + cocoaOptions.failedRequestStatusCodes = + kmpOptions.failedRequestStatusCodes.map { + SentryHttpStatusCodeRange( + min = it.min.convert(), + max = it.max.convert(), + ) + } } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt index b2af2f828..d8d7bfe81 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt @@ -3,18 +3,20 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaUser import io.sentry.kotlin.multiplatform.protocol.User -internal fun User.toCocoaUser() = CocoaUser().apply { - val scope = this@toCocoaUser - userId = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress -} +internal fun User.toCocoaUser() = + CocoaUser().apply { + val scope = this@toCocoaUser + userId = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + } -internal fun CocoaUser.toKmpUser() = User().apply { - val scope = this@toKmpUser - id = scope.userId - username = scope.username - email = scope.email - ipAddress = scope.ipAddress -} +internal fun CocoaUser.toKmpUser() = + User().apply { + val scope = this@toKmpUser + id = scope.userId + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt index 86a4ec47f..1f1dee42c 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt @@ -11,9 +11,12 @@ import cocoapods.Sentry.SentryLogger as CocoaSentryLogger */ internal class CocoaSentryLoggerAdapter( private val cocoaLoggerProvider: () -> CocoaSentryLogger, - logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory + logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory, ) : BaseSentryLogger(logBuilderFactory) { - override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { + override fun sendLog( + level: SentryLogLevel, + formatted: FormattedLog, + ) { val cocoaLogger = cocoaLoggerProvider() val attributes = formatted.attributes.toCocoaMap() when (level) { diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt index d2043b5d6..ed235ec50 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt @@ -13,47 +13,53 @@ import io.sentry.kotlin.multiplatform.SentryAttributes as KmpSentryAttributes * Converts Cocoa SDK's [CocoaSentryLogLevel] to KMP [SentryLogLevel]. */ @Suppress("MagicNumber") -internal fun CocoaSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = when (this.convert()) { - 0 -> SentryLogLevel.TRACE - 1 -> SentryLogLevel.DEBUG - 2 -> SentryLogLevel.INFO - 3 -> SentryLogLevel.WARN - 4 -> SentryLogLevel.ERROR - 5 -> SentryLogLevel.FATAL - else -> SentryLogLevel.DEBUG -} +internal fun CocoaSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = + when (this.convert()) { + 0 -> SentryLogLevel.TRACE + 1 -> SentryLogLevel.DEBUG + 2 -> SentryLogLevel.INFO + 3 -> SentryLogLevel.WARN + 4 -> SentryLogLevel.ERROR + 5 -> SentryLogLevel.FATAL + else -> SentryLogLevel.DEBUG + } /** * Converts KMP's [SentryLogLevel] to Cocoa SDK's [CocoaSentryLogLevel]. */ @Suppress("MagicNumber") -internal fun SentryLogLevel.toCocoaSentryLogLevel(): CocoaSentryLogLevel = when (this) { - SentryLogLevel.TRACE -> 0.convert() - SentryLogLevel.DEBUG -> 1.convert() - SentryLogLevel.INFO -> 2.convert() - SentryLogLevel.WARN -> 3.convert() - SentryLogLevel.ERROR -> 4.convert() - SentryLogLevel.FATAL -> 5.convert() -} +internal fun SentryLogLevel.toCocoaSentryLogLevel(): CocoaSentryLogLevel = + when (this) { + SentryLogLevel.TRACE -> 0.convert() + SentryLogLevel.DEBUG -> 1.convert() + SentryLogLevel.INFO -> 2.convert() + SentryLogLevel.WARN -> 3.convert() + SentryLogLevel.ERROR -> 4.convert() + SentryLogLevel.FATAL -> 5.convert() + } /** * Converts a Cocoa SentryLog to a KMP SentryLog for use in beforeSendLog callback. * After the callback, changes are applied back via [updateFrom]. */ -internal fun CocoaSentryLog.toKmpSentryLog(): SentryLog = SentryLog( - timestamp = timestamp().timeIntervalSince1970, - level = level().toKmpSentryLogLevel(), - body = body(), - severityNumber = severityNumber()?.intValue, - attributes = toKmpSentryAttributes() -) +internal fun CocoaSentryLog.toKmpSentryLog(): SentryLog = + SentryLog( + timestamp = timestamp().timeIntervalSince1970, + level = level().toKmpSentryLogLevel(), + body = body(), + severityNumber = severityNumber()?.intValue, + attributes = toKmpSentryAttributes(), + ) /** * Updates this Cocoa SentryLog from a KMP SentryLog. * @param kmpLog The modified KMP log after user's beforeSendLog callback. * @param originalKmpAttributes The original KMP attributes before the callback, used to detect changes. */ -internal fun CocoaSentryLog.updateFrom(kmpLog: SentryLog, originalKmpAttributes: KmpSentryAttributes) { +internal fun CocoaSentryLog.updateFrom( + kmpLog: SentryLog, + originalKmpAttributes: KmpSentryAttributes, +) { setBody(kmpLog.body) setLevel(kmpLog.level.toCocoaSentryLogLevel()) setSeverityNumber(kmpLog.severityNumber?.let { NSNumber(int = it) }) @@ -68,8 +74,7 @@ private fun CocoaSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { attributes() .mapNotNull { (key, value) -> (key as? String)?.let { it to (value as? SentryStructuredLogAttribute) } - } - .forEach { (key, attribute) -> + }.forEach { (key, attribute) -> attribute ?: return@forEach when (attribute.type()) { "string" -> kmpAttributes[key] = attribute.value() as String @@ -86,7 +91,7 @@ private fun CocoaSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { */ private fun CocoaSentryLog.updateAttributesFrom( modifiedKmpAttributes: KmpSentryAttributes, - originalKmpAttributes: KmpSentryAttributes + originalKmpAttributes: KmpSentryAttributes, ) { val mergedAttributes = attributes().toMutableMap() @@ -94,13 +99,14 @@ private fun CocoaSentryLog.updateAttributesFrom( (originalKmpAttributes.keys - modifiedKmpAttributes.keys).forEach { mergedAttributes.remove(it) } modifiedKmpAttributes.forEach { (key, attrValue) -> - mergedAttributes[key] = when (attrValue) { - is SentryAttributeValue.LongValue -> - SentryStructuredLogAttribute(integer = (attrValue.value as Long).convert()) - is SentryAttributeValue.DoubleValue -> SentryStructuredLogAttribute(double = attrValue.value as Double) - is SentryAttributeValue.StringValue -> SentryStructuredLogAttribute(string = attrValue.value as String) - is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) - } + mergedAttributes[key] = + when (attrValue) { + is SentryAttributeValue.LongValue -> + SentryStructuredLogAttribute(integer = (attrValue.value as Long).convert()) + is SentryAttributeValue.DoubleValue -> SentryStructuredLogAttribute(double = attrValue.value as Double) + is SentryAttributeValue.StringValue -> SentryStructuredLogAttribute(string = attrValue.value as String) + is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) + } } setAttributes(mergedAttributes) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt index 3ea684d84..686139800 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt @@ -26,17 +26,19 @@ import kotlin.reflect.KClass * of the [causes][Throwable.cause] will be appended, else causes are ignored. */ internal fun Throwable.asNSException(appendCausedBy: Boolean = false): NSException { - val returnAddresses = getFilteredStackTraceAddresses().let { addresses -> - if (!appendCausedBy) return@let addresses - addresses.toMutableList().apply { - for (cause in causes) { - addAll(cause.getFilteredStackTraceAddresses(true, addresses)) + val returnAddresses = + getFilteredStackTraceAddresses() + .let { addresses -> + if (!appendCausedBy) return@let addresses + addresses.toMutableList().apply { + for (cause in causes) { + addAll(cause.getFilteredStackTraceAddresses(true, addresses)) + } + } + }.map { + @Suppress("RemoveExplicitTypeArguments") + NSNumber(unsignedInteger = it.convert()) } - } - }.map { - @Suppress("RemoveExplicitTypeArguments") - NSNumber(unsignedInteger = it.convert()) - } return ThrowableNSException(name, getReason(appendCausedBy), returnAddresses) } @@ -68,7 +70,7 @@ internal fun Throwable.getReason(appendCausedBy: Boolean = false): String? { internal class ThrowableNSException( name: String, reason: String?, - private val returnAddresses: List + private val returnAddresses: List, ) : NSException(name, reason, null) { override fun callStackReturnAddresses(): List = returnAddresses } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt index 040d22132..0bc0210d3 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt @@ -39,15 +39,15 @@ private typealias CocoapodsSentryEnvelopeItem = cocoapods.Sentry.SentryEnvelopeI /** * Drops the Kotlin crash that follows an unhandled Kotlin exception except our custom SentryEvent. */ -internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentryEvent? { - return event?.takeUnless { - (it as InternalSentryEvent).isFatalEvent && ( - it.tags?.containsKey( - KOTLIN_CRASH_TAG - ) ?: false +internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentryEvent? = + event?.takeUnless { + (it as InternalSentryEvent).isFatalEvent && + ( + it.tags?.containsKey( + KOTLIN_CRASH_TAG, + ) ?: false ) } -} /** * Sets the unhandled exception hook such that all unhandled exceptions are logged to Sentry as fatal exceptions. @@ -55,25 +55,26 @@ internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentry * Note: once the exception is logged the program will be terminated. * @see wrapUnhandledExceptionHook */ -public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook { throwable -> - val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter - val handler = crashReporter.uncaughtExceptionHandler +public fun setSentryUnhandledExceptionHook(): Unit = + wrapUnhandledExceptionHook { throwable -> + val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter + val handler = crashReporter.uncaughtExceptionHandler - if (handler != null) { - // This will: - // 1. Write a crash report to disk with ALL synced scope data - // 2. Include tags, user, context, breadcrumbs, etc. - // 3. The crash will be sent on next app launch - handler.invoke(throwable.asNSException(appendCausedBy = true)) - } else { - // Fallback to old approach if handler not available - val envelope = throwable.asSentryEnvelope() - InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) - CocoapodsSentrySDK.configureScope { scope -> - scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) + if (handler != null) { + // This will: + // 1. Write a crash report to disk with ALL synced scope data + // 2. Include tags, user, context, breadcrumbs, etc. + // 3. The crash will be sent on next app launch + handler.invoke(throwable.asNSException(appendCausedBy = true)) + } else { + // Fallback to old approach if handler not available + val envelope = throwable.asSentryEnvelope() + InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) + CocoapodsSentrySDK.configureScope { scope -> + scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) + } } } -} /** * Tag used to mark the Kotlin termination crash. @@ -85,10 +86,12 @@ internal const val KOTLIN_CRASH_TAG = "nsexceptionkt.kotlin_crashed" */ private fun Throwable.asSentryEnvelope(): CocoapodsSentryEnvelope { val event = asSentryEvent() as InternalSentryEvent - val preparedEvent = InternalSentrySDK.currentHub().let { hub -> - hub.getClient() - ?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isFatalEvent = true) - } ?: event + val preparedEvent = + InternalSentrySDK.currentHub().let { hub -> + hub + .getClient() + ?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isFatalEvent = true) + } ?: event val item = CocoapodsSentryEnvelopeItem(event = preparedEvent as cocoapods.Sentry.SentryEvent) // TODO: pass traceState when enabling performance monitoring for KMP SDK val header = CocoapodsSentryEnvelopeHeader(id = preparedEvent.eventId) @@ -106,29 +109,32 @@ private fun Throwable.asSentryEnvelope(): CocoapodsSentryEnvelope { internal fun Throwable.asSentryEvent( level: CocoaSentryLevel = kSentryLevelFatal, isHandled: Boolean = false, - markThreadAsCrashed: Boolean = true + markThreadAsCrashed: Boolean = true, ): CocoapodsSentryEvent = CocoapodsSentryEvent(level).apply { @Suppress("UNCHECKED_CAST") val threads = threadInspector?.getCurrentThreadsWithStackTrace() as List? this.threads = threads - val currentThread = threads?.firstOrNull { it.current?.boolValue ?: false }?.apply { - if (markThreadAsCrashed) { - setCrashed(NSNumber(true)) - // Crashed threads shouldn't have a stacktrace, the thread_id should be set on the exception instead - // https://develop.sentry.dev/sdk/event-payloads/threads/ - stacktrace = null + val currentThread = + threads?.firstOrNull { it.current?.boolValue ?: false }?.apply { + if (markThreadAsCrashed) { + setCrashed(NSNumber(true)) + // Crashed threads shouldn't have a stacktrace, the thread_id should be set on the exception instead + // https://develop.sentry.dev/sdk/event-payloads/threads/ + stacktrace = null + } } - } - debugMeta = threads?.let { - InternalSentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads( - it - ) - } - exceptions = this@asSentryEvent - .let { throwable -> throwable.causes.asReversed() + throwable } - .map { it.asNSException().asSentryException(currentThread?.threadId, isHandled) } + debugMeta = + threads?.let { + InternalSentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads( + it, + ) + } + exceptions = + this@asSentryEvent + .let { throwable -> throwable.causes.asReversed() + throwable } + .map { it.asNSException().asSentryException(currentThread?.threadId, isHandled) } } /** @@ -136,18 +142,21 @@ internal fun Throwable.asSentryEvent( */ private fun NSException.asSentryException( threadId: NSNumber?, - isHandled: Boolean = false -): CocoapodsSentryException = CocoapodsSentryException(reason ?: "", name ?: "Throwable").apply { - this.threadId = threadId - mechanism = CocoapodsSentryMechanism("generic").apply { - setHandled(NSNumber(isHandled)) - } - stacktrace = threadInspector?.stacktraceBuilder?.let { stacktraceBuilder -> - val cursor = NSExceptionKt_SentryCrashStackCursorFromNSException(this@asSentryException) - val stacktrace = stacktraceBuilder.retrieveStacktraceFromCursor(cursor) - stacktrace as CocoapodsSentryStacktrace + isHandled: Boolean = false, +): CocoapodsSentryException = + CocoapodsSentryException(reason ?: "", name ?: "Throwable").apply { + this.threadId = threadId + mechanism = + CocoapodsSentryMechanism("generic").apply { + setHandled(NSNumber(isHandled)) + } + stacktrace = + threadInspector?.stacktraceBuilder?.let { stacktraceBuilder -> + val cursor = NSExceptionKt_SentryCrashStackCursorFromNSException(this@asSentryException) + val stacktrace = stacktraceBuilder.retrieveStacktraceFromCursor(cursor) + stacktrace as CocoapodsSentryStacktrace + } } -} private val threadInspector: InternalSentryThreadInspector? get() = InternalSentrySDK.currentHub().getClient()?.threadInspector diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt index 27d8f8ec3..54249dc0c 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt @@ -19,14 +19,15 @@ package io.sentry.kotlin.multiplatform.nsexception * The first element will be the cause, the second the cause of the cause, etc. * This function stops once a reference cycles is detected. */ -internal val Throwable.causes: List get() = buildList { - val causes = mutableSetOf() - var cause = cause - while (cause != null && causes.add(cause)) { - add(cause) - cause = cause.cause +internal val Throwable.causes: List get() = + buildList { + val causes = mutableSetOf() + var cause = cause + while (cause != null && causes.add(cause)) { + add(cause) + cause = cause.cause + } } -} /** * Returns a list of stack trace addresses representing @@ -37,12 +38,14 @@ internal val Throwable.causes: List get() = buildList { */ internal fun Throwable.getFilteredStackTraceAddresses( keepLastInit: Boolean = false, - commonAddresses: List = emptyList() -): List = getStackTraceAddresses().dropInitAddresses( - qualifiedClassName = this::class.qualifiedName ?: Throwable::class.qualifiedName!!, - stackTrace = getStackTrace(), - keepLast = keepLastInit -).dropCommonAddresses(commonAddresses) + commonAddresses: List = emptyList(), +): List = + getStackTraceAddresses() + .dropInitAddresses( + qualifiedClassName = this::class.qualifiedName ?: Throwable::class.qualifiedName!!, + stackTrace = getStackTrace(), + keepLast = keepLastInit, + ).dropCommonAddresses(commonAddresses) /** * Returns a list containing all addresses expect for the first addresses @@ -52,7 +55,7 @@ internal fun Throwable.getFilteredStackTraceAddresses( internal fun List.dropInitAddresses( qualifiedClassName: String, stackTrace: Array, - keepLast: Boolean = false + keepLast: Boolean = false, ): List { val exceptionInit = "kfun:$qualifiedClassName#" var dropCount = 0 @@ -72,9 +75,7 @@ internal fun List.dropInitAddresses( /** * Returns a list containing all addresses expect for the last addresses that match with the [commonAddresses]. */ -internal fun List.dropCommonAddresses( - commonAddresses: List -): List { +internal fun List.dropCommonAddresses(commonAddresses: List): List { var i = commonAddresses.size if (i == 0) return this diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt index 9f054bfee..98f2884cf 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt @@ -2,8 +2,9 @@ package io.sentry.kotlin.multiplatform.protocol import io.sentry.kotlin.multiplatform.CocoaSentryId -public actual data class SentryId actual constructor(val sentryIdString: String) { - +public actual data class SentryId actual constructor( + val sentryIdString: String, +) { public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } @@ -11,14 +12,13 @@ public actual data class SentryId actual constructor(val sentryIdString: String) private var cocoaSentryId: CocoaSentryId? = null init { - cocoaSentryId = if (sentryIdString.isEmpty()) { - CocoaSentryId.empty() - } else { - CocoaSentryId(sentryIdString) - } + cocoaSentryId = + if (sentryIdString.isEmpty()) { + CocoaSentryId.empty() + } else { + CocoaSentryId(sentryIdString) + } } - actual override fun toString(): String { - return cocoaSentryId.toString() - } + actual override fun toString(): String = cocoaSentryId.toString() } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt index 9601553be..c2a056b95 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt @@ -5,7 +5,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class AppleSentryIdTest { - @Test fun `Cocoa SentryId with invalid uuid string returns only zeroes`() { val uuidString = "ec720-b6f6-4efc--5c1" diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt index c0f92c77e..47120637f 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt @@ -7,12 +7,14 @@ import kotlin.test.assertEquals class ApplyKmpEventTest { @Test fun `native release is not set if kmp release has same value`() { - val nativeEvent = FakeSentryEvent().apply { - releaseName = "1.0.0" - } - val kmpEvent = SentryEvent().apply { - release = "1.0.0" - } + val nativeEvent = + FakeSentryEvent().apply { + releaseName = "1.0.0" + } + val kmpEvent = + SentryEvent().apply { + release = "1.0.0" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -21,12 +23,14 @@ class ApplyKmpEventTest { @Test fun `native dist is not set if kmp dist has same value`() { - val nativeEvent = FakeSentryEvent().apply { - dist = "randomDist" - } - val kmpEvent = SentryEvent().apply { - dist = "randomDist" - } + val nativeEvent = + FakeSentryEvent().apply { + dist = "randomDist" + } + val kmpEvent = + SentryEvent().apply { + dist = "randomDist" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -35,12 +39,14 @@ class ApplyKmpEventTest { @Test fun `native release is set if kmp release has different value`() { - val nativeEvent = FakeSentryEvent().apply { - releaseName = "1.0.0" - } - val kmpEvent = SentryEvent().apply { - release = "7.0.0" - } + val nativeEvent = + FakeSentryEvent().apply { + releaseName = "1.0.0" + } + val kmpEvent = + SentryEvent().apply { + release = "7.0.0" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -49,12 +55,14 @@ class ApplyKmpEventTest { @Test fun `native dist is set if kmp dist has different value`() { - val nativeEvent = FakeSentryEvent().apply { - dist = "randomDist" - } - val kmpEvent = SentryEvent().apply { - dist = "differentDist" - } + val nativeEvent = + FakeSentryEvent().apply { + dist = "randomDist" + } + val kmpEvent = + SentryEvent().apply { + dist = "differentDist" + } nativeEvent.applyKmpEvent(kmpEvent) diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 3fdcc19e0..49faa3fcd 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,6 +3,7 @@ package io.sentry.kotlin.multiplatform actual abstract class BaseSentryTest { actual val platform: String = "Apple" actual val authToken: String? = "fake-auth-token" + actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index 906f89fd9..bc10c9cf6 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -4,25 +4,16 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaBreadcrumb import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -actual data class BreadcrumbTestConverter actual constructor(val breadcrumb: Breadcrumb) { +actual data class BreadcrumbTestConverter actual constructor( + val breadcrumb: Breadcrumb, +) { + actual fun getType(): String? = breadcrumb.toCocoaBreadcrumb().type - actual fun getType(): String? { - return breadcrumb.toCocoaBreadcrumb().type - } + actual fun getCategory(): String? = breadcrumb.toCocoaBreadcrumb().category - actual fun getCategory(): String? { - return breadcrumb.toCocoaBreadcrumb().category - } + actual fun getMessage(): String? = breadcrumb.toCocoaBreadcrumb().message - actual fun getMessage(): String? { - return breadcrumb.toCocoaBreadcrumb().message - } + actual fun getData(): MutableMap = breadcrumb.toCocoaBreadcrumb().data as MutableMap - actual fun getData(): MutableMap { - return breadcrumb.toCocoaBreadcrumb().data as MutableMap - } - - actual fun getLevel(): SentryLevel? { - return breadcrumb.toCocoaBreadcrumb().level.toKmpSentryLevel() - } + actual fun getLevel(): SentryLevel? = breadcrumb.toCocoaBreadcrumb().level.toKmpSentryLevel() } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt index e772fbefb..eab1cdb7b 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt @@ -11,8 +11,9 @@ actual interface PlatformOptions : CommonPlatformOptions { val enableUnhandledCppExceptionMonitoring: Boolean } -open class SentryAppleOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : - PlatformOptions { +open class SentryAppleOptionsWrapper( + private val cocoaOptions: CocoaSentryOptions, +) : PlatformOptions { private var cachedEnableUnhandledCppExceptionMonitoring = true override val dsn: String? @@ -94,7 +95,8 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio assertEquals(appleOptions.enableUnhandledCppExceptionMonitoring, kmpOptions.enableUnhandledCppExceptionMonitoring) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - val cocoaOptions = it as CocoaSentryOptions - cocoaOptions.dsn = fakeDsn -} +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + val cocoaOptions = it as CocoaSentryOptions + cocoaOptions.dsn = fakeDsn + } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt index 578b634b5..3f8c8d60a 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt @@ -4,6 +4,5 @@ import io.sentry.kotlin.multiplatform.log.toCocoaMap class SentryAttributesConversionTest : BaseSentryAttributesConversionTest() { @Suppress("UNCHECKED_CAST") - override fun SentryAttributes.toMap(): Map = - toCocoaMap() as Map + override fun SentryAttributes.toMap(): Map = toCocoaMap() as Map } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt index c6b2ebffa..18e546fbe 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt @@ -65,9 +65,11 @@ actual class SentryBridgeTest { } // WHEN - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } // THEN assert(option.beforeSend != null) @@ -80,9 +82,11 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } // THEN assert(option.beforeSend != null) @@ -93,10 +97,12 @@ actual class SentryBridgeTest { actual fun `default beforeSend in init does not drop the event after prepareForInit`() { fixture.sut.init { } - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - prepareForInit() - }.let { it as CocoaSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + prepareForInit() + }.let { it as CocoaSentryOptions } assert(option.beforeSend != null) assert(option.beforeSend!!.invoke(CocoaSentryEvent()) != null) @@ -108,9 +114,11 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } val event = option.beforeSend!!.invoke(CocoaSentryEvent()) val packages = event?.sdk()?.get("packages") as? List> diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt index fbcf20372..56b4521be 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt @@ -11,46 +11,47 @@ class SentryExceptionTest { private val type = "type" private val threadId = 1 - private fun getCocoaSentryException(): CocoaSentryException { - return CocoaSentryException(value = value, type = type) - } + private fun getCocoaSentryException(): CocoaSentryException = CocoaSentryException(value = value, type = type) - private fun getKmpSentryException(threadId: Long? = this.threadId.toLong()): SentryException { - return SentryException(value = value, type = type, threadId = threadId) - } + private fun getKmpSentryException(threadId: Long? = this.threadId.toLong()): SentryException = + SentryException(value = value, type = type, threadId = threadId) @Test fun `SentryException ThreadId NSNumber long conversion`() { - val cocoaSentryException = getCocoaSentryException().apply { - threadId = NSNumber(long = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = + getCocoaSentryException().apply { + threadId = NSNumber(long = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber longLong conversion`() { - val cocoaSentryException = getCocoaSentryException().apply { - threadId = NSNumber(longLong = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = + getCocoaSentryException().apply { + threadId = NSNumber(longLong = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber int conversion`() { - val cocoaSentryException = getCocoaSentryException().apply { - threadId = NSNumber(int = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = + getCocoaSentryException().apply { + threadId = NSNumber(int = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber short conversion`() { - val cocoaSentryException = getCocoaSentryException().apply { - threadId = NSNumber(short = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = + getCocoaSentryException().apply { + threadId = NSNumber(short = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index 10ffa1217..c43e300ef 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -4,7 +4,5 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaSentryLevel import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel actual class SentryLevelTestConverter actual constructor() { - actual fun convert(sentryLevel: SentryLevel?): SentryLevel? { - return sentryLevel?.toCocoaSentryLevel()?.toKmpSentryLevel() - } + actual fun convert(sentryLevel: SentryLevel?): SentryLevel? = sentryLevel?.toCocoaSentryLevel()?.toKmpSentryLevel() } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt index cbdb5f33d..e8ae58fbd 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt @@ -7,14 +7,14 @@ import kotlin.test.Test import kotlin.test.assertEquals class UserFeedbackExtensionsTest { - private val sentryIdString = "dcebada57d794590a6da3d1977eed58a" @Test fun `toCocoaUserFeedback correctly maps comments`() { - val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { - comments = "Test comment" - } + val userFeedback = + UserFeedback(SentryId(sentryIdString)).apply { + comments = "Test comment" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -23,9 +23,10 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback correctly maps email`() { - val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { - email = "test@email.com" - } + val userFeedback = + UserFeedback(SentryId(sentryIdString)).apply { + email = "test@email.com" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -34,9 +35,10 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback correctly maps name`() { - val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { - name = "John Doe" - } + val userFeedback = + UserFeedback(SentryId(sentryIdString)).apply { + name = "John Doe" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -78,11 +80,12 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback maps all properties correctly`() { - val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error" - } + val userFeedback = + UserFeedback(SentryId(sentryIdString)).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConvertersTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConvertersTest.kt index 57a9fadb9..ca46abace 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConvertersTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConvertersTest.kt @@ -1,7 +1,9 @@ package io.sentry.kotlin.multiplatform.log +import kotlinx.cinterop.convert import kotlin.test.Test import kotlin.test.assertEquals +import cocoapods.Sentry.SentryLogLevel as CocoaSentryLogLevel /** Tests for Apple/Cocoa log level conversion functions in SentryLogConverters.apple.kt. */ class SentryLogConvertersTest { @@ -10,7 +12,7 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.TRACE val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(0L, cocoa) + assertEquals(0, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @@ -19,7 +21,7 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.DEBUG val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(1L, cocoa) + assertEquals(1, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @@ -28,7 +30,7 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.INFO val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(2L, cocoa) + assertEquals(2, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @@ -37,7 +39,7 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.WARN val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(3L, cocoa) + assertEquals(3, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @@ -46,7 +48,7 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.ERROR val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(4L, cocoa) + assertEquals(4, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @@ -55,13 +57,13 @@ class SentryLogConvertersTest { val kmp = SentryLogLevel.FATAL val cocoa = kmp.toCocoaSentryLogLevel() - assertEquals(5L, cocoa) + assertEquals(5, cocoa.convert()) assertEquals(kmp, cocoa.toKmpSentryLogLevel()) } @Test fun `unknown Cocoa value defaults to DEBUG`() { - val unknownValue = 99L + val unknownValue: CocoaSentryLogLevel = 99.convert() val kmpLevel = unknownValue.toKmpSentryLogLevel() assertEquals(SentryLogLevel.DEBUG, kmpLevel) diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt index a5a81db20..ae989f8e9 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt @@ -18,17 +18,17 @@ import kotlin.test.Test import kotlin.test.assertEquals class InitAddressesTests { - private val qualifiedClassName = "my.app.CustomException" private val addresses = listOf(0, 1, 2, 3, 4, 5) - private val stackTrace = arrayOf( - "123 kfun:kotlin.Throwable#(kotlin.String?){} + 24 abc", - "456 kfun:kotlin.Exception#(kotlin.String?){} + 5 def", - "789 kfun:my.app.CustomException#(kotlin.String?){} + 10 hij", - "012 kfun:my.app.CustomException#(){} + 12 klm", - "345 kfun:my.app.class#function1(){} + 50 nop", - "678 kfun:my.app.class#function2(){} + 60 qrs" - ) + private val stackTrace = + arrayOf( + "123 kfun:kotlin.Throwable#(kotlin.String?){} + 24 abc", + "456 kfun:kotlin.Exception#(kotlin.String?){} + 5 def", + "789 kfun:my.app.CustomException#(kotlin.String?){} + 10 hij", + "012 kfun:my.app.CustomException#(){} + 12 klm", + "345 kfun:my.app.class#function1(){} + 50 nop", + "678 kfun:my.app.class#function2(){} + 60 qrs", + ) @Test fun testDropInit() { diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt index cce236bb8..9610f75b9 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt @@ -18,7 +18,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableCausesTests { - @Test fun testNoCauses() { assert(Throwable().causes.isEmpty()) @@ -39,7 +38,9 @@ class ThrowableCausesTests { assertEquals(listOf(cause2, cause1), throwable.causes) } - private class MyThrowable(override val message: String?) : Throwable() { + private class MyThrowable( + override val message: String?, + ) : Throwable() { override var cause: Throwable? = null } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt index 2caeda5c3..3211bd854 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt @@ -18,7 +18,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableNameTests { - private class MyThrowable : Throwable() @Test diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt index d7cb9f90f..c1801c86d 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt @@ -18,8 +18,10 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableReasonTests { - - private fun testReasonNoCause(message: String?, appendCausedBy: Boolean) { + private fun testReasonNoCause( + message: String?, + appendCausedBy: Boolean, + ) { val exception = Exception(message) val reason = exception.getReason(appendCausedBy) assertEquals(message, reason) @@ -56,7 +58,7 @@ class ThrowableReasonTests { Test message Caused by: kotlin.Exception: Cause message """.trimIndent(), - reason + reason, ) } @@ -69,7 +71,7 @@ class ThrowableReasonTests { """ Caused by: kotlin.Exception: Cause message """.trimIndent(), - reason + reason, ) } @@ -82,7 +84,7 @@ class ThrowableReasonTests { Test message Caused by: kotlin.Exception """.trimIndent(), - reason + reason, ) } @@ -98,7 +100,7 @@ class ThrowableReasonTests { Caused by: kotlin.Exception: Cause2 message Caused by: kotlin.Exception: Cause1 message """.trimIndent(), - reason + reason, ) } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt index 3fd4131f0..7dd8a3539 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt @@ -1,7 +1,6 @@ package io.sentry.kotlin.multiplatform public actual class Attachment { - internal var jvmAttachment: JvmAttachment public actual val filename: String @@ -17,9 +16,8 @@ public actual class Attachment { get() = jvmAttachment.contentType public actual companion object { - public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment { - return Attachment(screenshotBytes, "screenshot.png", "image/png") - } + public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment = + Attachment(screenshotBytes, "screenshot.png", "image/png") } public actual constructor(pathname: String) { diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt index 766cf9c7f..27c03b057 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt @@ -9,8 +9,9 @@ import io.sentry.kotlin.multiplatform.extensions.toMap import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User -internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { - +internal class JvmScopeProvider( + private val scope: JvmIScope, +) : Scope { override var level: SentryLevel? set(value) { scope.level = value?.toJvmSentryLevel() @@ -31,13 +32,9 @@ internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { scope.clearAttachments() } - override fun getContexts(): MutableMap { - return scope.contexts.toMap().toMutableMap() - } + override fun getContexts(): MutableMap = scope.contexts.toMap().toMutableMap() - override fun getTags(): MutableMap { - return scope.tags - } + override fun getTags(): MutableMap = scope.tags override fun addBreadcrumb(breadcrumb: Breadcrumb) { scope.addBreadcrumb(breadcrumb.toJvmBreadcrumb()) @@ -47,31 +44,52 @@ internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { scope.clearBreadcrumbs() } - override fun setContext(key: String, value: Any) { + override fun setContext( + key: String, + value: Any, + ) { scope.setContexts(key, value) } - override fun setContext(key: String, value: Boolean) { + override fun setContext( + key: String, + value: Boolean, + ) { scope.setContexts(key, value) } - override fun setContext(key: String, value: String) { + override fun setContext( + key: String, + value: String, + ) { scope.setContexts(key, value) } - override fun setContext(key: String, value: Number) { + override fun setContext( + key: String, + value: Number, + ) { scope.setContexts(key, value) } - override fun setContext(key: String, value: Collection<*>) { + override fun setContext( + key: String, + value: Collection<*>, + ) { scope.setContexts(key, value) } - override fun setContext(key: String, value: Array<*>) { + override fun setContext( + key: String, + value: Array<*>, + ) { scope.setContexts(key, value as Array) } - override fun setContext(key: String, value: Char) { + override fun setContext( + key: String, + value: Char, + ) { scope.setContexts(key, value) } @@ -79,7 +97,10 @@ internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { scope.removeContexts(key) } - override fun setTag(key: String, value: String) { + override fun setTag( + key: String, + value: String, + ) { scope.setTag(key, value) } @@ -87,7 +108,10 @@ internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { scope.removeTag(key) } - override fun setExtra(key: String, value: String) { + override fun setExtra( + key: String, + value: String, + ) { scope.setExtra(key, value) } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt index e8a0f8f13..c10b32f90 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt @@ -13,10 +13,15 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback internal expect fun SentryPlatformOptions.prepareForInitBridge() -internal actual class SentryBridge actual constructor(private val sentryInstance: SentryInstance) { +internal actual class SentryBridge actual constructor( + private val sentryInstance: SentryInstance, +) { private val logger = JvmSentryLoggerAdapter(Sentry::logger) - actual fun init(context: Context, configuration: OptionsConfiguration) { + actual fun init( + context: Context, + configuration: OptionsConfiguration, + ) { init(configuration) } @@ -39,7 +44,10 @@ internal actual class SentryBridge actual constructor(private val sentryInstance return SentryId(jvmSentryId.toString()) } - actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { + actual fun captureMessage( + message: String, + scopeCallback: ScopeCallback, + ): SentryId { val jvmSentryId = Sentry.captureMessage(message, configureScopeCallback(scopeCallback)) return SentryId(jvmSentryId.toString()) } @@ -49,7 +57,10 @@ internal actual class SentryBridge actual constructor(private val sentryInstance return SentryId(jvmSentryId.toString()) } - actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { + actual fun captureException( + throwable: Throwable, + scopeCallback: ScopeCallback, + ): SentryId { val jvmSentryId = Sentry.captureException(throwable, configureScopeCallback(scopeCallback)) return SentryId(jvmSentryId.toString()) @@ -71,26 +82,19 @@ internal actual class SentryBridge actual constructor(private val sentryInstance Sentry.setUser(user?.toJvmUser()) } - actual fun logger(): SentryLogger { - return logger - } + actual fun logger(): SentryLogger = logger - actual fun isCrashedLastRun(): Boolean { - return Sentry.isCrashedLastRun() ?: false - } + actual fun isCrashedLastRun(): Boolean = Sentry.isCrashedLastRun() ?: false - actual fun isEnabled(): Boolean { - return Sentry.isEnabled() - } + actual fun isEnabled(): Boolean = Sentry.isEnabled() actual fun close() { Sentry.close() } - private fun configureScopeCallback(scopeCallback: ScopeCallback): (JvmIScope) -> Unit { - return { + private fun configureScopeCallback(scopeCallback: ScopeCallback): (JvmIScope) -> Unit = + { val jvmScopeProvider = JvmScopeProvider(it) scopeCallback.invoke(jvmScopeProvider) } - } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt index b8f18cdbe..f15a147b0 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt @@ -3,22 +3,24 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmBreadcrumb import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -internal fun Breadcrumb.toJvmBreadcrumb() = JvmBreadcrumb().apply { - val scope = this@toJvmBreadcrumb - message = scope.message - type = scope.type - category = scope.category - scope.getData()?.forEach { - setData(it.key, it.value) +internal fun Breadcrumb.toJvmBreadcrumb() = + JvmBreadcrumb().apply { + val scope = this@toJvmBreadcrumb + message = scope.message + type = scope.type + category = scope.category + scope.getData()?.forEach { + setData(it.key, it.value) + } + level = scope.level?.toJvmSentryLevel() } - level = scope.level?.toJvmSentryLevel() -} -internal fun JvmBreadcrumb.toKmpBreadcrumb() = Breadcrumb().apply { - val scope = this@toKmpBreadcrumb - message = scope.message - type = scope.type - category = scope.category - setData(scope.data.toMutableMap()) - level = scope.level?.toKmpSentryLevel() -} +internal fun JvmBreadcrumb.toKmpBreadcrumb() = + Breadcrumb().apply { + val scope = this@toKmpBreadcrumb + message = scope.message + type = scope.type + category = scope.category + setData(scope.data.toMutableMap()) + level = scope.level?.toKmpSentryLevel() + } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt index 07c5d7c5c..f9c6ef16a 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt @@ -3,15 +3,17 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmMessage import io.sentry.kotlin.multiplatform.protocol.Message -internal fun JvmMessage.toKmpMessage() = Message( - message = message, - params = params, - formatted = formatted -) +internal fun JvmMessage.toKmpMessage() = + Message( + message = message, + params = params, + formatted = formatted, + ) -internal fun Message.toJvmMessage() = JvmMessage().apply { - val scope = this@toJvmMessage - message = scope.message - params = scope.params - formatted = scope.formatted -} +internal fun Message.toJvmMessage() = + JvmMessage().apply { + val scope = this@toJvmMessage + message = scope.message + params = scope.params + formatted = scope.formatted + } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt index 7fdfcef2d..278171a76 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt @@ -3,9 +3,10 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmSentryException import io.sentry.kotlin.multiplatform.protocol.SentryException -internal fun JvmSentryException.toKmpSentryException() = SentryException( - type = type, - value = value, - module = module, - threadId = threadId -) +internal fun JvmSentryException.toKmpSentryException() = + SentryException( + type = type, + value = value, + module = module, + threadId = threadId, + ) diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt index eb039a06c..7ac792621 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt @@ -3,22 +3,20 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmSentryLevel import io.sentry.kotlin.multiplatform.SentryLevel -internal fun SentryLevel.toJvmSentryLevel(): JvmSentryLevel? { - return when (this) { +internal fun SentryLevel.toJvmSentryLevel(): JvmSentryLevel? = + when (this) { SentryLevel.DEBUG -> JvmSentryLevel.DEBUG SentryLevel.INFO -> JvmSentryLevel.INFO SentryLevel.WARNING -> JvmSentryLevel.WARNING SentryLevel.ERROR -> JvmSentryLevel.ERROR SentryLevel.FATAL -> JvmSentryLevel.FATAL } -} -internal fun JvmSentryLevel.toKmpSentryLevel(): SentryLevel? { - return when (this) { +internal fun JvmSentryLevel.toKmpSentryLevel(): SentryLevel? = + when (this) { JvmSentryLevel.DEBUG -> SentryLevel.DEBUG JvmSentryLevel.INFO -> SentryLevel.INFO JvmSentryLevel.WARNING -> SentryLevel.WARNING JvmSentryLevel.ERROR -> SentryLevel.ERROR JvmSentryLevel.FATAL -> SentryLevel.FATAL } -} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt index f3025ed2b..345265651 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt @@ -6,13 +6,14 @@ import io.sentry.kotlin.multiplatform.SentryOptions import io.sentry.kotlin.multiplatform.log.toKmpSentryLog import io.sentry.kotlin.multiplatform.log.updateFrom -internal fun SentryOptions.toJvmSentryOptionsCallback(): (JvmSentryOptions) -> Unit = { - it.applyJvmBaseOptions(this) +internal fun SentryOptions.toJvmSentryOptionsCallback(): (JvmSentryOptions) -> Unit = + { + it.applyJvmBaseOptions(this) - sdk?.packages?.forEach { sdkPackage -> - it.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + sdk?.packages?.forEach { sdkPackage -> + it.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + } } -} /** * Applies the given base SentryOptions to this JvmSentryOption diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt index 49f31208e..96a362c44 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt @@ -3,22 +3,24 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmUser import io.sentry.kotlin.multiplatform.protocol.User -internal fun User.toJvmUser() = JvmUser().apply { - val scope = this@toJvmUser - id = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - data = scope.other?.toMutableMap() - unknown = scope.unknown?.toMutableMap() -} +internal fun User.toJvmUser() = + JvmUser().apply { + val scope = this@toJvmUser + id = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + data = scope.other?.toMutableMap() + unknown = scope.unknown?.toMutableMap() + } -internal fun JvmUser.toKmpUser() = User().apply { - val scope = this@toKmpUser - id = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - other = scope.data?.toMutableMap() - unknown = scope.unknown?.toMutableMap() -} +internal fun JvmUser.toKmpUser() = + User().apply { + val scope = this@toKmpUser + id = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + other = scope.data?.toMutableMap() + unknown = scope.unknown?.toMutableMap() + } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt index e4d58e656..cf3e08fb6 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt @@ -11,9 +11,12 @@ import io.sentry.logger.SentryLogParameters */ internal class JvmSentryLoggerAdapter( private val jvmLoggerProvider: () -> ILoggerApi, - logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory + logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory, ) : BaseSentryLogger(logBuilderFactory) { - override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { + override fun sendLog( + level: SentryLogLevel, + formatted: FormattedLog, + ) { val jvmLogger = jvmLoggerProvider() val jvmLevel = level.toJvmSentryLogLevel() if (formatted.attributes.isEmpty()) { diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt index 38934f853..2d22113ae 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt @@ -11,26 +11,28 @@ import io.sentry.kotlin.multiplatform.SentryAttributes as KmpSentryAttributes /** * Converts KMP [SentryLogLevel] to Java SDK's [JvmSentryLogLevel]. */ -internal fun SentryLogLevel.toJvmSentryLogLevel(): JvmSentryLogLevel = when (this) { - SentryLogLevel.TRACE -> JvmSentryLogLevel.TRACE - SentryLogLevel.DEBUG -> JvmSentryLogLevel.DEBUG - SentryLogLevel.INFO -> JvmSentryLogLevel.INFO - SentryLogLevel.WARN -> JvmSentryLogLevel.WARN - SentryLogLevel.ERROR -> JvmSentryLogLevel.ERROR - SentryLogLevel.FATAL -> JvmSentryLogLevel.FATAL -} +internal fun SentryLogLevel.toJvmSentryLogLevel(): JvmSentryLogLevel = + when (this) { + SentryLogLevel.TRACE -> JvmSentryLogLevel.TRACE + SentryLogLevel.DEBUG -> JvmSentryLogLevel.DEBUG + SentryLogLevel.INFO -> JvmSentryLogLevel.INFO + SentryLogLevel.WARN -> JvmSentryLogLevel.WARN + SentryLogLevel.ERROR -> JvmSentryLogLevel.ERROR + SentryLogLevel.FATAL -> JvmSentryLogLevel.FATAL + } /** * Converts Java SDK's [JvmSentryLogLevel] to KMP [SentryLogLevel]. */ -internal fun JvmSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = when (this) { - JvmSentryLogLevel.TRACE -> SentryLogLevel.TRACE - JvmSentryLogLevel.DEBUG -> SentryLogLevel.DEBUG - JvmSentryLogLevel.INFO -> SentryLogLevel.INFO - JvmSentryLogLevel.WARN -> SentryLogLevel.WARN - JvmSentryLogLevel.ERROR -> SentryLogLevel.ERROR - JvmSentryLogLevel.FATAL -> SentryLogLevel.FATAL -} +internal fun JvmSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = + when (this) { + JvmSentryLogLevel.TRACE -> SentryLogLevel.TRACE + JvmSentryLogLevel.DEBUG -> SentryLogLevel.DEBUG + JvmSentryLogLevel.INFO -> SentryLogLevel.INFO + JvmSentryLogLevel.WARN -> SentryLogLevel.WARN + JvmSentryLogLevel.ERROR -> SentryLogLevel.ERROR + JvmSentryLogLevel.FATAL -> SentryLogLevel.FATAL + } /** * Converts KMP [KmpSentryAttributes] to Java SDK's [JvmSentryAttributes]. @@ -48,20 +50,24 @@ internal fun KmpSentryAttributes.toJvmSentryAttributes(): JvmSentryAttributes { * Converts a JVM SentryLog to a KMP SentryLog for use in beforeSendLog callback. * After the callback, changes are applied back via [updateFrom]. */ -internal fun JvmSentryLog.toKmpSentryLog(): SentryLog = SentryLog( - timestamp = timestamp, - level = level.toKmpSentryLogLevel(), - body = body, - severityNumber = severityNumber, - attributes = toKmpSentryAttributes() -) +internal fun JvmSentryLog.toKmpSentryLog(): SentryLog = + SentryLog( + timestamp = timestamp, + level = level.toKmpSentryLogLevel(), + body = body, + severityNumber = severityNumber, + attributes = toKmpSentryAttributes(), + ) /** * Updates this JVM SentryLog from a KMP SentryLog. * @param kmpLog The modified KMP log after user's beforeSendLog callback. * @param originalKmpAttributes The original KMP attributes before the callback, used to detect changes. */ -internal fun JvmSentryLog.updateFrom(kmpLog: SentryLog, originalKmpAttributes: KmpSentryAttributes) { +internal fun JvmSentryLog.updateFrom( + kmpLog: SentryLog, + originalKmpAttributes: KmpSentryAttributes, +) { body = kmpLog.body level = kmpLog.level.toJvmSentryLogLevel() severityNumber = kmpLog.severityNumber @@ -95,7 +101,7 @@ private fun JvmSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { */ private fun JvmSentryLog.updateAttributesFrom( modifiedKmpAttributes: KmpSentryAttributes, - originalKmpAttributes: KmpSentryAttributes + originalKmpAttributes: KmpSentryAttributes, ) { // Remove attributes that were deleted by the user (present in original but not in modified) (originalKmpAttributes.keys - modifiedKmpAttributes.keys).forEach { key -> @@ -104,12 +110,13 @@ private fun JvmSentryLog.updateAttributesFrom( // Add or update attributes from the modified KMP attributes modifiedKmpAttributes.forEach { (key, attrValue) -> - val jvmType = when (attrValue) { - is KmpSentryAttributeValue.StringValue -> JvmSentryAttributeType.STRING - is KmpSentryAttributeValue.LongValue -> JvmSentryAttributeType.INTEGER - is KmpSentryAttributeValue.DoubleValue -> JvmSentryAttributeType.DOUBLE - is KmpSentryAttributeValue.BooleanValue -> JvmSentryAttributeType.BOOLEAN - } + val jvmType = + when (attrValue) { + is KmpSentryAttributeValue.StringValue -> JvmSentryAttributeType.STRING + is KmpSentryAttributeValue.LongValue -> JvmSentryAttributeType.INTEGER + is KmpSentryAttributeValue.DoubleValue -> JvmSentryAttributeType.DOUBLE + is KmpSentryAttributeValue.BooleanValue -> JvmSentryAttributeType.BOOLEAN + } setAttribute(key, SentryLogEventAttributeValue(jvmType, attrValue.value)) } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt index 1387710ce..a747246c7 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt @@ -2,8 +2,9 @@ package io.sentry.kotlin.multiplatform.protocol import io.sentry.kotlin.multiplatform.JvmSentryId -public actual data class SentryId actual constructor(val sentryIdString: String) { - +public actual data class SentryId actual constructor( + val sentryIdString: String, +) { public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } @@ -11,14 +12,13 @@ public actual data class SentryId actual constructor(val sentryIdString: String) private var jvmSentryId: JvmSentryId? = null init { - jvmSentryId = if (sentryIdString.isEmpty()) { - JvmSentryId.EMPTY_ID - } else { - JvmSentryId(sentryIdString) - } + jvmSentryId = + if (sentryIdString.isEmpty()) { + JvmSentryId.EMPTY_ID + } else { + JvmSentryId(sentryIdString) + } } - actual override fun toString(): String { - return jvmSentryId.toString() - } + actual override fun toString(): String = jvmSentryId.toString() } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index a95a3e24c..2c619a662 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -4,25 +4,16 @@ import io.sentry.kotlin.multiplatform.extensions.toJvmBreadcrumb import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -actual data class BreadcrumbTestConverter actual constructor(val breadcrumb: Breadcrumb) { +actual data class BreadcrumbTestConverter actual constructor( + val breadcrumb: Breadcrumb, +) { + actual fun getType(): String? = breadcrumb.toJvmBreadcrumb().type - actual fun getType(): String? { - return breadcrumb.toJvmBreadcrumb().type - } + actual fun getCategory(): String? = breadcrumb.toJvmBreadcrumb().category - actual fun getCategory(): String? { - return breadcrumb.toJvmBreadcrumb().category - } + actual fun getMessage(): String? = breadcrumb.toJvmBreadcrumb().message - actual fun getMessage(): String? { - return breadcrumb.toJvmBreadcrumb().message - } + actual fun getData(): MutableMap = breadcrumb.toJvmBreadcrumb().data - actual fun getData(): MutableMap { - return breadcrumb.toJvmBreadcrumb().data - } - - actual fun getLevel(): SentryLevel? { - return breadcrumb.toJvmBreadcrumb().level?.toKmpSentryLevel() - } + actual fun getLevel(): SentryLevel? = breadcrumb.toJvmBreadcrumb().level?.toKmpSentryLevel() } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt index 66b16ee3a..cff4b3438 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt @@ -5,7 +5,6 @@ import kotlin.test.Test import kotlin.test.assertFailsWith class JvmSentryIdTest { - @Test fun `Jvm SentryId with invalid uuid string throws IllegalArgumentException`() { val uuidString = "ec720-b6f6-4efc--5c1" diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt index b1b978854..82c291267 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt @@ -4,6 +4,5 @@ import io.sentry.kotlin.multiplatform.log.toJvmSentryAttributes /** Tests for SentryAttributes to JVM conversion. */ class SentryAttributesConversionTest : BaseSentryAttributesConversionTest() { - override fun SentryAttributes.toMap(): Map = - toJvmSentryAttributes().attributes.mapValues { it.value.value } + override fun SentryAttributes.toMap(): Map = toJvmSentryAttributes().attributes.mapValues { it.value.value } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt index 0d08dbbf8..3b2936856 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt @@ -49,9 +49,11 @@ actual class SentryBridgeTest { } // WHEN - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.beforeSend != null) @@ -64,9 +66,11 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.beforeSend != null) @@ -77,10 +81,12 @@ actual class SentryBridgeTest { actual fun `default beforeSend in init does not drop the event after prepareForInit`() { fixture.sut.init { } - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - prepareForInit() - }.let { it as JvmSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + prepareForInit() + }.let { it as JvmSentryOptions } assert(option.beforeSend != null) assert(option.beforeSend!!.execute(JvmSentryEvent(), Hint()) != null) @@ -90,9 +96,11 @@ actual class SentryBridgeTest { actual fun `init sets the SDK packages`() { // WHEN fixture.sut.init { } - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.sdkVersion?.packageSet != null) @@ -110,9 +118,11 @@ actual class SentryBridgeTest { // When fixture.sut.init(configuration) - val option = SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = + SentryPlatformOptions() + .apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // Then assertTrue(option.sdkVersion!!.name.contains("kmp")) diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index ac6fcb1f6..4f2d3e9da 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -4,7 +4,5 @@ import io.sentry.kotlin.multiplatform.extensions.toJvmSentryLevel import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel actual class SentryLevelTestConverter actual constructor() { - actual fun convert(sentryLevel: SentryLevel?): SentryLevel? { - return sentryLevel?.toJvmSentryLevel()?.toKmpSentryLevel() - } + actual fun convert(sentryLevel: SentryLevel?): SentryLevel? = sentryLevel?.toJvmSentryLevel()?.toKmpSentryLevel() } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt index e38013bda..4568ace79 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt @@ -2,7 +2,6 @@ package io.sentry.kotlin.multiplatform /** An attachment to be sent along with the event. */ public expect class Attachment { - /** The bytes of the attachment. */ public val bytes: ByteArray? diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt index 76694a979..2a22dd473 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt @@ -9,13 +9,13 @@ package io.sentry.kotlin.multiplatform * @property min the min status code of the range * @property max the max status code of the range */ -public data class HttpStatusCodeRange(val min: Int = DEFAULT_MIN, val max: Int = DEFAULT_MAX) { - +public data class HttpStatusCodeRange( + val min: Int = DEFAULT_MIN, + val max: Int = DEFAULT_MAX, +) { public constructor(statusCode: Int) : this(statusCode, statusCode) - public fun isInRange(statusCode: Int): Boolean { - return statusCode in min..max - } + public fun isInRange(statusCode: Int): Boolean = statusCode in min..max public companion object { /** The default min status code of the range. */ diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt index 86d540376..5a8f67b30 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt @@ -13,7 +13,6 @@ import io.sentry.kotlin.multiplatform.protocol.User * - For Cocoa: [io.sentry.kotlin.multiplatform.CocoaScopeProvider] */ public interface Scope { - /** * Returns the scope's tags */ @@ -61,7 +60,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Any) + public fun setContext( + key: String, + value: Any, + ) /** * Sets the Scope's contexts @@ -69,7 +71,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Boolean) + public fun setContext( + key: String, + value: Boolean, + ) /** * Sets the Scope's context @@ -77,7 +82,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: String) + public fun setContext( + key: String, + value: String, + ) /** * Sets the Scope's context @@ -85,7 +93,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Number) + public fun setContext( + key: String, + value: Number, + ) /** * Sets the Scope's context @@ -93,7 +104,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Collection<*>) + public fun setContext( + key: String, + value: Collection<*>, + ) /** * Sets the Scope's context @@ -101,7 +115,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Array<*>) + public fun setContext( + key: String, + value: Array<*>, + ) /** * Sets the Scope's context @@ -109,7 +126,10 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext(key: String, value: Char) + public fun setContext( + key: String, + value: Char, + ) /** * Removes a value from the Scope's contexts @@ -124,7 +144,10 @@ public interface Scope { * @param key the key * @param value the value */ - public fun setTag(key: String, value: String) + public fun setTag( + key: String, + value: String, + ) /** * Removes a tag from the Scope's tags @@ -139,7 +162,10 @@ public interface Scope { * @param key the key * @param value the value */ - public fun setExtra(key: String, value: String) + public fun setExtra( + key: String, + value: String, + ) /** * Removes an extra from the Scope's extras diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt index 9d18d2a91..ffe7bcdcc 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt @@ -11,19 +11,27 @@ package io.sentry.kotlin.multiplatform */ public sealed class SentryAttributeValue( /** The underlying raw value. */ - public val value: Any + public val value: Any, ) { /** Holds a [String] attribute value. */ - public class StringValue(value: String) : SentryAttributeValue(value) + public class StringValue( + value: String, + ) : SentryAttributeValue(value) /** Holds a [Long] attribute value. */ - public class LongValue(value: Long) : SentryAttributeValue(value) + public class LongValue( + value: Long, + ) : SentryAttributeValue(value) /** Holds a [Double] attribute value. */ - public class DoubleValue(value: Double) : SentryAttributeValue(value) + public class DoubleValue( + value: Double, + ) : SentryAttributeValue(value) /** Holds a [Boolean] attribute value. */ - public class BooleanValue(value: Boolean) : SentryAttributeValue(value) + public class BooleanValue( + value: Boolean, + ) : SentryAttributeValue(value) /** Returns the String value, or null if this is not a [StringValue]. */ public val stringOrNull: String? get() = (this as? StringValue)?.value as? String diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt index 863057a4a..d6fe4c6c7 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt @@ -6,35 +6,53 @@ package io.sentry.kotlin.multiplatform * (e.g., `stringOrNull`, `longOrNull`) to extract typed values. */ public class SentryAttributes private constructor( - private val attributes: MutableMap + private val attributes: MutableMap, ) : MutableMap by attributes { /** Sets a [String] value by key. */ - public operator fun set(key: String, value: String) { + public operator fun set( + key: String, + value: String, + ) { attributes[key] = SentryAttributeValue.string(value) } /** Sets an [Int] value by key. Stored as 64-bit Long value. */ - public operator fun set(key: String, value: Int) { + public operator fun set( + key: String, + value: Int, + ) { attributes[key] = SentryAttributeValue.long(value.toLong()) } /** Sets a [Long] value by key. */ - public operator fun set(key: String, value: Long) { + public operator fun set( + key: String, + value: Long, + ) { attributes[key] = SentryAttributeValue.long(value) } /** Sets an [Float] value by key. Stored as 64-bit Double value. */ - public operator fun set(key: String, value: Float) { + public operator fun set( + key: String, + value: Float, + ) { attributes[key] = SentryAttributeValue.double(value.toDouble()) } /** Sets a [Double] value by key. */ - public operator fun set(key: String, value: Double) { + public operator fun set( + key: String, + value: Double, + ) { attributes[key] = SentryAttributeValue.double(value) } /** Sets a [Boolean] value by key. */ - public operator fun set(key: String, value: Boolean) { + public operator fun set( + key: String, + value: Boolean, + ) { attributes[key] = SentryAttributeValue.boolean(value) } @@ -46,9 +64,7 @@ public class SentryAttributes private constructor( public fun empty(): SentryAttributes = SentryAttributes(mutableMapOf()) /** Creates a [SentryAttributes] collection from the given map. */ - public fun of(attributes: Map): SentryAttributes { - return SentryAttributes(attributes.toMutableMap()) - } + public fun of(attributes: Map): SentryAttributes = SentryAttributes(attributes.toMutableMap()) /** * Creates a [SentryAttributes] collection from the given key-value pairs. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt index 604df1c19..756f703dd 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt @@ -7,7 +7,7 @@ import io.sentry.kotlin.multiplatform.protocol.User /** Base class for all Sentry events. */ public abstract class SentryBaseEvent( /** The Sentry event ID. */ - public open var eventId: SentryId = SentryId.EMPTY_ID + public open var eventId: SentryId = SentryId.EMPTY_ID, ) { /** The event release. */ public open var release: String? = null @@ -65,7 +65,10 @@ public abstract class SentryBaseEvent( tags.remove(key) } - public fun setTag(key: String, value: String) { + public fun setTag( + key: String, + value: String, + ) { tags.set(key, value) } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt index 33648df5e..18a822b9d 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt @@ -6,8 +6,13 @@ import io.sentry.kotlin.multiplatform.protocol.SentryId import io.sentry.kotlin.multiplatform.protocol.User import io.sentry.kotlin.multiplatform.protocol.UserFeedback -internal expect class SentryBridge(sentryInstance: SentryInstance = SentryPlatformInstance()) { - fun init(context: Context, configuration: OptionsConfiguration) +internal expect class SentryBridge( + sentryInstance: SentryInstance = SentryPlatformInstance(), +) { + fun init( + context: Context, + configuration: OptionsConfiguration, + ) fun init(configuration: OptionsConfiguration) @@ -15,11 +20,17 @@ internal expect class SentryBridge(sentryInstance: SentryInstance = SentryPlatfo fun captureMessage(message: String): SentryId - fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId + fun captureMessage( + message: String, + scopeCallback: ScopeCallback, + ): SentryId fun captureException(throwable: Throwable): SentryId - fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId + fun captureException( + throwable: Throwable, + scopeCallback: ScopeCallback, + ): SentryId fun configureScope(scopeCallback: ScopeCallback) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt index 7c346c762..1c8bfba19 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt @@ -30,9 +30,12 @@ public object Sentry { @HiddenFromObjC @Deprecated( "Use init(OptionsConfiguration) instead.", - ReplaceWith("Sentry.init(configuration)") + ReplaceWith("Sentry.init(configuration)"), ) - public fun init(context: Context, configuration: OptionsConfiguration) { + public fun init( + context: Context, + configuration: OptionsConfiguration, + ) { bridge.init(context, configuration) } @@ -72,9 +75,7 @@ public object Sentry { * * @param message The message to send. */ - public fun captureMessage(message: String): SentryId { - return bridge.captureMessage(message) - } + public fun captureMessage(message: String): SentryId = bridge.captureMessage(message) /** * Captures the exception. @@ -82,18 +83,17 @@ public object Sentry { * @param message The message to send. * @param scopeCallback The local scope callback. */ - public fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { - return bridge.captureMessage(message, scopeCallback) - } + public fun captureMessage( + message: String, + scopeCallback: ScopeCallback, + ): SentryId = bridge.captureMessage(message, scopeCallback) /** * Captures the exception. * * @param throwable The exception. */ - public fun captureException(throwable: Throwable): SentryId { - return bridge.captureException(throwable) - } + public fun captureException(throwable: Throwable): SentryId = bridge.captureException(throwable) /** * Captures the exception. @@ -101,18 +101,17 @@ public object Sentry { * @param throwable The exception. * @param scopeCallback The local scope callback. */ - public fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { - return bridge.captureException(throwable, scopeCallback) - } + public fun captureException( + throwable: Throwable, + scopeCallback: ScopeCallback, + ): SentryId = bridge.captureException(throwable, scopeCallback) /** * Captures a manually created user feedback and sends it to Sentry. * * @param userFeedback The user feedback to send to Sentry. */ - public fun captureUserFeedback(userFeedback: UserFeedback) { - return bridge.captureUserFeedback(userFeedback) - } + public fun captureUserFeedback(userFeedback: UserFeedback): Unit = bridge.captureUserFeedback(userFeedback) /** * Configures the scope through the callback. @@ -172,23 +171,17 @@ public object Sentry { /** * Returns true if the app crashed during last run. */ - public fun isCrashedLastRun(): Boolean { - return bridge.isCrashedLastRun() - } + public fun isCrashedLastRun(): Boolean = bridge.isCrashedLastRun() /** * Throws a RuntimeException, useful for testing. */ - public fun crash() { - throw RuntimeException("Uncaught Exception from Kotlin Multiplatform.") - } + public fun crash(): Unit = throw RuntimeException("Uncaught Exception from Kotlin Multiplatform.") /** * Checks if the SDK is enabled. */ - public fun isEnabled(): Boolean { - return bridge.isEnabled() - } + public fun isEnabled(): Boolean = bridge.isEnabled() /** * Closes the SDK. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt index c07d0b474..6f70a817f 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt @@ -9,26 +9,26 @@ internal object SentryLevelNumConstants { } /** The level of the event similar to logging levels. */ -public enum class SentryLevel(private val value: Int) { +public enum class SentryLevel( + private val value: Int, +) { DEBUG(SentryLevelNumConstants.DEBUG_LEVEL), INFO(SentryLevelNumConstants.INFO_LEVEL), WARNING(SentryLevelNumConstants.WARNING_LEVEL), ERROR(SentryLevelNumConstants.ERROR_LEVEL), - FATAL(SentryLevelNumConstants.FATAL_LEVEL); + FATAL(SentryLevelNumConstants.FATAL_LEVEL), + ; - internal fun toInt(): Int { - return this.value - } + internal fun toInt(): Int = this.value internal companion object { - fun fromInt(value: Int): SentryLevel? { - return try { + fun fromInt(value: Int): SentryLevel? = + try { values().first { it.value == value } } catch (throwable: Throwable) { null } - } } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt index 286485180..e0fdc20bb 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt @@ -11,7 +11,6 @@ public data class SentryReplayOptions( * The default is null (disabled). */ public var sessionSampleRate: Double? = null, - /** * Indicates the percentage in which a 30 seconds replay will be sent with error events. * Specifying 0 means never, 1.0 means always. The value needs to be >= 0.0 and <= 1.0. @@ -19,26 +18,23 @@ public data class SentryReplayOptions( * The default is null (disabled). */ public var onErrorSampleRate: Double? = null, - /** * Makss all text content. Draws a rectangle of text bounds with text color on top. * * The default is true. */ public var maskAllText: Boolean = true, - /** * Masks all image content. Draws a rectangle of image bounds with image's dominant color on top. * * The default is true. */ public var maskAllImages: Boolean = true, - /** * Defines the quality of the session replay. The higher the quality, the more accurate the replay * will be, but also more data to transfer and more CPU load, defaults to MEDIUM. */ - public var quality: Quality = Quality.MEDIUM + public var quality: Quality = Quality.MEDIUM, ) { /** * Quality of the session replay. @@ -51,7 +47,7 @@ public data class SentryReplayOptions( * Defines the quality of the session replay. Higher bit rates have better replay quality, but * also affect the final payload size to transfer, defaults to 40kbps. */ - public val bitRate: Int + public val bitRate: Int, ) { /** Video Scale: 80% Bit Rate: 50.000 */ LOW(0.8f, 50000), @@ -60,6 +56,6 @@ public data class SentryReplayOptions( MEDIUM(1.0f, 75000), /** Video Scale: 100% Bit Rate: 100.000 */ - HIGH(1.0f, 100000) + HIGH(1.0f, 100000), } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt index 3d7ccc6f4..d10ccb792 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt @@ -14,7 +14,7 @@ import io.sentry.kotlin.multiplatform.SentryAttributes * the formatted log to their native SDK. */ internal abstract class BaseSentryLogger( - private val logBuilderFactory: SentryLogBuilderFactory + private val logBuilderFactory: SentryLogBuilderFactory, ) : SentryLogger { /** * Sends a formatted log to the native SDK. @@ -23,86 +23,153 @@ internal abstract class BaseSentryLogger( * @param level The log level * @param formatted The formatted log with body and attributes */ - protected abstract fun sendLog(level: SentryLogLevel, formatted: FormattedLog) - - override fun trace(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.TRACE, message, args) - override fun debug(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.DEBUG, message, args) - override fun info(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.INFO, message, args) - override fun warn(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.WARN, message, args) - override fun error(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.ERROR, message, args) - override fun fatal(message: String, vararg args: Any?) = - logWithParams(SentryLogLevel.FATAL, message, args) - - override fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.TRACE, message, attributes = attributes) - override fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.DEBUG, message, attributes = attributes) - override fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.INFO, message, attributes = attributes) - override fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.WARN, message, attributes = attributes) - override fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.ERROR, message, attributes = attributes) - override fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.FATAL, message, attributes = attributes) - - override fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.TRACE, message, args, attributes) - override fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.DEBUG, message, args, attributes) - override fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.INFO, message, args, attributes) - override fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.WARN, message, args, attributes) - override fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.ERROR, message, args, attributes) - override fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = - logWithParams(SentryLogLevel.FATAL, message, args, attributes) - - override fun log(level: SentryLogLevel, message: String, vararg args: Any?) = - logWithParams(level, message, args) + protected abstract fun sendLog( + level: SentryLogLevel, + formatted: FormattedLog, + ) + + override fun trace( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.TRACE, message, args) + + override fun debug( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.DEBUG, message, args) + + override fun info( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.INFO, message, args) + + override fun warn( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.WARN, message, args) + + override fun error( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.ERROR, message, args) + + override fun fatal( + message: String, + vararg args: Any?, + ) = logWithParams(SentryLogLevel.FATAL, message, args) + + override fun trace( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.TRACE, message, attributes = attributes) + + override fun debug( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.DEBUG, message, attributes = attributes) + + override fun info( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.INFO, message, attributes = attributes) + + override fun warn( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.WARN, message, attributes = attributes) + + override fun error( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.ERROR, message, attributes = attributes) + + override fun fatal( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.FATAL, message, attributes = attributes) + + override fun trace( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.TRACE, message, args, attributes) + + override fun debug( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.DEBUG, message, args, attributes) + + override fun info( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.INFO, message, args, attributes) + + override fun warn( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.WARN, message, args, attributes) + + override fun error( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.ERROR, message, args, attributes) + + override fun fatal( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) = logWithParams(SentryLogLevel.FATAL, message, args, attributes) + + override fun log( + level: SentryLogLevel, + message: String, + vararg args: Any?, + ) = logWithParams(level, message, args) @Suppress("SpreadOperator") override fun log( level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit + attributes: @SentryLogDsl SentryAttributes.() -> Unit, ) = logWithParams(level, message, args, attributes) - override fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, level) - - override fun trace(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.TRACE) - override fun debug(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.DEBUG) - override fun info(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.INFO) - override fun warn(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.WARN) - override fun error(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.ERROR) - override fun fatal(block: SentryLogBuilder.() -> Unit) = - logWithBuilder(block, SentryLogLevel.FATAL) + override fun log( + level: SentryLogLevel, + block: SentryLogBuilder.() -> Unit, + ) = logWithBuilder(block, level) + + override fun trace(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.TRACE) + + override fun debug(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.DEBUG) + + override fun info(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.INFO) + + override fun warn(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.WARN) + + override fun error(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.ERROR) + + override fun fatal(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.FATAL) @Suppress("SpreadOperator") private fun logWithParams( level: SentryLogLevel, message: String, args: Array = emptyArray(), - attributes: (@SentryLogDsl SentryAttributes.() -> Unit)? = null + attributes: (@SentryLogDsl SentryAttributes.() -> Unit)? = null, ) = logWithBuilder({ if (args.isEmpty()) message(message) else message(message, *args) attributes?.let { attributes(it) } }, level) - private inline fun logWithBuilder(block: SentryLogBuilder.() -> Unit, level: SentryLogLevel) { + private inline fun logWithBuilder( + block: SentryLogBuilder.() -> Unit, + level: SentryLogLevel, + ) { val formatted = logBuilderFactory().apply(block).buildFormatted() ?: return sendLog(level, formatted) } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt index d4116e5e3..aaaf0bf77 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt @@ -32,7 +32,10 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { args = emptyArray() } - override fun message(template: String, vararg args: Any?) { + override fun message( + template: String, + vararg args: Any?, + ) { this.template = template this.args = args } @@ -55,7 +58,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { return FormattedLog( body = formattedBody, - attributes = allAttributes + attributes = allAttributes, ) } @@ -63,7 +66,10 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { * Formats the message by substituting %s placeholders with argument values. * Use %% to produce a literal percent sign. */ - private fun formatMessage(template: String, args: Array): String { + private fun formatMessage( + template: String, + args: Array, + ): String { if (!template.contains('%')) return template var argIndex = 0 @@ -82,7 +88,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { private fun buildAllAttributes( template: String, args: Array, - customAttributes: SentryAttributes + customAttributes: SentryAttributes, ): SentryAttributes { val result = SentryAttributes.empty() diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt index f42369ba0..ab69ee45e 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt @@ -10,16 +10,12 @@ import io.sentry.kotlin.multiplatform.SentryAttributes public open class SentryLog( /** Unix timestamp in seconds when the log was created. */ public open val timestamp: Double, - /** The severity level of this log entry. */ public open var level: SentryLogLevel, - /** The log message body. */ public open var body: String, - /** Optional numeric severity. */ public open var severityNumber: Int? = null, - /** Custom key-value attributes attached to this log entry. */ - public open val attributes: SentryAttributes = SentryAttributes.empty() + public open val attributes: SentryAttributes = SentryAttributes.empty(), ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt index 9945e0356..208eb6b12 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt @@ -50,7 +50,10 @@ public interface SentryLogBuilder { * @param template The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the template via toString() */ - public fun message(template: String, vararg args: Any?) + public fun message( + template: String, + vararg args: Any?, + ) /** * Merges prebuilt attributes into this log entry. @@ -97,5 +100,5 @@ public class FormattedLog( /** The formatted message body with placeholders substituted. */ public val body: String, /** Complete attributes including template info and custom attributes. */ - public val attributes: SentryAttributes + public val attributes: SentryAttributes, ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt index 98110eded..ad46fd911 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt @@ -9,5 +9,5 @@ public enum class SentryLogLevel { INFO, WARN, ERROR, - FATAL + FATAL, } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt index 1f9c604f8..1fc47ba29 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt @@ -15,7 +15,11 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun log(level: SentryLogLevel, message: String, vararg args: Any?) + public fun log( + level: SentryLogLevel, + message: String, + vararg args: Any?, + ) /** * Logs a message at a specific level with inline attributes. @@ -29,7 +33,7 @@ public interface SentryLogger { level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit + attributes: @SentryLogDsl SentryAttributes.() -> Unit, ) /** @@ -49,7 +53,10 @@ public interface SentryLogger { * @param level The log level * @param block A lambda with [SentryLogBuilder] receiver to configure the log entry */ - public fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) + public fun log( + level: SentryLogLevel, + block: SentryLogBuilder.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.TRACE] level. @@ -57,7 +64,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun trace(message: String, vararg args: Any?) + public fun trace( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.DEBUG] level. @@ -65,7 +75,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun debug(message: String, vararg args: Any?) + public fun debug( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.INFO] level. @@ -73,7 +86,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun info(message: String, vararg args: Any?) + public fun info( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.WARN] level. @@ -81,7 +97,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun warn(message: String, vararg args: Any?) + public fun warn( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.ERROR] level. @@ -89,7 +108,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun error(message: String, vararg args: Any?) + public fun error( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.FATAL] level. @@ -97,7 +119,10 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun fatal(message: String, vararg args: Any?) + public fun fatal( + message: String, + vararg args: Any?, + ) /** * Logs a message at [SentryLogLevel.TRACE] level with inline attributes. @@ -113,7 +138,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun trace( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.DEBUG] level with inline attributes. @@ -129,7 +157,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun debug( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.INFO] level with inline attributes. @@ -145,7 +176,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun info( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.WARN] level with inline attributes. @@ -161,7 +195,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun warn( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.TRACE] level with template parameters and inline attributes. @@ -178,7 +215,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun trace( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.DEBUG] level with template parameters and inline attributes. @@ -195,7 +236,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun debug( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.INFO] level with template parameters and inline attributes. @@ -212,7 +257,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun info( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.WARN] level with template parameters and inline attributes. @@ -229,7 +278,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun warn( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.ERROR] level with template parameters and inline attributes. @@ -246,7 +299,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun error( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.FATAL] level with template parameters and inline attributes. @@ -263,7 +320,11 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun fatal( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.ERROR] level with inline attributes. @@ -279,7 +340,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun error( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.FATAL] level with inline attributes. @@ -295,7 +359,10 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) + public fun fatal( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) /** * Logs a message at [SentryLogLevel.TRACE] level using a DSL builder. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt index 71d95e801..4205cbc30 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt @@ -10,107 +10,110 @@ import io.sentry.kotlin.multiplatform.SentryLevel public data class Breadcrumb( /** The breadcrumb's level */ var level: SentryLevel? = null, - /** The breadcrumb's type */ var type: String? = null, - /** The breadcrumb's message */ var message: String? = null, - /** The breadcrumb's category */ var category: String? = null, - - private var data: MutableMap? = null + private var data: MutableMap? = null, ) { - public companion object { - public fun user(category: String, message: String): Breadcrumb { - return Breadcrumb().apply { + public fun user( + category: String, + message: String, + ): Breadcrumb = + Breadcrumb().apply { this.category = category this.message = message this.type = "user" } - } - public fun http(url: String, method: String): Breadcrumb { - return Breadcrumb().apply { + public fun http( + url: String, + method: String, + ): Breadcrumb = + Breadcrumb().apply { this.type = "http" this.category = "http" this.setData("url", url) this.setData("method", method.uppercase()) } - } - public fun http(url: String, method: String, code: Int?): Breadcrumb { - return http(url, method).apply { + public fun http( + url: String, + method: String, + code: Int?, + ): Breadcrumb = + http(url, method).apply { code?.let { this.setData("status_code", code) } } - } - public fun navigation(from: String, to: String): Breadcrumb { - return Breadcrumb().apply { + public fun navigation( + from: String, + to: String, + ): Breadcrumb = + Breadcrumb().apply { this.category = "navigation" this.type = "navigation" this.setData("from", from) this.setData("to", to) } - } - public fun transaction(message: String): Breadcrumb { - return Breadcrumb().apply { + public fun transaction(message: String): Breadcrumb = + Breadcrumb().apply { this.type = "default" this.category = "sentry.transaction" this.message = message } - } public fun debug(message: String): Breadcrumb { - val breadcrumb = Breadcrumb().apply { - this.type = "debug" - this.message = message - this.level = SentryLevel.DEBUG - } + val breadcrumb = + Breadcrumb().apply { + this.type = "debug" + this.message = message + this.level = SentryLevel.DEBUG + } return breadcrumb } - public fun error(message: String): Breadcrumb { - return Breadcrumb().apply { + public fun error(message: String): Breadcrumb = + Breadcrumb().apply { this.type = "error" this.message = message this.level = SentryLevel.ERROR } - } - public fun info(message: String): Breadcrumb { - return Breadcrumb().apply { + public fun info(message: String): Breadcrumb = + Breadcrumb().apply { this.type = "info" this.message = message this.level = SentryLevel.INFO } - } - public fun query(message: String): Breadcrumb { - return Breadcrumb().apply { + public fun query(message: String): Breadcrumb = + Breadcrumb().apply { this.type = "query" this.message = message } - } - public fun ui(category: String, message: String): Breadcrumb { - return Breadcrumb().apply { + public fun ui( + category: String, + message: String, + ): Breadcrumb = + Breadcrumb().apply { this.type = "default" this.category = "ui.$category" this.message = message } - } public fun userInteraction( subCategory: String, viewId: String?, viewClass: String?, - additionalData: Map - ): Breadcrumb { - return Breadcrumb().apply { + additionalData: Map, + ): Breadcrumb = + Breadcrumb().apply { this.type = "user" this.category = "ui.$subCategory" this.level = SentryLevel.INFO @@ -122,15 +125,12 @@ public data class Breadcrumb( } } } - } public fun userInteraction( subCategory: String, viewId: String?, - viewClass: String? - ): Breadcrumb { - return userInteraction(subCategory, viewId, viewClass, emptyMap()) - } + viewClass: String?, + ): Breadcrumb = userInteraction(subCategory, viewId, viewClass, emptyMap()) } /** @@ -139,7 +139,10 @@ public data class Breadcrumb( * @param key The key * @param value The value */ - public fun setData(key: String, value: Any) { + public fun setData( + key: String, + value: Any, + ) { if (data == null) data = mutableMapOf() data?.put(key, value) } @@ -154,9 +157,7 @@ public data class Breadcrumb( } /** Returns the breadcrumb's data */ - public fun getData(): MutableMap? { - return data - } + public fun getData(): MutableMap? = data /** Clears the breadcrumb and returns it to the default state */ public fun clear() { diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt index 37d525e50..a6f9e4189 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt @@ -16,5 +16,5 @@ public data class Message( * The formatted message. If `message` and `params` are given, Sentry will attempt to backfill * `formatted` if empty. */ - public var formatted: String? = null + public var formatted: String? = null, ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt index c28381d47..f7fd2df69 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt @@ -4,15 +4,17 @@ package io.sentry.kotlin.multiplatform.protocol public data class SdkVersion( /** The name of the SDK. */ val name: String, - /** The version of the SDK. */ - val version: String + val version: String, ) { /** Packages used by the SDK. */ var packages: List? = mutableListOf() private set - public fun addPackage(name: String, version: String) { + public fun addPackage( + name: String, + version: String, + ) { val mutableList = packages?.toMutableList() mutableList?.add(Package(name, version)) packages = mutableList @@ -24,5 +26,5 @@ public data class Package( /** The name of the package. */ val name: String, /** The version of the package. */ - val version: String + val version: String, ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt index af3db1930..e614ee551 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt @@ -14,5 +14,5 @@ public data class SentryException( /** The optional module, or package which the exception type lives in. */ val module: String? = null, /** An optional value that refers to a thread. */ - val threadId: Long? = null + val threadId: Long? = null, ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt index 1db521a5e..07244c48f 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt @@ -1,10 +1,13 @@ package io.sentry.kotlin.multiplatform.protocol /** The Sentry event ID */ -public expect class SentryId(sentryIdString: String) { +public expect class SentryId( + sentryIdString: String, +) { public companion object { /** Returns a new empty SentryId */ public val EMPTY_ID: SentryId } + override fun toString(): String } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt index 0927dfd9e..aa4ef3f59 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt @@ -4,33 +4,27 @@ package io.sentry.kotlin.multiplatform.protocol public data class User( /** The user's email */ var email: String? = null, - /** The user's id */ var id: String? = null, - /** The user's username */ var username: String? = null, - /** The user's ip address*/ var ipAddress: String? = null, - /** * Additional arbitrary fields, as stored in the database (and sometimes as sent by clients). All * data from `self.other` should end up here after store normalization. */ var other: MutableMap? = null, - /** Unknown fields, only internal usage. */ - var unknown: MutableMap? = null + var unknown: MutableMap? = null, ) { - public constructor(user: User) : this( user.email, user.id, user.username, user.ipAddress, user.other, - user.unknown + user.unknown, ) // This secondary constructor allows Swift also to init without specifying nil explicitly diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt index 9569a03ee..b801aae62 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt @@ -3,7 +3,7 @@ package io.sentry.kotlin.multiplatform.protocol /** UserFeedback adds additional information about what happened to an event. */ public data class UserFeedback( /** The Sentry event ID */ - val sentryId: SentryId + val sentryId: SentryId, ) { /** The user's name */ var name: String? = null diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt index 84d0bf2dd..c229840f8 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt @@ -1,7 +1,6 @@ package io.sentry.kotlin.multiplatform public actual class Attachment { - public actual val bytes: ByteArray? public actual val contentType: String? public actual val pathname: String? diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt index 9870f9f26..b5b3e6606 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt @@ -9,79 +9,143 @@ import io.sentry.kotlin.multiplatform.log.SentryLogger * No-op implementation of [SentryLogger] for stub/unsupported platforms. */ internal class NoOpSentryLogger : SentryLogger { - override fun trace(message: String, vararg args: Any?) { + override fun trace( + message: String, + vararg args: Any?, + ) { // No-op } - override fun debug(message: String, vararg args: Any?) { + override fun debug( + message: String, + vararg args: Any?, + ) { // No-op } - override fun info(message: String, vararg args: Any?) { + override fun info( + message: String, + vararg args: Any?, + ) { // No-op } - override fun warn(message: String, vararg args: Any?) { + override fun warn( + message: String, + vararg args: Any?, + ) { // No-op } - override fun error(message: String, vararg args: Any?) { + override fun error( + message: String, + vararg args: Any?, + ) { // No-op } - override fun fatal(message: String, vararg args: Any?) { + override fun fatal( + message: String, + vararg args: Any?, + ) { // No-op } - override fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun trace( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun debug( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun info( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun warn( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun error( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun fatal( + message: String, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun trace( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun debug( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun info( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun warn( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun error( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { + override fun fatal( + message: String, + vararg args: Any?, + attributes: @SentryLogDsl SentryAttributes.() -> Unit, + ) { // No-op } - override fun log(level: SentryLogLevel, message: String, vararg args: Any?) { + override fun log( + level: SentryLogLevel, + message: String, + vararg args: Any?, + ) { // No-op } @@ -89,12 +153,15 @@ internal class NoOpSentryLogger : SentryLogger { level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit + attributes: @SentryLogDsl SentryAttributes.() -> Unit, ) { // No-op } - override fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) { + override fun log( + level: SentryLogLevel, + block: SentryLogBuilder.() -> Unit, + ) { // No-op } diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt index 85c2bc8cf..81d7189f4 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt @@ -8,9 +8,12 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback @Suppress("UnusedPrivateMember") internal actual class SentryBridge actual constructor( - private val sentryInstance: SentryInstance + private val sentryInstance: SentryInstance, ) { - actual fun init(context: Context, configuration: OptionsConfiguration) { + actual fun init( + context: Context, + configuration: OptionsConfiguration, + ) { // No-op } @@ -22,21 +25,19 @@ internal actual class SentryBridge actual constructor( // No-op } - actual fun captureMessage(message: String): SentryId { - return SentryId.EMPTY_ID - } + actual fun captureMessage(message: String): SentryId = SentryId.EMPTY_ID - actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { - return SentryId.EMPTY_ID - } + actual fun captureMessage( + message: String, + scopeCallback: ScopeCallback, + ): SentryId = SentryId.EMPTY_ID - actual fun captureException(throwable: Throwable): SentryId { - return SentryId.EMPTY_ID - } + actual fun captureException(throwable: Throwable): SentryId = SentryId.EMPTY_ID - actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { - return SentryId.EMPTY_ID - } + actual fun captureException( + throwable: Throwable, + scopeCallback: ScopeCallback, + ): SentryId = SentryId.EMPTY_ID actual fun configureScope(scopeCallback: ScopeCallback) { // No-op @@ -54,17 +55,11 @@ internal actual class SentryBridge actual constructor( // No-op } - actual fun logger(): SentryLogger { - return NoOpSentryLogger() - } + actual fun logger(): SentryLogger = NoOpSentryLogger() - actual fun isCrashedLastRun(): Boolean { - return false - } + actual fun isCrashedLastRun(): Boolean = false - actual fun isEnabled(): Boolean { - return false - } + actual fun isEnabled(): Boolean = false actual fun close() { // No-op diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt index da302990f..910b4abbb 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt @@ -1,6 +1,8 @@ package io.sentry.kotlin.multiplatform.protocol -public actual data class SentryId actual constructor(private val sentryIdString: String) { +public actual data class SentryId actual constructor( + private val sentryIdString: String, +) { public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt index c42db0e01..5f12036b4 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt @@ -5,7 +5,6 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class AttachmentTest { - @Test fun `adding pathname to attachment returns correct values`() { val pathname = "test" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt index 9d168846c..e57982562 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt @@ -1,6 +1,5 @@ package io.sentry.kotlin.multiplatform expect abstract class BaseSentryScopeTest() { - fun initializeScope(): Scope } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 512b69c4c..b0484e7e7 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,6 +3,8 @@ package io.sentry.kotlin.multiplatform expect abstract class BaseSentryTest() { val platform: String val authToken: String? + fun sentryInit(optionsConfiguration: OptionsConfiguration) + fun sentryInitWithPlatformOptions(platformOptionsConfiguration: PlatformOptionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt index 27fe61657..2e68599c7 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt @@ -11,127 +11,138 @@ class BeforeBreadcrumbIntegrationTest { @Test fun `breadcrumb is not null if KMP beforeBreadcrumb callback config is null`() { - val breadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - } + val breadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(breadcrumb) } @Test fun `breadcrumb is null if KMP beforeBreadcrumb callback config returns null`() { - val breadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { - null + val breadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { + null + } } - } assertNull(breadcrumb) } @Test fun `breadcrumb is not null if KMP beforeBreadcrumb callback config returns not null`() { - val breadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb + val breadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb + } } - } assertNotNull(breadcrumb) } @Test fun `breadcrumb level is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb + } } - } assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level) } @Test fun `breadcrumb level is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.level = SentryLevel.WARNING - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.level = SentryLevel.WARNING + breadcrumb + } } - } assertEquals(SentryLevel.WARNING, modifiedBreadcrumb?.level) } @Test fun `breadcrumb category is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb + } } - } assertEquals(originalBreadcrumb.category, modifiedBreadcrumb?.category) } @Test fun `breadcrumb category is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.category = "category" - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.category = "category" + breadcrumb + } } - } assertEquals("category", modifiedBreadcrumb?.category) } @Test fun `breadcrumb type is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb + } } - } assertEquals(originalBreadcrumb.type, modifiedBreadcrumb?.type) } @Test fun `breadcrumb type is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.type = "type" - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.type = "type" + breadcrumb + } } - } assertEquals("type", modifiedBreadcrumb?.type) } @Test fun `breadcrumb message is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb + } } - } assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level) } @Test fun `breadcrumb message is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.message = "message" - breadcrumb + val modifiedBreadcrumb = + breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.message = "message" + breadcrumb + } } - } assertEquals("message", modifiedBreadcrumb?.message) } } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt index b143d8df9..35c53924f 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt @@ -13,44 +13,48 @@ class BeforeSendIntegrationTest { @Test fun `event is not null if KMP beforeSend option is null`() { - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) } @Test fun `event is null if KMP beforeSend callback config returns null`() { - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { - null + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { + null + } } - } assertNull(event) } @Test fun `event is not null if KMP beforeSend callback config returns not null`() { - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event + } } - } assertNotNull(event) } @Test fun `event logger is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.logger = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.logger = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.logger) } @@ -58,13 +62,14 @@ class BeforeSendIntegrationTest { @Test fun `event level is modified if KMP beforeSend callback config modifies it`() { val expected = SentryLevel.DEBUG - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.level = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.level = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.level) } @@ -72,13 +77,14 @@ class BeforeSendIntegrationTest { @Test fun `event message is modified if KMP beforeSend callback config modifies it`() { val expected = Message("test") - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.message = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.message = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.message) } @@ -86,13 +92,14 @@ class BeforeSendIntegrationTest { @Test fun `event release is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.release = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.release = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.release) } @@ -100,13 +107,14 @@ class BeforeSendIntegrationTest { @Test fun `event environment is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.environment = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.environment = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.environment) } @@ -114,13 +122,14 @@ class BeforeSendIntegrationTest { @Test fun `event serverName is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.serverName = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.serverName = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.serverName) } @@ -128,13 +137,14 @@ class BeforeSendIntegrationTest { @Test fun `event dist is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.dist = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.dist = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.dist) } @@ -142,13 +152,14 @@ class BeforeSendIntegrationTest { @Test fun `event fingerprint is modified if KMP beforeSend callback config modifies it`() { val expected = mutableListOf("test") - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.fingerprint = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.fingerprint = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.fingerprint) } @@ -156,13 +167,14 @@ class BeforeSendIntegrationTest { @Test fun `event tags are modified if KMP beforeSend callback config modifies it`() { val expected = mutableMapOf("test" to "test") - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.tags = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.tags = expected + event + } } - } assertNotNull(event) assertEquals(expected, event.tags) } @@ -170,13 +182,14 @@ class BeforeSendIntegrationTest { @Test fun `event breadcrumbs are modified if KMP beforeSend callback config modifies it`() { val expected = mutableListOf(Breadcrumb.debug("test")) - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.breadcrumbs = expected - event + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.breadcrumbs = expected + event + } } - } assertNotNull(event) assertEquals(expected.first().type, event.breadcrumbs.first().type) assertEquals(expected.first().message, event.breadcrumbs.first().message) @@ -186,9 +199,10 @@ class BeforeSendIntegrationTest { @Test fun `event logger is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.logger, event.logger) } @@ -204,9 +218,10 @@ class BeforeSendIntegrationTest { @Test fun `event message is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.message, event.message) } @@ -214,9 +229,10 @@ class BeforeSendIntegrationTest { @Test fun `event release is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.release, event.release) } @@ -224,9 +240,10 @@ class BeforeSendIntegrationTest { @Test fun `event environment is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.environment, event.environment) } @@ -234,9 +251,10 @@ class BeforeSendIntegrationTest { @Test fun `event serverName is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.serverName, event.serverName) } @@ -244,9 +262,10 @@ class BeforeSendIntegrationTest { @Test fun `event dist is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.dist, event.dist) } @@ -254,9 +273,10 @@ class BeforeSendIntegrationTest { @Test fun `event fingerprint is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.fingerprint, event.fingerprint) } @@ -264,9 +284,10 @@ class BeforeSendIntegrationTest { @Test fun `event tags are not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.tags, event.tags) } @@ -274,9 +295,10 @@ class BeforeSendIntegrationTest { @Test fun `event breadcrumbs are not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = + sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.breadcrumbs, event.breadcrumbs) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt index 922515ab6..e6b221196 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt @@ -10,7 +10,6 @@ import kotlin.test.assertTrue /** Tests that verify if the beforeSend hook correctly modifies events */ class BeforeSendTest { - @Test fun `beforeSend drops event`() { val options = SentryOptions() @@ -130,11 +129,12 @@ class BeforeSendTest { @Test fun `beforeSend modifies user`() { - val expected = User().apply { - id = "test" - username = "username" - email = "email" - } + val expected = + User().apply { + id = "test" + username = "username" + email = "email" + } val options = SentryOptions() options.beforeSend = { @@ -218,11 +218,12 @@ class BeforeSendTest { it } - val event = options.beforeSend?.invoke( - SentryEvent().apply { - contexts = mapOf("test" to "test") - } - ) + val event = + options.beforeSend?.invoke( + SentryEvent().apply { + contexts = mapOf("test" to "test") + }, + ) assertEquals(contexts, event?.contexts) } @@ -236,11 +237,12 @@ class BeforeSendTest { it } - val event = options.beforeSend?.invoke( - SentryEvent().apply { - exceptions = listOf(SentryException("test")) - } - ) + val event = + options.beforeSend?.invoke( + SentryEvent().apply { + exceptions = listOf(SentryException("test")) + }, + ) assertEquals(exceptions, event?.exceptions) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt index 4dcda258e..fad34df3a 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt @@ -8,6 +8,8 @@ import io.sentry.kotlin.multiplatform.protocol.Breadcrumb */ expect class BreadcrumbConfigurator() { val originalBreadcrumb: Breadcrumb + fun applyOptions(optionsConfiguration: OptionsConfiguration): Breadcrumb? + fun applyOptions(options: SentryOptions = SentryOptions()): Breadcrumb? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt index aa8362442..adc9d3a54 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt @@ -5,7 +5,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class BreadcrumbTest { - private val testMessage = "TestMessage" private val testCategory = "TestCategory" private val testUrl = "sentry.io" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index 5dbdc4b31..db34fdcb5 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -2,10 +2,16 @@ package io.sentry.kotlin.multiplatform import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -expect class BreadcrumbTestConverter(breadcrumb: Breadcrumb) { +expect class BreadcrumbTestConverter( + breadcrumb: Breadcrumb, +) { fun getType(): String? + fun getCategory(): String? + fun getMessage(): String? + fun getData(): MutableMap + fun getLevel(): SentryLevel? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt index d373ae667..b2a789ce9 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt @@ -8,7 +8,6 @@ import kotlin.test.assertEquals import kotlin.test.assertNull class ScopeTest : BaseSentryScopeTest() { - private val testUsername = "MyUsername" private val testEmail = "Email" private val testId = "TestId" @@ -29,14 +28,13 @@ class ScopeTest : BaseSentryScopeTest() { user = null } - private fun createTestUser(): User { - return User().apply { + private fun createTestUser(): User = + User().apply { username = testUsername email = testEmail id = testId ipAddress = testIpAddress } - } @Test fun `adding user to scope should properly persist user in scope`() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt index 6567bbba2..cd1772c23 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt @@ -6,7 +6,6 @@ import kotlin.test.assertIs /** Tests for [SentryAttributeValue] factory methods and type hierarchy. */ class SentryAttributeValueTest { - @Test fun `string factory creates StringValue with correct value`() { val value = SentryAttributeValue.string("myValue") diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt index d95e6150d..33cc83038 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt @@ -8,7 +8,6 @@ import kotlin.test.assertTrue /** Tests for [SentryAttributes] collection operations. */ class SentryAttributesTest { - @Test fun `set and get string value`() { val attrs = SentryAttributes.empty() @@ -100,10 +99,11 @@ class SentryAttributesTest { @Test fun `of from map creates SentryAttributes with entries`() { - val map = mapOf( - "name" to SentryAttributeValue.string("test"), - "count" to SentryAttributeValue.long(5) - ) + val map = + mapOf( + "name" to SentryAttributeValue.string("test"), + "count" to SentryAttributeValue.long(5), + ) val attrs = SentryAttributes.of(map) diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt index d44a8d2db..31980c515 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt @@ -2,9 +2,14 @@ package io.sentry.kotlin.multiplatform expect class SentryBridgeTest { fun `init sets correct configuration`() + fun `setting null in beforeSend during init drops the event`() + fun `default beforeSend in init does not drop the event`() + fun `default beforeSend in init does not drop the event after prepareForInit`() + fun `init sets the SDK packages`() + fun `init sets SDK version and name`() } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt index 4ec1036e0..aa95e48c1 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt @@ -34,7 +34,7 @@ private data class SentryEventSerializable( val fingerprint: List = listOf(), val level: String? = null, val logger: String? = null, - val title: String? = null + val title: String? = null, ) class SentryE2ETest : BaseSentryTest() { @@ -58,27 +58,29 @@ class SentryE2ETest : BaseSentryTest() { private suspend fun fetchEvent(eventId: String): String { val url = "https://sentry.io/api/0/projects/$org/$projectSlug/events/$eventId/" - val response = client.get(url) { - headers { - append( - HttpHeaders.Authorization, - "Bearer $authToken" - ) + val response = + client.get(url) { + headers { + append( + HttpHeaders.Authorization, + "Bearer $authToken", + ) + } } - } return response.bodyAsText() } private suspend fun waitForEventRetrieval(eventId: String): SentryEventSerializable { var json = "" - val result: SentryEventSerializable = withContext(Dispatchers.Default) { - while (json.isEmpty() || json.contains("Event not found")) { - delay(20000) - json = fetchEvent(eventId) - assertFalse(json.contains("Invalid token"), "Invalid auth token") + val result: SentryEventSerializable = + withContext(Dispatchers.Default) { + while (json.isEmpty() || json.contains("Event not found")) { + delay(20000) + json = fetchEvent(eventId) + assertFalse(json.contains("Invalid token"), "Invalid auth token") + } + jsonDecoder.decodeFromString(json) } - jsonDecoder.decodeFromString(json) - } return result } @@ -86,39 +88,41 @@ class SentryE2ETest : BaseSentryTest() { // See: https://github.com/getsentry/sentry-kotlin-multiplatform/issues/17 @Test - fun `capture message and fetch event from Sentry`() = runTest(timeout = 60.seconds) { - if (platform != "Apple") { - val message = "Test running on $platform" - val eventId = Sentry.captureMessage(message) - val fetchedEvent = waitForEventRetrieval(eventId.toString()) - fetchedEvent.tags.forEach { println(it["value"]) } - assertEquals(eventId.toString(), fetchedEvent.id) - assertEquals(sentEvent?.message?.formatted, fetchedEvent.message) - assertEquals(message, fetchedEvent.title) - assertEquals(sentEvent?.release, fetchedEvent.release) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) - assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.level?.name?.lowercase() }?.size) - assertEquals(sentEvent?.logger, fetchedEvent.logger) + fun `capture message and fetch event from Sentry`() = + runTest(timeout = 60.seconds) { + if (platform != "Apple") { + val message = "Test running on $platform" + val eventId = Sentry.captureMessage(message) + val fetchedEvent = waitForEventRetrieval(eventId.toString()) + fetchedEvent.tags.forEach { println(it["value"]) } + assertEquals(eventId.toString(), fetchedEvent.id) + assertEquals(sentEvent?.message?.formatted, fetchedEvent.message) + assertEquals(message, fetchedEvent.title) + assertEquals(sentEvent?.release, fetchedEvent.release) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) + assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.level?.name?.lowercase() }?.size) + assertEquals(sentEvent?.logger, fetchedEvent.logger) + } } - } @Test - fun `capture exception and fetch event from Sentry`() = runTest(timeout = 30.seconds) { - if (platform != "Apple") { - val exceptionMessage = "Test exception on platform $platform" - val eventId = - Sentry.captureException(IllegalArgumentException(exceptionMessage)) - val fetchedEvent = waitForEventRetrieval(eventId.toString()) - assertEquals(eventId.toString(), fetchedEvent.id) - assertEquals("IllegalArgumentException: $exceptionMessage", fetchedEvent.title) - assertEquals(sentEvent?.release, fetchedEvent.release) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) - assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) - assertEquals(2, fetchedEvent.tags.find { it["value"] == SentryLevel.ERROR.toString().lowercase() }?.size) - assertEquals(sentEvent?.logger, fetchedEvent.logger) + fun `capture exception and fetch event from Sentry`() = + runTest(timeout = 30.seconds) { + if (platform != "Apple") { + val exceptionMessage = "Test exception on platform $platform" + val eventId = + Sentry.captureException(IllegalArgumentException(exceptionMessage)) + val fetchedEvent = waitForEventRetrieval(eventId.toString()) + assertEquals(eventId.toString(), fetchedEvent.id) + assertEquals("IllegalArgumentException: $exceptionMessage", fetchedEvent.title) + assertEquals(sentEvent?.release, fetchedEvent.release) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) + assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) + assertEquals(2, fetchedEvent.tags.find { it["value"] == SentryLevel.ERROR.toString().lowercase() }?.size) + assertEquals(sentEvent?.logger, fetchedEvent.logger) + } } - } @AfterTest fun tearDown() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt index d995661d7..67909fc68 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt @@ -6,6 +6,8 @@ package io.sentry.kotlin.multiplatform */ expect class SentryEventConfigurator() { val originalEvent: SentryEvent + fun applyOptions(optionsConfiguration: OptionsConfiguration): SentryEvent? + fun applyOptions(options: SentryOptions = SentryOptions()): SentryEvent? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt index b9e9607f9..712e3fb54 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt @@ -9,7 +9,6 @@ import kotlin.test.assertNull import kotlin.test.assertTrue class SentryEventTest { - @Test fun `setTag should add a new tag`() { val event = SentryEvent() diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt index d128d27e1..e5a5417a3 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt @@ -5,7 +5,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class SentryIdTest { - @Test fun `SentryId with valid uuid string returns valid SentryId string`() { val uuidString = "ec81a720-b6f6-4efc-9d74-6627a09157c1" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt index c64c956ce..dc0cf2d3e 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt @@ -61,11 +61,17 @@ class SentryIntegrationTest : BaseSentryTest() { assertEquals(2, capturedEvents.size) val event = capturedEvents[0] - event.exceptions.first().type?.let { assertTrue(it.contains("RuntimeException")) } + event.exceptions + .first() + .type + ?.let { assertTrue(it.contains("RuntimeException")) } assertEquals("test", event.exceptions.first().value) val event2 = capturedEvents[1] - event2.exceptions.first().type?.let { assertTrue(it.contains("RuntimeException")) } + event2.exceptions + .first() + .type + ?.let { assertTrue(it.contains("RuntimeException")) } assertEquals("test2", event2.exceptions.first().value) } @@ -213,12 +219,13 @@ class SentryIntegrationTest : BaseSentryTest() { } Sentry.configureScope { - it.user = User().apply { - this.email = expectedEmail - this.id = expectedId - this.ipAddress = expectedIpAddress - this.username = expectedUsername - } + it.user = + User().apply { + this.email = expectedEmail + this.id = expectedId + this.ipAddress = expectedIpAddress + this.username = expectedUsername + } } Sentry.captureException(RuntimeException("test")) @@ -244,59 +251,60 @@ class SentryIntegrationTest : BaseSentryTest() { } @Test - fun `global scope sets context correctly with different data types`() = runTest { - val stringKey = "stringKey" - val stringValue = "stringValue" - val booleanKey = "booleanKey" - val booleanValue = true - val numberKey = "numberKey" - val numberValue = 123 - val collectionKey = "collectionKey" - val collectionValue = listOf("abc", 123, true) - - val expectedStringValue = mapOf("value" to stringValue) - val expectedBooleanValue = mapOf("value" to booleanValue) - val expectedNumberValue = mapOf("value" to numberValue) - val expectedCollectionValue = mapOf("value" to collectionValue) - - var actualStringValue: Map? = null - var actualBooleanValue: Map? = null - var actualNumberValue: Map? = null - var actualCollectionValue: Map? = null - - sentryInit { - it.dsn = fakeDsn - it.beforeSend = { event -> - val contexts = event.contexts - assertNotNull(contexts) - actualStringValue = contexts[stringKey] as Map? - actualBooleanValue = contexts[booleanKey] as Map? - actualNumberValue = contexts[numberKey] as Map? - actualCollectionValue = contexts[collectionKey] as Map? - null + fun `global scope sets context correctly with different data types`() = + runTest { + val stringKey = "stringKey" + val stringValue = "stringValue" + val booleanKey = "booleanKey" + val booleanValue = true + val numberKey = "numberKey" + val numberValue = 123 + val collectionKey = "collectionKey" + val collectionValue = listOf("abc", 123, true) + + val expectedStringValue = mapOf("value" to stringValue) + val expectedBooleanValue = mapOf("value" to booleanValue) + val expectedNumberValue = mapOf("value" to numberValue) + val expectedCollectionValue = mapOf("value" to collectionValue) + + var actualStringValue: Map? = null + var actualBooleanValue: Map? = null + var actualNumberValue: Map? = null + var actualCollectionValue: Map? = null + + sentryInit { + it.dsn = fakeDsn + it.beforeSend = { event -> + val contexts = event.contexts + assertNotNull(contexts) + actualStringValue = contexts[stringKey] as Map? + actualBooleanValue = contexts[booleanKey] as Map? + actualNumberValue = contexts[numberKey] as Map? + actualCollectionValue = contexts[collectionKey] as Map? + null + } } - } - Sentry.configureScope { - it.setContext(stringKey, stringValue) - it.setContext(booleanKey, booleanValue) - it.setContext(numberKey, numberValue) - it.setContext(collectionKey, collectionValue) - } + Sentry.configureScope { + it.setContext(stringKey, stringValue) + it.setContext(booleanKey, booleanValue) + it.setContext(numberKey, numberValue) + it.setContext(collectionKey, collectionValue) + } - Sentry.captureException(RuntimeException("test")) + Sentry.captureException(RuntimeException("test")) - assertEquals(expectedStringValue, actualStringValue) - assertEquals(expectedBooleanValue, actualBooleanValue) - assertEquals(expectedNumberValue, actualNumberValue) - assertEquals(expectedCollectionValue, actualCollectionValue) - } + assertEquals(expectedStringValue, actualStringValue) + assertEquals(expectedBooleanValue, actualBooleanValue) + assertEquals(expectedNumberValue, actualNumberValue) + assertEquals(expectedCollectionValue, actualCollectionValue) + } // region Logger Tests private fun initWithLogCapture( enabled: Boolean = true, - beforeSend: ((SentryLog) -> SentryLog?)? = null + beforeSend: ((SentryLog) -> SentryLog?)? = null, ): MutableList { val capturedLogs = mutableListOf() sentryInit { @@ -323,14 +331,15 @@ class SentryIntegrationTest : BaseSentryTest() { assertEquals(6, capturedLogs.size) - val expectedLevels = listOf( - SentryLogLevel.TRACE, - SentryLogLevel.DEBUG, - SentryLogLevel.INFO, - SentryLogLevel.WARN, - SentryLogLevel.ERROR, - SentryLogLevel.FATAL - ) + val expectedLevels = + listOf( + SentryLogLevel.TRACE, + SentryLogLevel.DEBUG, + SentryLogLevel.INFO, + SentryLogLevel.WARN, + SentryLogLevel.ERROR, + SentryLogLevel.FATAL, + ) val expectedBodies = listOf("trace", "debug", "info", "warn", "error", "fatal") capturedLogs.forEachIndexed { index, log -> diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt index ca429292b..afa21aed0 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt @@ -4,7 +4,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class SentryLevelConversionTest { - private var converter: SentryLevelTestConverter? = SentryLevelTestConverter() @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index 27f80a0bc..d7988b231 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -1,6 +1,5 @@ package io.sentry.kotlin.multiplatform expect class SentryLevelTestConverter() { - fun convert(sentryLevel: SentryLevel?): SentryLevel? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt index 293caf8ee..0c6187cb5 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt @@ -47,19 +47,21 @@ class SentryOptionsTest : BaseSentryTest() { configuration.invoke(options) } - val expectedBreadcrumb = Breadcrumb().apply { - message = "changed message" - type = "changed type" - category = "changed category" - setData(mutableMapOf("data1" to 12, "data2" to "value", "key" to "value")) - } + val expectedBreadcrumb = + Breadcrumb().apply { + message = "changed message" + type = "changed type" + category = "changed category" + setData(mutableMapOf("data1" to 12, "data2" to "value", "key" to "value")) + } - val breadcrumb = Breadcrumb().apply { - message = "another message" - type = "another type" - category = "another category" - setData(mutableMapOf("data1" to 12, "data2" to "value")) - } + val breadcrumb = + Breadcrumb().apply { + message = "another message" + type = "another type" + category = "another category" + setData(mutableMapOf("data1" to 12, "data2" to "value")) + } mockInit { it.beforeBreadcrumb = { breadcrumb -> @@ -140,36 +142,37 @@ class SentryOptionsTest : BaseSentryTest() { @Test fun `GIVEN non-default SentryOptions WHEN options initialized THEN applies values to native options`() { - val options = SentryOptions().apply { - dsn = fakeDsn - attachStackTrace = false - release = "release" - debug = true - environment = "environment" - dist = "dist" - enableAutoSessionTracking = false - sessionTrackingIntervalMillis = 1000L - diagnosticLevel = SentryLevel.ERROR - maxBreadcrumbs = 10 - maxAttachmentSize = 100L - sampleRate = 0.5 - tracesSampleRate = 0.5 - attachScreenshot = true - attachViewHierarchy = true - enableAppHangTracking = false - appHangTimeoutIntervalMillis = 1000L - isAnrEnabled = false - anrTimeoutIntervalMillis = 1000L - enableWatchdogTerminationTracking = false - enableUnhandledCppExceptionMonitoring = false - sessionReplay.onErrorSampleRate = 0.5 - sessionReplay.sessionSampleRate = 0.5 - sessionReplay.maskAllText = false - sessionReplay.maskAllImages = false - sessionReplay.quality = SentryReplayOptions.Quality.LOW - sendDefaultPii = true - proguardUuid = "test-proguard-uuid-12345" - } + val options = + SentryOptions().apply { + dsn = fakeDsn + attachStackTrace = false + release = "release" + debug = true + environment = "environment" + dist = "dist" + enableAutoSessionTracking = false + sessionTrackingIntervalMillis = 1000L + diagnosticLevel = SentryLevel.ERROR + maxBreadcrumbs = 10 + maxAttachmentSize = 100L + sampleRate = 0.5 + tracesSampleRate = 0.5 + attachScreenshot = true + attachViewHierarchy = true + enableAppHangTracking = false + appHangTimeoutIntervalMillis = 1000L + isAnrEnabled = false + anrTimeoutIntervalMillis = 1000L + enableWatchdogTerminationTracking = false + enableUnhandledCppExceptionMonitoring = false + sessionReplay.onErrorSampleRate = 0.5 + sessionReplay.sessionSampleRate = 0.5 + sessionReplay.maskAllText = false + sessionReplay.maskAllImages = false + sessionReplay.quality = SentryReplayOptions.Quality.LOW + sendDefaultPii = true + proguardUuid = "test-proguard-uuid-12345" + } val platformOptions = createPlatformOptions() platformOptions.applyFromOptions(options) diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt index c6b09de33..e1ce35adc 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt @@ -6,7 +6,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class UserFeedbackTest { - private val sentryIdString = "dcebada57d794590a6da3d1977eed58a" @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt index f343d1d07..e2215228d 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt @@ -8,8 +8,8 @@ import kotlin.test.assertEquals class UserTest { private var user = User() - private fun createTestUser(): User { - return User().apply { + private fun createTestUser(): User = + User().apply { username = "TestUsername" email = "TestEmail" id = "TestId" @@ -17,7 +17,6 @@ class UserTest { unknown = mutableMapOf("key" to "value", "key2" to 12) other = mutableMapOf("key" to "value") } - } @BeforeTest fun setup() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt index 666a384e4..a9c2ce814 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt @@ -5,7 +5,6 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class BaseSentryLoggerTest { - // region Simple message API (level-specific) @Test @@ -497,7 +496,12 @@ class BaseSentryLoggerTest { assertEquals(1, logger.logs.size) assertEquals(SentryLogLevel.TRACE, logger.logs[0].level) assertEquals("User alice logged in", logger.logs[0].formatted.body) - assertEquals("us-east", logger.logs[0].formatted.attributes["region"]?.stringOrNull) + assertEquals( + "us-east", + logger.logs[0] + .formatted.attributes["region"] + ?.stringOrNull, + ) } @Test @@ -629,9 +633,9 @@ class BaseSentryLoggerTest { SentryLogLevel.INFO, SentryLogLevel.WARN, SentryLogLevel.ERROR, - SentryLogLevel.FATAL + SentryLogLevel.FATAL, ), - logger.logs.map { it.level } + logger.logs.map { it.level }, ) } @@ -642,11 +646,17 @@ class BaseSentryLoggerTest { * Test implementation of [BaseSentryLogger] that captures all logs for verification. */ private class TestSentryLogger : BaseSentryLogger(::DefaultSentryLogBuilder) { - data class CapturedLog(val level: SentryLogLevel, val formatted: FormattedLog) + data class CapturedLog( + val level: SentryLogLevel, + val formatted: FormattedLog, + ) val logs = mutableListOf() - override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { + override fun sendLog( + level: SentryLogLevel, + formatted: FormattedLog, + ) { logs.add(CapturedLog(level, formatted)) } } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt index bcc0edda0..93d4d3808 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt @@ -8,7 +8,6 @@ import kotlin.test.assertTrue /** Tests for [DefaultSentryLogBuilder] DSL builder. */ class SentryLogBuilderTest { - // region Message configuration @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt index 003fc74a8..840ec0d76 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt @@ -7,7 +7,6 @@ import kotlin.test.assertNull /** Tests for [SentryLogOptions] configuration and beforeSend callback. */ class SentryLogOptionsTest { - @Test fun `enabled is false by default`() { val options = SentryLogOptions() @@ -102,6 +101,6 @@ class SentryLogOptionsTest { private fun createTestLog( timestamp: Double = 1234567890.0, level: SentryLogLevel = SentryLogLevel.INFO, - body: String = "test message" + body: String = "test message", ): SentryLog = SentryLog(timestamp, level, body) } diff --git a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt index c2c52ad06..f801bb0d2 100644 --- a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt +++ b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt @@ -4,5 +4,4 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaOptionsConfiguration public actual typealias SentryPlatformOptions = cocoapods.Sentry.SentryOptions -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - toCocoaOptionsConfiguration() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toCocoaOptionsConfiguration() diff --git a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt index bc3e1a658..7d9a4818a 100644 --- a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt +++ b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt @@ -2,10 +2,12 @@ package io.sentry.kotlin.multiplatform actual interface ApplePlatformOptions : PlatformOptions -class SentryTvWatchMacOsOptionsWrapper(cocoaOptions: CocoaSentryOptions) : SentryAppleOptionsWrapper(cocoaOptions) +class SentryTvWatchMacOsOptionsWrapper( + cocoaOptions: CocoaSentryOptions, +) : SentryAppleOptionsWrapper(cocoaOptions), + ApplePlatformOptions -actual fun createApplePlatformOptions(): PlatformOptions = - SentryTvWatchMacOsOptionsWrapper(CocoaSentryOptions()) +actual fun createApplePlatformOptions(): PlatformOptions = SentryTvWatchMacOsOptionsWrapper(CocoaSentryOptions()) actual fun ApplePlatformOptions.assertApplePlatformSpecificOptions(options: SentryOptions) { // no-op diff --git a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt index b495be182..31d07b259 100644 --- a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt @@ -4,5 +4,4 @@ import io.sentry.kotlin.multiplatform.extensions.toIosOptionsConfiguration public actual typealias SentryPlatformOptions = cocoapods.Sentry.SentryOptions -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - toIosOptionsConfiguration() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toIosOptionsConfiguration() diff --git a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt index f5311921b..4bec55fd9 100644 --- a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt @@ -4,34 +4,40 @@ import cocoapods.Sentry.SentryReplayOptions import io.sentry.kotlin.multiplatform.CocoaSentryOptions import io.sentry.kotlin.multiplatform.SentryOptions -internal fun SentryOptions.toIosOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = { options -> - options?.let { cocoaOptions -> - val kmpOptions = this@toIosOptionsConfiguration +internal fun SentryOptions.toIosOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = + { options -> + options?.let { cocoaOptions -> + val kmpOptions = this@toIosOptionsConfiguration - // Apply base options available to all Cocoa/Apple targets - cocoaOptions.applyCocoaBaseOptions(kmpOptions) + // Apply base options available to all Cocoa/Apple targets + cocoaOptions.applyCocoaBaseOptions(kmpOptions) - // Apply iOS specific options - cocoaOptions.attachScreenshot = this.attachScreenshot - cocoaOptions.attachViewHierarchy = this.attachViewHierarchy + // Apply iOS specific options + cocoaOptions.attachScreenshot = this.attachScreenshot + cocoaOptions.attachViewHierarchy = this.attachViewHierarchy - // Replay options - val replayOptions = SentryReplayOptions( - dictionary = mapOf( - // Setting the onErrorSampleRate like this, using setOnErrorSampleRate - // crashes on compose multiplatform for some unknown reason - "errorSampleRate" to kmpOptions.sessionReplay.onErrorSampleRate?.toFloat() - ) - ).apply { - setMaskAllText(kmpOptions.sessionReplay.maskAllText) - setMaskAllImages(kmpOptions.sessionReplay.maskAllImages) - kmpOptions.sessionReplay.sessionSampleRate?.let { setSessionSampleRate(it.toFloat()) } - setQuality(kmpOptions.sessionReplay.quality.ordinal.toLong()) + // Replay options + val replayOptions = + SentryReplayOptions( + dictionary = + mapOf( + // Setting the onErrorSampleRate like this, using setOnErrorSampleRate + // crashes on compose multiplatform for some unknown reason + "errorSampleRate" to kmpOptions.sessionReplay.onErrorSampleRate?.toFloat(), + ), + ).apply { + setMaskAllText(kmpOptions.sessionReplay.maskAllText) + setMaskAllImages(kmpOptions.sessionReplay.maskAllImages) + kmpOptions.sessionReplay.sessionSampleRate?.let { setSessionSampleRate(it.toFloat()) } + setQuality( + kmpOptions.sessionReplay.quality.ordinal + .toLong(), + ) + } + cocoaOptions.setSessionReplay(replayOptions) + } ?: run { + // Log a warning if options is null + // TODO: Replace with actual logging when a logger is available + println("Warning: CocoaSentryOptions is null, skipping iOS configuration") } - cocoaOptions.setSessionReplay(replayOptions) - } ?: run { - // Log a warning if options is null - // TODO: Replace with actual logging when a logger is available - println("Warning: CocoaSentryOptions is null, skipping iOS configuration") } -} diff --git a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt index 914eb46fb..d66b6e9aa 100644 --- a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt @@ -12,7 +12,10 @@ actual interface ApplePlatformOptions : PlatformOptions { val sessionReplay: SentryReplayOptions } -class SentryIosOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : SentryAppleOptionsWrapper(cocoaOptions), ApplePlatformOptions { +class SentryIosOptionsWrapper( + private val cocoaOptions: CocoaSentryOptions, +) : SentryAppleOptionsWrapper(cocoaOptions), + ApplePlatformOptions { override val attachScreenshot: Boolean get() = cocoaOptions.attachScreenshot @@ -45,5 +48,9 @@ actual fun ApplePlatformOptions.assertApplePlatformSpecificOptions(options: Sent assertEquals(sessionReplay.maskAllImages(), options.sessionReplay.maskAllImages) assertEquals(sessionReplay.onErrorSampleRate().toDouble(), options.sessionReplay.onErrorSampleRate) assertEquals(sessionReplay.sessionSampleRate().toDouble(), options.sessionReplay.sessionSampleRate) - assertEquals(sessionReplay.quality(), options.sessionReplay.quality.ordinal.toLong()) + assertEquals( + sessionReplay.quality(), + options.sessionReplay.quality.ordinal + .toLong(), + ) } diff --git a/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt b/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt index 0a7a8d285..c42082418 100644 --- a/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt @@ -12,5 +12,4 @@ internal actual fun SentryPlatformOptions.prepareForInit() { } } -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - toJvmSentryOptionsCallback() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toJvmSentryOptionsCallback() diff --git a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 717a2b0e3..4886eba40 100644 --- a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,6 +3,7 @@ package io.sentry.kotlin.multiplatform actual abstract class BaseSentryTest { actual val platform: String = "JVM" actual val authToken: String? = System.getenv("SENTRY_AUTH_TOKEN") + actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt index 3a8059a1a..3bab0c7c6 100644 --- a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt @@ -7,7 +7,9 @@ import kotlin.test.assertEquals actual interface PlatformOptions : CommonPlatformOptions -class SentryJvmOptionsWrapper(private val jvmOptions: JvmSentryOptions) : PlatformOptions { +class SentryJvmOptionsWrapper( + private val jvmOptions: JvmSentryOptions, +) : PlatformOptions { override val dsn: String? get() = jvmOptions.dsn @@ -64,6 +66,7 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio assertEquals(proguardUuid, kmpOptions.proguardUuid) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - it.dsn = fakeDsn -} +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + it.dsn = fakeDsn + } diff --git a/sentry-samples/kmp-app-cocoapods/androidApp/build.gradle.kts b/sentry-samples/kmp-app-cocoapods/androidApp/build.gradle.kts index b0dfb6066..3b28133e5 100644 --- a/sentry-samples/kmp-app-cocoapods/androidApp/build.gradle.kts +++ b/sentry-samples/kmp-app-cocoapods/androidApp/build.gradle.kts @@ -7,6 +7,7 @@ plugins { } android { + namespace = "sample.kmp.app.android" compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 diff --git a/sentry-samples/kmp-app-cocoapods/androidApp/src/main/AndroidManifest.xml b/sentry-samples/kmp-app-cocoapods/androidApp/src/main/AndroidManifest.xml index 73a2e9397..9e4b74b77 100644 --- a/sentry-samples/kmp-app-cocoapods/androidApp/src/main/AndroidManifest.xml +++ b/sentry-samples/kmp-app-cocoapods/androidApp/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + - + diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt b/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt index 11c6831d7..e2d563b44 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt @@ -2,6 +2,7 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" -} +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" + } diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt index 21fc2cd00..6b68005b0 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt @@ -9,7 +9,9 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid -class InvalidUsernameException(message: String) : Exception(message) +class InvalidUsernameException( + message: String, +) : Exception(message) object LoginImpl { /** @@ -50,10 +52,11 @@ object LoginImpl { } // DSL builder with prebuilt SentryAttributes - val prebuiltAttrs = SentryAttributes.of( - "source" to "login-form", - "version" to 2 - ) + val prebuiltAttrs = + SentryAttributes.of( + "source" to "login-form", + "version" to 2, + ) Sentry.logger.debug { message("Session token generated for user: %s", username) attributes(prebuiltAttrs) @@ -73,24 +76,27 @@ object LoginImpl { try { validateUsername(username) } catch (exception: InvalidUsernameException) { - val sentryId = Sentry.captureException(exception) { - val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") - breadcrumb.setData("touch event", "on login") - it.addBreadcrumb(breadcrumb) - it.setContext("Login", "Failed with Invalid Username") - it.setTag("login", "failed auth") - it.level = SentryLevel.WARNING - val user = User().apply { - this.username = "John Doe" - this.email = "john@doe.com" + val sentryId = + Sentry.captureException(exception) { + val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") + breadcrumb.setData("touch event", "on login") + it.addBreadcrumb(breadcrumb) + it.setContext("Login", "Failed with Invalid Username") + it.setTag("login", "failed auth") + it.level = SentryLevel.WARNING + val user = + User().apply { + this.username = "John Doe" + this.email = "john@doe.com" + } + it.user = user + } + val userFeedback = + UserFeedback(sentryId).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error during login on ${Platform().platform}" } - it.user = user - } - val userFeedback = UserFeedback(sentryId).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error during login on ${Platform().platform}" - } Sentry.captureUserFeedback(userFeedback) } catch (exception: IllegalArgumentException) { throw exception diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt index 8ed65c638..2a26d2ef7 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt @@ -14,8 +14,8 @@ fun configureSentryScope() { it.addAttachment( Attachment( "This is a shared text attachment".encodeToByteArray(), - "shared.log" - ) + "shared.log", + ), ) } } @@ -35,8 +35,8 @@ fun initializeSentry(useNativeOptions: Boolean = false) { expect fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration /** Returns a shared options configuration */ -private fun optionsConfiguration(): OptionsConfiguration { - return { +private fun optionsConfiguration(): OptionsConfiguration = + { it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" it.attachStackTrace = true it.attachThreads = true @@ -68,4 +68,3 @@ private fun optionsConfiguration(): OptionsConfiguration { } } } -} diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt index b63d03af6..b82766cb0 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt @@ -9,13 +9,14 @@ import platform.Foundation.dataTaskWithRequest fun captureHttpClientError() { val url = NSURL(string = "https://httpbin.org/status/404") val request = NSURLRequest(uRL = url) - NSURLSession.sharedSession.dataTaskWithRequest(request) { data, response, error -> - if (error != null) { - // handle error - println("error: $error") - } else { - // handle successful response - println("response: $response") - } - }.resume() + NSURLSession.sharedSession + .dataTaskWithRequest(request) { data, response, error -> + if (error != null) { + // handle error + println("error: $error") + } else { + // handle successful response + println("response: $response") + } + }.resume() } diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt index 11c6831d7..e2d563b44 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt @@ -2,6 +2,7 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" -} +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" + } diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt b/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt index 11c6831d7..e2d563b44 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt @@ -2,6 +2,7 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" -} +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" + } diff --git a/sentry-samples/kmp-app-spm/androidApp/build.gradle.kts b/sentry-samples/kmp-app-spm/androidApp/build.gradle.kts index d6cd30825..6e881469c 100644 --- a/sentry-samples/kmp-app-spm/androidApp/build.gradle.kts +++ b/sentry-samples/kmp-app-spm/androidApp/build.gradle.kts @@ -22,6 +22,7 @@ kotlin { } android { + namespace = "sample.kmp.app.android" compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 diff --git a/sentry-samples/kmp-app-spm/androidApp/src/main/AndroidManifest.xml b/sentry-samples/kmp-app-spm/androidApp/src/main/AndroidManifest.xml index 73a2e9397..9e4b74b77 100644 --- a/sentry-samples/kmp-app-spm/androidApp/src/main/AndroidManifest.xml +++ b/sentry-samples/kmp-app-spm/androidApp/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + - + diff --git a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt index db6e90c08..06273d38f 100644 --- a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt +++ b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt @@ -6,7 +6,9 @@ import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User import io.sentry.kotlin.multiplatform.protocol.UserFeedback -class InvalidUsernameException(message: String) : Exception(message) +class InvalidUsernameException( + message: String, +) : Exception(message) object LoginImpl { /** @@ -23,24 +25,27 @@ object LoginImpl { try { validateUsername(username) } catch (exception: InvalidUsernameException) { - val sentryId = Sentry.captureException(exception) { - val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") - breadcrumb.setData("touch event", "on login") - it.addBreadcrumb(breadcrumb) - it.setContext("Login", "Failed with Invalid Username") - it.setTag("login", "failed auth") - it.level = SentryLevel.WARNING - val user = User().apply { - this.username = "John Doe" - this.email = "john@doe.com" + val sentryId = + Sentry.captureException(exception) { + val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") + breadcrumb.setData("touch event", "on login") + it.addBreadcrumb(breadcrumb) + it.setContext("Login", "Failed with Invalid Username") + it.setTag("login", "failed auth") + it.level = SentryLevel.WARNING + val user = + User().apply { + this.username = "John Doe" + this.email = "john@doe.com" + } + it.user = user + } + val userFeedback = + UserFeedback(sentryId).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error during login on ${Platform().platform}" } - it.user = user - } - val userFeedback = UserFeedback(sentryId).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error during login on ${Platform().platform}" - } Sentry.captureUserFeedback(userFeedback) } catch (exception: IllegalArgumentException) { throw exception diff --git a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt index be7e6e27a..e023590cf 100644 --- a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt +++ b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt @@ -13,8 +13,8 @@ fun configureSentryScope() { it.addAttachment( Attachment( "This is a shared text attachment".encodeToByteArray(), - "shared.log" - ) + "shared.log", + ), ) } } @@ -28,8 +28,8 @@ fun initializeSentry() { } /** Returns a shared options configuration */ -private fun optionsConfiguration(): OptionsConfiguration { - return { +private fun optionsConfiguration(): OptionsConfiguration = + { it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" it.attachStackTrace = true it.attachThreads = true @@ -50,4 +50,3 @@ private fun optionsConfiguration(): OptionsConfiguration { } } } -} diff --git a/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt b/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt index b63d03af6..b82766cb0 100644 --- a/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt +++ b/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt @@ -9,13 +9,14 @@ import platform.Foundation.dataTaskWithRequest fun captureHttpClientError() { val url = NSURL(string = "https://httpbin.org/status/404") val request = NSURLRequest(uRL = url) - NSURLSession.sharedSession.dataTaskWithRequest(request) { data, response, error -> - if (error != null) { - // handle error - println("error: $error") - } else { - // handle successful response - println("response: $response") - } - }.resume() + NSURLSession.sharedSession + .dataTaskWithRequest(request) { data, response, error -> + if (error != null) { + // handle error + println("error: $error") + } else { + // handle successful response + println("response: $response") + } + }.resume() } From a37c6f8c6e23804e30de77dc2c99ec7f6d1ba1bd Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 10 Jun 2026 12:58:22 +0200 Subject: [PATCH 2/4] chore(build): Restore release versionName and drop unrelated changes Revert the local dev versionName suffix that leaked in from another branch (root and Gradle plugin properties) back to the released 0.27.0, and remove the compose.version property that nothing reads anymore. Co-Authored-By: Claude Fable 5 --- gradle.properties | 3 --- .../sentry_kotlin_multiplatform.podspec | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 41fa62c82..01b2074b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,9 +4,6 @@ kotlin.code.style=official kotlin.mpp.stability.nowarn=true android.useAndroidX=true -# Jetpack Compose -compose.version=1.3.1-rc01 - # Release information versionName=0.27.0 diff --git a/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec b/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec index 7007b3cc7..251872b27 100644 --- a/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec +++ b/sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec @@ -54,4 +54,4 @@ Pod::Spec.new do |spec| } ] -end \ No newline at end of file +end From e676b2cbe628fb7d7bd5767cfda5c4cd12b6de2b Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 10 Jun 2026 13:17:40 +0200 Subject: [PATCH 3/4] docs: Add changelog entry for toolchain bump Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7e6089ab..1a3f808a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Kotlin from `2.1.21` to `2.2.21` and Gradle from `8.6` to `8.13` ([#556](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/556)) + - Also bumps AGP to `8.7.3` and `compileSdk` to 35 + ## 0.27.0 ### Features From 0cf9fd708c096f30f091ac112a3db64b78299cd8 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 10 Jun 2026 14:06:06 +0200 Subject: [PATCH 4/4] style: Keep ktlint 1.x on pre-1.0 formatting conventions Spotless 7 upgraded ktlint to 1.x, whose new ktlint_official default style reformatted ~150 files (multiline expression wrapping, trailing commas, signature rewraps) and drowned out the substantive toolchain changes. Pin the legacy intellij_idea style and disable the 1.x reflow rules via an explicit editorConfigOverride in the Spotless config (Spotless does not reliably forward ij_* properties from .editorconfig to ktlint), and restore the affected sources to their original formatting. The two functional fixes the Kotlin 2.2.21 bump requires are kept: the Cocoa log-level cinterop conversion in SentryLogConvertersTest and the ApplePlatformOptions supertype on the tv/watch/macOS test wrapper. Adopting ktlint_official remains possible as a dedicated style-only PR that deletes the pin and runs spotlessApply. Co-Authored-By: Claude Fable 5 --- .editorconfig | 11 +- build.gradle.kts | 31 ++- buildSrc/src/main/java/Publication.kt | 50 ++-- config/detekt/baseline.xml | 6 - .../build.gradle.kts | 4 +- .../gradle/AutoInstallExtension.kt | 36 ++- .../gradle/CocoaFrameworkLinker.kt | 46 ++-- .../gradle/CocoapodsAutoInstallExtension.kt | 42 ++-- .../gradle/DerivedDataPathValueSource.kt | 31 ++- .../multiplatform/gradle/FrameworkLinker.kt | 37 +-- .../gradle/FrameworkPathResolver.kt | 101 ++++---- .../multiplatform/gradle/LinkerExtension.kt | 66 +++--- .../ManualFrameworkPathSearchValueSource.kt | 39 ++- .../multiplatform/gradle/SentryExtension.kt | 28 +-- .../multiplatform/gradle/SentryPlugin.kt | 57 ++--- .../gradle/SourceSetAutoInstallExtension.kt | 42 ++-- .../CocoaFrameworkLinkerIntegrationTest.kt | 45 ++-- .../gradle/CocoaFrameworkLinkerTest.kt | 86 +++---- .../gradle/CustomPathStrategyTest.kt | 15 +- .../gradle/DerivedDataPathTest.kt | 29 +-- .../gradle/DerivedDataStrategyTest.kt | 59 ++--- .../gradle/FrameworkPathResolverTest.kt | 7 +- .../gradle/ManualSearchStrategyTest.kt | 13 +- .../gradle/SentryFrameworkArchitectureTest.kt | 64 +++-- .../multiplatform/gradle/SentryPluginTest.kt | 9 +- sentry-kotlin-multiplatform/build.gradle.kts | 4 +- .../kotlin/multiplatform/Context.android.kt | 15 +- .../SentryPlatformInstance.android.kt | 9 +- .../SentryPlatformOptions.android.kt | 3 +- .../SentryOptionsExtensions.android.kt | 51 ++-- .../kotlin/multiplatform/BaseSentryTest.kt | 1 - .../multiplatform/PlatformOptions.android.kt | 25 +- .../multiplatform/SentryAndroidBridgeTest.kt | 11 +- .../kotlin/multiplatform/Attachment.apple.kt | 6 +- .../multiplatform/CocoaScopeProvider.kt | 54 +---- .../multiplatform/SentryBridge.apple.kt | 65 +++-- .../kotlin/multiplatform/SentryEvent.apple.kt | 14 +- .../extensions/BreadcrumbExtensions.apple.kt | 38 ++- .../extensions/FoundationExtensions.kt | 22 +- .../extensions/MessageExtensions.apple.kt | 11 +- .../SentryExceptionExtensions.apple.kt | 13 +- .../SentryOptionsExtensions.apple.kt | 35 ++- .../extensions/UserExtensions.apple.kt | 30 ++- .../log/CocoaSentryLoggerAdapter.kt | 7 +- .../log/SentryLogConverters.apple.kt | 76 +++--- .../multiplatform/nsexception/NSException.kt | 24 +- .../nsexception/SentryUnhandledExceptions.kt | 117 +++++---- .../multiplatform/nsexception/Throwable.kt | 35 ++- .../multiplatform/protocol/SentryId.apple.kt | 20 +- .../kotlin/multiplatform/AppleSentryIdTest.kt | 1 + .../kotlin/multiplatform/ApplyKmpEventTest.kt | 56 ++--- .../kotlin/multiplatform/BaseSentryTest.kt | 1 - .../multiplatform/BreadcrumbTestConverter.kt | 25 +- .../multiplatform/PlatformOptions.apple.kt | 14 +- .../SentryAttributesConversionTest.kt | 3 +- .../multiplatform/SentryBridgeTest.apple.kt | 34 +-- .../multiplatform/SentryExceptionTest.kt | 37 ++- .../multiplatform/SentryLevelTestConverter.kt | 4 +- .../UserFeedbackExtensionsTest.kt | 33 ++- .../nsexception/InitAddressesTests.kt | 18 +- .../nsexception/ThrowableCausesTests.kt | 5 +- .../nsexception/ThrowableNameTests.kt | 1 + .../nsexception/ThrowableReasonTests.kt | 14 +- .../kotlin/multiplatform/Attachment.jvm.kt | 6 +- .../kotlin/multiplatform/JvmScopeProvider.kt | 58 ++--- .../multiplatform/SentryBridge.commonJvm.kt | 36 ++- .../extensions/BreadcrumbExtensions.jvm.kt | 36 ++- .../extensions/MessageExtensions.jvm.kt | 24 +- .../SentryExceptionExtensions.jvm.kt | 13 +- .../extensions/SentryLevelExtensions.jvm.kt | 10 +- .../extensions/SentryOptionsExtensions.jvm.kt | 11 +- .../extensions/UserExtensions.jvm.kt | 38 ++- .../log/JvmSentryLoggerAdapter.kt | 7 +- .../log/SentryLogConverters.jvm.kt | 69 +++--- .../multiplatform/protocol/SentryId.jvm.kt | 20 +- .../multiplatform/BreadcrumbTestConverter.kt | 25 +- .../kotlin/multiplatform/JvmSentryIdTest.kt | 1 + .../SentryAttributesConversionTest.kt | 3 +- .../SentryBridgeTest.commonJvm.kt | 42 ++-- .../multiplatform/SentryLevelTestConverter.kt | 4 +- .../sentry/kotlin/multiplatform/Attachment.kt | 1 + .../multiplatform/HttpStatusCodeRange.kt | 10 +- .../io/sentry/kotlin/multiplatform/Scope.kt | 46 +--- .../multiplatform/SentryAttributeValue.kt | 18 +- .../kotlin/multiplatform/SentryAttributes.kt | 36 +-- .../kotlin/multiplatform/SentryBaseEvent.kt | 7 +- .../kotlin/multiplatform/SentryBridge.kt | 19 +- .../sentry/kotlin/multiplatform/SentryKMP.kt | 45 ++-- .../kotlin/multiplatform/SentryLevel.kt | 16 +- .../multiplatform/SentryReplayOptions.kt | 10 +- .../multiplatform/log/BaseSentryLogger.kt | 191 +++++---------- .../log/DefaultSentryLogBuilder.kt | 14 +- .../kotlin/multiplatform/log/SentryLog.kt | 6 +- .../multiplatform/log/SentryLogBuilder.kt | 7 +- .../multiplatform/log/SentryLogLevel.kt | 2 +- .../kotlin/multiplatform/log/SentryLogger.kt | 109 ++------- .../multiplatform/protocol/Breadcrumb.kt | 101 ++++---- .../kotlin/multiplatform/protocol/Message.kt | 2 +- .../multiplatform/protocol/SdkVersion.kt | 10 +- .../multiplatform/protocol/SentryException.kt | 2 +- .../kotlin/multiplatform/protocol/SentryId.kt | 5 +- .../kotlin/multiplatform/protocol/User.kt | 10 +- .../multiplatform/protocol/UserFeedback.kt | 2 +- .../multiplatform/Attachment.commonStub.kt | 1 + .../kotlin/multiplatform/NoOpSentryLogger.kt | 109 ++------- .../multiplatform/SentryBridge.commonStub.kt | 41 ++-- .../protocol/SentryId.commonStub.kt | 4 +- .../kotlin/multiplatform/AttachmentTest.kt | 1 + .../multiplatform/BaseSentryScopeTest.kt | 1 + .../kotlin/multiplatform/BaseSentryTest.kt | 2 - .../BeforeBreadcrumbIntegrationTest.kt | 125 +++++----- .../BeforeSendIntegrationTest.kt | 222 ++++++++---------- .../kotlin/multiplatform/BeforeSendTest.kt | 34 ++- .../multiplatform/BreadcrumbConfigurator.kt | 2 - .../kotlin/multiplatform/BreadcrumbTest.kt | 1 + .../multiplatform/BreadcrumbTestConverter.kt | 8 +- .../sentry/kotlin/multiplatform/ScopeTest.kt | 6 +- .../multiplatform/SentryAttributeValueTest.kt | 1 + .../multiplatform/SentryAttributesTest.kt | 10 +- .../kotlin/multiplatform/SentryBridgeTest.kt | 5 - .../kotlin/multiplatform/SentryE2ETest.kt | 92 ++++---- .../multiplatform/SentryEventConfigurator.kt | 2 - .../kotlin/multiplatform/SentryEventTest.kt | 1 + .../kotlin/multiplatform/SentryIdTest.kt | 1 + .../multiplatform/SentryIntegrationTest.kt | 129 +++++----- .../SentryLevelConversionTest.kt | 1 + .../multiplatform/SentryLevelTestConverter.kt | 1 + .../kotlin/multiplatform/SentryOptionsTest.kt | 87 ++++--- .../kotlin/multiplatform/UserFeedbackTest.kt | 1 + .../sentry/kotlin/multiplatform/UserTest.kt | 5 +- .../multiplatform/log/BaseSentryLoggerTest.kt | 22 +- .../multiplatform/log/SentryLogBuilderTest.kt | 1 + .../multiplatform/log/SentryLogOptionsTest.kt | 3 +- .../SentryPlatformOptions.tvwatchmacos.kt | 3 +- .../PlatformOptions.tvwatchmacos.kt | 5 +- .../SentryPlatformOptions.ios.kt | 3 +- .../extensions/SentryOptionsExtensions.ios.kt | 58 ++--- .../multiplatform/PlatformOptions.ios.kt | 11 +- .../SentryPlatformOptions.jvm.kt | 3 +- .../kotlin/multiplatform/BaseSentryTest.kt | 1 - .../multiplatform/PlatformOptions.jvm.kt | 11 +- .../kotlin/sample.kmp.app.desktop/Main.kt | 29 ++- .../sample/kmp/app/SentrySetup.android.kt | 7 +- .../kotlin/sample.kmp.app/LoginImpl.kt | 50 ++-- .../kotlin/sample.kmp.app/SentrySetup.kt | 9 +- .../kotlin/sample.kmp.app/HttpClient.kt | 19 +- .../kotlin/sample.kmp.app/SentrySetup.ios.kt | 7 +- .../kotlin/sample/kmp/app/SentrySetup.jvm.kt | 7 +- .../kotlin/sample.kmp.app.desktop/Main.kt | 29 ++- .../kmp-app-spm/shared/build.gradle.kts | 2 +- .../kotlin/sample.kmp.app/LoginImpl.kt | 41 ++-- .../kotlin/sample.kmp.app/SentrySetup.kt | 9 +- .../kotlin/sample.kmp.app/HttpClient.kt | 19 +- 153 files changed, 1827 insertions(+), 2373 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8cea45444..6a262a5fa 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,16 @@ root = true [*.{kt,kts}] -# ktlint 1.x enables stricter naming rules by default. The codebase relies on +# ktlint 1.x defaults to the new ktlint_official code style, which would reformat +# most of the codebase (multiline expression wrapping, trailing commas, signature +# wrapping). Pin the pre-1.x style until a dedicated style-migration PR adopts +# ktlint_official deliberately. +ktlint_code_style = intellij_idea +# ktlint 1.x adds trailing commas by default regardless of code style; the +# codebase doesn't use them. +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +# ktlint 1.x also enables stricter naming rules by default. The codebase relies on # backtick-wrapped test function names and constant-style vals that predate # these rules, so keep them disabled to match existing conventions. ktlint_standard_function-naming = disabled diff --git a/build.gradle.kts b/build.gradle.kts index b3a9e802a..00128e0be 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -113,7 +113,7 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { "wasm-js", "linuxx64", "linuxarm64", - "mingwx64", + "mingwx64" ) val artifactPaths = @@ -122,7 +122,7 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { addAll( platforms.map { platform -> distributionDir.resolve("$baseFileName-$platform-$version.zip") - }, + } ) } @@ -131,7 +131,7 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { "javadoc", "sources", "module", - "pom-default.xml", + "pom-default.xml" ) artifactPaths.forEach { artifactFile -> @@ -167,7 +167,7 @@ private fun Project.validateKotlinMultiplatformCoreArtifacts() { val actualKlibFiles = entries.count { it.contains("klib") } if (actualKlibFiles != expectedNumOfKlibFiles) { throw GradleException( - "❌ Expected $expectedNumOfKlibFiles klib files in ${artifactFile.name}, but found $actualKlibFiles", + "❌ Expected $expectedNumOfKlibFiles klib files in ${artifactFile.name}, but found $actualKlibFiles" ) } else { println("✅ Found $expectedNumOfKlibFiles klib files in ${artifactFile.name}") @@ -199,18 +199,37 @@ subprojects { } } +// Keep ktlint 1.x on the pre-1.0 formatting conventions (see .editorconfig for the +// rationale). Spotless does not reliably forward the ij_* properties from +// .editorconfig to ktlint, so pass them explicitly. +val ktlintEditorConfigOverride = + mapOf( + "ktlint_code_style" to "intellij_idea", + "ij_kotlin_allow_trailing_comma" to "false", + "ij_kotlin_allow_trailing_comma_on_call_site" to "false", + "ktlint_standard_argument-list-wrapping" to "disabled", + "ktlint_standard_chain-method-continuation" to "disabled", + "ktlint_standard_class-signature" to "disabled", + "ktlint_standard_condition-wrapping" to "disabled", + "ktlint_standard_function-expression-body" to "disabled", + "ktlint_standard_function-signature" to "disabled", + "ktlint_standard_multiline-expression-wrapping" to "disabled", + "ktlint_standard_function-naming" to "disabled", + "ktlint_standard_property-naming" to "disabled" + ) + spotless { lineEndings = LineEnding.UNIX kotlin { target("**/*.kt") targetExclude("**/generated/**/*.kt") - ktlint() + ktlint().editorConfigOverride(ktlintEditorConfigOverride) } kotlinGradle { target("**/*.kts") targetExclude("**/generated/**/*.kts") - ktlint() + ktlint().editorConfigOverride(ktlintEditorConfigOverride) } } diff --git a/buildSrc/src/main/java/Publication.kt b/buildSrc/src/main/java/Publication.kt index 749024baf..96bb9f884 100644 --- a/buildSrc/src/main/java/Publication.kt +++ b/buildSrc/src/main/java/Publication.kt @@ -5,38 +5,34 @@ import java.io.File private val sep: String = File.separator -fun DistributionContainer.configureForMultiplatform( - project: Project, - buildPublishDir: String, -) { +fun DistributionContainer.configureForMultiplatform(project: Project, buildPublishDir: String) { val version = project.property("versionName").toString() if (version.isEmpty()) { throw GradleException("DistZip: version name is empty") } val projectName = project.name - val platforms = - mapOf( - "main" to projectName, - "android" to "$projectName-android", - "jvm" to "$projectName-jvm", - "iosarm64" to "$projectName-iosarm64", - "iossimulatorarm64" to "$projectName-iossimulatorarm64", - "iosx64" to "$projectName-iosx64", - "macosarm64" to "$projectName-macosarm64", - "macosx64" to "$projectName-macosx64", - "tvosarm64" to "$projectName-tvosarm64", - "tvossimulatorarm64" to "$projectName-tvossimulatorarm64", - "tvosx64" to "$projectName-tvosx64", - "watchosarm32" to "$projectName-watchosarm32", - "watchosarm64" to "$projectName-watchosarm64", - "watchossimulatorarm64" to "$projectName-watchossimulatorarm64", - "watchosx64" to "$projectName-watchosx64", - "js" to "$projectName-js", - "wasm-js" to "$projectName-wasm-js", - "mingwx64" to "$projectName-mingwx64", - "linuxarm64" to "$projectName-linuxarm64", - "linuxx64" to "$projectName-linuxx64", - ) + val platforms = mapOf( + "main" to projectName, + "android" to "$projectName-android", + "jvm" to "$projectName-jvm", + "iosarm64" to "$projectName-iosarm64", + "iossimulatorarm64" to "$projectName-iossimulatorarm64", + "iosx64" to "$projectName-iosx64", + "macosarm64" to "$projectName-macosarm64", + "macosx64" to "$projectName-macosx64", + "tvosarm64" to "$projectName-tvosarm64", + "tvossimulatorarm64" to "$projectName-tvossimulatorarm64", + "tvosx64" to "$projectName-tvosx64", + "watchosarm32" to "$projectName-watchosarm32", + "watchosarm64" to "$projectName-watchosarm64", + "watchossimulatorarm64" to "$projectName-watchossimulatorarm64", + "watchosx64" to "$projectName-watchosx64", + "js" to "$projectName-js", + "wasm-js" to "$projectName-wasm-js", + "mingwx64" to "$projectName-mingwx64", + "linuxarm64" to "$projectName-linuxarm64", + "linuxx64" to "$projectName-linuxx64" + ) platforms.forEach { (distName, projectName) -> val distribution = maybeCreate(distName) diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index b1bd6b1d5..46dc74477 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -2,13 +2,7 @@ - MaxLineLength:ManualFrameworkPathSearchValueSource.kt$ManualFrameworkPathSearchValueSource$abstract MaxLineLength:SentryAttributes.kt$SentryAttributes.Companion$public - MaxLineLength:SentryLogConverters.apple.kt$is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) - MaxLineLength:SentryPlatformOptions.android.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration - MaxLineLength:SentryPlatformOptions.ios.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration - MaxLineLength:SentryPlatformOptions.jvm.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration - MaxLineLength:SentryPlatformOptions.tvwatchmacos.kt$internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration SwallowedException:CocoaScopeProvider.kt$CocoaScopeProvider$e: Throwable SwallowedException:SentryLevel.kt$SentryLevel.Companion$throwable: Throwable TooGenericExceptionCaught:CocoaScopeProvider.kt$CocoaScopeProvider$e: Throwable diff --git a/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts b/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts index 41aea54be..60295f70d 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts +++ b/sentry-kotlin-multiplatform-gradle-plugin/build.gradle.kts @@ -93,12 +93,12 @@ buildConfig { buildConfigField( "String", "SentryCocoaVersion", - provider { "\"${project.property("sentryCocoaVersion")}\"" }, + provider { "\"${project.property("sentryCocoaVersion")}\"" } ) buildConfigField( "String", "SentryKmpVersion", - provider { "\"${project.property("versionName")}\"" }, + provider { "\"${project.property("versionName")}\"" } ) } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt index e0ec94b3b..9132450cb 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/AutoInstallExtension.kt @@ -5,26 +5,22 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class AutoInstallExtension - @Inject - constructor( - project: Project, - ) { - private val objects = project.objects +abstract class AutoInstallExtension @Inject constructor(project: Project) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry dependencies through [CocoapodsAutoInstallExtension] - * and [SourceSetAutoInstallExtension]. - * - * Disabling this will prevent the plugin from auto installing any dependency. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry dependencies through [CocoapodsAutoInstallExtension] + * and [SourceSetAutoInstallExtension]. + * + * Disabling this will prevent the plugin from auto installing any dependency. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - val cocoapods: CocoapodsAutoInstallExtension = - objects.newInstance(CocoapodsAutoInstallExtension::class.java, project) + val cocoapods: CocoapodsAutoInstallExtension = + objects.newInstance(CocoapodsAutoInstallExtension::class.java, project) - val commonMain: SourceSetAutoInstallExtension = - objects.newInstance(SourceSetAutoInstallExtension::class.java, project) - } + val commonMain: SourceSetAutoInstallExtension = + objects.newInstance(SourceSetAutoInstallExtension::class.java, project) +} diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt index 68908d635..ee47e83fe 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinker.kt @@ -13,13 +13,13 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget class CocoaFrameworkLinker( private val logger: Logger, private val pathResolver: FrameworkPathResolver, - private val binaryLinker: FrameworkLinker, + private val binaryLinker: FrameworkLinker ) { fun configure(appleTargets: List) { appleTargets.forEach { target -> try { logger.info( - "Start resolving Sentry Cocoa framework paths for target: ${target.name}", + "Start resolving Sentry Cocoa framework paths for target: ${target.name}" ) processTarget(target) logger.lifecycle("Successfully configured Sentry Cocoa framework linking for target: ${target.name}") @@ -42,7 +42,7 @@ class CocoaFrameworkLinker( internal class FrameworkLinkingException( message: String, - cause: Throwable? = null, + cause: Throwable? = null ) : GradleException(message, cause) /** @@ -56,18 +56,17 @@ internal class FrameworkLinkingException( * @return Set of possible architecture folder names for the given target. * Returns empty set if target is not supported. */ -internal fun KotlinNativeTarget.toSentryFrameworkArchitecture(): Set = - buildSet { - when (name) { - "iosSimulatorArm64", "iosX64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_SIMULATOR_AND_X64) - "iosArm64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_ARM64) - "macosArm64", "macosX64" -> addAll(SentryCocoaFrameworkArchitectures.MACOS_ARM64_AND_X64) - "tvosSimulatorArm64", "tvosX64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_SIMULATOR_AND_X64) - "tvosArm64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_ARM64) - "watchosArm32", "watchosArm64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_ARM) - "watchosSimulatorArm64", "watchosX64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_SIMULATOR_AND_X64) - } +internal fun KotlinNativeTarget.toSentryFrameworkArchitecture(): Set = buildSet { + when (name) { + "iosSimulatorArm64", "iosX64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_SIMULATOR_AND_X64) + "iosArm64" -> addAll(SentryCocoaFrameworkArchitectures.IOS_ARM64) + "macosArm64", "macosX64" -> addAll(SentryCocoaFrameworkArchitectures.MACOS_ARM64_AND_X64) + "tvosSimulatorArm64", "tvosX64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_SIMULATOR_AND_X64) + "tvosArm64" -> addAll(SentryCocoaFrameworkArchitectures.TVOS_ARM64) + "watchosArm32", "watchosArm64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_ARM) + "watchosSimulatorArm64", "watchosX64" -> addAll(SentryCocoaFrameworkArchitectures.WATCHOS_SIMULATOR_AND_X64) } +} internal object SentryCocoaFrameworkArchitectures { val IOS_SIMULATOR_AND_X64 = setOf("ios-arm64_x86_64-simulator") @@ -79,16 +78,15 @@ internal object SentryCocoaFrameworkArchitectures { val WATCHOS_SIMULATOR_AND_X64 = setOf("watchos-arm64_i386_x86_64-simulator") // Used for tests - val all = - setOf( - IOS_SIMULATOR_AND_X64, - IOS_ARM64, - MACOS_ARM64_AND_X64, - TVOS_SIMULATOR_AND_X64, - TVOS_ARM64, - WATCHOS_ARM, - WATCHOS_SIMULATOR_AND_X64, - ) + val all = setOf( + IOS_SIMULATOR_AND_X64, + IOS_ARM64, + MACOS_ARM64_AND_X64, + TVOS_SIMULATOR_AND_X64, + TVOS_ARM64, + WATCHOS_ARM, + WATCHOS_SIMULATOR_AND_X64 + ) } internal fun KotlinMultiplatformExtension.appleTargets() = diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt index 3021782ff..e38772113 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/CocoapodsAutoInstallExtension.kt @@ -6,28 +6,24 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class CocoapodsAutoInstallExtension - @Inject - constructor( - project: Project, - ) { - private val objects = project.objects +abstract class CocoapodsAutoInstallExtension @Inject constructor(project: Project) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry Cocoa SDK pod. - * - * If the cocoapods plugin is applied and no existing Sentry pod configuration exists, the - * Sentry-Cocoa SDK pod will be installed. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry Cocoa SDK pod. + * + * If the cocoapods plugin is applied and no existing Sentry pod configuration exists, the + * Sentry-Cocoa SDK pod will be installed. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - /** - * Overrides default Sentry Cocoa version. - * - * Defaults to the version used in the latest KMP SDK. - */ - val sentryCocoaVersion: Property = - objects.property(String::class.java).convention("~> ${BuildConfig.SentryCocoaVersion}") - } + /** + * Overrides default Sentry Cocoa version. + * + * Defaults to the version used in the latest KMP SDK. + */ + val sentryCocoaVersion: Property = + objects.property(String::class.java).convention("~> ${BuildConfig.SentryCocoaVersion}") +} diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt index c680088d9..a529412d7 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathValueSource.kt @@ -14,7 +14,8 @@ import javax.inject.Inject * * e.g /Users/theusername/Library/Developer/Xcode/DerivedData/iosApp-ddefikekigqzzgcnpfkkdallksmlfpln/ */ -abstract class DerivedDataPathValueSource : ValueSource { +abstract class DerivedDataPathValueSource : + ValueSource { interface Parameters : ValueSourceParameters { @get:Input val xcodeprojPath: Property @@ -31,19 +32,17 @@ abstract class DerivedDataPathValueSource : ValueSource when (binary) { @@ -26,38 +26,27 @@ class FrameworkLinker( } } - private fun chooseTestPath( - dynamic: String?, - static: String?, - ) = when { + private fun chooseTestPath(dynamic: String?, static: String?) = when { dynamic != null -> dynamic static != null -> static else -> throw FrameworkLinkingException("No valid framework path found for tests") } - private fun linkTestBinary( - binary: TestExecutable, - path: String, - ) { + private fun linkTestBinary(binary: TestExecutable, path: String) { // Linking in test binaries works with both dynamic and static framework binary.linkerOpts("-rpath", path, "-F$path") logger.info("Linked Sentry Cocoa framework to test binary ${binary.name}") } - private fun linkFrameworkBinary( - binary: Framework, - dynamicPath: String?, - staticPath: String?, - ) { - val (path, type) = - when { - binary.isStatic && staticPath != null -> staticPath to "static" - !binary.isStatic && dynamicPath != null -> dynamicPath to "dynamic" - else -> throw FrameworkLinkingException( - "Framework mismatch for ${binary.name}. " + - "Required ${if (binary.isStatic) "static" else "dynamic"} Sentry Cocoa framework not found.", - ) - } + private fun linkFrameworkBinary(binary: Framework, dynamicPath: String?, staticPath: String?) { + val (path, type) = when { + binary.isStatic && staticPath != null -> staticPath to "static" + !binary.isStatic && dynamicPath != null -> dynamicPath to "dynamic" + else -> throw FrameworkLinkingException( + "Framework mismatch for ${binary.name}. " + + "Required ${if (binary.isStatic) "static" else "dynamic"} Sentry Cocoa framework not found." + ) + } binary.linkerOpts("-F$path") logger.info("Linked $type Sentry Cocoa framework to ${binary.name}") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt index 1ee4064de..ec405e7cf 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolver.kt @@ -11,12 +11,12 @@ import kotlin.io.path.absolutePathString enum class FrameworkType { STATIC, - DYNAMIC, + DYNAMIC } data class FrameworkPaths( val dynamic: String? = null, - val static: String? = null, + val static: String? = null ) { companion object { val NONE = FrameworkPaths(null, null) @@ -25,17 +25,15 @@ data class FrameworkPaths( dynamicBasePath: String? = null, staticBasePath: String? = null, architectures: Set, - pathExists: (String) -> Boolean = { path -> File(path).exists() }, + pathExists: (String) -> Boolean = { path -> File(path).exists() } ): FrameworkPaths { - val dynamicPath = - dynamicBasePath?.let { basePath -> - architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } - } + val dynamicPath = dynamicBasePath?.let { basePath -> + architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } + } - val staticPath = - staticBasePath?.let { basePath -> - architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } - } + val staticPath = staticBasePath?.let { basePath -> + architectures.map { arch -> "$basePath/$arch" }.firstOrNull { pathExists(it) } + } return when { dynamicPath != null && staticPath != null -> @@ -63,35 +61,32 @@ interface FrameworkResolutionStrategy { * This should generally be executed first. */ class CustomPathStrategy( - private val project: Project, + private val project: Project ) : FrameworkResolutionStrategy { private val linker: LinkerExtension = project.extensions.getByType(LinkerExtension::class.java) // In this function we don't distinguish between static and dynamic frameworks // We trust that the user knows the distinction if they purposefully override the framework path override fun resolvePaths(architectures: Set): FrameworkPaths { - val result = - linker.frameworkPath.orNull?.takeIf { it.isNotEmpty() }?.let { basePath -> - when { - basePath.endsWith("Sentry.xcframework") -> - FrameworkPaths.createValidated( - staticBasePath = basePath, - architectures = architectures, - ) + val result = linker.frameworkPath.orNull?.takeIf { it.isNotEmpty() }?.let { basePath -> + when { + basePath.endsWith("Sentry.xcframework") -> FrameworkPaths.createValidated( + staticBasePath = basePath, + architectures = architectures + ) - basePath.endsWith("Sentry-Dynamic.xcframework") -> - FrameworkPaths.createValidated( - dynamicBasePath = basePath, - architectures = architectures, - ) + basePath.endsWith("Sentry-Dynamic.xcframework") -> FrameworkPaths.createValidated( + dynamicBasePath = basePath, + architectures = architectures + ) - else -> FrameworkPaths.NONE - } - } ?: FrameworkPaths.NONE + else -> FrameworkPaths.NONE + } + } ?: FrameworkPaths.NONE if (linker.frameworkPath.orNull != null && result == FrameworkPaths.NONE) { project.logger.warn( "Custom framework path has been set manually but could not be found. " + - "Trying to resolve framework paths using other strategies.", + "Trying to resolve framework paths using other strategies." ) } return result @@ -108,11 +103,10 @@ class CustomPathStrategy( class DerivedDataStrategy( private val project: Project, private val derivedDataProvider: (String) -> String? = { xcodeprojPath -> - project.providers - .of(DerivedDataPathValueSource::class.java) { - it.parameters.xcodeprojPath.set(xcodeprojPath) - }.orNull - }, + project.providers.of(DerivedDataPathValueSource::class.java) { + it.parameters.xcodeprojPath.set(xcodeprojPath) + }.orNull + } ) : FrameworkResolutionStrategy { private val linker: LinkerExtension = project.extensions.getByType(LinkerExtension::class.java) @@ -132,7 +126,7 @@ class DerivedDataStrategy( return FrameworkPaths.createValidated( dynamicBasePath = dynamicBasePath, staticBasePath = staticBasePath, - architectures = architectures, + architectures = architectures ) } @@ -149,9 +143,9 @@ class DerivedDataStrategy( object : SimpleFileVisitor() { override fun preVisitDirectory( dir: Path, - attrs: BasicFileAttributes, - ): FileVisitResult = - when { + attrs: BasicFileAttributes + ): FileVisitResult { + return when { // Check if current directory is a xcodeproj before checking ignored dirs dir.toString().endsWith(".xcodeproj") -> { foundXcodeprojPath = dir.absolutePathString() @@ -161,7 +155,8 @@ class DerivedDataStrategy( ignoredDirectories.contains(dir.fileName.toString()) -> FileVisitResult.SKIP_SUBTREE else -> FileVisitResult.CONTINUE } - }, + } + } ) if (foundXcodeprojPath != null) { @@ -184,7 +179,7 @@ class DerivedDataStrategy( */ class ManualSearchStrategy( private val project: Project, - private val basePathToSearch: String? = null, + private val basePathToSearch: String? = null ) : FrameworkResolutionStrategy { // TODO: currently the search doesnt differentiate between Cocoa versions // we can improve this by checking the info.plist and prefer the ones that are the version we are looking for @@ -207,26 +202,28 @@ class ManualSearchStrategy( return FrameworkPaths.createValidated( dynamicBasePath = dynamicValueSource.orNull, staticBasePath = staticValueSource.orNull, - architectures = architectures, + architectures = architectures ) } } class FrameworkPathResolver( private val project: Project, - private val strategies: List = defaultStrategies(project), + private val strategies: List = defaultStrategies(project) ) { - fun resolvePaths(architectures: Set): FrameworkPaths { + fun resolvePaths( + architectures: Set + ): FrameworkPaths { strategies.forEach { strategy -> try { project.logger.info( - "Attempt to resolve Sentry Cocoa framework paths using ${strategy::class.simpleName}", + "Attempt to resolve Sentry Cocoa framework paths using ${strategy::class.simpleName}" ) val result = strategy.resolvePaths(architectures) if (result != FrameworkPaths.NONE) { val path = result.dynamic ?: result.static project.logger.lifecycle( - "Found Sentry Cocoa framework path using ${strategy::class.simpleName} at $path", + "Found Sentry Cocoa framework path using ${strategy::class.simpleName} at $path" ) return result } else { @@ -234,7 +231,7 @@ class FrameworkPathResolver( } } catch (e: FrameworkLinkingException) { project.logger.warn( - "Strategy ${strategy::class.simpleName} failed due to error: ${e.message}", + "Strategy ${strategy::class.simpleName} failed due to error: ${e.message}" ) } } @@ -243,8 +240,7 @@ class FrameworkPathResolver( throw FrameworkLinkingException(frameworkNotFoundMessage) } - private val frameworkNotFoundMessage = - """ + private val frameworkNotFoundMessage = """ Failed to find Sentry Cocoa framework. Steps to resolve: 1. Install Sentry Cocoa via SPM in Xcode @@ -258,7 +254,7 @@ class FrameworkPathResolver( frameworkPath.set("path/to/Sentry.xcframework") } } - """.trimIndent() + """.trimIndent() companion object { /** @@ -268,13 +264,14 @@ class FrameworkPathResolver( * resolved by the first successful strategy. Specifically here Custom Path will be checked first, * if that fails then it is followed by the Derived Data strategy etc... */ - fun defaultStrategies(project: Project): List = - listOf( + fun defaultStrategies(project: Project): List { + return listOf( CustomPathStrategy(project), DerivedDataStrategy(project), - ManualSearchStrategy(project), + ManualSearchStrategy(project) // TODO: add DownloadStrategy -> downloads the framework and stores it in build dir // this is especially useful for users who dont have a monorepo setup ) + } } } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt index 1d1951520..f9f0114e5 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/LinkerExtension.kt @@ -5,40 +5,36 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class LinkerExtension - @Inject - constructor( - project: Project, - ) { - private val objects = project.objects +abstract class LinkerExtension @Inject constructor(project: Project) { + private val objects = project.objects - /** - * Path to the Xcode project that will be used to link the framework. - * This is used to find the derived data path in which the framework is stored for SPM. - */ - val xcodeprojPath: Property = objects.property(String::class.java) + /** + * Path to the Xcode project that will be used to link the framework. + * This is used to find the derived data path in which the framework is stored for SPM. + */ + val xcodeprojPath: Property = objects.property(String::class.java) - /** - * Path to the framework that will be linked. - * Takes precedence over [xcodeprojPath] if both are set. - * - * The path must: - * 1. Point directly to the .xcframework folder - * 2. The .xcframework folder needs to be either `Sentry.xcframework` or `Sentry-Dynamic.xcframework` - * - * ### Usage Example: - * ```kotlin - * sentryKmp { - * frameworkPath.set( - * "path/to/Sentry.xcframework" // Static framework - * // or - * "path/to/Sentry-Dynamic.xcframework" // Dynamic framework - * ) - * } - * ``` - * - * ### Typical Locations: - * `~/Library/Developer/Xcode/DerivedData/{PROJECT}/SourcePackages/artifacts/sentry-cocoa` - */ - val frameworkPath: Property = objects.property(String::class.java) - } + /** + * Path to the framework that will be linked. + * Takes precedence over [xcodeprojPath] if both are set. + * + * The path must: + * 1. Point directly to the .xcframework folder + * 2. The .xcframework folder needs to be either `Sentry.xcframework` or `Sentry-Dynamic.xcframework` + * + * ### Usage Example: + * ```kotlin + * sentryKmp { + * frameworkPath.set( + * "path/to/Sentry.xcframework" // Static framework + * // or + * "path/to/Sentry-Dynamic.xcframework" // Dynamic framework + * ) + * } + * ``` + * + * ### Typical Locations: + * `~/Library/Developer/Xcode/DerivedData/{PROJECT}/SourcePackages/artifacts/sentry-cocoa` + */ + val frameworkPath: Property = objects.property(String::class.java) +} diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt index d05a2d428..06f92471f 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/ManualFrameworkPathSearchValueSource.kt @@ -7,7 +7,8 @@ import org.gradle.api.provider.ValueSourceParameters import org.gradle.process.ExecOperations import java.io.ByteArrayOutputStream -abstract class ManualFrameworkPathSearchValueSource : ValueSource { +abstract class ManualFrameworkPathSearchValueSource : + ValueSource { interface Parameters : ValueSourceParameters { val frameworkType: Property val basePathToSearch: Property @@ -30,42 +31,40 @@ abstract class ManualFrameworkPathSearchValueSource : ValueSource { project.extensions.create( SENTRY_EXTENSION_NAME, SentryExtension::class.java, - project, + project ) project.extensions.add(LINKER_EXTENSION_NAME, sentryExtension.linker) project.extensions.add(AUTO_INSTALL_EXTENSION_NAME, sentryExtension.autoInstall) project.extensions.add( COCOAPODS_AUTO_INSTALL_EXTENSION_NAME, - sentryExtension.autoInstall.cocoapods, + sentryExtension.autoInstall.cocoapods ) project.extensions.add( COMMON_MAIN_AUTO_INSTALL_EXTENSION_NAME, - sentryExtension.autoInstall.commonMain, + sentryExtension.autoInstall.commonMain ) afterEvaluate { @@ -47,7 +47,7 @@ class SentryPlugin : Plugin { internal fun executeConfiguration( project: Project, - hostIsMac: Boolean = HostManager.hostIsMac, + hostIsMac: Boolean = HostManager.hostIsMac ) { val sentryExtension = project.extensions.getByType(SentryExtension::class.java) val hasCocoapodsPlugin = @@ -78,7 +78,7 @@ class SentryPlugin : Plugin { private fun maybeLinkCocoaFramework( project: Project, hasCocoapods: Boolean, - hostIsMac: Boolean, + hostIsMac: Boolean ) { if (hostIsMac && !hasCocoapods) { // Register a task graph listener so that we only configure Cocoa framework linking @@ -104,7 +104,7 @@ private fun maybeLinkCocoaFramework( if (activeTargets.isEmpty()) { project.logger.lifecycle( "No Apple compile task scheduled for this build " + - "- skipping Sentry Cocoa framework linking", + "- skipping Sentry Cocoa framework linking" ) return@whenReady } @@ -114,7 +114,7 @@ private fun maybeLinkCocoaFramework( CocoaFrameworkLinker( logger = project.logger, pathResolver = FrameworkPathResolver(project), - binaryLinker = FrameworkLinker(project.logger), + binaryLinker = FrameworkLinker(project.logger) ).configure(appleTargets = activeTargets) } } @@ -123,27 +123,26 @@ private fun maybeLinkCocoaFramework( private fun getActiveTargets( project: Project, appleTargets: List, - graph: TaskExecutionGraph, -): List = - appleTargets.filter { target -> - val targetName = - target.name.replaceFirstChar { - it.uppercase() - } - val path = - if (project.path == ":") { - ":compileKotlin$targetName" - } else { - "${project.path}:compileKotlin$targetName" - } - try { - graph.hasTask(path) - } catch (_: Exception) { - false - } + graph: TaskExecutionGraph +): List = appleTargets.filter { target -> + val targetName = target.name.replaceFirstChar { + it.uppercase() + } + val path = if (project.path == ":") { + ":compileKotlin$targetName" + } else { + "${project.path}:compileKotlin$targetName" } + try { + graph.hasTask(path) + } catch (_: Exception) { + false + } +} -internal fun Project.installSentryForKmp(commonMainAutoInstallExtension: SourceSetAutoInstallExtension) { +internal fun Project.installSentryForKmp( + commonMainAutoInstallExtension: SourceSetAutoInstallExtension +) { val kmpExtension = extensions.findByName(KOTLIN_EXTENSION_NAME) if (kmpExtension !is KotlinMultiplatformExtension) { logger.info("Kotlin Multiplatform plugin not found. Skipping Sentry installation.") @@ -157,7 +156,7 @@ internal fun Project.installSentryForKmp(commonMainAutoInstallExtension: SourceS "Unsupported target: ${target.name}. " + "Cannot auto install in commonMain. " + "Please create an intermediate sourceSet with targets that the Sentry SDK " + - "supports and add the dependency manually.", + "supports and add the dependency manually." ) } } @@ -168,7 +167,9 @@ internal fun Project.installSentryForKmp(commonMainAutoInstallExtension: SourceS commonMain?.dependencies { api("io.sentry:sentry-kotlin-multiplatform:$sentryVersion") } } -internal fun Project.installSentryForCocoapods(cocoapodsAutoInstallExtension: CocoapodsAutoInstallExtension) { +internal fun Project.installSentryForCocoapods( + cocoapodsAutoInstallExtension: CocoapodsAutoInstallExtension +) { val kmpExtension = extensions.findByName(KOTLIN_EXTENSION_NAME) if (kmpExtension !is KotlinMultiplatformExtension || kmpExtension.targets.isEmpty() || !HostManager.hostIsMac) { logger.info("Skipping Cocoapods installation.") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt index 3e4f0eede..6e4ec17c2 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SourceSetAutoInstallExtension.kt @@ -6,28 +6,24 @@ import org.gradle.api.provider.Property import javax.inject.Inject @Suppress("UnnecessaryAbstractClass") -abstract class SourceSetAutoInstallExtension - @Inject - constructor( - project: Project, - ) { - private val objects = project.objects +abstract class SourceSetAutoInstallExtension @Inject constructor(project: Project) { + private val objects = project.objects - /** - * Enable auto-installation of the Sentry Kotlin Multiplatform SDK dependency in the commonMain - * source set. - * - * Defaults to true. - */ - val enabled: Property = objects.property(Boolean::class.java).convention(true) + /** + * Enable auto-installation of the Sentry Kotlin Multiplatform SDK dependency in the commonMain + * source set. + * + * Defaults to true. + */ + val enabled: Property = objects.property(Boolean::class.java).convention(true) - /** - * Overrides the default Sentry Kotlin Multiplatform SDK dependency version. - * - * Defaults to the version of this plugin which is synchronized with the KMP SDK version. - */ - val sentryKmpVersion: Property = - objects - .property(String::class.java) - .convention(BuildConfig.SentryKmpVersion) - } + /** + * Overrides the default Sentry Kotlin Multiplatform SDK dependency version. + * + * Defaults to the version of this plugin which is synchronized with the KMP SDK version. + */ + val sentryKmpVersion: Property = + objects + .property(String::class.java) + .convention(BuildConfig.SentryKmpVersion) +} diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt index 32349df25..d67263cbf 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerIntegrationTest.kt @@ -19,9 +19,7 @@ class CocoaFrameworkLinkerIntegrationTest { * contains only non-Apple targets. */ @Test - fun `linker is not configured when only non-Apple tasks are requested`( - @TempDir projectDir: File, - ) { + fun `linker is not configured when only non-Apple tasks are requested`(@TempDir projectDir: File) { writeBuildFiles(projectDir) val output = ByteArrayOutputStream() @@ -38,9 +36,7 @@ class CocoaFrameworkLinkerIntegrationTest { * task is present in the task graph. */ @Test - fun `linker is configured when an Apple task is requested`( - @TempDir projectDir: File, - ) { + fun `linker is configured when an Apple task is requested`(@TempDir projectDir: File) { writeBuildFiles(projectDir) val output = ByteArrayOutputStream() @@ -64,20 +60,18 @@ class CocoaFrameworkLinkerIntegrationTest { // can resolve a valid framework path even on CI machines where SPM // (and hence DerivedData) is not available. // ----------------------------------------------------------------- - val fakeFrameworkDir = - File(dir, "Sentry-Dynamic.xcframework").apply { - // Create minimal structure that satisfies path validation logic - val archDirName = "ios-arm64_x86_64-simulator" // architecture used for iosSimulatorArm64 - val archDir = File(this, archDirName) - archDir.mkdirs() - } + val fakeFrameworkDir = File(dir, "Sentry-Dynamic.xcframework").apply { + // Create minimal structure that satisfies path validation logic + val archDirName = "ios-arm64_x86_64-simulator" // architecture used for iosSimulatorArm64 + val archDir = File(this, archDirName) + archDir.mkdirs() + } File(dir, "settings.gradle").writeText("""rootProject.name = "fixture"""") - val pluginClasspath = - PluginUnderTestMetadataReading - .readImplementationClasspath() - .joinToString(", ") { "\"${it.absolutePath.replace('\\', '/')}\"" } + val pluginClasspath = PluginUnderTestMetadataReading + .readImplementationClasspath() + .joinToString(", ") { "\"${it.absolutePath.replace('\\', '/')}\"" } File(dir, "build.gradle").writeText( """ @@ -116,24 +110,17 @@ class CocoaFrameworkLinkerIntegrationTest { frameworkPath.set("${fakeFrameworkDir.absolutePath.replace('\\', '/')}") } } - """.trimIndent(), + """.trimIndent() ) } /** Returns a pre-configured [GradleRunner] that logs into [out]. */ - private fun defaultRunner( - projectDir: File, - out: ByteArrayOutputStream, - ): GradleRunner = - GradleRunner - .create() + private fun defaultRunner(projectDir: File, out: ByteArrayOutputStream): GradleRunner = + GradleRunner.create() .withProjectDir(projectDir) .withPluginClasspath() - .withGradleVersion( - org.gradle.util.GradleVersion - .current() - .version, - ).forwardStdOutput(OutputStreamWriter(SynchronizedOutputStream(out))) + .withGradleVersion(org.gradle.util.GradleVersion.current().version) + .forwardStdOutput(OutputStreamWriter(SynchronizedOutputStream(out))) .forwardStdError(OutputStreamWriter(SynchronizedOutputStream(out))) .withArguments("--stacktrace") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt index de4f3bb76..473456295 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CocoaFrameworkLinkerTest.kt @@ -23,19 +23,18 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for static Framework binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = - listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64(), - ) + val appleTargets = listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64() + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -56,19 +55,18 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for dynamic Framework binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = - listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64(), - ) + val appleTargets = listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64() + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -89,19 +87,18 @@ class CocoaFrameworkLinkerTest { @Test fun `framework linking succeeds for TestExecutable binary`() { val kmpExtension = fixture.project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val appleTargets = - listOf( - kmpExtension.iosSimulatorArm64(), - kmpExtension.iosArm64(), - kmpExtension.watchosArm32(), - kmpExtension.watchosSimulatorArm64(), - kmpExtension.watchosX64(), - kmpExtension.macosArm64(), - kmpExtension.macosX64(), - kmpExtension.tvosArm64(), - kmpExtension.tvosSimulatorArm64(), - kmpExtension.tvosX64(), - ) + val appleTargets = listOf( + kmpExtension.iosSimulatorArm64(), + kmpExtension.iosArm64(), + kmpExtension.watchosArm32(), + kmpExtension.watchosSimulatorArm64(), + kmpExtension.watchosX64(), + kmpExtension.macosArm64(), + kmpExtension.macosX64(), + kmpExtension.tvosArm64(), + kmpExtension.tvosSimulatorArm64(), + kmpExtension.tvosX64() + ) appleTargets.forEach { it.binaries.framework { baseName = "MyFramework" @@ -132,19 +129,22 @@ class CocoaFrameworkLinkerTest { } } - fun getSut(): CocoaFrameworkLinker = - CocoaFrameworkLinker( + fun getSut(): CocoaFrameworkLinker { + return CocoaFrameworkLinker( project.logger, FrameworkPathResolver(project, strategies = listOf(FakeStrategy())), - FrameworkLinker(project.logger), + FrameworkLinker(project.logger) ) + } } } // We don't really care what the strategy exactly does in this test // The strategies themselves are tested independently private class FakeStrategy : FrameworkResolutionStrategy { - override fun resolvePaths(architectures: Set): FrameworkPaths = FrameworkPaths(static = staticPath, dynamic = dynamicPath) + override fun resolvePaths(architectures: Set): FrameworkPaths { + return FrameworkPaths(static = staticPath, dynamic = dynamicPath) + } } private const val staticPath = "/path/to/static/Sentry.xcframework" diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt index f748c8c4d..8876beb6c 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/CustomPathStrategyTest.kt @@ -25,7 +25,7 @@ class CustomPathStrategyTest { @MethodSource("architectureMappingProvider") fun `should return static path when framework is Sentry xcframework`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { val xcframeworkPath = dir.resolve("Sentry.xcframework") Files.createDirectory(xcframeworkPath) @@ -42,7 +42,7 @@ class CustomPathStrategyTest { @MethodSource("architectureMappingProvider") fun `should return dynamic path when framework is Sentry xcframework`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { val xcframeworkPath = dir.resolve("Sentry-Dynamic.xcframework") Files.createDirectory(xcframeworkPath) @@ -72,9 +72,7 @@ class CustomPathStrategyTest { } @Test - fun `should return NONE when framework has invalid name`( - @TempDir dir: Path, - ) { + fun `should return NONE when framework has invalid name`(@TempDir dir: Path) { val xcframeworkPath = dir.resolve("Invalid.xcframework") val sut = fixture.getSut(xcframeworkPath.absolutePathString()) @@ -85,10 +83,9 @@ class CustomPathStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = - SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt index 61300b5cb..99c2cab5b 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataPathTest.kt @@ -22,26 +22,24 @@ class DerivedDataPathTest { execOperations = mockk() parameters = mockk() - valueSource = - object : DerivedDataPathValueSource() { - override val execOperations: ExecOperations = this@DerivedDataPathTest.execOperations - - override fun getParameters(): Parameters = this@DerivedDataPathTest.parameters + valueSource = object : DerivedDataPathValueSource() { + override val execOperations: ExecOperations = this@DerivedDataPathTest.execOperations + override fun getParameters(): Parameters { + return this@DerivedDataPathTest.parameters } + } } @Test fun `obtain should return correct derived data path`() { - val xcodebuildOutput = - """ + val xcodebuildOutput = """ Build settings for action build and target MyTarget: BUILD_DIR = /DerivedData/Example/Build/Products - """.trimIndent() + """.trimIndent() - every { parameters.xcodeprojPath } returns - mockk { - every { get() } returns "/path/to/project.xcodeproj" - } + every { parameters.xcodeprojPath } returns mockk { + every { get() } returns "/path/to/project.xcodeproj" + } every { execOperations.exec(any()) } answers { val execSpecLambda = it.invocation.args[0] as Action @@ -75,10 +73,9 @@ class DerivedDataPathTest { fun `obtain should return null when BUILD_DIR is not found`() { val xcodebuildOutput = "Some output without BUILD_DIR" - every { parameters.xcodeprojPath } returns - mockk { - every { get() } returns "/path/to/project.xcodeproj" - } + every { parameters.xcodeprojPath } returns mockk { + every { get() } returns "/path/to/project.xcodeproj" + } every { execOperations.exec(any()) } answers { val execSpecLambda = it.invocation.args[0] as Action diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt index 62c1ddd6d..93f1a2749 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/DerivedDataStrategyTest.kt @@ -26,7 +26,7 @@ class DerivedDataStrategyTest { @MethodSource("architectureMappingProvider") fun `if xcodeproj is null and find xcode project successfully then resolve static path`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { Files.createDirectory(dir.resolve("project.xcodeproj")) val xcframeworkPath = @@ -35,10 +35,9 @@ class DerivedDataStrategyTest { val archDirectory = Files.createDirectory(xcframeworkDirectory.resolve(expectedArchitecture.first())) - val sut = - fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(expectedArchitecture) assertEquals(archDirectory.absolutePathString(), paths.static) @@ -49,7 +48,7 @@ class DerivedDataStrategyTest { @MethodSource("architectureMappingProvider") fun `if xcodeproj is null and find xcode project successfully then resolve dynamic path`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { Files.createDirectory(dir.resolve("project.xcodeproj")) val xcframeworkPath = @@ -58,10 +57,9 @@ class DerivedDataStrategyTest { val archDirectory = Files.createDirectory(xcframeworkDirectory.resolve(expectedArchitecture.first())) - val sut = - fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(expectedArchitecture) assertEquals(archDirectory.absolutePathString(), paths.dynamic) @@ -70,12 +68,11 @@ class DerivedDataStrategyTest { @Test fun `if xcodeproj is null and find xcode project is not successful then return NONE`( - @TempDir dir: Path, + @TempDir dir: Path ) { - val sut = - fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> - dir.toFile().absolutePath - } + val sut = fixture.getSut(null, rootDirPath = dir.toFile().absolutePath) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(setOf("doesnt matter")) assertEquals(FrameworkPaths.NONE, paths) @@ -83,15 +80,14 @@ class DerivedDataStrategyTest { @Test fun `if xcodeproj is not null and find xcode project is not successful then return NONE`( - @TempDir dir: Path, + @TempDir dir: Path ) { - val sut = - fixture.getSut( - "some invalid path", - rootDirPath = dir.toFile().absolutePath, - ) { _: String -> - dir.toFile().absolutePath - } + val sut = fixture.getSut( + "some invalid path", + rootDirPath = dir.toFile().absolutePath + ) { _: String -> + dir.toFile().absolutePath + } val paths = sut.resolvePaths(setOf("doesnt matter")) assertEquals(FrameworkPaths.NONE, paths) @@ -99,23 +95,20 @@ class DerivedDataStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = - SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { fun getSut( xcodeprojPath: String?, rootDirPath: String, - derivedDataProvider: (String) -> String?, + derivedDataProvider: (String) -> String? ): DerivedDataStrategy { - val project = - ProjectBuilder - .builder() - .withProjectDir(File(rootDirPath)) - .build() + val project = ProjectBuilder.builder() + .withProjectDir(File(rootDirPath)) + .build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt index c1f178f49..e32839ef8 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/FrameworkPathResolverTest.kt @@ -23,10 +23,9 @@ class FrameworkPathResolverTest { @Test fun `does not execute subsequent strategies after first success`() { - val strategy1 = - mockk { - every { resolvePaths(any()) } returns FrameworkPaths(dynamic = "dyn") - } + val strategy1 = mockk { + every { resolvePaths(any()) } returns FrameworkPaths(dynamic = "dyn") + } val strategy2 = mockk() val sut = fixture.getSut(listOf(strategy1, strategy2)) diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt index 578f5a47e..347c3e1c2 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/ManualSearchStrategyTest.kt @@ -27,7 +27,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return static path when framework exists`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { val xcframeworkPath = dir.resolve("somewhere/hidden/Sentry.xcframework").createDirectories() val archDirectory = Files.createDirectory(xcframeworkPath.resolve(expectedArchitecture.first())) @@ -43,7 +43,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return dynamic path when framework exists`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { val xcframeworkPath = dir.resolve("somewhere/hidden/Sentry-Dynamic.xcframework").createDirectories() val archDirectory = Files.createDirectory(xcframeworkPath.resolve(expectedArchitecture.first())) @@ -59,7 +59,7 @@ class ManualSearchStrategyTest { @MethodSource("architectureMappingProvider") fun `should return most recently used path when multiple framework exists`( expectedArchitecture: Set, - @TempDir dir: Path, + @TempDir dir: Path ) { val xcframeworkPath1 = dir.resolve("somewhere/hidden/Sentry.xcframework").createDirectories() Files.createDirectory(xcframeworkPath1.resolve(expectedArchitecture.first())) @@ -88,10 +88,9 @@ class ManualSearchStrategyTest { companion object { @JvmStatic - fun architectureMappingProvider() = - SentryCocoaFrameworkArchitectures.all - .map { Arguments.of(it) } - .toList() + fun architectureMappingProvider() = SentryCocoaFrameworkArchitectures.all + .map { Arguments.of(it) } + .toList() } private class Fixture { diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt index 37c84b896..3578e8968 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryFrameworkArchitectureTest.kt @@ -18,19 +18,20 @@ import java.util.zip.ZipFile class SentryFrameworkArchitectureTest { companion object { @JvmStatic - fun cocoaVersions(): List = - listOf( - Arguments.of("8.37.0"), - Arguments.of("8.38.0"), - Arguments.of("8.58.2"), + fun cocoaVersions(): List = listOf( + Arguments.of("8.37.0"), + Arguments.of("8.38.0"), + Arguments.of("8.58.2") // Arguments.of("latest"), - // TODO: Latest is already v9 which is currently failing - let's fix this when we bump to v9 - ) + // TODO: Latest is already v9 which is currently failing - let's fix this when we bump to v9 + ) } @ParameterizedTest(name = "Test architecture name compatibility with Cocoa Version {0} in static framework") @MethodSource("cocoaVersions") - fun `finds arch folders in static framework`(cocoaVersion: String) { + fun `finds arch folders in static framework`( + cocoaVersion: String + ) { val project = ProjectBuilder.builder().build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") @@ -50,7 +51,7 @@ class SentryFrameworkArchitectureTest { watchosSimulatorArm64(), tvosX64(), tvosArm64(), - tvosSimulatorArm64(), + tvosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" @@ -66,10 +67,9 @@ class SentryFrameworkArchitectureTest { kmpExtension.appleTargets().forEach { val mappedArchNames = it.toSentryFrameworkArchitecture() - val foundMatch = - mappedArchNames.any { mappedArchName -> - downloadedArchNames.contains(mappedArchName) - } + val foundMatch = mappedArchNames.any { mappedArchName -> + downloadedArchNames.contains(mappedArchName) + } assert(foundMatch) { "Expected to find one of $mappedArchNames in $xcFramework for target ${it.name}.\nFound instead: ${ @@ -82,7 +82,9 @@ class SentryFrameworkArchitectureTest { @ParameterizedTest(name = "Test architecture name compatibility with Cocoa Version {0} in dynamic framework") @MethodSource("cocoaVersions") - fun `finds arch folders in dynamic framework`(cocoaVersion: String) { + fun `finds arch folders in dynamic framework`( + cocoaVersion: String + ) { val project = ProjectBuilder.builder().build() project.pluginManager.apply { apply("org.jetbrains.kotlin.multiplatform") @@ -102,7 +104,7 @@ class SentryFrameworkArchitectureTest { watchosSimulatorArm64(), tvosX64(), tvosArm64(), - tvosSimulatorArm64(), + tvosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" @@ -118,10 +120,9 @@ class SentryFrameworkArchitectureTest { kmpExtension.appleTargets().forEach { val mappedArchNames = it.toSentryFrameworkArchitecture() - val foundMatch = - mappedArchNames.any { mappedArchName -> - downloadedArchNames.contains(mappedArchName) - } + val foundMatch = mappedArchNames.any { mappedArchName -> + downloadedArchNames.contains(mappedArchName) + } assert(foundMatch) { "Expected to find one of $mappedArchNames in $xcFramework for target ${it.name}.\nFound instead: ${ @@ -136,23 +137,18 @@ class SentryFrameworkArchitectureTest { fun `returns empty list if target is unsupported`() { val unsupportedTarget = mockk() every { unsupportedTarget.name } returns "unsupported" - every { unsupportedTarget.konanTarget } returns - mockk { - every { family } returns - mockk { - every { isAppleFamily } returns true - } + every { unsupportedTarget.konanTarget } returns mockk { + every { family } returns mockk { + every { isAppleFamily } returns true } + } assert(unsupportedTarget.toSentryFrameworkArchitecture().isEmpty()) { "Expected empty list for unsupported target" } } - private fun downloadAndUnzip( - cocoaVersion: String, - isStatic: Boolean, - ): File { + private fun downloadAndUnzip(cocoaVersion: String, isStatic: Boolean): File { val tempDir = Files.createTempDirectory("sentry-cocoa-test").toFile() tempDir.deleteOnExit() @@ -161,19 +157,13 @@ class SentryFrameworkArchitectureTest { // Download val xcFrameworkZip = if (isStatic) "Sentry.xcframework.zip" else "Sentry-Dynamic.xcframework.zip" val downloadLink = - if (cocoaVersion == - "latest" - ) { - "https://github.com/getsentry/sentry-cocoa/releases/latest/download/$xcFrameworkZip" - } else { - "https://github.com/getsentry/sentry-cocoa/releases/download/$cocoaVersion/$xcFrameworkZip" - } + if (cocoaVersion == "latest") "https://github.com/getsentry/sentry-cocoa/releases/latest/download/$xcFrameworkZip" else "https://github.com/getsentry/sentry-cocoa/releases/download/$cocoaVersion/$xcFrameworkZip" val url = URL(downloadLink) url.openStream().use { input -> Files.copy( input, targetFile.toPath(), - StandardCopyOption.REPLACE_EXISTING, + StandardCopyOption.REPLACE_EXISTING ) } diff --git a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt index 052634e5f..5af06837e 100644 --- a/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt +++ b/sentry-kotlin-multiplatform-gradle-plugin/src/test/java/io/sentry/kotlin/multiplatform/gradle/SentryPluginTest.kt @@ -136,11 +136,10 @@ class SentryPluginTest { project.installSentryForKmp(project.extensions.getByName("commonMain") as SourceSetAutoInstallExtension) - val sentryDependencies = - project.configurations - .flatMap { it.dependencies } - .filter { it.group == "io.sentry" && it.name == "sentry-kotlin-multiplatform" } - .toList() + val sentryDependencies = project.configurations + .flatMap { it.dependencies } + .filter { it.group == "io.sentry" && it.name == "sentry-kotlin-multiplatform" } + .toList() assertTrue(sentryDependencies.isNotEmpty()) diff --git a/sentry-kotlin-multiplatform/build.gradle.kts b/sentry-kotlin-multiplatform/build.gradle.kts index 52de40bd6..f07abb7cc 100644 --- a/sentry-kotlin-multiplatform/build.gradle.kts +++ b/sentry-kotlin-multiplatform/build.gradle.kts @@ -181,7 +181,7 @@ kotlin { tvosX64(), tvosSimulatorArm64(), macosX64(), - macosArm64(), + macosArm64() ).forEach { it.compilations.getByName("main") { cinterops.create("Sentry.Internal") { @@ -203,7 +203,7 @@ kotlin { "-compiler-option", "-DSentryIntegrationProtocol=SentryIntegrationProtocolUnavailable", "-compiler-option", - "-DSentryMetricsAPIDelegate=SentryMetricsAPIDelegateUnavailable", + "-DSentryMetricsAPIDelegate=SentryMetricsAPIDelegateUnavailable" ) } diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/Context.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/Context.android.kt index 4180fdcfc..aa0d51e77 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/Context.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/Context.android.kt @@ -37,7 +37,7 @@ internal class SentryContextProvider : ContentProvider() { projection: Array?, selection: String?, selectionArgs: Array?, - sortOrder: String?, + sortOrder: String? ): Cursor? { error("Not allowed.") } @@ -46,18 +46,11 @@ internal class SentryContextProvider : ContentProvider() { error("Not allowed.") } - override fun insert( - uri: Uri, - values: ContentValues?, - ): Uri? { + override fun insert(uri: Uri, values: ContentValues?): Uri? { error("Not allowed.") } - override fun delete( - uri: Uri, - selection: String?, - selectionArgs: Array?, - ): Int { + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int { error("Not allowed.") } @@ -65,7 +58,7 @@ internal class SentryContextProvider : ContentProvider() { uri: Uri, values: ContentValues?, selection: String?, - selectionArgs: Array?, + selectionArgs: Array? ): Int { error("Not allowed.") } diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt index 4126ebc56..0cd4779d5 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformInstance.android.kt @@ -4,11 +4,10 @@ import io.sentry.android.core.SentryAndroid internal actual class SentryPlatformInstance : SentryInstance { actual override fun init(configuration: PlatformOptionsConfiguration) { - val context = - applicationContext ?: run { - // TODO: add logging later - return - } + val context = applicationContext ?: run { + // TODO: add logging later + return + } SentryAndroid.init(context, configuration) } diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt index fdbbbfc95..8fa945fe5 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.android.kt @@ -13,7 +13,8 @@ internal actual fun SentryPlatformOptions.prepareForInit() { nativeSdkName = BuildKonfig.SENTRY_KMP_NATIVE_ANDROID_SDK_NAME } -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toAndroidSentryOptionsCallback() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + toAndroidSentryOptionsCallback() internal actual fun SentryPlatformOptions.prepareForInitBridge() { prepareForInit() diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt index 44ade8df1..910d6706d 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt @@ -8,37 +8,36 @@ import io.sentry.kotlin.multiplatform.SentryOptions import io.sentry.kotlin.multiplatform.SentryReplayOptions import kotlin.collections.forEach as kForEach -internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = - { androidOptions -> - val kmpOptions = this +internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = { androidOptions -> + val kmpOptions = this - // Apply base options available to all JVM targets - androidOptions.applyJvmBaseOptions(kmpOptions) + // Apply base options available to all JVM targets + androidOptions.applyJvmBaseOptions(kmpOptions) - // Apply Android specific options - androidOptions.isAttachScreenshot = kmpOptions.attachScreenshot - androidOptions.isAttachViewHierarchy = kmpOptions.attachViewHierarchy - androidOptions.isAnrEnabled = kmpOptions.isAnrEnabled - androidOptions.anrTimeoutIntervalMillis = kmpOptions.anrTimeoutIntervalMillis + // Apply Android specific options + androidOptions.isAttachScreenshot = kmpOptions.attachScreenshot + androidOptions.isAttachViewHierarchy = kmpOptions.attachViewHierarchy + androidOptions.isAnrEnabled = kmpOptions.isAnrEnabled + androidOptions.anrTimeoutIntervalMillis = kmpOptions.anrTimeoutIntervalMillis - // Replay options - androidOptions.sessionReplay.maskAllText = - kmpOptions.sessionReplay.maskAllText - androidOptions.sessionReplay.maskAllImages = - kmpOptions.sessionReplay.maskAllImages - androidOptions.sessionReplay.sessionSampleRate = - kmpOptions.sessionReplay.sessionSampleRate - androidOptions.sessionReplay.onErrorSampleRate = - kmpOptions.sessionReplay.onErrorSampleRate - androidOptions.sessionReplay.quality = - kmpOptions.sessionReplay.quality.toAndroidSentryQuality() + // Replay options + androidOptions.sessionReplay.maskAllText = + kmpOptions.sessionReplay.maskAllText + androidOptions.sessionReplay.maskAllImages = + kmpOptions.sessionReplay.maskAllImages + androidOptions.sessionReplay.sessionSampleRate = + kmpOptions.sessionReplay.sessionSampleRate + androidOptions.sessionReplay.onErrorSampleRate = + kmpOptions.sessionReplay.onErrorSampleRate + androidOptions.sessionReplay.quality = + kmpOptions.sessionReplay.quality.toAndroidSentryQuality() - // kForEach solves an issue with linter where it thinks forEach is the Java version - // see here: https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/68897591#68897591 - this.sdk?.packages?.kForEach { sdkPackage -> - androidOptions.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) - } + // kForEach solves an issue with linter where it thinks forEach is the Java version + // see here: https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/68897591#68897591 + this.sdk?.packages?.kForEach { sdkPackage -> + androidOptions.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) } +} internal fun SentryReplayOptions.Quality.toAndroidSentryQuality(): JvmSentryReplayQuality { val kmpQuality = this diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 72647c512..d32877340 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -9,7 +9,6 @@ import kotlin.test.BeforeTest actual abstract class BaseSentryTest { actual val platform: String = "Android" actual val authToken: String? = System.getenv("SENTRY_AUTH_TOKEN") - actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt index 089741e7a..22e4774f3 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt @@ -17,9 +17,8 @@ actual interface PlatformOptions : CommonPlatformOptions { val sessionReplay: AndroidSentryReplayOptions } -class SentryAndroidOptionsWrapper( - private val androidOptions: SentryAndroidOptions, -) : PlatformOptions { +class SentryAndroidOptionsWrapper(private val androidOptions: SentryAndroidOptions) : + PlatformOptions { override val dsn: String? get() = androidOptions.dsn @@ -85,7 +84,8 @@ class SentryAndroidOptionsWrapper( } } -actual fun createPlatformOptions(): PlatformOptions = SentryAndroidOptionsWrapper(SentryAndroidOptions()) +actual fun createPlatformOptions(): PlatformOptions = + SentryAndroidOptionsWrapper(SentryAndroidOptions()) actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptions) { val androidOptions = this @@ -99,36 +99,35 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio kmpReplayOptions.maskAllText, androidOptions.sessionReplay.maskViewClasses, androidOptions.sessionReplay.unmaskViewClasses, - AndroidSentryReplayOptions.TEXT_VIEW_CLASS_NAME, + AndroidSentryReplayOptions.TEXT_VIEW_CLASS_NAME ) assertViewClassMasking( kmpReplayOptions.maskAllImages, androidOptions.sessionReplay.maskViewClasses, androidOptions.sessionReplay.unmaskViewClasses, - AndroidSentryReplayOptions.IMAGE_VIEW_CLASS_NAME, + AndroidSentryReplayOptions.IMAGE_VIEW_CLASS_NAME ) assertEquals( androidOptions.sessionReplay.onErrorSampleRate, - kmpReplayOptions.onErrorSampleRate, + kmpReplayOptions.onErrorSampleRate ) assertEquals( androidOptions.sessionReplay.sessionSampleRate, - kmpReplayOptions.sessionSampleRate, + kmpReplayOptions.sessionSampleRate ) assertEquals(androidOptions.sessionReplay.quality.name, kmpReplayOptions.quality.name) assertEquals(androidOptions.proguardUuid, kmpOptions.proguardUuid) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - it.dsn = fakeDsn - } +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + it.dsn = fakeDsn +} private fun assertViewClassMasking( kmpMaskAll: Boolean, maskViewClasses: Collection, unmaskViewClasses: Collection, - viewClassName: String, + viewClassName: String ) { if (kmpMaskAll) { assertContains(maskViewClasses, viewClassName) diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt index ccf7cf462..49981170d 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/SentryAndroidBridgeTest.kt @@ -19,10 +19,9 @@ class SentryAndroidBridgeTest { sut.init { } - val option = - SentryPlatformOptions().apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + } assertEquals(BuildKonfig.SENTRY_KMP_NATIVE_ANDROID_SDK_NAME, option.nativeSdkName) } @@ -31,5 +30,7 @@ class SentryAndroidBridgeTest { internal class Fixture { val sentryInstance = FakeSentryInstance() - fun getSut(): SentryBridge = SentryBridge(sentryInstance) + fun getSut(): SentryBridge { + return SentryBridge(sentryInstance) + } } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt index ecd4d94d5..d69637cc4 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.apple.kt @@ -4,6 +4,7 @@ import io.sentry.kotlin.multiplatform.extensions.toByteArray import io.sentry.kotlin.multiplatform.extensions.toNSData public actual class Attachment { + internal lateinit var cocoaAttachment: CocoaAttachment public actual val filename: String @@ -19,8 +20,9 @@ public actual class Attachment { get() = cocoaAttachment.contentType public actual companion object { - public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment = - Attachment(screenshotBytes, "screenshot.png", "image/png") + public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment { + return Attachment(screenshotBytes, "screenshot.png", "image/png") + } } public actual constructor(pathname: String) { diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt index 09cb37989..88870d1ee 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt @@ -9,9 +9,7 @@ import io.sentry.kotlin.multiplatform.extensions.toMutableMap import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User -internal class CocoaScopeProvider( - private val scope: CocoaScope, -) : Scope { +internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope { /* This bridge exposes private Cocoa SDK API to fetch internal properties such as user, level, etc. We need this in order to return properties because the Cocoa SDK doesn't implement getters. @@ -64,17 +62,11 @@ internal class CocoaScopeProvider( scope.clearBreadcrumbs() } - private fun setContextForPrimitiveValues( - key: String, - value: Any, - ) { + private fun setContextForPrimitiveValues(key: String, value: Any) { scope.setContextValue(mapOf("value" to value), key) } - override fun setContext( - key: String, - value: Any, - ) { + override fun setContext(key: String, value: Any) { try { (value as? Map)?.let { scope.setContextValue(it, key) @@ -84,45 +76,27 @@ internal class CocoaScopeProvider( } } - override fun setContext( - key: String, - value: String, - ) { + override fun setContext(key: String, value: String) { setContextForPrimitiveValues(key, value) } - override fun setContext( - key: String, - value: Boolean, - ) { + override fun setContext(key: String, value: Boolean) { setContextForPrimitiveValues(key, value) } - override fun setContext( - key: String, - value: Number, - ) { + override fun setContext(key: String, value: Number) { setContextForPrimitiveValues(key, value) } - override fun setContext( - key: String, - value: Char, - ) { + override fun setContext(key: String, value: Char) { setContextForPrimitiveValues(key, value) } - override fun setContext( - key: String, - value: Array<*>, - ) { + override fun setContext(key: String, value: Array<*>) { setContextForPrimitiveValues(key, value) } - override fun setContext( - key: String, - value: Collection<*>, - ) { + override fun setContext(key: String, value: Collection<*>) { setContextForPrimitiveValues(key, value) } @@ -130,10 +104,7 @@ internal class CocoaScopeProvider( scope.removeContextForKey(key) } - override fun setTag( - key: String, - value: String, - ) { + override fun setTag(key: String, value: String) { scope.setTagValue(value, key) } @@ -141,10 +112,7 @@ internal class CocoaScopeProvider( scope.removeTagForKey(key) } - override fun setExtra( - key: String, - value: String, - ) { + override fun setExtra(key: String, value: String) { scope.setExtraValue(value, key) } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt index 9026e5ee3..bc02c9f24 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt @@ -47,15 +47,10 @@ internal actual fun SentryPlatformOptions.prepareForInit() { PrivateSentrySDKOnly.setSdkName(BuildKonfig.SENTRY_KMP_COCOA_SDK_NAME, BuildKonfig.VERSION_NAME) } -internal actual class SentryBridge actual constructor( - private val sentryInstance: SentryInstance, -) { +internal actual class SentryBridge actual constructor(private val sentryInstance: SentryInstance) { private val logger = CocoaSentryLoggerAdapter(SentrySDK::logger) - actual fun init( - context: Context, - configuration: OptionsConfiguration, - ) { + actual fun init(context: Context, configuration: OptionsConfiguration) { init(configuration) } @@ -79,35 +74,27 @@ internal actual class SentryBridge actual constructor( return SentryId(cocoaSentryId.toString()) } - actual fun captureMessage( - message: String, - scopeCallback: ScopeCallback, - ): SentryId { + actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { val cocoaSentryId = SentrySDK.captureMessage(message, configureScopeCallback(scopeCallback)) return SentryId(cocoaSentryId.toString()) } actual fun captureException(throwable: Throwable): SentryId { - val event = - throwable.asSentryEvent( - level = kSentryLevelError, - isHandled = true, - markThreadAsCrashed = false, - ) + val event = throwable.asSentryEvent( + level = kSentryLevelError, + isHandled = true, + markThreadAsCrashed = false + ) val cocoaSentryId = SentrySDK.captureEvent(event) return SentryId(cocoaSentryId.toString()) } - actual fun captureException( - throwable: Throwable, - scopeCallback: ScopeCallback, - ): SentryId { - val event = - throwable.asSentryEvent( - level = kSentryLevelError, - isHandled = true, - markThreadAsCrashed = false, - ) + actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { + val event = throwable.asSentryEvent( + level = kSentryLevelError, + isHandled = true, + markThreadAsCrashed = false + ) val cocoaSentryId = SentrySDK.captureEvent(event, configureScopeCallback(scopeCallback)) return SentryId(cocoaSentryId.toString()) } @@ -128,26 +115,32 @@ internal actual class SentryBridge actual constructor( SentrySDK.setUser(user?.toCocoaUser()) } - actual fun isCrashedLastRun(): Boolean = SentrySDK.crashedLastRun() + actual fun isCrashedLastRun(): Boolean { + return SentrySDK.crashedLastRun() + } - actual fun isEnabled(): Boolean = SentrySDK.isEnabled() + actual fun isEnabled(): Boolean { + return SentrySDK.isEnabled() + } actual fun close() { SentrySDK.close() } - private fun configureScopeCallback(scopeCallback: ScopeCallback): (CocoaScope?) -> Unit = - { cocoaScope -> - val cocoaScopeProvider = - cocoaScope?.let { - CocoaScopeProvider(it) - } + private fun configureScopeCallback(scopeCallback: ScopeCallback): (CocoaScope?) -> Unit { + return { cocoaScope -> + val cocoaScopeProvider = cocoaScope?.let { + CocoaScopeProvider(it) + } cocoaScopeProvider?.let { scopeCallback.invoke(it) } } + } - actual fun logger(): SentryLogger = logger + actual fun logger(): SentryLogger { + return logger + } } @Suppress("unused") diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt index f677a9afe..45c14ff9a 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryEvent.apple.kt @@ -38,20 +38,14 @@ public actual class SentryEvent actual constructor() : SentryBaseEvent() { val cocoaFingerprint = cocoaSentryEvent.fingerprint()?.toMutableList() as? MutableList val cocoaSentryExceptions = - cocoaSentryEvent.exceptions - ?.map { (it as CocoaSentryException).toKmpSentryException() } + cocoaSentryEvent.exceptions?.map { (it as CocoaSentryException).toKmpSentryException() } ?.toMutableList() val cocoaContexts = cocoaSentryEvent.context?.mapKeys { it.key as String }?.mapValues { it.value as Any } - val cocoaBreadcrumbs = - cocoaSentryEvent.breadcrumbs - ?.mapNotNull { it as? CocoaBreadcrumb } - ?.map { it.toKmpBreadcrumb() } - ?.toMutableList() + val cocoaBreadcrumbs = cocoaSentryEvent.breadcrumbs?.mapNotNull { it as? CocoaBreadcrumb } + ?.map { it.toKmpBreadcrumb() }?.toMutableList() val cocoaTags = - cocoaSentryEvent.tags - ?.mapKeys { it.key as String } - ?.mapValues { it.value as String } + cocoaSentryEvent.tags?.mapKeys { it.key as String }?.mapValues { it.value as String } ?.toMutableMap() cocoaFingerprint?.let { fingerprint = it } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt index 2006f121b..385d2af41 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.apple.kt @@ -3,25 +3,23 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaBreadcrumb import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -internal fun Breadcrumb.toCocoaBreadcrumb() = - CocoaBreadcrumb().apply { - val scope = this@toCocoaBreadcrumb - setMessage(scope.message) - setType(scope.type) - scope.category?.let { setCategory(it) } - scope.level?.let { setLevel(it.toCocoaSentryLevel()) } - setData(scope.getData()?.toMap()) - } +internal fun Breadcrumb.toCocoaBreadcrumb() = CocoaBreadcrumb().apply { + val scope = this@toCocoaBreadcrumb + setMessage(scope.message) + setType(scope.type) + scope.category?.let { setCategory(it) } + scope.level?.let { setLevel(it.toCocoaSentryLevel()) } + setData(scope.getData()?.toMap()) +} -internal fun CocoaBreadcrumb.toKmpBreadcrumb() = - Breadcrumb().apply { - val scope = this@toKmpBreadcrumb - message = scope.message - type = scope.type - category = scope.category - val map = scope.data as? Map - map?.let { - this.setData(it.toMutableMap()) - } - level = scope.level.toKmpSentryLevel() +internal fun CocoaBreadcrumb.toKmpBreadcrumb() = Breadcrumb().apply { + val scope = this@toKmpBreadcrumb + message = scope.message + type = scope.type + category = scope.category + val map = scope.data as? Map + map?.let { + this.setData(it.toMutableMap()) } + level = scope.level.toKmpSentryLevel() +} diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt index f9d5fde39..8788c4b44 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/FoundationExtensions.kt @@ -20,17 +20,15 @@ internal fun NSMutableDictionary.toMutableMap(): MutableMap { return map } -internal fun NSData.toByteArray(): ByteArray = - ByteArray(this@toByteArray.length.toInt()).apply { - usePinned { - memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) - } +internal fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply { + usePinned { + memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) } +} -internal fun ByteArray.toNSData(): NSData = - memScoped { - NSData.create( - bytes = allocArrayOf(this@toNSData), - length = this@toNSData.size.toULong().convert(), - ) - } +internal fun ByteArray.toNSData(): NSData = memScoped { + NSData.create( + bytes = allocArrayOf(this@toNSData), + length = this@toNSData.size.toULong().convert() + ) +} diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt index f723b6556..c605f9025 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.apple.kt @@ -3,12 +3,11 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaMessage import io.sentry.kotlin.multiplatform.protocol.Message -internal fun CocoaMessage.toKmpMessage() = - Message( - message = message, - params = params as? List, - formatted = formatted, - ) +internal fun CocoaMessage.toKmpMessage() = Message( + message = message, + params = params as? List, + formatted = formatted +) internal fun Message.toCocoaMessage(): CocoaMessage { val scope = this@toCocoaMessage diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt index 4dd0cac7f..d811f745f 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.apple.kt @@ -3,10 +3,9 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaSentryException import io.sentry.kotlin.multiplatform.protocol.SentryException -internal fun CocoaSentryException.toKmpSentryException() = - SentryException( - type = type, - value = value, - module = module, - threadId = threadId?.longLongValue, // longLong represents a 64-bit integer like Kotlin Long - ) +internal fun CocoaSentryException.toKmpSentryException() = SentryException( + type = type, + value = value, + module = module, + threadId = threadId?.longLongValue // longLong represents a 64-bit integer like Kotlin Long +) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt index 583554ed5..40d528167 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt @@ -11,10 +11,9 @@ import io.sentry.kotlin.multiplatform.setEnableUnhandledCppExceptionMonitoring import kotlinx.cinterop.convert import platform.Foundation.NSNumber -internal fun SentryOptions.toCocoaOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = - { - it?.applyCocoaBaseOptions(this) - } +internal fun SentryOptions.toCocoaOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = { + it?.applyCocoaBaseOptions(this) +} /** * Applies the given options to this CocoaSentryOptions. @@ -66,12 +65,9 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(kmpOptions: SentryOptions) cocoaOptions.beforeSend = { event -> val sdk = event?.sdk?.toMutableMap() - val packages = - kmpOptions.sdk - ?.packages - ?.map { - mapOf("name" to it.name, "version" to it.version) - }?.toMutableList() ?: mutableListOf() + val packages = kmpOptions.sdk?.packages?.map { + mapOf("name" to it.name, "version" to it.version) + }?.toMutableList() ?: mutableListOf() sdk?.set("packages", packages) @@ -91,20 +87,17 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(kmpOptions: SentryOptions) if (kmpOptions.beforeBreadcrumb == null) { cocoaBreadcrumb } else { - cocoaBreadcrumb - ?.toKmpBreadcrumb() - ?.let { kmpOptions.beforeBreadcrumb?.invoke(it) } - ?.toCocoaBreadcrumb() + cocoaBreadcrumb?.toKmpBreadcrumb() + ?.let { kmpOptions.beforeBreadcrumb?.invoke(it) }?.toCocoaBreadcrumb() } } cocoaOptions.enableCaptureFailedRequests = kmpOptions.enableCaptureFailedRequests cocoaOptions.failedRequestTargets = kmpOptions.failedRequestTargets - cocoaOptions.failedRequestStatusCodes = - kmpOptions.failedRequestStatusCodes.map { - SentryHttpStatusCodeRange( - min = it.min.convert(), - max = it.max.convert(), - ) - } + cocoaOptions.failedRequestStatusCodes = kmpOptions.failedRequestStatusCodes.map { + SentryHttpStatusCodeRange( + min = it.min.convert(), + max = it.max.convert() + ) + } } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt index d8d7bfe81..b2af2f828 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.apple.kt @@ -3,20 +3,18 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.CocoaUser import io.sentry.kotlin.multiplatform.protocol.User -internal fun User.toCocoaUser() = - CocoaUser().apply { - val scope = this@toCocoaUser - userId = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - } +internal fun User.toCocoaUser() = CocoaUser().apply { + val scope = this@toCocoaUser + userId = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress +} -internal fun CocoaUser.toKmpUser() = - User().apply { - val scope = this@toKmpUser - id = scope.userId - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - } +internal fun CocoaUser.toKmpUser() = User().apply { + val scope = this@toKmpUser + id = scope.userId + username = scope.username + email = scope.email + ipAddress = scope.ipAddress +} diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt index 1f1dee42c..86a4ec47f 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/CocoaSentryLoggerAdapter.kt @@ -11,12 +11,9 @@ import cocoapods.Sentry.SentryLogger as CocoaSentryLogger */ internal class CocoaSentryLoggerAdapter( private val cocoaLoggerProvider: () -> CocoaSentryLogger, - logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory, + logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory ) : BaseSentryLogger(logBuilderFactory) { - override fun sendLog( - level: SentryLogLevel, - formatted: FormattedLog, - ) { + override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { val cocoaLogger = cocoaLoggerProvider() val attributes = formatted.attributes.toCocoaMap() when (level) { diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt index ed235ec50..d2043b5d6 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.apple.kt @@ -13,53 +13,47 @@ import io.sentry.kotlin.multiplatform.SentryAttributes as KmpSentryAttributes * Converts Cocoa SDK's [CocoaSentryLogLevel] to KMP [SentryLogLevel]. */ @Suppress("MagicNumber") -internal fun CocoaSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = - when (this.convert()) { - 0 -> SentryLogLevel.TRACE - 1 -> SentryLogLevel.DEBUG - 2 -> SentryLogLevel.INFO - 3 -> SentryLogLevel.WARN - 4 -> SentryLogLevel.ERROR - 5 -> SentryLogLevel.FATAL - else -> SentryLogLevel.DEBUG - } +internal fun CocoaSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = when (this.convert()) { + 0 -> SentryLogLevel.TRACE + 1 -> SentryLogLevel.DEBUG + 2 -> SentryLogLevel.INFO + 3 -> SentryLogLevel.WARN + 4 -> SentryLogLevel.ERROR + 5 -> SentryLogLevel.FATAL + else -> SentryLogLevel.DEBUG +} /** * Converts KMP's [SentryLogLevel] to Cocoa SDK's [CocoaSentryLogLevel]. */ @Suppress("MagicNumber") -internal fun SentryLogLevel.toCocoaSentryLogLevel(): CocoaSentryLogLevel = - when (this) { - SentryLogLevel.TRACE -> 0.convert() - SentryLogLevel.DEBUG -> 1.convert() - SentryLogLevel.INFO -> 2.convert() - SentryLogLevel.WARN -> 3.convert() - SentryLogLevel.ERROR -> 4.convert() - SentryLogLevel.FATAL -> 5.convert() - } +internal fun SentryLogLevel.toCocoaSentryLogLevel(): CocoaSentryLogLevel = when (this) { + SentryLogLevel.TRACE -> 0.convert() + SentryLogLevel.DEBUG -> 1.convert() + SentryLogLevel.INFO -> 2.convert() + SentryLogLevel.WARN -> 3.convert() + SentryLogLevel.ERROR -> 4.convert() + SentryLogLevel.FATAL -> 5.convert() +} /** * Converts a Cocoa SentryLog to a KMP SentryLog for use in beforeSendLog callback. * After the callback, changes are applied back via [updateFrom]. */ -internal fun CocoaSentryLog.toKmpSentryLog(): SentryLog = - SentryLog( - timestamp = timestamp().timeIntervalSince1970, - level = level().toKmpSentryLogLevel(), - body = body(), - severityNumber = severityNumber()?.intValue, - attributes = toKmpSentryAttributes(), - ) +internal fun CocoaSentryLog.toKmpSentryLog(): SentryLog = SentryLog( + timestamp = timestamp().timeIntervalSince1970, + level = level().toKmpSentryLogLevel(), + body = body(), + severityNumber = severityNumber()?.intValue, + attributes = toKmpSentryAttributes() +) /** * Updates this Cocoa SentryLog from a KMP SentryLog. * @param kmpLog The modified KMP log after user's beforeSendLog callback. * @param originalKmpAttributes The original KMP attributes before the callback, used to detect changes. */ -internal fun CocoaSentryLog.updateFrom( - kmpLog: SentryLog, - originalKmpAttributes: KmpSentryAttributes, -) { +internal fun CocoaSentryLog.updateFrom(kmpLog: SentryLog, originalKmpAttributes: KmpSentryAttributes) { setBody(kmpLog.body) setLevel(kmpLog.level.toCocoaSentryLogLevel()) setSeverityNumber(kmpLog.severityNumber?.let { NSNumber(int = it) }) @@ -74,7 +68,8 @@ private fun CocoaSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { attributes() .mapNotNull { (key, value) -> (key as? String)?.let { it to (value as? SentryStructuredLogAttribute) } - }.forEach { (key, attribute) -> + } + .forEach { (key, attribute) -> attribute ?: return@forEach when (attribute.type()) { "string" -> kmpAttributes[key] = attribute.value() as String @@ -91,7 +86,7 @@ private fun CocoaSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { */ private fun CocoaSentryLog.updateAttributesFrom( modifiedKmpAttributes: KmpSentryAttributes, - originalKmpAttributes: KmpSentryAttributes, + originalKmpAttributes: KmpSentryAttributes ) { val mergedAttributes = attributes().toMutableMap() @@ -99,14 +94,13 @@ private fun CocoaSentryLog.updateAttributesFrom( (originalKmpAttributes.keys - modifiedKmpAttributes.keys).forEach { mergedAttributes.remove(it) } modifiedKmpAttributes.forEach { (key, attrValue) -> - mergedAttributes[key] = - when (attrValue) { - is SentryAttributeValue.LongValue -> - SentryStructuredLogAttribute(integer = (attrValue.value as Long).convert()) - is SentryAttributeValue.DoubleValue -> SentryStructuredLogAttribute(double = attrValue.value as Double) - is SentryAttributeValue.StringValue -> SentryStructuredLogAttribute(string = attrValue.value as String) - is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) - } + mergedAttributes[key] = when (attrValue) { + is SentryAttributeValue.LongValue -> + SentryStructuredLogAttribute(integer = (attrValue.value as Long).convert()) + is SentryAttributeValue.DoubleValue -> SentryStructuredLogAttribute(double = attrValue.value as Double) + is SentryAttributeValue.StringValue -> SentryStructuredLogAttribute(string = attrValue.value as String) + is SentryAttributeValue.BooleanValue -> SentryStructuredLogAttribute(boolean = attrValue.value as Boolean) + } } setAttributes(mergedAttributes) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt index 686139800..3ea684d84 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/NSException.kt @@ -26,19 +26,17 @@ import kotlin.reflect.KClass * of the [causes][Throwable.cause] will be appended, else causes are ignored. */ internal fun Throwable.asNSException(appendCausedBy: Boolean = false): NSException { - val returnAddresses = - getFilteredStackTraceAddresses() - .let { addresses -> - if (!appendCausedBy) return@let addresses - addresses.toMutableList().apply { - for (cause in causes) { - addAll(cause.getFilteredStackTraceAddresses(true, addresses)) - } - } - }.map { - @Suppress("RemoveExplicitTypeArguments") - NSNumber(unsignedInteger = it.convert()) + val returnAddresses = getFilteredStackTraceAddresses().let { addresses -> + if (!appendCausedBy) return@let addresses + addresses.toMutableList().apply { + for (cause in causes) { + addAll(cause.getFilteredStackTraceAddresses(true, addresses)) } + } + }.map { + @Suppress("RemoveExplicitTypeArguments") + NSNumber(unsignedInteger = it.convert()) + } return ThrowableNSException(name, getReason(appendCausedBy), returnAddresses) } @@ -70,7 +68,7 @@ internal fun Throwable.getReason(appendCausedBy: Boolean = false): String? { internal class ThrowableNSException( name: String, reason: String?, - private val returnAddresses: List, + private val returnAddresses: List ) : NSException(name, reason, null) { override fun callStackReturnAddresses(): List = returnAddresses } diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt index 0bc0210d3..040d22132 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt @@ -39,15 +39,15 @@ private typealias CocoapodsSentryEnvelopeItem = cocoapods.Sentry.SentryEnvelopeI /** * Drops the Kotlin crash that follows an unhandled Kotlin exception except our custom SentryEvent. */ -internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentryEvent? = - event?.takeUnless { - (it as InternalSentryEvent).isFatalEvent && - ( - it.tags?.containsKey( - KOTLIN_CRASH_TAG, - ) ?: false +internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentryEvent? { + return event?.takeUnless { + (it as InternalSentryEvent).isFatalEvent && ( + it.tags?.containsKey( + KOTLIN_CRASH_TAG + ) ?: false ) } +} /** * Sets the unhandled exception hook such that all unhandled exceptions are logged to Sentry as fatal exceptions. @@ -55,26 +55,25 @@ internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentry * Note: once the exception is logged the program will be terminated. * @see wrapUnhandledExceptionHook */ -public fun setSentryUnhandledExceptionHook(): Unit = - wrapUnhandledExceptionHook { throwable -> - val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter - val handler = crashReporter.uncaughtExceptionHandler +public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook { throwable -> + val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter + val handler = crashReporter.uncaughtExceptionHandler - if (handler != null) { - // This will: - // 1. Write a crash report to disk with ALL synced scope data - // 2. Include tags, user, context, breadcrumbs, etc. - // 3. The crash will be sent on next app launch - handler.invoke(throwable.asNSException(appendCausedBy = true)) - } else { - // Fallback to old approach if handler not available - val envelope = throwable.asSentryEnvelope() - InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) - CocoapodsSentrySDK.configureScope { scope -> - scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) - } + if (handler != null) { + // This will: + // 1. Write a crash report to disk with ALL synced scope data + // 2. Include tags, user, context, breadcrumbs, etc. + // 3. The crash will be sent on next app launch + handler.invoke(throwable.asNSException(appendCausedBy = true)) + } else { + // Fallback to old approach if handler not available + val envelope = throwable.asSentryEnvelope() + InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) + CocoapodsSentrySDK.configureScope { scope -> + scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) } } +} /** * Tag used to mark the Kotlin termination crash. @@ -86,12 +85,10 @@ internal const val KOTLIN_CRASH_TAG = "nsexceptionkt.kotlin_crashed" */ private fun Throwable.asSentryEnvelope(): CocoapodsSentryEnvelope { val event = asSentryEvent() as InternalSentryEvent - val preparedEvent = - InternalSentrySDK.currentHub().let { hub -> - hub - .getClient() - ?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isFatalEvent = true) - } ?: event + val preparedEvent = InternalSentrySDK.currentHub().let { hub -> + hub.getClient() + ?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isFatalEvent = true) + } ?: event val item = CocoapodsSentryEnvelopeItem(event = preparedEvent as cocoapods.Sentry.SentryEvent) // TODO: pass traceState when enabling performance monitoring for KMP SDK val header = CocoapodsSentryEnvelopeHeader(id = preparedEvent.eventId) @@ -109,32 +106,29 @@ private fun Throwable.asSentryEnvelope(): CocoapodsSentryEnvelope { internal fun Throwable.asSentryEvent( level: CocoaSentryLevel = kSentryLevelFatal, isHandled: Boolean = false, - markThreadAsCrashed: Boolean = true, + markThreadAsCrashed: Boolean = true ): CocoapodsSentryEvent = CocoapodsSentryEvent(level).apply { @Suppress("UNCHECKED_CAST") val threads = threadInspector?.getCurrentThreadsWithStackTrace() as List? this.threads = threads - val currentThread = - threads?.firstOrNull { it.current?.boolValue ?: false }?.apply { - if (markThreadAsCrashed) { - setCrashed(NSNumber(true)) - // Crashed threads shouldn't have a stacktrace, the thread_id should be set on the exception instead - // https://develop.sentry.dev/sdk/event-payloads/threads/ - stacktrace = null - } + val currentThread = threads?.firstOrNull { it.current?.boolValue ?: false }?.apply { + if (markThreadAsCrashed) { + setCrashed(NSNumber(true)) + // Crashed threads shouldn't have a stacktrace, the thread_id should be set on the exception instead + // https://develop.sentry.dev/sdk/event-payloads/threads/ + stacktrace = null } - debugMeta = - threads?.let { - InternalSentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads( - it, - ) - } - exceptions = - this@asSentryEvent - .let { throwable -> throwable.causes.asReversed() + throwable } - .map { it.asNSException().asSentryException(currentThread?.threadId, isHandled) } + } + debugMeta = threads?.let { + InternalSentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads( + it + ) + } + exceptions = this@asSentryEvent + .let { throwable -> throwable.causes.asReversed() + throwable } + .map { it.asNSException().asSentryException(currentThread?.threadId, isHandled) } } /** @@ -142,21 +136,18 @@ internal fun Throwable.asSentryEvent( */ private fun NSException.asSentryException( threadId: NSNumber?, - isHandled: Boolean = false, -): CocoapodsSentryException = - CocoapodsSentryException(reason ?: "", name ?: "Throwable").apply { - this.threadId = threadId - mechanism = - CocoapodsSentryMechanism("generic").apply { - setHandled(NSNumber(isHandled)) - } - stacktrace = - threadInspector?.stacktraceBuilder?.let { stacktraceBuilder -> - val cursor = NSExceptionKt_SentryCrashStackCursorFromNSException(this@asSentryException) - val stacktrace = stacktraceBuilder.retrieveStacktraceFromCursor(cursor) - stacktrace as CocoapodsSentryStacktrace - } + isHandled: Boolean = false +): CocoapodsSentryException = CocoapodsSentryException(reason ?: "", name ?: "Throwable").apply { + this.threadId = threadId + mechanism = CocoapodsSentryMechanism("generic").apply { + setHandled(NSNumber(isHandled)) + } + stacktrace = threadInspector?.stacktraceBuilder?.let { stacktraceBuilder -> + val cursor = NSExceptionKt_SentryCrashStackCursorFromNSException(this@asSentryException) + val stacktrace = stacktraceBuilder.retrieveStacktraceFromCursor(cursor) + stacktrace as CocoapodsSentryStacktrace } +} private val threadInspector: InternalSentryThreadInspector? get() = InternalSentrySDK.currentHub().getClient()?.threadInspector diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt index 54249dc0c..27d8f8ec3 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/Throwable.kt @@ -19,15 +19,14 @@ package io.sentry.kotlin.multiplatform.nsexception * The first element will be the cause, the second the cause of the cause, etc. * This function stops once a reference cycles is detected. */ -internal val Throwable.causes: List get() = - buildList { - val causes = mutableSetOf() - var cause = cause - while (cause != null && causes.add(cause)) { - add(cause) - cause = cause.cause - } +internal val Throwable.causes: List get() = buildList { + val causes = mutableSetOf() + var cause = cause + while (cause != null && causes.add(cause)) { + add(cause) + cause = cause.cause } +} /** * Returns a list of stack trace addresses representing @@ -38,14 +37,12 @@ internal val Throwable.causes: List get() = */ internal fun Throwable.getFilteredStackTraceAddresses( keepLastInit: Boolean = false, - commonAddresses: List = emptyList(), -): List = - getStackTraceAddresses() - .dropInitAddresses( - qualifiedClassName = this::class.qualifiedName ?: Throwable::class.qualifiedName!!, - stackTrace = getStackTrace(), - keepLast = keepLastInit, - ).dropCommonAddresses(commonAddresses) + commonAddresses: List = emptyList() +): List = getStackTraceAddresses().dropInitAddresses( + qualifiedClassName = this::class.qualifiedName ?: Throwable::class.qualifiedName!!, + stackTrace = getStackTrace(), + keepLast = keepLastInit +).dropCommonAddresses(commonAddresses) /** * Returns a list containing all addresses expect for the first addresses @@ -55,7 +52,7 @@ internal fun Throwable.getFilteredStackTraceAddresses( internal fun List.dropInitAddresses( qualifiedClassName: String, stackTrace: Array, - keepLast: Boolean = false, + keepLast: Boolean = false ): List { val exceptionInit = "kfun:$qualifiedClassName#" var dropCount = 0 @@ -75,7 +72,9 @@ internal fun List.dropInitAddresses( /** * Returns a list containing all addresses expect for the last addresses that match with the [commonAddresses]. */ -internal fun List.dropCommonAddresses(commonAddresses: List): List { +internal fun List.dropCommonAddresses( + commonAddresses: List +): List { var i = commonAddresses.size if (i == 0) return this diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt index 98f2884cf..9f054bfee 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.apple.kt @@ -2,9 +2,8 @@ package io.sentry.kotlin.multiplatform.protocol import io.sentry.kotlin.multiplatform.CocoaSentryId -public actual data class SentryId actual constructor( - val sentryIdString: String, -) { +public actual data class SentryId actual constructor(val sentryIdString: String) { + public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } @@ -12,13 +11,14 @@ public actual data class SentryId actual constructor( private var cocoaSentryId: CocoaSentryId? = null init { - cocoaSentryId = - if (sentryIdString.isEmpty()) { - CocoaSentryId.empty() - } else { - CocoaSentryId(sentryIdString) - } + cocoaSentryId = if (sentryIdString.isEmpty()) { + CocoaSentryId.empty() + } else { + CocoaSentryId(sentryIdString) + } } - actual override fun toString(): String = cocoaSentryId.toString() + actual override fun toString(): String { + return cocoaSentryId.toString() + } } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt index c2a056b95..9601553be 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/AppleSentryIdTest.kt @@ -5,6 +5,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class AppleSentryIdTest { + @Test fun `Cocoa SentryId with invalid uuid string returns only zeroes`() { val uuidString = "ec720-b6f6-4efc--5c1" diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt index 47120637f..c0f92c77e 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/ApplyKmpEventTest.kt @@ -7,14 +7,12 @@ import kotlin.test.assertEquals class ApplyKmpEventTest { @Test fun `native release is not set if kmp release has same value`() { - val nativeEvent = - FakeSentryEvent().apply { - releaseName = "1.0.0" - } - val kmpEvent = - SentryEvent().apply { - release = "1.0.0" - } + val nativeEvent = FakeSentryEvent().apply { + releaseName = "1.0.0" + } + val kmpEvent = SentryEvent().apply { + release = "1.0.0" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -23,14 +21,12 @@ class ApplyKmpEventTest { @Test fun `native dist is not set if kmp dist has same value`() { - val nativeEvent = - FakeSentryEvent().apply { - dist = "randomDist" - } - val kmpEvent = - SentryEvent().apply { - dist = "randomDist" - } + val nativeEvent = FakeSentryEvent().apply { + dist = "randomDist" + } + val kmpEvent = SentryEvent().apply { + dist = "randomDist" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -39,14 +35,12 @@ class ApplyKmpEventTest { @Test fun `native release is set if kmp release has different value`() { - val nativeEvent = - FakeSentryEvent().apply { - releaseName = "1.0.0" - } - val kmpEvent = - SentryEvent().apply { - release = "7.0.0" - } + val nativeEvent = FakeSentryEvent().apply { + releaseName = "1.0.0" + } + val kmpEvent = SentryEvent().apply { + release = "7.0.0" + } nativeEvent.applyKmpEvent(kmpEvent) @@ -55,14 +49,12 @@ class ApplyKmpEventTest { @Test fun `native dist is set if kmp dist has different value`() { - val nativeEvent = - FakeSentryEvent().apply { - dist = "randomDist" - } - val kmpEvent = - SentryEvent().apply { - dist = "differentDist" - } + val nativeEvent = FakeSentryEvent().apply { + dist = "randomDist" + } + val kmpEvent = SentryEvent().apply { + dist = "differentDist" + } nativeEvent.applyKmpEvent(kmpEvent) diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 49faa3fcd..3fdcc19e0 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,7 +3,6 @@ package io.sentry.kotlin.multiplatform actual abstract class BaseSentryTest { actual val platform: String = "Apple" actual val authToken: String? = "fake-auth-token" - actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index bc10c9cf6..906f89fd9 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -4,16 +4,25 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaBreadcrumb import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -actual data class BreadcrumbTestConverter actual constructor( - val breadcrumb: Breadcrumb, -) { - actual fun getType(): String? = breadcrumb.toCocoaBreadcrumb().type +actual data class BreadcrumbTestConverter actual constructor(val breadcrumb: Breadcrumb) { - actual fun getCategory(): String? = breadcrumb.toCocoaBreadcrumb().category + actual fun getType(): String? { + return breadcrumb.toCocoaBreadcrumb().type + } - actual fun getMessage(): String? = breadcrumb.toCocoaBreadcrumb().message + actual fun getCategory(): String? { + return breadcrumb.toCocoaBreadcrumb().category + } - actual fun getData(): MutableMap = breadcrumb.toCocoaBreadcrumb().data as MutableMap + actual fun getMessage(): String? { + return breadcrumb.toCocoaBreadcrumb().message + } - actual fun getLevel(): SentryLevel? = breadcrumb.toCocoaBreadcrumb().level.toKmpSentryLevel() + actual fun getData(): MutableMap { + return breadcrumb.toCocoaBreadcrumb().data as MutableMap + } + + actual fun getLevel(): SentryLevel? { + return breadcrumb.toCocoaBreadcrumb().level.toKmpSentryLevel() + } } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt index eab1cdb7b..e772fbefb 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.apple.kt @@ -11,9 +11,8 @@ actual interface PlatformOptions : CommonPlatformOptions { val enableUnhandledCppExceptionMonitoring: Boolean } -open class SentryAppleOptionsWrapper( - private val cocoaOptions: CocoaSentryOptions, -) : PlatformOptions { +open class SentryAppleOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : + PlatformOptions { private var cachedEnableUnhandledCppExceptionMonitoring = true override val dsn: String? @@ -95,8 +94,7 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio assertEquals(appleOptions.enableUnhandledCppExceptionMonitoring, kmpOptions.enableUnhandledCppExceptionMonitoring) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - val cocoaOptions = it as CocoaSentryOptions - cocoaOptions.dsn = fakeDsn - } +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + val cocoaOptions = it as CocoaSentryOptions + cocoaOptions.dsn = fakeDsn +} diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt index 3f8c8d60a..578b634b5 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt @@ -4,5 +4,6 @@ import io.sentry.kotlin.multiplatform.log.toCocoaMap class SentryAttributesConversionTest : BaseSentryAttributesConversionTest() { @Suppress("UNCHECKED_CAST") - override fun SentryAttributes.toMap(): Map = toCocoaMap() as Map + override fun SentryAttributes.toMap(): Map = + toCocoaMap() as Map } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt index 18e546fbe..c6b2ebffa 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt @@ -65,11 +65,9 @@ actual class SentryBridgeTest { } // WHEN - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } // THEN assert(option.beforeSend != null) @@ -82,11 +80,9 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } // THEN assert(option.beforeSend != null) @@ -97,12 +93,10 @@ actual class SentryBridgeTest { actual fun `default beforeSend in init does not drop the event after prepareForInit`() { fixture.sut.init { } - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - prepareForInit() - }.let { it as CocoaSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + prepareForInit() + }.let { it as CocoaSentryOptions } assert(option.beforeSend != null) assert(option.beforeSend!!.invoke(CocoaSentryEvent()) != null) @@ -114,11 +108,9 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as CocoaSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as CocoaSentryOptions } val event = option.beforeSend!!.invoke(CocoaSentryEvent()) val packages = event?.sdk()?.get("packages") as? List> diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt index 56b4521be..fbcf20372 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryExceptionTest.kt @@ -11,47 +11,46 @@ class SentryExceptionTest { private val type = "type" private val threadId = 1 - private fun getCocoaSentryException(): CocoaSentryException = CocoaSentryException(value = value, type = type) + private fun getCocoaSentryException(): CocoaSentryException { + return CocoaSentryException(value = value, type = type) + } - private fun getKmpSentryException(threadId: Long? = this.threadId.toLong()): SentryException = - SentryException(value = value, type = type, threadId = threadId) + private fun getKmpSentryException(threadId: Long? = this.threadId.toLong()): SentryException { + return SentryException(value = value, type = type, threadId = threadId) + } @Test fun `SentryException ThreadId NSNumber long conversion`() { - val cocoaSentryException = - getCocoaSentryException().apply { - threadId = NSNumber(long = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = getCocoaSentryException().apply { + threadId = NSNumber(long = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber longLong conversion`() { - val cocoaSentryException = - getCocoaSentryException().apply { - threadId = NSNumber(longLong = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = getCocoaSentryException().apply { + threadId = NSNumber(longLong = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber int conversion`() { - val cocoaSentryException = - getCocoaSentryException().apply { - threadId = NSNumber(int = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = getCocoaSentryException().apply { + threadId = NSNumber(int = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } @Test fun `SentryException ThreadId NSNumber short conversion`() { - val cocoaSentryException = - getCocoaSentryException().apply { - threadId = NSNumber(short = this@SentryExceptionTest.threadId.convert()) - } + val cocoaSentryException = getCocoaSentryException().apply { + threadId = NSNumber(short = this@SentryExceptionTest.threadId.convert()) + } val sentryException = getKmpSentryException() assert(cocoaSentryException.toKmpSentryException() == sentryException) } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index c43e300ef..10ffa1217 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -4,5 +4,7 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaSentryLevel import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel actual class SentryLevelTestConverter actual constructor() { - actual fun convert(sentryLevel: SentryLevel?): SentryLevel? = sentryLevel?.toCocoaSentryLevel()?.toKmpSentryLevel() + actual fun convert(sentryLevel: SentryLevel?): SentryLevel? { + return sentryLevel?.toCocoaSentryLevel()?.toKmpSentryLevel() + } } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt index e8ae58fbd..cbdb5f33d 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackExtensionsTest.kt @@ -7,14 +7,14 @@ import kotlin.test.Test import kotlin.test.assertEquals class UserFeedbackExtensionsTest { + private val sentryIdString = "dcebada57d794590a6da3d1977eed58a" @Test fun `toCocoaUserFeedback correctly maps comments`() { - val userFeedback = - UserFeedback(SentryId(sentryIdString)).apply { - comments = "Test comment" - } + val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { + comments = "Test comment" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -23,10 +23,9 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback correctly maps email`() { - val userFeedback = - UserFeedback(SentryId(sentryIdString)).apply { - email = "test@email.com" - } + val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { + email = "test@email.com" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -35,10 +34,9 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback correctly maps name`() { - val userFeedback = - UserFeedback(SentryId(sentryIdString)).apply { - name = "John Doe" - } + val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { + name = "John Doe" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() @@ -80,12 +78,11 @@ class UserFeedbackExtensionsTest { @Test fun `toCocoaUserFeedback maps all properties correctly`() { - val userFeedback = - UserFeedback(SentryId(sentryIdString)).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error" - } + val userFeedback = UserFeedback(SentryId(sentryIdString)).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error" + } val cocoaUserFeedback = userFeedback.toCocoaUserFeedback() diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt index ae989f8e9..a5a81db20 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/InitAddressesTests.kt @@ -18,17 +18,17 @@ import kotlin.test.Test import kotlin.test.assertEquals class InitAddressesTests { + private val qualifiedClassName = "my.app.CustomException" private val addresses = listOf(0, 1, 2, 3, 4, 5) - private val stackTrace = - arrayOf( - "123 kfun:kotlin.Throwable#(kotlin.String?){} + 24 abc", - "456 kfun:kotlin.Exception#(kotlin.String?){} + 5 def", - "789 kfun:my.app.CustomException#(kotlin.String?){} + 10 hij", - "012 kfun:my.app.CustomException#(){} + 12 klm", - "345 kfun:my.app.class#function1(){} + 50 nop", - "678 kfun:my.app.class#function2(){} + 60 qrs", - ) + private val stackTrace = arrayOf( + "123 kfun:kotlin.Throwable#(kotlin.String?){} + 24 abc", + "456 kfun:kotlin.Exception#(kotlin.String?){} + 5 def", + "789 kfun:my.app.CustomException#(kotlin.String?){} + 10 hij", + "012 kfun:my.app.CustomException#(){} + 12 klm", + "345 kfun:my.app.class#function1(){} + 50 nop", + "678 kfun:my.app.class#function2(){} + 60 qrs" + ) @Test fun testDropInit() { diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt index 9610f75b9..cce236bb8 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableCausesTests.kt @@ -18,6 +18,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableCausesTests { + @Test fun testNoCauses() { assert(Throwable().causes.isEmpty()) @@ -38,9 +39,7 @@ class ThrowableCausesTests { assertEquals(listOf(cause2, cause1), throwable.causes) } - private class MyThrowable( - override val message: String?, - ) : Throwable() { + private class MyThrowable(override val message: String?) : Throwable() { override var cause: Throwable? = null } diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt index 3211bd854..2caeda5c3 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableNameTests.kt @@ -18,6 +18,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableNameTests { + private class MyThrowable : Throwable() @Test diff --git a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt index c1801c86d..d7cb9f90f 100644 --- a/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt +++ b/sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/nsexception/ThrowableReasonTests.kt @@ -18,10 +18,8 @@ import kotlin.test.Test import kotlin.test.assertEquals class ThrowableReasonTests { - private fun testReasonNoCause( - message: String?, - appendCausedBy: Boolean, - ) { + + private fun testReasonNoCause(message: String?, appendCausedBy: Boolean) { val exception = Exception(message) val reason = exception.getReason(appendCausedBy) assertEquals(message, reason) @@ -58,7 +56,7 @@ class ThrowableReasonTests { Test message Caused by: kotlin.Exception: Cause message """.trimIndent(), - reason, + reason ) } @@ -71,7 +69,7 @@ class ThrowableReasonTests { """ Caused by: kotlin.Exception: Cause message """.trimIndent(), - reason, + reason ) } @@ -84,7 +82,7 @@ class ThrowableReasonTests { Test message Caused by: kotlin.Exception """.trimIndent(), - reason, + reason ) } @@ -100,7 +98,7 @@ class ThrowableReasonTests { Caused by: kotlin.Exception: Cause2 message Caused by: kotlin.Exception: Cause1 message """.trimIndent(), - reason, + reason ) } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt index 7dd8a3539..3fd4131f0 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.jvm.kt @@ -1,6 +1,7 @@ package io.sentry.kotlin.multiplatform public actual class Attachment { + internal var jvmAttachment: JvmAttachment public actual val filename: String @@ -16,8 +17,9 @@ public actual class Attachment { get() = jvmAttachment.contentType public actual companion object { - public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment = - Attachment(screenshotBytes, "screenshot.png", "image/png") + public actual fun fromScreenshot(screenshotBytes: ByteArray): Attachment { + return Attachment(screenshotBytes, "screenshot.png", "image/png") + } } public actual constructor(pathname: String) { diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt index 27c03b057..766cf9c7f 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/JvmScopeProvider.kt @@ -9,9 +9,8 @@ import io.sentry.kotlin.multiplatform.extensions.toMap import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User -internal class JvmScopeProvider( - private val scope: JvmIScope, -) : Scope { +internal class JvmScopeProvider(private val scope: JvmIScope) : Scope { + override var level: SentryLevel? set(value) { scope.level = value?.toJvmSentryLevel() @@ -32,9 +31,13 @@ internal class JvmScopeProvider( scope.clearAttachments() } - override fun getContexts(): MutableMap = scope.contexts.toMap().toMutableMap() + override fun getContexts(): MutableMap { + return scope.contexts.toMap().toMutableMap() + } - override fun getTags(): MutableMap = scope.tags + override fun getTags(): MutableMap { + return scope.tags + } override fun addBreadcrumb(breadcrumb: Breadcrumb) { scope.addBreadcrumb(breadcrumb.toJvmBreadcrumb()) @@ -44,52 +47,31 @@ internal class JvmScopeProvider( scope.clearBreadcrumbs() } - override fun setContext( - key: String, - value: Any, - ) { + override fun setContext(key: String, value: Any) { scope.setContexts(key, value) } - override fun setContext( - key: String, - value: Boolean, - ) { + override fun setContext(key: String, value: Boolean) { scope.setContexts(key, value) } - override fun setContext( - key: String, - value: String, - ) { + override fun setContext(key: String, value: String) { scope.setContexts(key, value) } - override fun setContext( - key: String, - value: Number, - ) { + override fun setContext(key: String, value: Number) { scope.setContexts(key, value) } - override fun setContext( - key: String, - value: Collection<*>, - ) { + override fun setContext(key: String, value: Collection<*>) { scope.setContexts(key, value) } - override fun setContext( - key: String, - value: Array<*>, - ) { + override fun setContext(key: String, value: Array<*>) { scope.setContexts(key, value as Array) } - override fun setContext( - key: String, - value: Char, - ) { + override fun setContext(key: String, value: Char) { scope.setContexts(key, value) } @@ -97,10 +79,7 @@ internal class JvmScopeProvider( scope.removeContexts(key) } - override fun setTag( - key: String, - value: String, - ) { + override fun setTag(key: String, value: String) { scope.setTag(key, value) } @@ -108,10 +87,7 @@ internal class JvmScopeProvider( scope.removeTag(key) } - override fun setExtra( - key: String, - value: String, - ) { + override fun setExtra(key: String, value: String) { scope.setExtra(key, value) } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt index c10b32f90..e8a0f8f13 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonJvm.kt @@ -13,15 +13,10 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback internal expect fun SentryPlatformOptions.prepareForInitBridge() -internal actual class SentryBridge actual constructor( - private val sentryInstance: SentryInstance, -) { +internal actual class SentryBridge actual constructor(private val sentryInstance: SentryInstance) { private val logger = JvmSentryLoggerAdapter(Sentry::logger) - actual fun init( - context: Context, - configuration: OptionsConfiguration, - ) { + actual fun init(context: Context, configuration: OptionsConfiguration) { init(configuration) } @@ -44,10 +39,7 @@ internal actual class SentryBridge actual constructor( return SentryId(jvmSentryId.toString()) } - actual fun captureMessage( - message: String, - scopeCallback: ScopeCallback, - ): SentryId { + actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { val jvmSentryId = Sentry.captureMessage(message, configureScopeCallback(scopeCallback)) return SentryId(jvmSentryId.toString()) } @@ -57,10 +49,7 @@ internal actual class SentryBridge actual constructor( return SentryId(jvmSentryId.toString()) } - actual fun captureException( - throwable: Throwable, - scopeCallback: ScopeCallback, - ): SentryId { + actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { val jvmSentryId = Sentry.captureException(throwable, configureScopeCallback(scopeCallback)) return SentryId(jvmSentryId.toString()) @@ -82,19 +71,26 @@ internal actual class SentryBridge actual constructor( Sentry.setUser(user?.toJvmUser()) } - actual fun logger(): SentryLogger = logger + actual fun logger(): SentryLogger { + return logger + } - actual fun isCrashedLastRun(): Boolean = Sentry.isCrashedLastRun() ?: false + actual fun isCrashedLastRun(): Boolean { + return Sentry.isCrashedLastRun() ?: false + } - actual fun isEnabled(): Boolean = Sentry.isEnabled() + actual fun isEnabled(): Boolean { + return Sentry.isEnabled() + } actual fun close() { Sentry.close() } - private fun configureScopeCallback(scopeCallback: ScopeCallback): (JvmIScope) -> Unit = - { + private fun configureScopeCallback(scopeCallback: ScopeCallback): (JvmIScope) -> Unit { + return { val jvmScopeProvider = JvmScopeProvider(it) scopeCallback.invoke(jvmScopeProvider) } + } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt index f15a147b0..b8f18cdbe 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/BreadcrumbExtensions.jvm.kt @@ -3,24 +3,22 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmBreadcrumb import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -internal fun Breadcrumb.toJvmBreadcrumb() = - JvmBreadcrumb().apply { - val scope = this@toJvmBreadcrumb - message = scope.message - type = scope.type - category = scope.category - scope.getData()?.forEach { - setData(it.key, it.value) - } - level = scope.level?.toJvmSentryLevel() +internal fun Breadcrumb.toJvmBreadcrumb() = JvmBreadcrumb().apply { + val scope = this@toJvmBreadcrumb + message = scope.message + type = scope.type + category = scope.category + scope.getData()?.forEach { + setData(it.key, it.value) } + level = scope.level?.toJvmSentryLevel() +} -internal fun JvmBreadcrumb.toKmpBreadcrumb() = - Breadcrumb().apply { - val scope = this@toKmpBreadcrumb - message = scope.message - type = scope.type - category = scope.category - setData(scope.data.toMutableMap()) - level = scope.level?.toKmpSentryLevel() - } +internal fun JvmBreadcrumb.toKmpBreadcrumb() = Breadcrumb().apply { + val scope = this@toKmpBreadcrumb + message = scope.message + type = scope.type + category = scope.category + setData(scope.data.toMutableMap()) + level = scope.level?.toKmpSentryLevel() +} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt index f9c6ef16a..07c5d7c5c 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/MessageExtensions.jvm.kt @@ -3,17 +3,15 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmMessage import io.sentry.kotlin.multiplatform.protocol.Message -internal fun JvmMessage.toKmpMessage() = - Message( - message = message, - params = params, - formatted = formatted, - ) +internal fun JvmMessage.toKmpMessage() = Message( + message = message, + params = params, + formatted = formatted +) -internal fun Message.toJvmMessage() = - JvmMessage().apply { - val scope = this@toJvmMessage - message = scope.message - params = scope.params - formatted = scope.formatted - } +internal fun Message.toJvmMessage() = JvmMessage().apply { + val scope = this@toJvmMessage + message = scope.message + params = scope.params + formatted = scope.formatted +} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt index 278171a76..7fdfcef2d 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryExceptionExtensions.jvm.kt @@ -3,10 +3,9 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmSentryException import io.sentry.kotlin.multiplatform.protocol.SentryException -internal fun JvmSentryException.toKmpSentryException() = - SentryException( - type = type, - value = value, - module = module, - threadId = threadId, - ) +internal fun JvmSentryException.toKmpSentryException() = SentryException( + type = type, + value = value, + module = module, + threadId = threadId +) diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt index 7ac792621..eb039a06c 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryLevelExtensions.jvm.kt @@ -3,20 +3,22 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmSentryLevel import io.sentry.kotlin.multiplatform.SentryLevel -internal fun SentryLevel.toJvmSentryLevel(): JvmSentryLevel? = - when (this) { +internal fun SentryLevel.toJvmSentryLevel(): JvmSentryLevel? { + return when (this) { SentryLevel.DEBUG -> JvmSentryLevel.DEBUG SentryLevel.INFO -> JvmSentryLevel.INFO SentryLevel.WARNING -> JvmSentryLevel.WARNING SentryLevel.ERROR -> JvmSentryLevel.ERROR SentryLevel.FATAL -> JvmSentryLevel.FATAL } +} -internal fun JvmSentryLevel.toKmpSentryLevel(): SentryLevel? = - when (this) { +internal fun JvmSentryLevel.toKmpSentryLevel(): SentryLevel? { + return when (this) { JvmSentryLevel.DEBUG -> SentryLevel.DEBUG JvmSentryLevel.INFO -> SentryLevel.INFO JvmSentryLevel.WARNING -> SentryLevel.WARNING JvmSentryLevel.ERROR -> SentryLevel.ERROR JvmSentryLevel.FATAL -> SentryLevel.FATAL } +} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt index 345265651..f3025ed2b 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt @@ -6,14 +6,13 @@ import io.sentry.kotlin.multiplatform.SentryOptions import io.sentry.kotlin.multiplatform.log.toKmpSentryLog import io.sentry.kotlin.multiplatform.log.updateFrom -internal fun SentryOptions.toJvmSentryOptionsCallback(): (JvmSentryOptions) -> Unit = - { - it.applyJvmBaseOptions(this) +internal fun SentryOptions.toJvmSentryOptionsCallback(): (JvmSentryOptions) -> Unit = { + it.applyJvmBaseOptions(this) - sdk?.packages?.forEach { sdkPackage -> - it.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) - } + sdk?.packages?.forEach { sdkPackage -> + it.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) } +} /** * Applies the given base SentryOptions to this JvmSentryOption diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt index 96a362c44..49f31208e 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/UserExtensions.jvm.kt @@ -3,24 +3,22 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.kotlin.multiplatform.JvmUser import io.sentry.kotlin.multiplatform.protocol.User -internal fun User.toJvmUser() = - JvmUser().apply { - val scope = this@toJvmUser - id = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - data = scope.other?.toMutableMap() - unknown = scope.unknown?.toMutableMap() - } +internal fun User.toJvmUser() = JvmUser().apply { + val scope = this@toJvmUser + id = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + data = scope.other?.toMutableMap() + unknown = scope.unknown?.toMutableMap() +} -internal fun JvmUser.toKmpUser() = - User().apply { - val scope = this@toKmpUser - id = scope.id - username = scope.username - email = scope.email - ipAddress = scope.ipAddress - other = scope.data?.toMutableMap() - unknown = scope.unknown?.toMutableMap() - } +internal fun JvmUser.toKmpUser() = User().apply { + val scope = this@toKmpUser + id = scope.id + username = scope.username + email = scope.email + ipAddress = scope.ipAddress + other = scope.data?.toMutableMap() + unknown = scope.unknown?.toMutableMap() +} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt index cf3e08fb6..e4d58e656 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/JvmSentryLoggerAdapter.kt @@ -11,12 +11,9 @@ import io.sentry.logger.SentryLogParameters */ internal class JvmSentryLoggerAdapter( private val jvmLoggerProvider: () -> ILoggerApi, - logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory, + logBuilderFactory: SentryLogBuilderFactory = DefaultSentryLogBuilderFactory ) : BaseSentryLogger(logBuilderFactory) { - override fun sendLog( - level: SentryLogLevel, - formatted: FormattedLog, - ) { + override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { val jvmLogger = jvmLoggerProvider() val jvmLevel = level.toJvmSentryLogLevel() if (formatted.attributes.isEmpty()) { diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt index 2d22113ae..38934f853 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogConverters.jvm.kt @@ -11,28 +11,26 @@ import io.sentry.kotlin.multiplatform.SentryAttributes as KmpSentryAttributes /** * Converts KMP [SentryLogLevel] to Java SDK's [JvmSentryLogLevel]. */ -internal fun SentryLogLevel.toJvmSentryLogLevel(): JvmSentryLogLevel = - when (this) { - SentryLogLevel.TRACE -> JvmSentryLogLevel.TRACE - SentryLogLevel.DEBUG -> JvmSentryLogLevel.DEBUG - SentryLogLevel.INFO -> JvmSentryLogLevel.INFO - SentryLogLevel.WARN -> JvmSentryLogLevel.WARN - SentryLogLevel.ERROR -> JvmSentryLogLevel.ERROR - SentryLogLevel.FATAL -> JvmSentryLogLevel.FATAL - } +internal fun SentryLogLevel.toJvmSentryLogLevel(): JvmSentryLogLevel = when (this) { + SentryLogLevel.TRACE -> JvmSentryLogLevel.TRACE + SentryLogLevel.DEBUG -> JvmSentryLogLevel.DEBUG + SentryLogLevel.INFO -> JvmSentryLogLevel.INFO + SentryLogLevel.WARN -> JvmSentryLogLevel.WARN + SentryLogLevel.ERROR -> JvmSentryLogLevel.ERROR + SentryLogLevel.FATAL -> JvmSentryLogLevel.FATAL +} /** * Converts Java SDK's [JvmSentryLogLevel] to KMP [SentryLogLevel]. */ -internal fun JvmSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = - when (this) { - JvmSentryLogLevel.TRACE -> SentryLogLevel.TRACE - JvmSentryLogLevel.DEBUG -> SentryLogLevel.DEBUG - JvmSentryLogLevel.INFO -> SentryLogLevel.INFO - JvmSentryLogLevel.WARN -> SentryLogLevel.WARN - JvmSentryLogLevel.ERROR -> SentryLogLevel.ERROR - JvmSentryLogLevel.FATAL -> SentryLogLevel.FATAL - } +internal fun JvmSentryLogLevel.toKmpSentryLogLevel(): SentryLogLevel = when (this) { + JvmSentryLogLevel.TRACE -> SentryLogLevel.TRACE + JvmSentryLogLevel.DEBUG -> SentryLogLevel.DEBUG + JvmSentryLogLevel.INFO -> SentryLogLevel.INFO + JvmSentryLogLevel.WARN -> SentryLogLevel.WARN + JvmSentryLogLevel.ERROR -> SentryLogLevel.ERROR + JvmSentryLogLevel.FATAL -> SentryLogLevel.FATAL +} /** * Converts KMP [KmpSentryAttributes] to Java SDK's [JvmSentryAttributes]. @@ -50,24 +48,20 @@ internal fun KmpSentryAttributes.toJvmSentryAttributes(): JvmSentryAttributes { * Converts a JVM SentryLog to a KMP SentryLog for use in beforeSendLog callback. * After the callback, changes are applied back via [updateFrom]. */ -internal fun JvmSentryLog.toKmpSentryLog(): SentryLog = - SentryLog( - timestamp = timestamp, - level = level.toKmpSentryLogLevel(), - body = body, - severityNumber = severityNumber, - attributes = toKmpSentryAttributes(), - ) +internal fun JvmSentryLog.toKmpSentryLog(): SentryLog = SentryLog( + timestamp = timestamp, + level = level.toKmpSentryLogLevel(), + body = body, + severityNumber = severityNumber, + attributes = toKmpSentryAttributes() +) /** * Updates this JVM SentryLog from a KMP SentryLog. * @param kmpLog The modified KMP log after user's beforeSendLog callback. * @param originalKmpAttributes The original KMP attributes before the callback, used to detect changes. */ -internal fun JvmSentryLog.updateFrom( - kmpLog: SentryLog, - originalKmpAttributes: KmpSentryAttributes, -) { +internal fun JvmSentryLog.updateFrom(kmpLog: SentryLog, originalKmpAttributes: KmpSentryAttributes) { body = kmpLog.body level = kmpLog.level.toJvmSentryLogLevel() severityNumber = kmpLog.severityNumber @@ -101,7 +95,7 @@ private fun JvmSentryLog.toKmpSentryAttributes(): KmpSentryAttributes { */ private fun JvmSentryLog.updateAttributesFrom( modifiedKmpAttributes: KmpSentryAttributes, - originalKmpAttributes: KmpSentryAttributes, + originalKmpAttributes: KmpSentryAttributes ) { // Remove attributes that were deleted by the user (present in original but not in modified) (originalKmpAttributes.keys - modifiedKmpAttributes.keys).forEach { key -> @@ -110,13 +104,12 @@ private fun JvmSentryLog.updateAttributesFrom( // Add or update attributes from the modified KMP attributes modifiedKmpAttributes.forEach { (key, attrValue) -> - val jvmType = - when (attrValue) { - is KmpSentryAttributeValue.StringValue -> JvmSentryAttributeType.STRING - is KmpSentryAttributeValue.LongValue -> JvmSentryAttributeType.INTEGER - is KmpSentryAttributeValue.DoubleValue -> JvmSentryAttributeType.DOUBLE - is KmpSentryAttributeValue.BooleanValue -> JvmSentryAttributeType.BOOLEAN - } + val jvmType = when (attrValue) { + is KmpSentryAttributeValue.StringValue -> JvmSentryAttributeType.STRING + is KmpSentryAttributeValue.LongValue -> JvmSentryAttributeType.INTEGER + is KmpSentryAttributeValue.DoubleValue -> JvmSentryAttributeType.DOUBLE + is KmpSentryAttributeValue.BooleanValue -> JvmSentryAttributeType.BOOLEAN + } setAttribute(key, SentryLogEventAttributeValue(jvmType, attrValue.value)) } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt index a747246c7..1387710ce 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.jvm.kt @@ -2,9 +2,8 @@ package io.sentry.kotlin.multiplatform.protocol import io.sentry.kotlin.multiplatform.JvmSentryId -public actual data class SentryId actual constructor( - val sentryIdString: String, -) { +public actual data class SentryId actual constructor(val sentryIdString: String) { + public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } @@ -12,13 +11,14 @@ public actual data class SentryId actual constructor( private var jvmSentryId: JvmSentryId? = null init { - jvmSentryId = - if (sentryIdString.isEmpty()) { - JvmSentryId.EMPTY_ID - } else { - JvmSentryId(sentryIdString) - } + jvmSentryId = if (sentryIdString.isEmpty()) { + JvmSentryId.EMPTY_ID + } else { + JvmSentryId(sentryIdString) + } } - actual override fun toString(): String = jvmSentryId.toString() + actual override fun toString(): String { + return jvmSentryId.toString() + } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index 2c619a662..a95a3e24c 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -4,16 +4,25 @@ import io.sentry.kotlin.multiplatform.extensions.toJvmBreadcrumb import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -actual data class BreadcrumbTestConverter actual constructor( - val breadcrumb: Breadcrumb, -) { - actual fun getType(): String? = breadcrumb.toJvmBreadcrumb().type +actual data class BreadcrumbTestConverter actual constructor(val breadcrumb: Breadcrumb) { - actual fun getCategory(): String? = breadcrumb.toJvmBreadcrumb().category + actual fun getType(): String? { + return breadcrumb.toJvmBreadcrumb().type + } - actual fun getMessage(): String? = breadcrumb.toJvmBreadcrumb().message + actual fun getCategory(): String? { + return breadcrumb.toJvmBreadcrumb().category + } - actual fun getData(): MutableMap = breadcrumb.toJvmBreadcrumb().data + actual fun getMessage(): String? { + return breadcrumb.toJvmBreadcrumb().message + } - actual fun getLevel(): SentryLevel? = breadcrumb.toJvmBreadcrumb().level?.toKmpSentryLevel() + actual fun getData(): MutableMap { + return breadcrumb.toJvmBreadcrumb().data + } + + actual fun getLevel(): SentryLevel? { + return breadcrumb.toJvmBreadcrumb().level?.toKmpSentryLevel() + } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt index cff4b3438..66b16ee3a 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/JvmSentryIdTest.kt @@ -5,6 +5,7 @@ import kotlin.test.Test import kotlin.test.assertFailsWith class JvmSentryIdTest { + @Test fun `Jvm SentryId with invalid uuid string throws IllegalArgumentException`() { val uuidString = "ec720-b6f6-4efc--5c1" diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt index 82c291267..b1b978854 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesConversionTest.kt @@ -4,5 +4,6 @@ import io.sentry.kotlin.multiplatform.log.toJvmSentryAttributes /** Tests for SentryAttributes to JVM conversion. */ class SentryAttributesConversionTest : BaseSentryAttributesConversionTest() { - override fun SentryAttributes.toMap(): Map = toJvmSentryAttributes().attributes.mapValues { it.value.value } + override fun SentryAttributes.toMap(): Map = + toJvmSentryAttributes().attributes.mapValues { it.value.value } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt index 3b2936856..0d08dbbf8 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.commonJvm.kt @@ -49,11 +49,9 @@ actual class SentryBridgeTest { } // WHEN - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.beforeSend != null) @@ -66,11 +64,9 @@ actual class SentryBridgeTest { fixture.sut.init { } // WHEN - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.beforeSend != null) @@ -81,12 +77,10 @@ actual class SentryBridgeTest { actual fun `default beforeSend in init does not drop the event after prepareForInit`() { fixture.sut.init { } - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - prepareForInit() - }.let { it as JvmSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + prepareForInit() + }.let { it as JvmSentryOptions } assert(option.beforeSend != null) assert(option.beforeSend!!.execute(JvmSentryEvent(), Hint()) != null) @@ -96,11 +90,9 @@ actual class SentryBridgeTest { actual fun `init sets the SDK packages`() { // WHEN fixture.sut.init { } - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // THEN assert(option.sdkVersion?.packageSet != null) @@ -118,11 +110,9 @@ actual class SentryBridgeTest { // When fixture.sut.init(configuration) - val option = - SentryPlatformOptions() - .apply { - fixture.sentryInstance.lastConfiguration?.invoke(this) - }.let { it as JvmSentryOptions } + val option = SentryPlatformOptions().apply { + fixture.sentryInstance.lastConfiguration?.invoke(this) + }.let { it as JvmSentryOptions } // Then assertTrue(option.sdkVersion!!.name.contains("kmp")) diff --git a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index 4f2d3e9da..ac6fcb1f6 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -4,5 +4,7 @@ import io.sentry.kotlin.multiplatform.extensions.toJvmSentryLevel import io.sentry.kotlin.multiplatform.extensions.toKmpSentryLevel actual class SentryLevelTestConverter actual constructor() { - actual fun convert(sentryLevel: SentryLevel?): SentryLevel? = sentryLevel?.toJvmSentryLevel()?.toKmpSentryLevel() + actual fun convert(sentryLevel: SentryLevel?): SentryLevel? { + return sentryLevel?.toJvmSentryLevel()?.toKmpSentryLevel() + } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt index 4568ace79..e38013bda 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Attachment.kt @@ -2,6 +2,7 @@ package io.sentry.kotlin.multiplatform /** An attachment to be sent along with the event. */ public expect class Attachment { + /** The bytes of the attachment. */ public val bytes: ByteArray? diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt index 2a22dd473..76694a979 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt @@ -9,13 +9,13 @@ package io.sentry.kotlin.multiplatform * @property min the min status code of the range * @property max the max status code of the range */ -public data class HttpStatusCodeRange( - val min: Int = DEFAULT_MIN, - val max: Int = DEFAULT_MAX, -) { +public data class HttpStatusCodeRange(val min: Int = DEFAULT_MIN, val max: Int = DEFAULT_MAX) { + public constructor(statusCode: Int) : this(statusCode, statusCode) - public fun isInRange(statusCode: Int): Boolean = statusCode in min..max + public fun isInRange(statusCode: Int): Boolean { + return statusCode in min..max + } public companion object { /** The default min status code of the range. */ diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt index 5a8f67b30..86d540376 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/Scope.kt @@ -13,6 +13,7 @@ import io.sentry.kotlin.multiplatform.protocol.User * - For Cocoa: [io.sentry.kotlin.multiplatform.CocoaScopeProvider] */ public interface Scope { + /** * Returns the scope's tags */ @@ -60,10 +61,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Any, - ) + public fun setContext(key: String, value: Any) /** * Sets the Scope's contexts @@ -71,10 +69,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Boolean, - ) + public fun setContext(key: String, value: Boolean) /** * Sets the Scope's context @@ -82,10 +77,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: String, - ) + public fun setContext(key: String, value: String) /** * Sets the Scope's context @@ -93,10 +85,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Number, - ) + public fun setContext(key: String, value: Number) /** * Sets the Scope's context @@ -104,10 +93,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Collection<*>, - ) + public fun setContext(key: String, value: Collection<*>) /** * Sets the Scope's context @@ -115,10 +101,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Array<*>, - ) + public fun setContext(key: String, value: Array<*>) /** * Sets the Scope's context @@ -126,10 +109,7 @@ public interface Scope { * @param key the context key * @param value the context value */ - public fun setContext( - key: String, - value: Char, - ) + public fun setContext(key: String, value: Char) /** * Removes a value from the Scope's contexts @@ -144,10 +124,7 @@ public interface Scope { * @param key the key * @param value the value */ - public fun setTag( - key: String, - value: String, - ) + public fun setTag(key: String, value: String) /** * Removes a tag from the Scope's tags @@ -162,10 +139,7 @@ public interface Scope { * @param key the key * @param value the value */ - public fun setExtra( - key: String, - value: String, - ) + public fun setExtra(key: String, value: String) /** * Removes an extra from the Scope's extras diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt index ffe7bcdcc..9d18d2a91 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValue.kt @@ -11,27 +11,19 @@ package io.sentry.kotlin.multiplatform */ public sealed class SentryAttributeValue( /** The underlying raw value. */ - public val value: Any, + public val value: Any ) { /** Holds a [String] attribute value. */ - public class StringValue( - value: String, - ) : SentryAttributeValue(value) + public class StringValue(value: String) : SentryAttributeValue(value) /** Holds a [Long] attribute value. */ - public class LongValue( - value: Long, - ) : SentryAttributeValue(value) + public class LongValue(value: Long) : SentryAttributeValue(value) /** Holds a [Double] attribute value. */ - public class DoubleValue( - value: Double, - ) : SentryAttributeValue(value) + public class DoubleValue(value: Double) : SentryAttributeValue(value) /** Holds a [Boolean] attribute value. */ - public class BooleanValue( - value: Boolean, - ) : SentryAttributeValue(value) + public class BooleanValue(value: Boolean) : SentryAttributeValue(value) /** Returns the String value, or null if this is not a [StringValue]. */ public val stringOrNull: String? get() = (this as? StringValue)?.value as? String diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt index d6fe4c6c7..863057a4a 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryAttributes.kt @@ -6,53 +6,35 @@ package io.sentry.kotlin.multiplatform * (e.g., `stringOrNull`, `longOrNull`) to extract typed values. */ public class SentryAttributes private constructor( - private val attributes: MutableMap, + private val attributes: MutableMap ) : MutableMap by attributes { /** Sets a [String] value by key. */ - public operator fun set( - key: String, - value: String, - ) { + public operator fun set(key: String, value: String) { attributes[key] = SentryAttributeValue.string(value) } /** Sets an [Int] value by key. Stored as 64-bit Long value. */ - public operator fun set( - key: String, - value: Int, - ) { + public operator fun set(key: String, value: Int) { attributes[key] = SentryAttributeValue.long(value.toLong()) } /** Sets a [Long] value by key. */ - public operator fun set( - key: String, - value: Long, - ) { + public operator fun set(key: String, value: Long) { attributes[key] = SentryAttributeValue.long(value) } /** Sets an [Float] value by key. Stored as 64-bit Double value. */ - public operator fun set( - key: String, - value: Float, - ) { + public operator fun set(key: String, value: Float) { attributes[key] = SentryAttributeValue.double(value.toDouble()) } /** Sets a [Double] value by key. */ - public operator fun set( - key: String, - value: Double, - ) { + public operator fun set(key: String, value: Double) { attributes[key] = SentryAttributeValue.double(value) } /** Sets a [Boolean] value by key. */ - public operator fun set( - key: String, - value: Boolean, - ) { + public operator fun set(key: String, value: Boolean) { attributes[key] = SentryAttributeValue.boolean(value) } @@ -64,7 +46,9 @@ public class SentryAttributes private constructor( public fun empty(): SentryAttributes = SentryAttributes(mutableMapOf()) /** Creates a [SentryAttributes] collection from the given map. */ - public fun of(attributes: Map): SentryAttributes = SentryAttributes(attributes.toMutableMap()) + public fun of(attributes: Map): SentryAttributes { + return SentryAttributes(attributes.toMutableMap()) + } /** * Creates a [SentryAttributes] collection from the given key-value pairs. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt index 756f703dd..604df1c19 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBaseEvent.kt @@ -7,7 +7,7 @@ import io.sentry.kotlin.multiplatform.protocol.User /** Base class for all Sentry events. */ public abstract class SentryBaseEvent( /** The Sentry event ID. */ - public open var eventId: SentryId = SentryId.EMPTY_ID, + public open var eventId: SentryId = SentryId.EMPTY_ID ) { /** The event release. */ public open var release: String? = null @@ -65,10 +65,7 @@ public abstract class SentryBaseEvent( tags.remove(key) } - public fun setTag( - key: String, - value: String, - ) { + public fun setTag(key: String, value: String) { tags.set(key, value) } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt index 18a822b9d..33648df5e 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.kt @@ -6,13 +6,8 @@ import io.sentry.kotlin.multiplatform.protocol.SentryId import io.sentry.kotlin.multiplatform.protocol.User import io.sentry.kotlin.multiplatform.protocol.UserFeedback -internal expect class SentryBridge( - sentryInstance: SentryInstance = SentryPlatformInstance(), -) { - fun init( - context: Context, - configuration: OptionsConfiguration, - ) +internal expect class SentryBridge(sentryInstance: SentryInstance = SentryPlatformInstance()) { + fun init(context: Context, configuration: OptionsConfiguration) fun init(configuration: OptionsConfiguration) @@ -20,17 +15,11 @@ internal expect class SentryBridge( fun captureMessage(message: String): SentryId - fun captureMessage( - message: String, - scopeCallback: ScopeCallback, - ): SentryId + fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId fun captureException(throwable: Throwable): SentryId - fun captureException( - throwable: Throwable, - scopeCallback: ScopeCallback, - ): SentryId + fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId fun configureScope(scopeCallback: ScopeCallback) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt index 1c8bfba19..7c346c762 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryKMP.kt @@ -30,12 +30,9 @@ public object Sentry { @HiddenFromObjC @Deprecated( "Use init(OptionsConfiguration) instead.", - ReplaceWith("Sentry.init(configuration)"), + ReplaceWith("Sentry.init(configuration)") ) - public fun init( - context: Context, - configuration: OptionsConfiguration, - ) { + public fun init(context: Context, configuration: OptionsConfiguration) { bridge.init(context, configuration) } @@ -75,7 +72,9 @@ public object Sentry { * * @param message The message to send. */ - public fun captureMessage(message: String): SentryId = bridge.captureMessage(message) + public fun captureMessage(message: String): SentryId { + return bridge.captureMessage(message) + } /** * Captures the exception. @@ -83,17 +82,18 @@ public object Sentry { * @param message The message to send. * @param scopeCallback The local scope callback. */ - public fun captureMessage( - message: String, - scopeCallback: ScopeCallback, - ): SentryId = bridge.captureMessage(message, scopeCallback) + public fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { + return bridge.captureMessage(message, scopeCallback) + } /** * Captures the exception. * * @param throwable The exception. */ - public fun captureException(throwable: Throwable): SentryId = bridge.captureException(throwable) + public fun captureException(throwable: Throwable): SentryId { + return bridge.captureException(throwable) + } /** * Captures the exception. @@ -101,17 +101,18 @@ public object Sentry { * @param throwable The exception. * @param scopeCallback The local scope callback. */ - public fun captureException( - throwable: Throwable, - scopeCallback: ScopeCallback, - ): SentryId = bridge.captureException(throwable, scopeCallback) + public fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { + return bridge.captureException(throwable, scopeCallback) + } /** * Captures a manually created user feedback and sends it to Sentry. * * @param userFeedback The user feedback to send to Sentry. */ - public fun captureUserFeedback(userFeedback: UserFeedback): Unit = bridge.captureUserFeedback(userFeedback) + public fun captureUserFeedback(userFeedback: UserFeedback) { + return bridge.captureUserFeedback(userFeedback) + } /** * Configures the scope through the callback. @@ -171,17 +172,23 @@ public object Sentry { /** * Returns true if the app crashed during last run. */ - public fun isCrashedLastRun(): Boolean = bridge.isCrashedLastRun() + public fun isCrashedLastRun(): Boolean { + return bridge.isCrashedLastRun() + } /** * Throws a RuntimeException, useful for testing. */ - public fun crash(): Unit = throw RuntimeException("Uncaught Exception from Kotlin Multiplatform.") + public fun crash() { + throw RuntimeException("Uncaught Exception from Kotlin Multiplatform.") + } /** * Checks if the SDK is enabled. */ - public fun isEnabled(): Boolean = bridge.isEnabled() + public fun isEnabled(): Boolean { + return bridge.isEnabled() + } /** * Closes the SDK. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt index 6f70a817f..c07d0b474 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryLevel.kt @@ -9,26 +9,26 @@ internal object SentryLevelNumConstants { } /** The level of the event similar to logging levels. */ -public enum class SentryLevel( - private val value: Int, -) { +public enum class SentryLevel(private val value: Int) { DEBUG(SentryLevelNumConstants.DEBUG_LEVEL), INFO(SentryLevelNumConstants.INFO_LEVEL), WARNING(SentryLevelNumConstants.WARNING_LEVEL), ERROR(SentryLevelNumConstants.ERROR_LEVEL), - FATAL(SentryLevelNumConstants.FATAL_LEVEL), - ; + FATAL(SentryLevelNumConstants.FATAL_LEVEL); - internal fun toInt(): Int = this.value + internal fun toInt(): Int { + return this.value + } internal companion object { - fun fromInt(value: Int): SentryLevel? = - try { + fun fromInt(value: Int): SentryLevel? { + return try { values().first { it.value == value } } catch (throwable: Throwable) { null } + } } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt index e0fdc20bb..286485180 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt @@ -11,6 +11,7 @@ public data class SentryReplayOptions( * The default is null (disabled). */ public var sessionSampleRate: Double? = null, + /** * Indicates the percentage in which a 30 seconds replay will be sent with error events. * Specifying 0 means never, 1.0 means always. The value needs to be >= 0.0 and <= 1.0. @@ -18,23 +19,26 @@ public data class SentryReplayOptions( * The default is null (disabled). */ public var onErrorSampleRate: Double? = null, + /** * Makss all text content. Draws a rectangle of text bounds with text color on top. * * The default is true. */ public var maskAllText: Boolean = true, + /** * Masks all image content. Draws a rectangle of image bounds with image's dominant color on top. * * The default is true. */ public var maskAllImages: Boolean = true, + /** * Defines the quality of the session replay. The higher the quality, the more accurate the replay * will be, but also more data to transfer and more CPU load, defaults to MEDIUM. */ - public var quality: Quality = Quality.MEDIUM, + public var quality: Quality = Quality.MEDIUM ) { /** * Quality of the session replay. @@ -47,7 +51,7 @@ public data class SentryReplayOptions( * Defines the quality of the session replay. Higher bit rates have better replay quality, but * also affect the final payload size to transfer, defaults to 40kbps. */ - public val bitRate: Int, + public val bitRate: Int ) { /** Video Scale: 80% Bit Rate: 50.000 */ LOW(0.8f, 50000), @@ -56,6 +60,6 @@ public data class SentryReplayOptions( MEDIUM(1.0f, 75000), /** Video Scale: 100% Bit Rate: 100.000 */ - HIGH(1.0f, 100000), + HIGH(1.0f, 100000) } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt index d10ccb792..3d7ccc6f4 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLogger.kt @@ -14,7 +14,7 @@ import io.sentry.kotlin.multiplatform.SentryAttributes * the formatted log to their native SDK. */ internal abstract class BaseSentryLogger( - private val logBuilderFactory: SentryLogBuilderFactory, + private val logBuilderFactory: SentryLogBuilderFactory ) : SentryLogger { /** * Sends a formatted log to the native SDK. @@ -23,153 +23,86 @@ internal abstract class BaseSentryLogger( * @param level The log level * @param formatted The formatted log with body and attributes */ - protected abstract fun sendLog( - level: SentryLogLevel, - formatted: FormattedLog, - ) - - override fun trace( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.TRACE, message, args) - - override fun debug( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.DEBUG, message, args) - - override fun info( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.INFO, message, args) - - override fun warn( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.WARN, message, args) - - override fun error( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.ERROR, message, args) - - override fun fatal( - message: String, - vararg args: Any?, - ) = logWithParams(SentryLogLevel.FATAL, message, args) - - override fun trace( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.TRACE, message, attributes = attributes) - - override fun debug( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.DEBUG, message, attributes = attributes) - - override fun info( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.INFO, message, attributes = attributes) - - override fun warn( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.WARN, message, attributes = attributes) - - override fun error( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.ERROR, message, attributes = attributes) - - override fun fatal( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.FATAL, message, attributes = attributes) - - override fun trace( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.TRACE, message, args, attributes) - - override fun debug( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.DEBUG, message, args, attributes) - - override fun info( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.INFO, message, args, attributes) - - override fun warn( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.WARN, message, args, attributes) - - override fun error( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.ERROR, message, args, attributes) - - override fun fatal( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) = logWithParams(SentryLogLevel.FATAL, message, args, attributes) - - override fun log( - level: SentryLogLevel, - message: String, - vararg args: Any?, - ) = logWithParams(level, message, args) + protected abstract fun sendLog(level: SentryLogLevel, formatted: FormattedLog) + + override fun trace(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.TRACE, message, args) + override fun debug(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.DEBUG, message, args) + override fun info(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.INFO, message, args) + override fun warn(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.WARN, message, args) + override fun error(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.ERROR, message, args) + override fun fatal(message: String, vararg args: Any?) = + logWithParams(SentryLogLevel.FATAL, message, args) + + override fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.TRACE, message, attributes = attributes) + override fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.DEBUG, message, attributes = attributes) + override fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.INFO, message, attributes = attributes) + override fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.WARN, message, attributes = attributes) + override fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.ERROR, message, attributes = attributes) + override fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.FATAL, message, attributes = attributes) + + override fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.TRACE, message, args, attributes) + override fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.DEBUG, message, args, attributes) + override fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.INFO, message, args, attributes) + override fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.WARN, message, args, attributes) + override fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.ERROR, message, args, attributes) + override fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) = + logWithParams(SentryLogLevel.FATAL, message, args, attributes) + + override fun log(level: SentryLogLevel, message: String, vararg args: Any?) = + logWithParams(level, message, args) @Suppress("SpreadOperator") override fun log( level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, + attributes: @SentryLogDsl SentryAttributes.() -> Unit ) = logWithParams(level, message, args, attributes) - override fun log( - level: SentryLogLevel, - block: SentryLogBuilder.() -> Unit, - ) = logWithBuilder(block, level) - - override fun trace(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.TRACE) - - override fun debug(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.DEBUG) - - override fun info(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.INFO) - - override fun warn(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.WARN) - - override fun error(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.ERROR) - - override fun fatal(block: SentryLogBuilder.() -> Unit) = logWithBuilder(block, SentryLogLevel.FATAL) + override fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, level) + + override fun trace(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.TRACE) + override fun debug(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.DEBUG) + override fun info(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.INFO) + override fun warn(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.WARN) + override fun error(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.ERROR) + override fun fatal(block: SentryLogBuilder.() -> Unit) = + logWithBuilder(block, SentryLogLevel.FATAL) @Suppress("SpreadOperator") private fun logWithParams( level: SentryLogLevel, message: String, args: Array = emptyArray(), - attributes: (@SentryLogDsl SentryAttributes.() -> Unit)? = null, + attributes: (@SentryLogDsl SentryAttributes.() -> Unit)? = null ) = logWithBuilder({ if (args.isEmpty()) message(message) else message(message, *args) attributes?.let { attributes(it) } }, level) - private inline fun logWithBuilder( - block: SentryLogBuilder.() -> Unit, - level: SentryLogLevel, - ) { + private inline fun logWithBuilder(block: SentryLogBuilder.() -> Unit, level: SentryLogLevel) { val formatted = logBuilderFactory().apply(block).buildFormatted() ?: return sendLog(level, formatted) } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt index aaaf0bf77..d4116e5e3 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/DefaultSentryLogBuilder.kt @@ -32,10 +32,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { args = emptyArray() } - override fun message( - template: String, - vararg args: Any?, - ) { + override fun message(template: String, vararg args: Any?) { this.template = template this.args = args } @@ -58,7 +55,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { return FormattedLog( body = formattedBody, - attributes = allAttributes, + attributes = allAttributes ) } @@ -66,10 +63,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { * Formats the message by substituting %s placeholders with argument values. * Use %% to produce a literal percent sign. */ - private fun formatMessage( - template: String, - args: Array, - ): String { + private fun formatMessage(template: String, args: Array): String { if (!template.contains('%')) return template var argIndex = 0 @@ -88,7 +82,7 @@ internal class DefaultSentryLogBuilder : SentryLogBuilder { private fun buildAllAttributes( template: String, args: Array, - customAttributes: SentryAttributes, + customAttributes: SentryAttributes ): SentryAttributes { val result = SentryAttributes.empty() diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt index ab69ee45e..f42369ba0 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLog.kt @@ -10,12 +10,16 @@ import io.sentry.kotlin.multiplatform.SentryAttributes public open class SentryLog( /** Unix timestamp in seconds when the log was created. */ public open val timestamp: Double, + /** The severity level of this log entry. */ public open var level: SentryLogLevel, + /** The log message body. */ public open var body: String, + /** Optional numeric severity. */ public open var severityNumber: Int? = null, + /** Custom key-value attributes attached to this log entry. */ - public open val attributes: SentryAttributes = SentryAttributes.empty(), + public open val attributes: SentryAttributes = SentryAttributes.empty() ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt index 208eb6b12..9945e0356 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilder.kt @@ -50,10 +50,7 @@ public interface SentryLogBuilder { * @param template The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the template via toString() */ - public fun message( - template: String, - vararg args: Any?, - ) + public fun message(template: String, vararg args: Any?) /** * Merges prebuilt attributes into this log entry. @@ -100,5 +97,5 @@ public class FormattedLog( /** The formatted message body with placeholders substituted. */ public val body: String, /** Complete attributes including template info and custom attributes. */ - public val attributes: SentryAttributes, + public val attributes: SentryAttributes ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt index ad46fd911..98110eded 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogLevel.kt @@ -9,5 +9,5 @@ public enum class SentryLogLevel { INFO, WARN, ERROR, - FATAL, + FATAL } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt index 1fc47ba29..1f9c604f8 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogger.kt @@ -15,11 +15,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun log( - level: SentryLogLevel, - message: String, - vararg args: Any?, - ) + public fun log(level: SentryLogLevel, message: String, vararg args: Any?) /** * Logs a message at a specific level with inline attributes. @@ -33,7 +29,7 @@ public interface SentryLogger { level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, + attributes: @SentryLogDsl SentryAttributes.() -> Unit ) /** @@ -53,10 +49,7 @@ public interface SentryLogger { * @param level The log level * @param block A lambda with [SentryLogBuilder] receiver to configure the log entry */ - public fun log( - level: SentryLogLevel, - block: SentryLogBuilder.() -> Unit, - ) + public fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) /** * Logs a message at [SentryLogLevel.TRACE] level. @@ -64,10 +57,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun trace( - message: String, - vararg args: Any?, - ) + public fun trace(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.DEBUG] level. @@ -75,10 +65,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun debug( - message: String, - vararg args: Any?, - ) + public fun debug(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.INFO] level. @@ -86,10 +73,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun info( - message: String, - vararg args: Any?, - ) + public fun info(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.WARN] level. @@ -97,10 +81,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun warn( - message: String, - vararg args: Any?, - ) + public fun warn(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.ERROR] level. @@ -108,10 +89,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun error( - message: String, - vararg args: Any?, - ) + public fun error(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.FATAL] level. @@ -119,10 +97,7 @@ public interface SentryLogger { * @param message The message template (use %s for substitution, %% for literal %) * @param args Arguments to substitute into the message template via toString() */ - public fun fatal( - message: String, - vararg args: Any?, - ) + public fun fatal(message: String, vararg args: Any?) /** * Logs a message at [SentryLogLevel.TRACE] level with inline attributes. @@ -138,10 +113,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun trace( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.DEBUG] level with inline attributes. @@ -157,10 +129,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun debug( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.INFO] level with inline attributes. @@ -176,10 +145,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun info( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.WARN] level with inline attributes. @@ -195,10 +161,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun warn( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.TRACE] level with template parameters and inline attributes. @@ -215,11 +178,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun trace( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.DEBUG] level with template parameters and inline attributes. @@ -236,11 +195,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun debug( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.INFO] level with template parameters and inline attributes. @@ -257,11 +212,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun info( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.WARN] level with template parameters and inline attributes. @@ -278,11 +229,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun warn( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.ERROR] level with template parameters and inline attributes. @@ -299,11 +246,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun error( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.FATAL] level with template parameters and inline attributes. @@ -320,11 +263,7 @@ public interface SentryLogger { * @param args Arguments to substitute into the message template via toString() * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun fatal( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.ERROR] level with inline attributes. @@ -340,10 +279,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun error( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.FATAL] level with inline attributes. @@ -359,10 +295,7 @@ public interface SentryLogger { * @param message The log message * @param attributes A lambda with [SentryAttributes] receiver to set key-value attributes */ - public fun fatal( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) + public fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) /** * Logs a message at [SentryLogLevel.TRACE] level using a DSL builder. diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt index 4205cbc30..71d95e801 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Breadcrumb.kt @@ -10,110 +10,107 @@ import io.sentry.kotlin.multiplatform.SentryLevel public data class Breadcrumb( /** The breadcrumb's level */ var level: SentryLevel? = null, + /** The breadcrumb's type */ var type: String? = null, + /** The breadcrumb's message */ var message: String? = null, + /** The breadcrumb's category */ var category: String? = null, - private var data: MutableMap? = null, + + private var data: MutableMap? = null ) { + public companion object { - public fun user( - category: String, - message: String, - ): Breadcrumb = - Breadcrumb().apply { + public fun user(category: String, message: String): Breadcrumb { + return Breadcrumb().apply { this.category = category this.message = message this.type = "user" } + } - public fun http( - url: String, - method: String, - ): Breadcrumb = - Breadcrumb().apply { + public fun http(url: String, method: String): Breadcrumb { + return Breadcrumb().apply { this.type = "http" this.category = "http" this.setData("url", url) this.setData("method", method.uppercase()) } + } - public fun http( - url: String, - method: String, - code: Int?, - ): Breadcrumb = - http(url, method).apply { + public fun http(url: String, method: String, code: Int?): Breadcrumb { + return http(url, method).apply { code?.let { this.setData("status_code", code) } } + } - public fun navigation( - from: String, - to: String, - ): Breadcrumb = - Breadcrumb().apply { + public fun navigation(from: String, to: String): Breadcrumb { + return Breadcrumb().apply { this.category = "navigation" this.type = "navigation" this.setData("from", from) this.setData("to", to) } + } - public fun transaction(message: String): Breadcrumb = - Breadcrumb().apply { + public fun transaction(message: String): Breadcrumb { + return Breadcrumb().apply { this.type = "default" this.category = "sentry.transaction" this.message = message } + } public fun debug(message: String): Breadcrumb { - val breadcrumb = - Breadcrumb().apply { - this.type = "debug" - this.message = message - this.level = SentryLevel.DEBUG - } + val breadcrumb = Breadcrumb().apply { + this.type = "debug" + this.message = message + this.level = SentryLevel.DEBUG + } return breadcrumb } - public fun error(message: String): Breadcrumb = - Breadcrumb().apply { + public fun error(message: String): Breadcrumb { + return Breadcrumb().apply { this.type = "error" this.message = message this.level = SentryLevel.ERROR } + } - public fun info(message: String): Breadcrumb = - Breadcrumb().apply { + public fun info(message: String): Breadcrumb { + return Breadcrumb().apply { this.type = "info" this.message = message this.level = SentryLevel.INFO } + } - public fun query(message: String): Breadcrumb = - Breadcrumb().apply { + public fun query(message: String): Breadcrumb { + return Breadcrumb().apply { this.type = "query" this.message = message } + } - public fun ui( - category: String, - message: String, - ): Breadcrumb = - Breadcrumb().apply { + public fun ui(category: String, message: String): Breadcrumb { + return Breadcrumb().apply { this.type = "default" this.category = "ui.$category" this.message = message } + } public fun userInteraction( subCategory: String, viewId: String?, viewClass: String?, - additionalData: Map, - ): Breadcrumb = - Breadcrumb().apply { + additionalData: Map + ): Breadcrumb { + return Breadcrumb().apply { this.type = "user" this.category = "ui.$subCategory" this.level = SentryLevel.INFO @@ -125,12 +122,15 @@ public data class Breadcrumb( } } } + } public fun userInteraction( subCategory: String, viewId: String?, - viewClass: String?, - ): Breadcrumb = userInteraction(subCategory, viewId, viewClass, emptyMap()) + viewClass: String? + ): Breadcrumb { + return userInteraction(subCategory, viewId, viewClass, emptyMap()) + } } /** @@ -139,10 +139,7 @@ public data class Breadcrumb( * @param key The key * @param value The value */ - public fun setData( - key: String, - value: Any, - ) { + public fun setData(key: String, value: Any) { if (data == null) data = mutableMapOf() data?.put(key, value) } @@ -157,7 +154,9 @@ public data class Breadcrumb( } /** Returns the breadcrumb's data */ - public fun getData(): MutableMap? = data + public fun getData(): MutableMap? { + return data + } /** Clears the breadcrumb and returns it to the default state */ public fun clear() { diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt index a6f9e4189..37d525e50 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/Message.kt @@ -16,5 +16,5 @@ public data class Message( * The formatted message. If `message` and `params` are given, Sentry will attempt to backfill * `formatted` if empty. */ - public var formatted: String? = null, + public var formatted: String? = null ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt index f7fd2df69..c28381d47 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt @@ -4,17 +4,15 @@ package io.sentry.kotlin.multiplatform.protocol public data class SdkVersion( /** The name of the SDK. */ val name: String, + /** The version of the SDK. */ - val version: String, + val version: String ) { /** Packages used by the SDK. */ var packages: List? = mutableListOf() private set - public fun addPackage( - name: String, - version: String, - ) { + public fun addPackage(name: String, version: String) { val mutableList = packages?.toMutableList() mutableList?.add(Package(name, version)) packages = mutableList @@ -26,5 +24,5 @@ public data class Package( /** The name of the package. */ val name: String, /** The version of the package. */ - val version: String, + val version: String ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt index e614ee551..af3db1930 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryException.kt @@ -14,5 +14,5 @@ public data class SentryException( /** The optional module, or package which the exception type lives in. */ val module: String? = null, /** An optional value that refers to a thread. */ - val threadId: Long? = null, + val threadId: Long? = null ) diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt index 07244c48f..1db521a5e 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.kt @@ -1,13 +1,10 @@ package io.sentry.kotlin.multiplatform.protocol /** The Sentry event ID */ -public expect class SentryId( - sentryIdString: String, -) { +public expect class SentryId(sentryIdString: String) { public companion object { /** Returns a new empty SentryId */ public val EMPTY_ID: SentryId } - override fun toString(): String } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt index aa4ef3f59..0927dfd9e 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/User.kt @@ -4,27 +4,33 @@ package io.sentry.kotlin.multiplatform.protocol public data class User( /** The user's email */ var email: String? = null, + /** The user's id */ var id: String? = null, + /** The user's username */ var username: String? = null, + /** The user's ip address*/ var ipAddress: String? = null, + /** * Additional arbitrary fields, as stored in the database (and sometimes as sent by clients). All * data from `self.other` should end up here after store normalization. */ var other: MutableMap? = null, + /** Unknown fields, only internal usage. */ - var unknown: MutableMap? = null, + var unknown: MutableMap? = null ) { + public constructor(user: User) : this( user.email, user.id, user.username, user.ipAddress, user.other, - user.unknown, + user.unknown ) // This secondary constructor allows Swift also to init without specifying nil explicitly diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt index b801aae62..9569a03ee 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/UserFeedback.kt @@ -3,7 +3,7 @@ package io.sentry.kotlin.multiplatform.protocol /** UserFeedback adds additional information about what happened to an event. */ public data class UserFeedback( /** The Sentry event ID */ - val sentryId: SentryId, + val sentryId: SentryId ) { /** The user's name */ var name: String? = null diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt index c229840f8..84d0bf2dd 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/Attachment.commonStub.kt @@ -1,6 +1,7 @@ package io.sentry.kotlin.multiplatform public actual class Attachment { + public actual val bytes: ByteArray? public actual val contentType: String? public actual val pathname: String? diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt index b5b3e6606..9870f9f26 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/NoOpSentryLogger.kt @@ -9,143 +9,79 @@ import io.sentry.kotlin.multiplatform.log.SentryLogger * No-op implementation of [SentryLogger] for stub/unsupported platforms. */ internal class NoOpSentryLogger : SentryLogger { - override fun trace( - message: String, - vararg args: Any?, - ) { + override fun trace(message: String, vararg args: Any?) { // No-op } - override fun debug( - message: String, - vararg args: Any?, - ) { + override fun debug(message: String, vararg args: Any?) { // No-op } - override fun info( - message: String, - vararg args: Any?, - ) { + override fun info(message: String, vararg args: Any?) { // No-op } - override fun warn( - message: String, - vararg args: Any?, - ) { + override fun warn(message: String, vararg args: Any?) { // No-op } - override fun error( - message: String, - vararg args: Any?, - ) { + override fun error(message: String, vararg args: Any?) { // No-op } - override fun fatal( - message: String, - vararg args: Any?, - ) { + override fun fatal(message: String, vararg args: Any?) { // No-op } - override fun trace( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun trace(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun debug( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun debug(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun info( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun info(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun warn( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun warn(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun error( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun error(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun fatal( - message: String, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun fatal(message: String, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun trace( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun trace(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun debug( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun debug(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun info( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun info(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun warn( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun warn(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun error( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun error(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun fatal( - message: String, - vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, - ) { + override fun fatal(message: String, vararg args: Any?, attributes: @SentryLogDsl SentryAttributes.() -> Unit) { // No-op } - override fun log( - level: SentryLogLevel, - message: String, - vararg args: Any?, - ) { + override fun log(level: SentryLogLevel, message: String, vararg args: Any?) { // No-op } @@ -153,15 +89,12 @@ internal class NoOpSentryLogger : SentryLogger { level: SentryLogLevel, message: String, vararg args: Any?, - attributes: @SentryLogDsl SentryAttributes.() -> Unit, + attributes: @SentryLogDsl SentryAttributes.() -> Unit ) { // No-op } - override fun log( - level: SentryLogLevel, - block: SentryLogBuilder.() -> Unit, - ) { + override fun log(level: SentryLogLevel, block: SentryLogBuilder.() -> Unit) { // No-op } diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt index 81d7189f4..85c2bc8cf 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.commonStub.kt @@ -8,12 +8,9 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback @Suppress("UnusedPrivateMember") internal actual class SentryBridge actual constructor( - private val sentryInstance: SentryInstance, + private val sentryInstance: SentryInstance ) { - actual fun init( - context: Context, - configuration: OptionsConfiguration, - ) { + actual fun init(context: Context, configuration: OptionsConfiguration) { // No-op } @@ -25,19 +22,21 @@ internal actual class SentryBridge actual constructor( // No-op } - actual fun captureMessage(message: String): SentryId = SentryId.EMPTY_ID + actual fun captureMessage(message: String): SentryId { + return SentryId.EMPTY_ID + } - actual fun captureMessage( - message: String, - scopeCallback: ScopeCallback, - ): SentryId = SentryId.EMPTY_ID + actual fun captureMessage(message: String, scopeCallback: ScopeCallback): SentryId { + return SentryId.EMPTY_ID + } - actual fun captureException(throwable: Throwable): SentryId = SentryId.EMPTY_ID + actual fun captureException(throwable: Throwable): SentryId { + return SentryId.EMPTY_ID + } - actual fun captureException( - throwable: Throwable, - scopeCallback: ScopeCallback, - ): SentryId = SentryId.EMPTY_ID + actual fun captureException(throwable: Throwable, scopeCallback: ScopeCallback): SentryId { + return SentryId.EMPTY_ID + } actual fun configureScope(scopeCallback: ScopeCallback) { // No-op @@ -55,11 +54,17 @@ internal actual class SentryBridge actual constructor( // No-op } - actual fun logger(): SentryLogger = NoOpSentryLogger() + actual fun logger(): SentryLogger { + return NoOpSentryLogger() + } - actual fun isCrashedLastRun(): Boolean = false + actual fun isCrashedLastRun(): Boolean { + return false + } - actual fun isEnabled(): Boolean = false + actual fun isEnabled(): Boolean { + return false + } actual fun close() { // No-op diff --git a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt index 910b4abbb..da302990f 100644 --- a/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt +++ b/sentry-kotlin-multiplatform/src/commonStub/kotlin/io/sentry/kotlin/multiplatform/protocol/SentryId.commonStub.kt @@ -1,8 +1,6 @@ package io.sentry.kotlin.multiplatform.protocol -public actual data class SentryId actual constructor( - private val sentryIdString: String, -) { +public actual data class SentryId actual constructor(private val sentryIdString: String) { public actual companion object { public actual val EMPTY_ID: SentryId = SentryId("") } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt index 5f12036b4..c42db0e01 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/AttachmentTest.kt @@ -5,6 +5,7 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class AttachmentTest { + @Test fun `adding pathname to attachment returns correct values`() { val pathname = "test" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt index e57982562..9d168846c 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryScopeTest.kt @@ -1,5 +1,6 @@ package io.sentry.kotlin.multiplatform expect abstract class BaseSentryScopeTest() { + fun initializeScope(): Scope } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index b0484e7e7..512b69c4c 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,8 +3,6 @@ package io.sentry.kotlin.multiplatform expect abstract class BaseSentryTest() { val platform: String val authToken: String? - fun sentryInit(optionsConfiguration: OptionsConfiguration) - fun sentryInitWithPlatformOptions(platformOptionsConfiguration: PlatformOptionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt index 2e68599c7..27fe61657 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeBreadcrumbIntegrationTest.kt @@ -11,138 +11,127 @@ class BeforeBreadcrumbIntegrationTest { @Test fun `breadcrumb is not null if KMP beforeBreadcrumb callback config is null`() { - val breadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - } + val breadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(breadcrumb) } @Test fun `breadcrumb is null if KMP beforeBreadcrumb callback config returns null`() { - val breadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { - null - } + val breadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { + null } + } assertNull(breadcrumb) } @Test fun `breadcrumb is not null if KMP beforeBreadcrumb callback config returns not null`() { - val breadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb - } + val breadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb } + } assertNotNull(breadcrumb) } @Test fun `breadcrumb level is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb } + } assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level) } @Test fun `breadcrumb level is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.level = SentryLevel.WARNING - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.level = SentryLevel.WARNING + breadcrumb } + } assertEquals(SentryLevel.WARNING, modifiedBreadcrumb?.level) } @Test fun `breadcrumb category is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb } + } assertEquals(originalBreadcrumb.category, modifiedBreadcrumb?.category) } @Test fun `breadcrumb category is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.category = "category" - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.category = "category" + breadcrumb } + } assertEquals("category", modifiedBreadcrumb?.category) } @Test fun `breadcrumb type is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb } + } assertEquals(originalBreadcrumb.type, modifiedBreadcrumb?.type) } @Test fun `breadcrumb type is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.type = "type" - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.type = "type" + breadcrumb } + } assertEquals("type", modifiedBreadcrumb?.type) } @Test fun `breadcrumb message is not modified if KMP beforeBreadcrumb callback config does not modify it`() { val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb } + } assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level) } @Test fun `breadcrumb message is modified if KMP beforeBreadcrumb callback config modifies it`() { - val modifiedBreadcrumb = - breadcrumbConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeBreadcrumb = { breadcrumb -> - breadcrumb.message = "message" - breadcrumb - } + val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeBreadcrumb = { breadcrumb -> + breadcrumb.message = "message" + breadcrumb } + } assertEquals("message", modifiedBreadcrumb?.message) } } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt index 35c53924f..b143d8df9 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendIntegrationTest.kt @@ -13,48 +13,44 @@ class BeforeSendIntegrationTest { @Test fun `event is not null if KMP beforeSend option is null`() { - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) } @Test fun `event is null if KMP beforeSend callback config returns null`() { - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { - null - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { + null } + } assertNull(event) } @Test fun `event is not null if KMP beforeSend callback config returns not null`() { - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event } + } assertNotNull(event) } @Test fun `event logger is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.logger = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.logger = expected + event } + } assertNotNull(event) assertEquals(expected, event.logger) } @@ -62,14 +58,13 @@ class BeforeSendIntegrationTest { @Test fun `event level is modified if KMP beforeSend callback config modifies it`() { val expected = SentryLevel.DEBUG - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.level = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.level = expected + event } + } assertNotNull(event) assertEquals(expected, event.level) } @@ -77,14 +72,13 @@ class BeforeSendIntegrationTest { @Test fun `event message is modified if KMP beforeSend callback config modifies it`() { val expected = Message("test") - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.message = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.message = expected + event } + } assertNotNull(event) assertEquals(expected, event.message) } @@ -92,14 +86,13 @@ class BeforeSendIntegrationTest { @Test fun `event release is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.release = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.release = expected + event } + } assertNotNull(event) assertEquals(expected, event.release) } @@ -107,14 +100,13 @@ class BeforeSendIntegrationTest { @Test fun `event environment is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.environment = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.environment = expected + event } + } assertNotNull(event) assertEquals(expected, event.environment) } @@ -122,14 +114,13 @@ class BeforeSendIntegrationTest { @Test fun `event serverName is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.serverName = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.serverName = expected + event } + } assertNotNull(event) assertEquals(expected, event.serverName) } @@ -137,14 +128,13 @@ class BeforeSendIntegrationTest { @Test fun `event dist is modified if KMP beforeSend callback config modifies it`() { val expected = "test" - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.dist = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.dist = expected + event } + } assertNotNull(event) assertEquals(expected, event.dist) } @@ -152,14 +142,13 @@ class BeforeSendIntegrationTest { @Test fun `event fingerprint is modified if KMP beforeSend callback config modifies it`() { val expected = mutableListOf("test") - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.fingerprint = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.fingerprint = expected + event } + } assertNotNull(event) assertEquals(expected, event.fingerprint) } @@ -167,14 +156,13 @@ class BeforeSendIntegrationTest { @Test fun `event tags are modified if KMP beforeSend callback config modifies it`() { val expected = mutableMapOf("test" to "test") - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.tags = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.tags = expected + event } + } assertNotNull(event) assertEquals(expected, event.tags) } @@ -182,14 +170,13 @@ class BeforeSendIntegrationTest { @Test fun `event breadcrumbs are modified if KMP beforeSend callback config modifies it`() { val expected = mutableListOf(Breadcrumb.debug("test")) - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - it.beforeSend = { event -> - event.breadcrumbs = expected - event - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + it.beforeSend = { event -> + event.breadcrumbs = expected + event } + } assertNotNull(event) assertEquals(expected.first().type, event.breadcrumbs.first().type) assertEquals(expected.first().message, event.breadcrumbs.first().message) @@ -199,10 +186,9 @@ class BeforeSendIntegrationTest { @Test fun `event logger is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.logger, event.logger) } @@ -218,10 +204,9 @@ class BeforeSendIntegrationTest { @Test fun `event message is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.message, event.message) } @@ -229,10 +214,9 @@ class BeforeSendIntegrationTest { @Test fun `event release is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.release, event.release) } @@ -240,10 +224,9 @@ class BeforeSendIntegrationTest { @Test fun `event environment is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.environment, event.environment) } @@ -251,10 +234,9 @@ class BeforeSendIntegrationTest { @Test fun `event serverName is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.serverName, event.serverName) } @@ -262,10 +244,9 @@ class BeforeSendIntegrationTest { @Test fun `event dist is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.dist, event.dist) } @@ -273,10 +254,9 @@ class BeforeSendIntegrationTest { @Test fun `event fingerprint is not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.fingerprint, event.fingerprint) } @@ -284,10 +264,9 @@ class BeforeSendIntegrationTest { @Test fun `event tags are not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.tags, event.tags) } @@ -295,10 +274,9 @@ class BeforeSendIntegrationTest { @Test fun `event breadcrumbs are not modified if KMP beforeSend callback config is not modified`() { val originalEvent = sentryEventConfigurator.originalEvent - val event = - sentryEventConfigurator.applyOptions { - it.dsn = fakeDsn - } + val event = sentryEventConfigurator.applyOptions { + it.dsn = fakeDsn + } assertNotNull(event) assertEquals(originalEvent.breadcrumbs, event.breadcrumbs) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt index e6b221196..922515ab6 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BeforeSendTest.kt @@ -10,6 +10,7 @@ import kotlin.test.assertTrue /** Tests that verify if the beforeSend hook correctly modifies events */ class BeforeSendTest { + @Test fun `beforeSend drops event`() { val options = SentryOptions() @@ -129,12 +130,11 @@ class BeforeSendTest { @Test fun `beforeSend modifies user`() { - val expected = - User().apply { - id = "test" - username = "username" - email = "email" - } + val expected = User().apply { + id = "test" + username = "username" + email = "email" + } val options = SentryOptions() options.beforeSend = { @@ -218,12 +218,11 @@ class BeforeSendTest { it } - val event = - options.beforeSend?.invoke( - SentryEvent().apply { - contexts = mapOf("test" to "test") - }, - ) + val event = options.beforeSend?.invoke( + SentryEvent().apply { + contexts = mapOf("test" to "test") + } + ) assertEquals(contexts, event?.contexts) } @@ -237,12 +236,11 @@ class BeforeSendTest { it } - val event = - options.beforeSend?.invoke( - SentryEvent().apply { - exceptions = listOf(SentryException("test")) - }, - ) + val event = options.beforeSend?.invoke( + SentryEvent().apply { + exceptions = listOf(SentryException("test")) + } + ) assertEquals(exceptions, event?.exceptions) } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt index fad34df3a..4dcda258e 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbConfigurator.kt @@ -8,8 +8,6 @@ import io.sentry.kotlin.multiplatform.protocol.Breadcrumb */ expect class BreadcrumbConfigurator() { val originalBreadcrumb: Breadcrumb - fun applyOptions(optionsConfiguration: OptionsConfiguration): Breadcrumb? - fun applyOptions(options: SentryOptions = SentryOptions()): Breadcrumb? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt index adc9d3a54..aa8362442 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTest.kt @@ -5,6 +5,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class BreadcrumbTest { + private val testMessage = "TestMessage" private val testCategory = "TestCategory" private val testUrl = "sentry.io" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt index db34fdcb5..5dbdc4b31 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/BreadcrumbTestConverter.kt @@ -2,16 +2,10 @@ package io.sentry.kotlin.multiplatform import io.sentry.kotlin.multiplatform.protocol.Breadcrumb -expect class BreadcrumbTestConverter( - breadcrumb: Breadcrumb, -) { +expect class BreadcrumbTestConverter(breadcrumb: Breadcrumb) { fun getType(): String? - fun getCategory(): String? - fun getMessage(): String? - fun getData(): MutableMap - fun getLevel(): SentryLevel? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt index b2a789ce9..d373ae667 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/ScopeTest.kt @@ -8,6 +8,7 @@ import kotlin.test.assertEquals import kotlin.test.assertNull class ScopeTest : BaseSentryScopeTest() { + private val testUsername = "MyUsername" private val testEmail = "Email" private val testId = "TestId" @@ -28,13 +29,14 @@ class ScopeTest : BaseSentryScopeTest() { user = null } - private fun createTestUser(): User = - User().apply { + private fun createTestUser(): User { + return User().apply { username = testUsername email = testEmail id = testId ipAddress = testIpAddress } + } @Test fun `adding user to scope should properly persist user in scope`() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt index cd1772c23..6567bbba2 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributeValueTest.kt @@ -6,6 +6,7 @@ import kotlin.test.assertIs /** Tests for [SentryAttributeValue] factory methods and type hierarchy. */ class SentryAttributeValueTest { + @Test fun `string factory creates StringValue with correct value`() { val value = SentryAttributeValue.string("myValue") diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt index 33cc83038..d95e6150d 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryAttributesTest.kt @@ -8,6 +8,7 @@ import kotlin.test.assertTrue /** Tests for [SentryAttributes] collection operations. */ class SentryAttributesTest { + @Test fun `set and get string value`() { val attrs = SentryAttributes.empty() @@ -99,11 +100,10 @@ class SentryAttributesTest { @Test fun `of from map creates SentryAttributes with entries`() { - val map = - mapOf( - "name" to SentryAttributeValue.string("test"), - "count" to SentryAttributeValue.long(5), - ) + val map = mapOf( + "name" to SentryAttributeValue.string("test"), + "count" to SentryAttributeValue.long(5) + ) val attrs = SentryAttributes.of(map) diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt index 31980c515..d44a8d2db 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.kt @@ -2,14 +2,9 @@ package io.sentry.kotlin.multiplatform expect class SentryBridgeTest { fun `init sets correct configuration`() - fun `setting null in beforeSend during init drops the event`() - fun `default beforeSend in init does not drop the event`() - fun `default beforeSend in init does not drop the event after prepareForInit`() - fun `init sets the SDK packages`() - fun `init sets SDK version and name`() } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt index aa95e48c1..4ec1036e0 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryE2ETest.kt @@ -34,7 +34,7 @@ private data class SentryEventSerializable( val fingerprint: List = listOf(), val level: String? = null, val logger: String? = null, - val title: String? = null, + val title: String? = null ) class SentryE2ETest : BaseSentryTest() { @@ -58,29 +58,27 @@ class SentryE2ETest : BaseSentryTest() { private suspend fun fetchEvent(eventId: String): String { val url = "https://sentry.io/api/0/projects/$org/$projectSlug/events/$eventId/" - val response = - client.get(url) { - headers { - append( - HttpHeaders.Authorization, - "Bearer $authToken", - ) - } + val response = client.get(url) { + headers { + append( + HttpHeaders.Authorization, + "Bearer $authToken" + ) } + } return response.bodyAsText() } private suspend fun waitForEventRetrieval(eventId: String): SentryEventSerializable { var json = "" - val result: SentryEventSerializable = - withContext(Dispatchers.Default) { - while (json.isEmpty() || json.contains("Event not found")) { - delay(20000) - json = fetchEvent(eventId) - assertFalse(json.contains("Invalid token"), "Invalid auth token") - } - jsonDecoder.decodeFromString(json) + val result: SentryEventSerializable = withContext(Dispatchers.Default) { + while (json.isEmpty() || json.contains("Event not found")) { + delay(20000) + json = fetchEvent(eventId) + assertFalse(json.contains("Invalid token"), "Invalid auth token") } + jsonDecoder.decodeFromString(json) + } return result } @@ -88,41 +86,39 @@ class SentryE2ETest : BaseSentryTest() { // See: https://github.com/getsentry/sentry-kotlin-multiplatform/issues/17 @Test - fun `capture message and fetch event from Sentry`() = - runTest(timeout = 60.seconds) { - if (platform != "Apple") { - val message = "Test running on $platform" - val eventId = Sentry.captureMessage(message) - val fetchedEvent = waitForEventRetrieval(eventId.toString()) - fetchedEvent.tags.forEach { println(it["value"]) } - assertEquals(eventId.toString(), fetchedEvent.id) - assertEquals(sentEvent?.message?.formatted, fetchedEvent.message) - assertEquals(message, fetchedEvent.title) - assertEquals(sentEvent?.release, fetchedEvent.release) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) - assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.level?.name?.lowercase() }?.size) - assertEquals(sentEvent?.logger, fetchedEvent.logger) - } + fun `capture message and fetch event from Sentry`() = runTest(timeout = 60.seconds) { + if (platform != "Apple") { + val message = "Test running on $platform" + val eventId = Sentry.captureMessage(message) + val fetchedEvent = waitForEventRetrieval(eventId.toString()) + fetchedEvent.tags.forEach { println(it["value"]) } + assertEquals(eventId.toString(), fetchedEvent.id) + assertEquals(sentEvent?.message?.formatted, fetchedEvent.message) + assertEquals(message, fetchedEvent.title) + assertEquals(sentEvent?.release, fetchedEvent.release) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) + assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.level?.name?.lowercase() }?.size) + assertEquals(sentEvent?.logger, fetchedEvent.logger) } + } @Test - fun `capture exception and fetch event from Sentry`() = - runTest(timeout = 30.seconds) { - if (platform != "Apple") { - val exceptionMessage = "Test exception on platform $platform" - val eventId = - Sentry.captureException(IllegalArgumentException(exceptionMessage)) - val fetchedEvent = waitForEventRetrieval(eventId.toString()) - assertEquals(eventId.toString(), fetchedEvent.id) - assertEquals("IllegalArgumentException: $exceptionMessage", fetchedEvent.title) - assertEquals(sentEvent?.release, fetchedEvent.release) - assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) - assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) - assertEquals(2, fetchedEvent.tags.find { it["value"] == SentryLevel.ERROR.toString().lowercase() }?.size) - assertEquals(sentEvent?.logger, fetchedEvent.logger) - } + fun `capture exception and fetch event from Sentry`() = runTest(timeout = 30.seconds) { + if (platform != "Apple") { + val exceptionMessage = "Test exception on platform $platform" + val eventId = + Sentry.captureException(IllegalArgumentException(exceptionMessage)) + val fetchedEvent = waitForEventRetrieval(eventId.toString()) + assertEquals(eventId.toString(), fetchedEvent.id) + assertEquals("IllegalArgumentException: $exceptionMessage", fetchedEvent.title) + assertEquals(sentEvent?.release, fetchedEvent.release) + assertEquals(2, fetchedEvent.tags.find { it["value"] == sentEvent?.environment }?.size) + assertEquals(sentEvent?.fingerprint?.toList(), fetchedEvent.fingerprint) + assertEquals(2, fetchedEvent.tags.find { it["value"] == SentryLevel.ERROR.toString().lowercase() }?.size) + assertEquals(sentEvent?.logger, fetchedEvent.logger) } + } @AfterTest fun tearDown() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt index 67909fc68..d995661d7 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventConfigurator.kt @@ -6,8 +6,6 @@ package io.sentry.kotlin.multiplatform */ expect class SentryEventConfigurator() { val originalEvent: SentryEvent - fun applyOptions(optionsConfiguration: OptionsConfiguration): SentryEvent? - fun applyOptions(options: SentryOptions = SentryOptions()): SentryEvent? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt index 712e3fb54..b9e9607f9 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryEventTest.kt @@ -9,6 +9,7 @@ import kotlin.test.assertNull import kotlin.test.assertTrue class SentryEventTest { + @Test fun `setTag should add a new tag`() { val event = SentryEvent() diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt index e5a5417a3..d128d27e1 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIdTest.kt @@ -5,6 +5,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class SentryIdTest { + @Test fun `SentryId with valid uuid string returns valid SentryId string`() { val uuidString = "ec81a720-b6f6-4efc-9d74-6627a09157c1" diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt index dc0cf2d3e..c64c956ce 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryIntegrationTest.kt @@ -61,17 +61,11 @@ class SentryIntegrationTest : BaseSentryTest() { assertEquals(2, capturedEvents.size) val event = capturedEvents[0] - event.exceptions - .first() - .type - ?.let { assertTrue(it.contains("RuntimeException")) } + event.exceptions.first().type?.let { assertTrue(it.contains("RuntimeException")) } assertEquals("test", event.exceptions.first().value) val event2 = capturedEvents[1] - event2.exceptions - .first() - .type - ?.let { assertTrue(it.contains("RuntimeException")) } + event2.exceptions.first().type?.let { assertTrue(it.contains("RuntimeException")) } assertEquals("test2", event2.exceptions.first().value) } @@ -219,13 +213,12 @@ class SentryIntegrationTest : BaseSentryTest() { } Sentry.configureScope { - it.user = - User().apply { - this.email = expectedEmail - this.id = expectedId - this.ipAddress = expectedIpAddress - this.username = expectedUsername - } + it.user = User().apply { + this.email = expectedEmail + this.id = expectedId + this.ipAddress = expectedIpAddress + this.username = expectedUsername + } } Sentry.captureException(RuntimeException("test")) @@ -251,60 +244,59 @@ class SentryIntegrationTest : BaseSentryTest() { } @Test - fun `global scope sets context correctly with different data types`() = - runTest { - val stringKey = "stringKey" - val stringValue = "stringValue" - val booleanKey = "booleanKey" - val booleanValue = true - val numberKey = "numberKey" - val numberValue = 123 - val collectionKey = "collectionKey" - val collectionValue = listOf("abc", 123, true) - - val expectedStringValue = mapOf("value" to stringValue) - val expectedBooleanValue = mapOf("value" to booleanValue) - val expectedNumberValue = mapOf("value" to numberValue) - val expectedCollectionValue = mapOf("value" to collectionValue) - - var actualStringValue: Map? = null - var actualBooleanValue: Map? = null - var actualNumberValue: Map? = null - var actualCollectionValue: Map? = null - - sentryInit { - it.dsn = fakeDsn - it.beforeSend = { event -> - val contexts = event.contexts - assertNotNull(contexts) - actualStringValue = contexts[stringKey] as Map? - actualBooleanValue = contexts[booleanKey] as Map? - actualNumberValue = contexts[numberKey] as Map? - actualCollectionValue = contexts[collectionKey] as Map? - null - } - } + fun `global scope sets context correctly with different data types`() = runTest { + val stringKey = "stringKey" + val stringValue = "stringValue" + val booleanKey = "booleanKey" + val booleanValue = true + val numberKey = "numberKey" + val numberValue = 123 + val collectionKey = "collectionKey" + val collectionValue = listOf("abc", 123, true) + + val expectedStringValue = mapOf("value" to stringValue) + val expectedBooleanValue = mapOf("value" to booleanValue) + val expectedNumberValue = mapOf("value" to numberValue) + val expectedCollectionValue = mapOf("value" to collectionValue) + + var actualStringValue: Map? = null + var actualBooleanValue: Map? = null + var actualNumberValue: Map? = null + var actualCollectionValue: Map? = null - Sentry.configureScope { - it.setContext(stringKey, stringValue) - it.setContext(booleanKey, booleanValue) - it.setContext(numberKey, numberValue) - it.setContext(collectionKey, collectionValue) + sentryInit { + it.dsn = fakeDsn + it.beforeSend = { event -> + val contexts = event.contexts + assertNotNull(contexts) + actualStringValue = contexts[stringKey] as Map? + actualBooleanValue = contexts[booleanKey] as Map? + actualNumberValue = contexts[numberKey] as Map? + actualCollectionValue = contexts[collectionKey] as Map? + null } + } - Sentry.captureException(RuntimeException("test")) - - assertEquals(expectedStringValue, actualStringValue) - assertEquals(expectedBooleanValue, actualBooleanValue) - assertEquals(expectedNumberValue, actualNumberValue) - assertEquals(expectedCollectionValue, actualCollectionValue) + Sentry.configureScope { + it.setContext(stringKey, stringValue) + it.setContext(booleanKey, booleanValue) + it.setContext(numberKey, numberValue) + it.setContext(collectionKey, collectionValue) } + Sentry.captureException(RuntimeException("test")) + + assertEquals(expectedStringValue, actualStringValue) + assertEquals(expectedBooleanValue, actualBooleanValue) + assertEquals(expectedNumberValue, actualNumberValue) + assertEquals(expectedCollectionValue, actualCollectionValue) + } + // region Logger Tests private fun initWithLogCapture( enabled: Boolean = true, - beforeSend: ((SentryLog) -> SentryLog?)? = null, + beforeSend: ((SentryLog) -> SentryLog?)? = null ): MutableList { val capturedLogs = mutableListOf() sentryInit { @@ -331,15 +323,14 @@ class SentryIntegrationTest : BaseSentryTest() { assertEquals(6, capturedLogs.size) - val expectedLevels = - listOf( - SentryLogLevel.TRACE, - SentryLogLevel.DEBUG, - SentryLogLevel.INFO, - SentryLogLevel.WARN, - SentryLogLevel.ERROR, - SentryLogLevel.FATAL, - ) + val expectedLevels = listOf( + SentryLogLevel.TRACE, + SentryLogLevel.DEBUG, + SentryLogLevel.INFO, + SentryLogLevel.WARN, + SentryLogLevel.ERROR, + SentryLogLevel.FATAL + ) val expectedBodies = listOf("trace", "debug", "info", "warn", "error", "fatal") capturedLogs.forEachIndexed { index, log -> diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt index afa21aed0..ca429292b 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelConversionTest.kt @@ -4,6 +4,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class SentryLevelConversionTest { + private var converter: SentryLevelTestConverter? = SentryLevelTestConverter() @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt index d7988b231..27f80a0bc 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryLevelTestConverter.kt @@ -1,5 +1,6 @@ package io.sentry.kotlin.multiplatform expect class SentryLevelTestConverter() { + fun convert(sentryLevel: SentryLevel?): SentryLevel? } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt index 0c6187cb5..293caf8ee 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt @@ -47,21 +47,19 @@ class SentryOptionsTest : BaseSentryTest() { configuration.invoke(options) } - val expectedBreadcrumb = - Breadcrumb().apply { - message = "changed message" - type = "changed type" - category = "changed category" - setData(mutableMapOf("data1" to 12, "data2" to "value", "key" to "value")) - } + val expectedBreadcrumb = Breadcrumb().apply { + message = "changed message" + type = "changed type" + category = "changed category" + setData(mutableMapOf("data1" to 12, "data2" to "value", "key" to "value")) + } - val breadcrumb = - Breadcrumb().apply { - message = "another message" - type = "another type" - category = "another category" - setData(mutableMapOf("data1" to 12, "data2" to "value")) - } + val breadcrumb = Breadcrumb().apply { + message = "another message" + type = "another type" + category = "another category" + setData(mutableMapOf("data1" to 12, "data2" to "value")) + } mockInit { it.beforeBreadcrumb = { breadcrumb -> @@ -142,37 +140,36 @@ class SentryOptionsTest : BaseSentryTest() { @Test fun `GIVEN non-default SentryOptions WHEN options initialized THEN applies values to native options`() { - val options = - SentryOptions().apply { - dsn = fakeDsn - attachStackTrace = false - release = "release" - debug = true - environment = "environment" - dist = "dist" - enableAutoSessionTracking = false - sessionTrackingIntervalMillis = 1000L - diagnosticLevel = SentryLevel.ERROR - maxBreadcrumbs = 10 - maxAttachmentSize = 100L - sampleRate = 0.5 - tracesSampleRate = 0.5 - attachScreenshot = true - attachViewHierarchy = true - enableAppHangTracking = false - appHangTimeoutIntervalMillis = 1000L - isAnrEnabled = false - anrTimeoutIntervalMillis = 1000L - enableWatchdogTerminationTracking = false - enableUnhandledCppExceptionMonitoring = false - sessionReplay.onErrorSampleRate = 0.5 - sessionReplay.sessionSampleRate = 0.5 - sessionReplay.maskAllText = false - sessionReplay.maskAllImages = false - sessionReplay.quality = SentryReplayOptions.Quality.LOW - sendDefaultPii = true - proguardUuid = "test-proguard-uuid-12345" - } + val options = SentryOptions().apply { + dsn = fakeDsn + attachStackTrace = false + release = "release" + debug = true + environment = "environment" + dist = "dist" + enableAutoSessionTracking = false + sessionTrackingIntervalMillis = 1000L + diagnosticLevel = SentryLevel.ERROR + maxBreadcrumbs = 10 + maxAttachmentSize = 100L + sampleRate = 0.5 + tracesSampleRate = 0.5 + attachScreenshot = true + attachViewHierarchy = true + enableAppHangTracking = false + appHangTimeoutIntervalMillis = 1000L + isAnrEnabled = false + anrTimeoutIntervalMillis = 1000L + enableWatchdogTerminationTracking = false + enableUnhandledCppExceptionMonitoring = false + sessionReplay.onErrorSampleRate = 0.5 + sessionReplay.sessionSampleRate = 0.5 + sessionReplay.maskAllText = false + sessionReplay.maskAllImages = false + sessionReplay.quality = SentryReplayOptions.Quality.LOW + sendDefaultPii = true + proguardUuid = "test-proguard-uuid-12345" + } val platformOptions = createPlatformOptions() platformOptions.applyFromOptions(options) diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt index e1ce35adc..c6b09de33 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserFeedbackTest.kt @@ -6,6 +6,7 @@ import kotlin.test.Test import kotlin.test.assertEquals class UserFeedbackTest { + private val sentryIdString = "dcebada57d794590a6da3d1977eed58a" @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt index e2215228d..f343d1d07 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/UserTest.kt @@ -8,8 +8,8 @@ import kotlin.test.assertEquals class UserTest { private var user = User() - private fun createTestUser(): User = - User().apply { + private fun createTestUser(): User { + return User().apply { username = "TestUsername" email = "TestEmail" id = "TestId" @@ -17,6 +17,7 @@ class UserTest { unknown = mutableMapOf("key" to "value", "key2" to 12) other = mutableMapOf("key" to "value") } + } @BeforeTest fun setup() { diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt index a9c2ce814..666a384e4 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/BaseSentryLoggerTest.kt @@ -5,6 +5,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class BaseSentryLoggerTest { + // region Simple message API (level-specific) @Test @@ -496,12 +497,7 @@ class BaseSentryLoggerTest { assertEquals(1, logger.logs.size) assertEquals(SentryLogLevel.TRACE, logger.logs[0].level) assertEquals("User alice logged in", logger.logs[0].formatted.body) - assertEquals( - "us-east", - logger.logs[0] - .formatted.attributes["region"] - ?.stringOrNull, - ) + assertEquals("us-east", logger.logs[0].formatted.attributes["region"]?.stringOrNull) } @Test @@ -633,9 +629,9 @@ class BaseSentryLoggerTest { SentryLogLevel.INFO, SentryLogLevel.WARN, SentryLogLevel.ERROR, - SentryLogLevel.FATAL, + SentryLogLevel.FATAL ), - logger.logs.map { it.level }, + logger.logs.map { it.level } ) } @@ -646,17 +642,11 @@ class BaseSentryLoggerTest { * Test implementation of [BaseSentryLogger] that captures all logs for verification. */ private class TestSentryLogger : BaseSentryLogger(::DefaultSentryLogBuilder) { - data class CapturedLog( - val level: SentryLogLevel, - val formatted: FormattedLog, - ) + data class CapturedLog(val level: SentryLogLevel, val formatted: FormattedLog) val logs = mutableListOf() - override fun sendLog( - level: SentryLogLevel, - formatted: FormattedLog, - ) { + override fun sendLog(level: SentryLogLevel, formatted: FormattedLog) { logs.add(CapturedLog(level, formatted)) } } diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt index 93d4d3808..bcc0edda0 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogBuilderTest.kt @@ -8,6 +8,7 @@ import kotlin.test.assertTrue /** Tests for [DefaultSentryLogBuilder] DSL builder. */ class SentryLogBuilderTest { + // region Message configuration @Test diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt index 840ec0d76..003fc74a8 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/log/SentryLogOptionsTest.kt @@ -7,6 +7,7 @@ import kotlin.test.assertNull /** Tests for [SentryLogOptions] configuration and beforeSend callback. */ class SentryLogOptionsTest { + @Test fun `enabled is false by default`() { val options = SentryLogOptions() @@ -101,6 +102,6 @@ class SentryLogOptionsTest { private fun createTestLog( timestamp: Double = 1234567890.0, level: SentryLogLevel = SentryLogLevel.INFO, - body: String = "test message", + body: String = "test message" ): SentryLog = SentryLog(timestamp, level, body) } diff --git a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt index f801bb0d2..c2c52ad06 100644 --- a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt +++ b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.tvwatchmacos.kt @@ -4,4 +4,5 @@ import io.sentry.kotlin.multiplatform.extensions.toCocoaOptionsConfiguration public actual typealias SentryPlatformOptions = cocoapods.Sentry.SentryOptions -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toCocoaOptionsConfiguration() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + toCocoaOptionsConfiguration() diff --git a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt index 7d9a4818a..c3f579a22 100644 --- a/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt +++ b/sentry-kotlin-multiplatform/src/commonTvWatchMacOsTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.tvwatchmacos.kt @@ -2,9 +2,8 @@ package io.sentry.kotlin.multiplatform actual interface ApplePlatformOptions : PlatformOptions -class SentryTvWatchMacOsOptionsWrapper( - cocoaOptions: CocoaSentryOptions, -) : SentryAppleOptionsWrapper(cocoaOptions), +class SentryTvWatchMacOsOptionsWrapper(cocoaOptions: CocoaSentryOptions) : + SentryAppleOptionsWrapper(cocoaOptions), ApplePlatformOptions actual fun createApplePlatformOptions(): PlatformOptions = SentryTvWatchMacOsOptionsWrapper(CocoaSentryOptions()) diff --git a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt index 31d07b259..b495be182 100644 --- a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.ios.kt @@ -4,4 +4,5 @@ import io.sentry.kotlin.multiplatform.extensions.toIosOptionsConfiguration public actual typealias SentryPlatformOptions = cocoapods.Sentry.SentryOptions -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toIosOptionsConfiguration() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + toIosOptionsConfiguration() diff --git a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt index 4bec55fd9..f5311921b 100644 --- a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt @@ -4,40 +4,34 @@ import cocoapods.Sentry.SentryReplayOptions import io.sentry.kotlin.multiplatform.CocoaSentryOptions import io.sentry.kotlin.multiplatform.SentryOptions -internal fun SentryOptions.toIosOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = - { options -> - options?.let { cocoaOptions -> - val kmpOptions = this@toIosOptionsConfiguration +internal fun SentryOptions.toIosOptionsConfiguration(): (CocoaSentryOptions?) -> Unit = { options -> + options?.let { cocoaOptions -> + val kmpOptions = this@toIosOptionsConfiguration - // Apply base options available to all Cocoa/Apple targets - cocoaOptions.applyCocoaBaseOptions(kmpOptions) + // Apply base options available to all Cocoa/Apple targets + cocoaOptions.applyCocoaBaseOptions(kmpOptions) - // Apply iOS specific options - cocoaOptions.attachScreenshot = this.attachScreenshot - cocoaOptions.attachViewHierarchy = this.attachViewHierarchy + // Apply iOS specific options + cocoaOptions.attachScreenshot = this.attachScreenshot + cocoaOptions.attachViewHierarchy = this.attachViewHierarchy - // Replay options - val replayOptions = - SentryReplayOptions( - dictionary = - mapOf( - // Setting the onErrorSampleRate like this, using setOnErrorSampleRate - // crashes on compose multiplatform for some unknown reason - "errorSampleRate" to kmpOptions.sessionReplay.onErrorSampleRate?.toFloat(), - ), - ).apply { - setMaskAllText(kmpOptions.sessionReplay.maskAllText) - setMaskAllImages(kmpOptions.sessionReplay.maskAllImages) - kmpOptions.sessionReplay.sessionSampleRate?.let { setSessionSampleRate(it.toFloat()) } - setQuality( - kmpOptions.sessionReplay.quality.ordinal - .toLong(), - ) - } - cocoaOptions.setSessionReplay(replayOptions) - } ?: run { - // Log a warning if options is null - // TODO: Replace with actual logging when a logger is available - println("Warning: CocoaSentryOptions is null, skipping iOS configuration") + // Replay options + val replayOptions = SentryReplayOptions( + dictionary = mapOf( + // Setting the onErrorSampleRate like this, using setOnErrorSampleRate + // crashes on compose multiplatform for some unknown reason + "errorSampleRate" to kmpOptions.sessionReplay.onErrorSampleRate?.toFloat() + ) + ).apply { + setMaskAllText(kmpOptions.sessionReplay.maskAllText) + setMaskAllImages(kmpOptions.sessionReplay.maskAllImages) + kmpOptions.sessionReplay.sessionSampleRate?.let { setSessionSampleRate(it.toFloat()) } + setQuality(kmpOptions.sessionReplay.quality.ordinal.toLong()) } + cocoaOptions.setSessionReplay(replayOptions) + } ?: run { + // Log a warning if options is null + // TODO: Replace with actual logging when a logger is available + println("Warning: CocoaSentryOptions is null, skipping iOS configuration") } +} diff --git a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt index d66b6e9aa..914eb46fb 100644 --- a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt @@ -12,10 +12,7 @@ actual interface ApplePlatformOptions : PlatformOptions { val sessionReplay: SentryReplayOptions } -class SentryIosOptionsWrapper( - private val cocoaOptions: CocoaSentryOptions, -) : SentryAppleOptionsWrapper(cocoaOptions), - ApplePlatformOptions { +class SentryIosOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : SentryAppleOptionsWrapper(cocoaOptions), ApplePlatformOptions { override val attachScreenshot: Boolean get() = cocoaOptions.attachScreenshot @@ -48,9 +45,5 @@ actual fun ApplePlatformOptions.assertApplePlatformSpecificOptions(options: Sent assertEquals(sessionReplay.maskAllImages(), options.sessionReplay.maskAllImages) assertEquals(sessionReplay.onErrorSampleRate().toDouble(), options.sessionReplay.onErrorSampleRate) assertEquals(sessionReplay.sessionSampleRate().toDouble(), options.sessionReplay.sessionSampleRate) - assertEquals( - sessionReplay.quality(), - options.sessionReplay.quality.ordinal - .toLong(), - ) + assertEquals(sessionReplay.quality(), options.sessionReplay.quality.ordinal.toLong()) } diff --git a/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt b/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt index c42082418..0a7a8d285 100644 --- a/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/jvmMain/kotlin/io/sentry/kotlin/multiplatform/SentryPlatformOptions.jvm.kt @@ -12,4 +12,5 @@ internal actual fun SentryPlatformOptions.prepareForInit() { } } -internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = toJvmSentryOptionsCallback() +internal actual fun SentryOptions.toPlatformOptionsConfiguration(): PlatformOptionsConfiguration = + toJvmSentryOptionsCallback() diff --git a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt index 4886eba40..717a2b0e3 100644 --- a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt +++ b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/BaseSentryTest.kt @@ -3,7 +3,6 @@ package io.sentry.kotlin.multiplatform actual abstract class BaseSentryTest { actual val platform: String = "JVM" actual val authToken: String? = System.getenv("SENTRY_AUTH_TOKEN") - actual fun sentryInit(optionsConfiguration: OptionsConfiguration) { Sentry.init(optionsConfiguration) } diff --git a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt index 3bab0c7c6..3a8059a1a 100644 --- a/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt +++ b/sentry-kotlin-multiplatform/src/jvmTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.jvm.kt @@ -7,9 +7,7 @@ import kotlin.test.assertEquals actual interface PlatformOptions : CommonPlatformOptions -class SentryJvmOptionsWrapper( - private val jvmOptions: JvmSentryOptions, -) : PlatformOptions { +class SentryJvmOptionsWrapper(private val jvmOptions: JvmSentryOptions) : PlatformOptions { override val dsn: String? get() = jvmOptions.dsn @@ -66,7 +64,6 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(kmpOptions: SentryOptio assertEquals(proguardUuid, kmpOptions.proguardUuid) } -actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - it.dsn = fakeDsn - } +actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + it.dsn = fakeDsn +} diff --git a/sentry-samples/kmp-app-cocoapods/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt b/sentry-samples/kmp-app-cocoapods/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt index 474a74a33..0f82c6675 100644 --- a/sentry-samples/kmp-app-cocoapods/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt +++ b/sentry-samples/kmp-app-cocoapods/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt @@ -27,7 +27,7 @@ fun App() { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, + horizontalAlignment = Alignment.CenterHorizontally ) { val btnBackgroundColor = Color(56, 31, 67) Button({ @@ -48,21 +48,20 @@ fun App() { } } -fun main() = - application { - Window(onCloseRequest = ::exitApplication, title = "Jetpack Compose Desktop App (Cocoapods Sample Version)") { - // Initialize Sentry using shared code - initializeSentry() +fun main() = application { + Window(onCloseRequest = ::exitApplication, title = "Jetpack Compose Desktop App (Cocoapods Sample Version)") { + // Initialize Sentry using shared code + initializeSentry() - // Shared scope across all platforms - configureSentryScope() + // Shared scope across all platforms + configureSentryScope() - // Add platform specific scope in addition to the shared scope - Sentry.configureScope { - it.setContext("JVM Desktop Context", mapOf("context1" to 12, "context2" to false)) - it.addBreadcrumb(Breadcrumb.debug("initialized Sentry on JVM Desktop")) - } - - App() + // Add platform specific scope in addition to the shared scope + Sentry.configureScope { + it.setContext("JVM Desktop Context", mapOf("context1" to 12, "context2" to false)) + it.addBreadcrumb(Breadcrumb.debug("initialized Sentry on JVM Desktop")) } + + App() } +} diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt b/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt index e2d563b44..11c6831d7 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/androidMain/kotlin/sample/kmp/app/SentrySetup.android.kt @@ -2,7 +2,6 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" - } +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" +} diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt index 6b68005b0..21fc2cd00 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt @@ -9,9 +9,7 @@ import io.sentry.kotlin.multiplatform.protocol.UserFeedback import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid -class InvalidUsernameException( - message: String, -) : Exception(message) +class InvalidUsernameException(message: String) : Exception(message) object LoginImpl { /** @@ -52,11 +50,10 @@ object LoginImpl { } // DSL builder with prebuilt SentryAttributes - val prebuiltAttrs = - SentryAttributes.of( - "source" to "login-form", - "version" to 2, - ) + val prebuiltAttrs = SentryAttributes.of( + "source" to "login-form", + "version" to 2 + ) Sentry.logger.debug { message("Session token generated for user: %s", username) attributes(prebuiltAttrs) @@ -76,27 +73,24 @@ object LoginImpl { try { validateUsername(username) } catch (exception: InvalidUsernameException) { - val sentryId = - Sentry.captureException(exception) { - val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") - breadcrumb.setData("touch event", "on login") - it.addBreadcrumb(breadcrumb) - it.setContext("Login", "Failed with Invalid Username") - it.setTag("login", "failed auth") - it.level = SentryLevel.WARNING - val user = - User().apply { - this.username = "John Doe" - this.email = "john@doe.com" - } - it.user = user - } - val userFeedback = - UserFeedback(sentryId).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error during login on ${Platform().platform}" + val sentryId = Sentry.captureException(exception) { + val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") + breadcrumb.setData("touch event", "on login") + it.addBreadcrumb(breadcrumb) + it.setContext("Login", "Failed with Invalid Username") + it.setTag("login", "failed auth") + it.level = SentryLevel.WARNING + val user = User().apply { + this.username = "John Doe" + this.email = "john@doe.com" } + it.user = user + } + val userFeedback = UserFeedback(sentryId).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error during login on ${Platform().platform}" + } Sentry.captureUserFeedback(userFeedback) } catch (exception: IllegalArgumentException) { throw exception diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt index 2a26d2ef7..8ed65c638 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt @@ -14,8 +14,8 @@ fun configureSentryScope() { it.addAttachment( Attachment( "This is a shared text attachment".encodeToByteArray(), - "shared.log", - ), + "shared.log" + ) ) } } @@ -35,8 +35,8 @@ fun initializeSentry(useNativeOptions: Boolean = false) { expect fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration /** Returns a shared options configuration */ -private fun optionsConfiguration(): OptionsConfiguration = - { +private fun optionsConfiguration(): OptionsConfiguration { + return { it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" it.attachStackTrace = true it.attachThreads = true @@ -68,3 +68,4 @@ private fun optionsConfiguration(): OptionsConfiguration = } } } +} diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt index b82766cb0..b63d03af6 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt @@ -9,14 +9,13 @@ import platform.Foundation.dataTaskWithRequest fun captureHttpClientError() { val url = NSURL(string = "https://httpbin.org/status/404") val request = NSURLRequest(uRL = url) - NSURLSession.sharedSession - .dataTaskWithRequest(request) { data, response, error -> - if (error != null) { - // handle error - println("error: $error") - } else { - // handle successful response - println("response: $response") - } - }.resume() + NSURLSession.sharedSession.dataTaskWithRequest(request) { data, response, error -> + if (error != null) { + // handle error + println("error: $error") + } else { + // handle successful response + println("response: $response") + } + }.resume() } diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt index e2d563b44..11c6831d7 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/iosMain/kotlin/sample.kmp.app/SentrySetup.ios.kt @@ -2,7 +2,6 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" - } +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" +} diff --git a/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt b/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt index e2d563b44..11c6831d7 100644 --- a/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt +++ b/sentry-samples/kmp-app-cocoapods/shared/src/jvmMain/kotlin/sample/kmp/app/SentrySetup.jvm.kt @@ -2,7 +2,6 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration -actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = - { - it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" - } +actual fun createPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { + it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" +} diff --git a/sentry-samples/kmp-app-spm/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt b/sentry-samples/kmp-app-spm/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt index 9dd9f8ca4..987c29d5d 100644 --- a/sentry-samples/kmp-app-spm/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt +++ b/sentry-samples/kmp-app-spm/desktopApp/src/jvmMain/kotlin/sample.kmp.app.desktop/Main.kt @@ -27,7 +27,7 @@ fun App() { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, + horizontalAlignment = Alignment.CenterHorizontally ) { val btnBackgroundColor = Color(56, 31, 67) Button({ @@ -48,21 +48,20 @@ fun App() { } } -fun main() = - application { - Window(onCloseRequest = ::exitApplication, title = "Jetpack Compose Desktop App (SPM Sample Version)") { - // Initialize Sentry using shared code - initializeSentry() +fun main() = application { + Window(onCloseRequest = ::exitApplication, title = "Jetpack Compose Desktop App (SPM Sample Version)") { + // Initialize Sentry using shared code + initializeSentry() - // Shared scope across all platforms - configureSentryScope() + // Shared scope across all platforms + configureSentryScope() - // Add platform specific scope in addition to the shared scope - Sentry.configureScope { - it.setContext("JVM Desktop Context", mapOf("context1" to 12, "context2" to false)) - it.addBreadcrumb(Breadcrumb.debug("initialized Sentry on JVM Desktop")) - } - - App() + // Add platform specific scope in addition to the shared scope + Sentry.configureScope { + it.setContext("JVM Desktop Context", mapOf("context1" to 12, "context2" to false)) + it.addBreadcrumb(Breadcrumb.debug("initialized Sentry on JVM Desktop")) } + + App() } +} diff --git a/sentry-samples/kmp-app-spm/shared/build.gradle.kts b/sentry-samples/kmp-app-spm/shared/build.gradle.kts index b639ad0ad..be42e5916 100644 --- a/sentry-samples/kmp-app-spm/shared/build.gradle.kts +++ b/sentry-samples/kmp-app-spm/shared/build.gradle.kts @@ -24,7 +24,7 @@ kotlin { listOf( iosX64(), iosArm64(), - iosSimulatorArm64(), + iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" diff --git a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt index 06273d38f..db6e90c08 100644 --- a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt +++ b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/LoginImpl.kt @@ -6,9 +6,7 @@ import io.sentry.kotlin.multiplatform.protocol.Breadcrumb import io.sentry.kotlin.multiplatform.protocol.User import io.sentry.kotlin.multiplatform.protocol.UserFeedback -class InvalidUsernameException( - message: String, -) : Exception(message) +class InvalidUsernameException(message: String) : Exception(message) object LoginImpl { /** @@ -25,27 +23,24 @@ object LoginImpl { try { validateUsername(username) } catch (exception: InvalidUsernameException) { - val sentryId = - Sentry.captureException(exception) { - val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") - breadcrumb.setData("touch event", "on login") - it.addBreadcrumb(breadcrumb) - it.setContext("Login", "Failed with Invalid Username") - it.setTag("login", "failed auth") - it.level = SentryLevel.WARNING - val user = - User().apply { - this.username = "John Doe" - this.email = "john@doe.com" - } - it.user = user - } - val userFeedback = - UserFeedback(sentryId).apply { - name = "John Doe" - email = "john@doe.com" - comments = "I had an error during login on ${Platform().platform}" + val sentryId = Sentry.captureException(exception) { + val breadcrumb = Breadcrumb.debug("this is a test breadcrumb") + breadcrumb.setData("touch event", "on login") + it.addBreadcrumb(breadcrumb) + it.setContext("Login", "Failed with Invalid Username") + it.setTag("login", "failed auth") + it.level = SentryLevel.WARNING + val user = User().apply { + this.username = "John Doe" + this.email = "john@doe.com" } + it.user = user + } + val userFeedback = UserFeedback(sentryId).apply { + name = "John Doe" + email = "john@doe.com" + comments = "I had an error during login on ${Platform().platform}" + } Sentry.captureUserFeedback(userFeedback) } catch (exception: IllegalArgumentException) { throw exception diff --git a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt index e023590cf..be7e6e27a 100644 --- a/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt +++ b/sentry-samples/kmp-app-spm/shared/src/commonMain/kotlin/sample.kmp.app/SentrySetup.kt @@ -13,8 +13,8 @@ fun configureSentryScope() { it.addAttachment( Attachment( "This is a shared text attachment".encodeToByteArray(), - "shared.log", - ), + "shared.log" + ) ) } } @@ -28,8 +28,8 @@ fun initializeSentry() { } /** Returns a shared options configuration */ -private fun optionsConfiguration(): OptionsConfiguration = - { +private fun optionsConfiguration(): OptionsConfiguration { + return { it.dsn = "https://83f281ded2844eda83a8a413b080dbb9@o447951.ingest.sentry.io/5903800" it.attachStackTrace = true it.attachThreads = true @@ -50,3 +50,4 @@ private fun optionsConfiguration(): OptionsConfiguration = } } } +} diff --git a/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt b/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt index b82766cb0..b63d03af6 100644 --- a/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt +++ b/sentry-samples/kmp-app-spm/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt @@ -9,14 +9,13 @@ import platform.Foundation.dataTaskWithRequest fun captureHttpClientError() { val url = NSURL(string = "https://httpbin.org/status/404") val request = NSURLRequest(uRL = url) - NSURLSession.sharedSession - .dataTaskWithRequest(request) { data, response, error -> - if (error != null) { - // handle error - println("error: $error") - } else { - // handle successful response - println("response: $response") - } - }.resume() + NSURLSession.sharedSession.dataTaskWithRequest(request) { data, response, error -> + if (error != null) { + // handle error + println("error: $error") + } else { + // handle successful response + println("response: $response") + } + }.resume() }