diff --git a/.java_version b/.java_version index b4de3947..98d9bcb7 100644 --- a/.java_version +++ b/.java_version @@ -1 +1 @@ -11 +17 diff --git a/build.gradle.kts b/build.gradle.kts index de2fd127..c71e8b2a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,7 +28,14 @@ antibytesPublishing { } antibytesQuality { - codeAnalysis.set(CodeAnalysisConfiguration(project = project)) + codeAnalysis.set( + CodeAnalysisConfiguration( + project = project, + /*configurationFiles = project.files("${project.projectDir}/detekt/config.yml"), + baselineFile = project.file("${project.projectDir}/detekt/baseline.xml"), + sourceFiles = project.files(project.projectDir),*/ + ), + ) stableApi.set(StableApiConfiguration()) } diff --git a/core/api/android/core.api b/core/api/android/core.api index ce60a086..61bdc31a 100644 --- a/core/api/android/core.api +++ b/core/api/android/core.api @@ -1,10 +1,3 @@ -public final class tech/antibytes/kfixture/BuildConfig { - public static final field BUILD_TYPE Ljava/lang/String; - public static final field DEBUG Z - public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; - public fun ()V -} - public final class tech/antibytes/kfixture/ClassNameResolverKt { public static final fun resolveClassName (Lkotlin/reflect/KClass;)Ljava/lang/String; } @@ -105,6 +98,7 @@ public final class tech/antibytes/kfixture/PublicApi$RangedGenerator$DefaultImpl public final class tech/antibytes/kfixture/PublicApi$Sign : java/lang/Enum { public static final field NEGATIVE Ltech/antibytes/kfixture/PublicApi$Sign; public static final field POSITIVE Ltech/antibytes/kfixture/PublicApi$Sign; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Ltech/antibytes/kfixture/PublicApi$Sign; public static fun values ()[Ltech/antibytes/kfixture/PublicApi$Sign; } diff --git a/core/api/jvm/core.api b/core/api/jvm/core.api index 9e189826..61bdc31a 100644 --- a/core/api/jvm/core.api +++ b/core/api/jvm/core.api @@ -98,6 +98,7 @@ public final class tech/antibytes/kfixture/PublicApi$RangedGenerator$DefaultImpl public final class tech/antibytes/kfixture/PublicApi$Sign : java/lang/Enum { public static final field NEGATIVE Ltech/antibytes/kfixture/PublicApi$Sign; public static final field POSITIVE Ltech/antibytes/kfixture/PublicApi$Sign; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Ltech/antibytes/kfixture/PublicApi$Sign; public static fun values ()[Ltech/antibytes/kfixture/PublicApi$Sign; } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index dbe5d780..0499a674 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -11,7 +11,6 @@ import tech.antibytes.gradle.coverage.CoverageApiContract.JacocoCounter import tech.antibytes.gradle.coverage.CoverageApiContract.JacocoMeasurement import tech.antibytes.gradle.configuration.apple.ensureAppleDeviceCompatibility import tech.antibytes.gradle.configuration.sourcesets.nativeWithLegacy -import tech.antibytes.gradle.configuration.sourcesets.setupAndroidTest import tech.antibytes.gradle.kfixture.config.publishing.FixtureCoreConfiguration plugins { @@ -97,7 +96,7 @@ android { } kotlin { - android() + androidTarget() js(IR) { nodejs() @@ -143,9 +142,7 @@ kotlin { } } - setupAndroidTest() - - val androidTest by getting { + val androidUnitTest by getting { dependencies { implementation(antibytesCatalog.jvm.test.kotlin.core) implementation(antibytesCatalog.jvm.test.kotlin.junit4) diff --git a/core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt b/core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt similarity index 100% rename from core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt rename to core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt diff --git a/core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt b/core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt similarity index 100% rename from core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt rename to core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt diff --git a/core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt b/core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt similarity index 100% rename from core/src/androidAndroidTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt rename to core/src/androidInstrumentedTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt diff --git a/core/src/androidMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt b/core/src/androidMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt index 1aab928e..8636b2f4 100644 --- a/core/src/androidMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt +++ b/core/src/androidMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture import java.util.concurrent.ConcurrentHashMap diff --git a/core/src/androidTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt b/core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt similarity index 100% rename from core/src/androidTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt rename to core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/ClassNameResolverSpec.kt diff --git a/core/src/androidTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt b/core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt similarity index 100% rename from core/src/androidTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt rename to core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/IgnorePlatform.kt diff --git a/core/src/androidTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt b/core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt similarity index 100% rename from core/src/androidTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt rename to core/src/androidUnitTest/kotlin/tech/antibytes/kfixture/PlatformClassNames.kt diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt index 5a97f30d..e72fa24f 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture import kotlin.reflect.KClass diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/FilterableFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/FilterableFixture.kt index a8991e10..22652841 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/FilterableFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/FilterableFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("OPT_IN_USAGE") +@file:Suppress("OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedFixture.kt index 9f5199f5..bf7deb17 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedFixture.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture @InternalAPI diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedNumericArrayFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedNumericArrayFixture.kt index 8ffb4279..81c5df2a 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedNumericArrayFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedNumericArrayFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("OPT_IN_USAGE") +@file:Suppress("OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedSpecialArrayFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedSpecialArrayFixture.kt index 3c87b842..6737c663 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedSpecialArrayFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/RangedSpecialArrayFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("FINAL_UPPER_BOUND", "OPT_IN_USAGE") +@file:Suppress("FINAL_UPPER_BOUND", "OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericArrayFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericArrayFixture.kt index 4b3deee7..8e44e452 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericArrayFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericArrayFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("OPT_IN_USAGE") +@file:Suppress("OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericFixture.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericFixture.kt index a0ed50ea..eb1b09b4 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericFixture.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/SignedNumericFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("OPT_IN_USAGE") +@file:Suppress("OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture diff --git a/core/src/commonMain/kotlin/tech/antibytes/kfixture/generator/selector/Binding.kt b/core/src/commonMain/kotlin/tech/antibytes/kfixture/generator/selector/Binding.kt index 53277137..6b5fa011 100644 --- a/core/src/commonMain/kotlin/tech/antibytes/kfixture/generator/selector/Binding.kt +++ b/core/src/commonMain/kotlin/tech/antibytes/kfixture/generator/selector/Binding.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture.generator.selector import tech.antibytes.kfixture.PublicApi diff --git a/core/src/commonTest/kotlin/tech/antibytes/kfixture/fixture/RangedSpecialArrayFixtureSpec.kt b/core/src/commonTest/kotlin/tech/antibytes/kfixture/fixture/RangedSpecialArrayFixtureSpec.kt index fe47492d..77c679fb 100644 --- a/core/src/commonTest/kotlin/tech/antibytes/kfixture/fixture/RangedSpecialArrayFixtureSpec.kt +++ b/core/src/commonTest/kotlin/tech/antibytes/kfixture/fixture/RangedSpecialArrayFixtureSpec.kt @@ -185,7 +185,8 @@ class RangedSpecialArrayFixtureSpec { RangeType, PublicApi.Qualifier?, Function1, - FixtureType,> { + FixtureType, + > { return when (FixtureType::class) { CharArray::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture( @@ -294,7 +295,8 @@ class RangedSpecialArrayFixtureSpec { RangeType, PublicApi.Qualifier?, Function1, - FixtureType?,> { + FixtureType?, + > { return when (FixtureType::class) { CharArray::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture( @@ -1643,7 +1645,8 @@ class RangedSpecialArrayFixtureSpec { ClosedRange>, PublicApi.Qualifier?, Function1, - FixtureType,> { + FixtureType, + > { return when (FixtureType::class) { CharArray::class -> { fixture, range, qualifier, predicate -> fixture.fixture( @@ -1739,7 +1742,8 @@ class RangedSpecialArrayFixtureSpec { ClosedRange>, PublicApi.Qualifier?, Function1, - FixtureType?,> { + FixtureType?, + > { return when (FixtureType::class) { CharArray::class -> { fixture, range, qualifier, predicate -> fixture.fixture( diff --git a/core/src/jsMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt b/core/src/jsMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt index 899423a6..1165ba28 100644 --- a/core/src/jsMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt +++ b/core/src/jsMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture import kotlin.reflect.KClass diff --git a/core/src/jvmMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt b/core/src/jvmMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt index 8f4fd0c2..4374262a 100644 --- a/core/src/jvmMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt +++ b/core/src/jvmMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture import java.util.concurrent.ConcurrentHashMap diff --git a/core/src/nativeMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt b/core/src/nativeMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt index d5a02b3e..710e6c35 100644 --- a/core/src/nativeMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt +++ b/core/src/nativeMain/kotlin/tech/antibytes/kfixture/ClassNameResolver.kt @@ -1,12 +1,14 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture +import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass // Ensure stable names diff --git a/detekt/baseline.xml b/detekt/baseline.xml index 92ac31cb..d2b0439b 100644 --- a/detekt/baseline.xml +++ b/detekt/baseline.xml @@ -1,40 +1,77 @@ - + - + - ArrayPrimitive:ArrayFixtureSpec.kt$ArrayFixtureSpec$Array<Int> - FunctionOnlyReturningConstant:DefaultPredicate.kt$@Suppress("UNUSED_PARAMETER") @PublishedApi internal fun <T> defaultPredicate(value: T): Boolean - FunctionOnlyReturningConstant:PublicApi.kt$@Suppress("UNUSED_PARAMETER") @PublishedApi internal fun <T> defaultPredicate(value: T): Boolean - LongParameterList:TupleFixture.kt$( type: KClass<Triple<*, *, *>>, firstQualifier: Qualifier? = null, firstGenerator: Function1<Qualifier?, First>, secondQualifier: Qualifier? = null, secondGenerator: Function1<Qualifier?, Second>, thirdQualifier: Qualifier? = null, thirdGenerator: Function1<Qualifier?, Third>, ) - MagicNumber:Dangerfile.df.kts$1000 - MagicNumber:Dangerfile.df.kts$20 - MagicNumber:Dangerfile.df.kts$2000 - MagicNumber:Dangerfile.df.kts$500 - MagicNumber:build.gradle.kts$0.90 - MagicNumber:build.gradle.kts$0.97 - MagicNumber:build.gradle.kts$8 - MagicNumber:settings.gradle.kts$30 + BracesOnWhenStatements:Dangerfile.df.kts$-> + BracesOnWhenStatements:DateTimeFixture.kt$-> + BracesOnWhenStatements:FilterableFixture.kt$-> + BracesOnWhenStatements:InstantFixtureSpec.kt$InstantFixtureSpec$-> + BracesOnWhenStatements:RangedFixture.kt$-> + BracesOnWhenStatements:RangedNumericArrayFixture.kt$-> + BracesOnWhenStatements:RangedSpecialArrayFixtureSpec.kt$RangedSpecialArrayFixtureSpec$-> + BracesOnWhenStatements:SignedNumericArrayFixture.kt$-> + BracesOnWhenStatements:SignedNumericFixture.kt$-> + CollapsibleIfStatements:Dangerfile.df.kts$if (isFeatureBranch) { if (!isFeatureTitle) { fail( "Title is not following our pattern:\n" + "\nAdd|Change|Remove|Fix|Bump|Security {Core or Plugin title}" ) } } + CollapsibleIfStatements:Dangerfile.df.kts$if (isReleaseBranch) { if (!isReleaseTitle) { fail( "Title is not following our pattern: Prepare Release major.minor.patch (1.2.0)" ) } } + ComplexCondition:Dangerfile.df.kts$!isFeatureBranch && !isBugfixBranch && !isReleaseBranch && !isDependabotBranch + ConstructorParameterNaming:StringQualifier.kt$StringQualifier$private val _value: String + ForbiddenComment:ClassNameResolver.kt$// TODO: since JS does not provide a package prefix, think about to make it more unique, while keeping the current behaviour + FunctionOnlyReturningConstant:DefaultPredicate.kt$@Suppress("UNUSED_PARAMETER") @PublishedApi internal fun <T> defaultPredicate(value: T): Boolean + FunctionOnlyReturningConstant:PublicApi.kt$@Suppress("UNUSED_PARAMETER") @PublishedApi internal fun <T> defaultPredicate(value: T): Boolean + LongParameterList:MapFixture.kt$( type: KClass<Map<*, *>>, keyQualifier: PublicApi.Qualifier? = null, keyGenerator: Function1<PublicApi.Qualifier?, Key>, valueQualifier: PublicApi.Qualifier? = null, valueGenerator: Function1<PublicApi.Qualifier?, Value>, size: Int? = null, ) + LongParameterList:MapFixture.kt$( type: KClass<MutableMap<*, *>>, keyQualifier: PublicApi.Qualifier? = null, keyGenerator: Function1<PublicApi.Qualifier?, Key>, valueQualifier: PublicApi.Qualifier? = null, valueGenerator: Function1<PublicApi.Qualifier?, Value>, size: Int? = null, ) + LongParameterList:TupleFixture.kt$( firstQualifier: Qualifier? = null, firstGenerator: Function1<Qualifier?, First>, secondQualifier: Qualifier? = null, secondGenerator: Function1<Qualifier?, Second>, thirdQualifier: Qualifier? = null, thirdGenerator: Function1<Qualifier?, Third>, ) + LongParameterList:TupleFixture.kt$( type: KClass<Triple<*, *, *>>, firstQualifier: Qualifier? = null, firstGenerator: Function1<Qualifier?, First>, secondQualifier: Qualifier? = null, secondGenerator: Function1<Qualifier?, Second>, thirdQualifier: Qualifier? = null, ) + LongParameterList:TupleFixture.kt$( type: KClass<Triple<*, *, *>>, firstQualifier: Qualifier? = null, firstGenerator: Function1<Qualifier?, First>, secondQualifier: Qualifier? = null, secondGenerator: Function1<Qualifier?, Second>, thirdQualifier: Qualifier? = null, thirdGenerator: Function1<Qualifier?, Third>, ) + LongParameterList:TupleFixture.kt$( type: KClass<Triple<*, *, *>>, firstQualifier: Qualifier? = null, firstGenerator: Function1<Qualifier?, First>, secondQualifier: Qualifier? = null, thirdQualifier: Qualifier? = null, thirdGenerator: Function1<Qualifier?, Third>, ) + LongParameterList:TupleFixture.kt$( type: KClass<Triple<*, *, *>>, firstQualifier: Qualifier? = null, secondQualifier: Qualifier? = null, secondGenerator: Function1<Qualifier?, Second>, thirdQualifier: Qualifier? = null, thirdGenerator: Function1<Qualifier?, Third>, ) MaxLineLength:Dangerfile.df.kts$val - MaxLineLength:DateTimeFixture.kt$generator !is LocalizedDateTimeGenerator<*> -> throw IllegalStateException("Missing Generator for ClassID ($id).") - MaxLineLength:GradlePlugin.kt$GradlePlugin$const val runtimeConfig = "tech.antibytes.gradle-plugins:antibytes-runtime-configuration:${Version.Gradle.antibytes}" - MaxLineLength:TupleFixture.kt$public - MaxLineLength:build.gradle.kts$config = files("$projectDir/detekt/config.yml") + MaxLineLength:MapFixtureSpec.kt$MapFixtureSpec$fun + StringShouldBeRawString:Dangerfile.df.kts$"(?:(?:Prepare )?Release \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(?:-rc\\d{1,3})?)" + StringShouldBeRawString:Dangerfile.df.kts$"(?:(?:\\[[A-Z]{2,8}-\\d{1,6}\\]\\s)?(?:Add|Change|Remove|Fix|Bump|Security)\\s.*)" + StringShouldBeRawString:Dangerfile.df.kts$"(?:release\\/(?:\\d{1,3}\\.\\d{1,3}(?:\\.\\d{1,3})?(?:-rc\\d{1,3})?)(?:\\/prepare-\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(?:-rc\\d{1,3})?)?)" + StringShouldBeRawString:Dangerfile.df.kts$"Branch name is not following our pattern:\n" + "\nrelease/1.2(.3)(/prepare-1.2.3)\n" + "\nfeature/add|change|remove|fix|bump|security-feature-title\n" + "\n\n" + "\n Current name: $branchName" + StringShouldBeRawString:build.gradle.kts$"^tech\\.antibytes\\.[\\.a-z\\-]+" + StringShouldBeRawString:settings.gradle.kts$"^tech\\.antibytes\\.[\\.a-z\\-]+" ThrowsCount:InstantGenerator.kt$InstantGenerator$private fun guardRange( from: Long, to: Long, ) TooManyFunctions:MapFixture.kt$tech.antibytes.kfixture.MapFixture.kt - TooManyFunctions:RandomWrapper.kt$RandomWrapper : Random TooManyFunctions:RangedSpecialArrayFixture.kt$tech.antibytes.kfixture.RangedSpecialArrayFixture.kt TooManyFunctions:TupleFixture.kt$tech.antibytes.kfixture.TupleFixture.kt - UnusedPrivateMember:JsJodaTimeZoneModule.kt$private val jsJodaTz = JsJodaTimeZoneModule - UnusedPrivateMember:build.gradle.kts$val androidMain by getting { dependsOn(noJsMain) dependencies { implementation(Dependency.multiplatform.kotlin.android) } } - UnusedPrivateMember:build.gradle.kts$val androidTest by getting { dependsOn(noJsTest) dependsOn(androidAndroidTestRelease) dependsOn(androidTestFixtures) dependsOn(androidTestFixturesDebug) dependsOn(androidTestFixturesRelease) dependencies { implementation(Dependency.multiplatform.test.jvm) implementation(Dependency.multiplatform.test.junit) } } - UnusedPrivateMember:build.gradle.kts$val iosSimulatorArm64Main by getting { dependsOn(iosMain) } - UnusedPrivateMember:build.gradle.kts$val iosSimulatorArm64Test by getting { dependsOn(iosTest) } - UnusedPrivateMember:build.gradle.kts$val jsMain by getting { dependencies { implementation(Dependency.multiplatform.kotlin.js) implementation(Dependency.js.nodejs) } } - UnusedPrivateMember:build.gradle.kts$val jsTest by getting { dependencies { implementation(Dependency.multiplatform.test.js) implementation(npm(LocalDependency.npm.joda.name, LocalDependency.npm.joda.version)) } } - UnusedPrivateMember:build.gradle.kts$val jsTest by getting { dependencies { implementation(Dependency.multiplatform.test.js) } } - UnusedPrivateMember:build.gradle.kts$val jvmMain by getting { dependsOn(noJsMain) dependencies { implementation(Dependency.multiplatform.kotlin.jdk8) } } - UnusedPrivateMember:build.gradle.kts$val jvmTest by getting { dependsOn(noJsTest) dependencies { implementation(Dependency.multiplatform.test.jvm) implementation(Dependency.multiplatform.test.junit) } } - UnusedPrivateMember:build.gradle.kts$val linuxX64Main by getting { dependsOn(otherMain) } - UnusedPrivateMember:build.gradle.kts$val linuxX64Test by getting { dependsOn(otherTest) } + UnnecessaryParentheses:FloatGeneratorSpec.kt$FloatGeneratorSpec$(-expectedFloat) + UnnecessaryParentheses:FloatGeneratorSpec.kt$FloatGeneratorSpec$(expected + expectedFloat) + UnnecessaryParentheses:UIntegerGeneratorSpec.kt$UIntegerGeneratorSpec$((expectedMax.toInt() xor Int.MIN_VALUE) + 1) + UnnecessaryParentheses:ULongGeneratorSpec.kt$ULongGeneratorSpec$((expectedMax.toLong() xor Long.MIN_VALUE) + 1) + UnusedImports:build.gradle.kts$import tech.antibytes.gradle.dependency.helper.customArtifact + UnusedPrivateProperty:build.gradle.kts$val androidMain by getting { dependsOn(noJsMain) dependencies { implementation(antibytesCatalog.jvm.kotlin.stdlib.jdk8) } } + UnusedPrivateProperty:build.gradle.kts$val androidUnitTest by getting { dependencies { implementation(antibytesCatalog.jvm.test.kotlin.core) implementation(antibytesCatalog.jvm.test.kotlin.junit4) } } + UnusedPrivateProperty:build.gradle.kts$val appleMain by getting { dependsOn(nativeMain) } + UnusedPrivateProperty:build.gradle.kts$val appleTest by getting { dependsOn(nativeTest) } + UnusedPrivateProperty:build.gradle.kts$val jsMain by getting { dependencies { implementation(antibytesCatalog.js.kotlin.stdlib) implementation(antibytesCatalog.js.kotlinx.nodeJs) nodePeerPackage(local.node.jsJodaTimezone) } } + UnusedPrivateProperty:build.gradle.kts$val jsMain by getting { dependencies { implementation(antibytesCatalog.js.kotlin.stdlib) implementation(antibytesCatalog.js.kotlinx.nodeJs) } } + UnusedPrivateProperty:build.gradle.kts$val jsTest by getting { dependencies { implementation(antibytesCatalog.js.test.kotlin.core) nodeProductionPackage(local.node.jsJodaTimezone) } } + UnusedPrivateProperty:build.gradle.kts$val jsTest by getting { dependencies { implementation(antibytesCatalog.js.test.kotlin.core) } } + UnusedPrivateProperty:build.gradle.kts$val jvmMain by getting { dependsOn(noJsMain) } + UnusedPrivateProperty:build.gradle.kts$val jvmTest by getting { dependsOn(noJsTest) dependencies { implementation(antibytesCatalog.jvm.test.kotlin.core) implementation(antibytesCatalog.jvm.test.kotlin.junit4) } } + UnusedPrivateProperty:build.gradle.kts$val linuxX64Main by getting { dependsOn(nativeMain) } + UnusedPrivateProperty:build.gradle.kts$val linuxX64Test by getting { dependsOn(nativeTest) } + UnusedPrivateProperty:build.gradle.kts$val mingwX64Main by getting { dependsOn(nativeMain) } + UnusedPrivateProperty:build.gradle.kts$val mingwX64Test by getting { dependsOn(nativeTest) } + UnusedPrivateProperty:build.gradle.kts$val nativeMain by getting { dependsOn(noJsMain) } + UnusedPrivateProperty:build.gradle.kts$val nativeTest by getting { dependsOn(noJsTest) } + UseCheckOrError:DateTimeFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:FilterableFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:Fixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:RangedFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:RangedNumericArrayFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:SignedNumericArrayFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseCheckOrError:SignedNumericFixture.kt$throw IllegalStateException("Missing Generator for ClassID ($id).") + UseIfInsteadOfWhen:InstantFixtureSpec.kt$InstantFixtureSpec$when (FixtureType::class) { Instant::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture<Long, Instant>( from = from as Long, to = to as Long, qualifier = qualifier, predicate = predicate as Function1<Long?, Boolean>, ) as FixtureType } else -> throw RuntimeException() } + UseIfInsteadOfWhen:InstantFixtureSpec.kt$InstantFixtureSpec$when (FixtureType::class) { Instant::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture<Long, Instant?>( from = from as Long, to = to as Long, qualifier = qualifier, predicate = predicate as Function1<Long?, Boolean>, ) as FixtureType? } else -> throw RuntimeException() } + UseIfInsteadOfWhen:InstantFixtureSpec.kt$InstantFixtureSpec$when (FixtureType::class) { Instant::class -> { fixture, range, qualifier, predicate -> fixture.fixture<Long, Instant>( range = range as ClosedRange<Long>, qualifier = qualifier, predicate = predicate as Function1<Long?, Boolean>, ) as FixtureType } else -> throw RuntimeException() } + UseIfInsteadOfWhen:InstantFixtureSpec.kt$InstantFixtureSpec$when (FixtureType::class) { Instant::class -> { fixture, range, qualifier, predicate -> fixture.fixture<Long, Instant?>( range = range as ClosedRange<Long>, qualifier = qualifier, predicate = predicate as Function1<Long?, Boolean>, ) as FixtureType? } else -> throw RuntimeException() } + UseRequire:InstantGenerator.kt$InstantGenerator$throw IllegalArgumentException("The lower bound of an Instant must be greater than $MIN_TIME_STAMP!") + UseRequire:InstantGenerator.kt$InstantGenerator$throw IllegalArgumentException("The upper bound of an Instant must be greater than lower bound!") + UseRequire:InstantGenerator.kt$InstantGenerator$throw IllegalArgumentException("The upper bound of an Instant must be smaller than $MAX_TIME_STAMP!") + UseRequire:SelectorGeneratorFactory.kt$SelectorGeneratorFactory$throw IllegalArgumentException("Missing selectable items!") diff --git a/detekt/config.yml b/detekt/config.yml new file mode 100644 index 00000000..7615608c --- /dev/null +++ b/detekt/config.yml @@ -0,0 +1,784 @@ +build: + maxIssues: 0 + excludeCorrectable: false + weights: + # complexity: 2 + # LongParameterList: 1 + # style: 1 + # comments: 1 + +config: + validation: true + warningsAsErrors: false + checkExhaustiveness: false + # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' + excludes: '' + +processors: + active: true + exclude: + - 'DetektProgressListener' + # - 'KtFileCountProcessor' + # - 'PackageCountProcessor' + # - 'ClassCountProcessor' + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ProjectComplexityProcessor' + # - 'ProjectCognitiveComplexityProcessor' + # - 'ProjectLLOCProcessor' + # - 'ProjectCLOCProcessor' + # - 'ProjectLOCProcessor' + # - 'ProjectSLOCProcessor' + # - 'LicenseHeaderLoaderExtension' + +console-reports: + active: true + exclude: + - 'ProjectStatisticsReport' + - 'ComplexityReport' + - 'NotificationReport' + - 'FindingsReport' + - 'FileBasedFindingsReport' + # - 'LiteFindingsReport' + +output-reports: + active: true + exclude: + # - 'TxtOutputReport' + # - 'XmlOutputReport' + # - 'HtmlOutputReport' + # - 'MdOutputReport' + # - 'SarifOutputReport' + +comments: + active: true + AbsentOrWrongFileLicense: + active: false + licenseTemplateFile: 'license.template' + licenseTemplateIsRegex: false + CommentOverPrivateFunction: + active: false + CommentOverPrivateProperty: + active: false + DeprecatedBlockTag: + active: false + EndOfSentenceFormat: + active: false + endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' + KDocReferencesNonPublicProperty: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + OutdatedDocumentation: + active: false + matchTypeParameters: true + matchDeclarationsOrder: true + allowParamOnConstructorProperties: false + UndocumentedPublicClass: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + searchInProtectedClass: false + UndocumentedPublicFunction: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchProtectedFunction: false + UndocumentedPublicProperty: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchProtectedProperty: false + +complexity: + active: true + CognitiveComplexMethod: + active: false + threshold: 15 + ComplexCondition: + active: true + threshold: 4 + ComplexInterface: + active: false + threshold: 10 + includeStaticDeclarations: false + includePrivateDeclarations: false + ignoreOverloaded: false + CyclomaticComplexMethod: + active: true + threshold: 15 + ignoreSingleWhenExpression: false + ignoreSimpleWhenEntries: false + ignoreNestingFunctions: false + nestingFunctions: + - 'also' + - 'apply' + - 'forEach' + - 'isNotNull' + - 'ifNull' + - 'let' + - 'run' + - 'use' + - 'with' + LabeledExpression: + active: false + ignoredLabels: [] + LargeClass: + active: true + threshold: 600 + LongMethod: + active: true + threshold: 60 + LongParameterList: + active: true + functionThreshold: 6 + constructorThreshold: 7 + ignoreDefaultParameters: false + ignoreDataClasses: true + ignoreAnnotatedParameter: [] + MethodOverloading: + active: false + threshold: 6 + NamedArguments: + active: false + threshold: 3 + ignoreArgumentsMatchingNames: false + NestedBlockDepth: + active: true + threshold: 4 + NestedScopeFunctions: + active: false + threshold: 1 + functions: + - 'kotlin.apply' + - 'kotlin.run' + - 'kotlin.with' + - 'kotlin.let' + - 'kotlin.also' + ReplaceSafeCallChainWithRun: + active: false + StringLiteralDuplication: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + threshold: 3 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + thresholdInFiles: 11 + thresholdInClasses: 11 + thresholdInInterfaces: 11 + thresholdInObjects: 11 + thresholdInEnums: 11 + ignoreDeprecated: false + ignorePrivate: false + ignoreOverridden: false + +coroutines: + active: true + GlobalCoroutineUsage: + active: false + InjectDispatcher: + active: true + dispatcherNames: + - 'IO' + - 'Default' + - 'Unconfined' + RedundantSuspendModifier: + active: true + SleepInsteadOfDelay: + active: true + SuspendFunSwallowedCancellation: + active: false + SuspendFunWithCoroutineScopeReceiver: + active: false + SuspendFunWithFlowReturnType: + active: true + +empty-blocks: + active: true + EmptyCatchBlock: + active: true + allowedExceptionNameRegex: '_|(ignore|expected).*' + EmptyClassBlock: + active: true + EmptyDefaultConstructor: + active: true + EmptyDoWhileBlock: + active: true + EmptyElseBlock: + active: true + EmptyFinallyBlock: + active: true + EmptyForBlock: + active: true + EmptyFunctionBlock: + active: true + ignoreOverridden: false + EmptyIfBlock: + active: true + EmptyInitBlock: + active: true + EmptyKtFile: + active: true + EmptySecondaryConstructor: + active: true + EmptyTryBlock: + active: true + EmptyWhenBlock: + active: true + EmptyWhileBlock: + active: true + +exceptions: + active: true + ExceptionRaisedInUnexpectedLocation: + active: true + methodNames: + - 'equals' + - 'finalize' + - 'hashCode' + - 'toString' + InstanceOfCheckForException: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + NotImplementedDeclaration: + active: false + ObjectExtendsThrowable: + active: false + PrintStackTrace: + active: true + RethrowCaughtException: + active: true + ReturnFromFinally: + active: true + ignoreLabeled: false + SwallowedException: + active: true + ignoredExceptionTypes: + - 'InterruptedException' + - 'MalformedURLException' + - 'NumberFormatException' + - 'ParseException' + allowedExceptionNameRegex: '_|(ignore|expected).*' + ThrowingExceptionFromFinally: + active: true + ThrowingExceptionInMain: + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptions: + - 'ArrayIndexOutOfBoundsException' + - 'Exception' + - 'IllegalArgumentException' + - 'IllegalMonitorStateException' + - 'IllegalStateException' + - 'IndexOutOfBoundsException' + - 'NullPointerException' + - 'RuntimeException' + - 'Throwable' + ThrowingNewInstanceOfSameException: + active: true + TooGenericExceptionCaught: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptionNames: + - 'ArrayIndexOutOfBoundsException' + - 'Error' + - 'Exception' + - 'IllegalMonitorStateException' + - 'IndexOutOfBoundsException' + - 'NullPointerException' + - 'RuntimeException' + - 'Throwable' + allowedExceptionNameRegex: '_|(ignore|expected).*' + TooGenericExceptionThrown: + active: true + exceptionNames: + - 'Error' + - 'Exception' + - 'RuntimeException' + - 'Throwable' + +naming: + active: true + BooleanPropertyNaming: + active: false + allowedPattern: '^(is|has|are)' + ClassNaming: + active: true + classPattern: '[A-Z][a-zA-Z0-9]*' + ConstructorParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + privateParameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + EnumNaming: + active: true + enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + forbiddenName: [] + FunctionMaxLength: + active: false + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + minimumFunctionNameLength: 3 + FunctionNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + functionPattern: '[a-z][a-zA-Z0-9]*' + excludeClassPattern: '$^' + FunctionParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + InvalidPackageDeclaration: + active: true + rootPackage: '' + requireRootInDeclaration: false + LambdaParameterNaming: + active: false + parameterPattern: '[a-z][A-Za-z0-9]*|_' + MatchingDeclarationName: + active: true + mustBeFirst: true + MemberNameEqualsClassName: + active: true + ignoreOverridden: true + NoNameShadowing: + active: true + NonBooleanPropertyPrefixedWithIs: + active: false + ObjectPropertyNaming: + active: true + constantPattern: '[A-Za-z][_A-Za-z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: true + packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' + TopLevelPropertyNaming: + active: true + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' + VariableMaxLength: + active: false + maximumVariableNameLength: 64 + VariableMinLength: + active: false + minimumVariableNameLength: 1 + VariableNaming: + active: true + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + +performance: + active: true + ArrayPrimitive: + active: true + CouldBeSequence: + active: false + threshold: 3 + ForEachOnRange: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + SpreadOperator: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + UnnecessaryPartOfBinaryExpression: + active: false + UnnecessaryTemporaryInstantiation: + active: true + +potential-bugs: + active: true + AvoidReferentialEquality: + active: true + forbiddenTypePatterns: + - 'kotlin.String' + CastNullableToNonNullableType: + active: false + CastToNullableType: + active: false + Deprecation: + active: false + DontDowncastCollectionTypes: + active: false + DoubleMutabilityForCollection: + active: true + mutableTypes: + - 'kotlin.collections.MutableList' + - 'kotlin.collections.MutableMap' + - 'kotlin.collections.MutableSet' + - 'java.util.ArrayList' + - 'java.util.LinkedHashSet' + - 'java.util.HashSet' + - 'java.util.LinkedHashMap' + - 'java.util.HashMap' + ElseCaseInsteadOfExhaustiveWhen: + active: false + ignoredSubjectTypes: [] + EqualsAlwaysReturnsTrueOrFalse: + active: true + EqualsWithHashCodeExist: + active: true + ExitOutsideMain: + active: false + ExplicitGarbageCollectionCall: + active: true + HasPlatformType: + active: true + IgnoredReturnValue: + active: true + restrictToConfig: true + returnValueAnnotations: + - 'CheckResult' + - '*.CheckResult' + - 'CheckReturnValue' + - '*.CheckReturnValue' + ignoreReturnValueAnnotations: + - 'CanIgnoreReturnValue' + - '*.CanIgnoreReturnValue' + returnValueTypes: + - 'kotlin.sequences.Sequence' + - 'kotlinx.coroutines.flow.*Flow' + - 'java.util.stream.*Stream' + ignoreFunctionCall: [] + ImplicitDefaultLocale: + active: true + ImplicitUnitReturnType: + active: false + allowExplicitReturnType: true + InvalidRange: + active: true + IteratorHasNextCallsNextMethod: + active: true + IteratorNotThrowingNoSuchElementException: + active: true + LateinitUsage: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + ignoreOnClassesPattern: '' + MapGetWithNotNullAssertionOperator: + active: true + MissingPackageDeclaration: + active: false + excludes: ['**/*.kts'] + NullCheckOnMutableProperty: + active: false + NullableToStringCall: + active: false + PropertyUsedBeforeDeclaration: + active: false + UnconditionalJumpStatementInLoop: + active: false + UnnecessaryNotNullCheck: + active: false + UnnecessaryNotNullOperator: + active: true + UnnecessarySafeCall: + active: true + UnreachableCatchBlock: + active: true + UnreachableCode: + active: true + UnsafeCallOnNullableType: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + UnsafeCast: + active: true + UnusedUnaryOperator: + active: true + UselessPostfixExpression: + active: true + WrongEqualsTypeParameter: + active: true + +style: + active: true + AlsoCouldBeApply: + active: false + BracesOnIfStatements: + active: false + singleLine: 'never' + multiLine: 'always' + BracesOnWhenStatements: + active: false + singleLine: 'necessary' + multiLine: 'consistent' + CanBeNonNullable: + active: false + CascadingCallWrapping: + active: false + includeElvis: true + ClassOrdering: + active: false + CollapsibleIfStatements: + active: false + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: + - 'to' + allowOperators: false + DataClassShouldBeImmutable: + active: false + DestructuringDeclarationWithTooManyEntries: + active: true + maxDestructuringEntries: 3 + DoubleNegativeLambda: + active: false + negativeFunctions: + - reason: 'Use `takeIf` instead.' + value: 'takeUnless' + - reason: 'Use `all` instead.' + value: 'none' + negativeFunctionNameParts: + - 'not' + - 'non' + EqualsNullCall: + active: true + EqualsOnSignatureLine: + active: false + ExplicitCollectionElementAccessMethod: + active: false + ExplicitItLambdaParameter: + active: true + ExpressionBodySyntax: + active: false + includeLineWrapping: false + ForbiddenAnnotation: + active: false + annotations: + - reason: 'it is a java annotation. Use `Suppress` instead.' + value: 'java.lang.SuppressWarnings' + - reason: 'it is a java annotation. Use `kotlin.Deprecated` instead.' + value: 'java.lang.Deprecated' + - reason: 'it is a java annotation. Use `kotlin.annotation.MustBeDocumented` instead.' + value: 'java.lang.annotation.Documented' + - reason: 'it is a java annotation. Use `kotlin.annotation.Target` instead.' + value: 'java.lang.annotation.Target' + - reason: 'it is a java annotation. Use `kotlin.annotation.Retention` instead.' + value: 'java.lang.annotation.Retention' + - reason: 'it is a java annotation. Use `kotlin.annotation.Repeatable` instead.' + value: 'java.lang.annotation.Repeatable' + - reason: 'Kotlin does not support @Inherited annotation, see https://youtrack.jetbrains.com/issue/KT-22265' + value: 'java.lang.annotation.Inherited' + ForbiddenComment: + active: true + comments: + - reason: 'Forbidden FIXME todo marker in comment, please fix the problem.' + value: 'FIXME:' + - reason: 'Forbidden STOPSHIP todo marker in comment, please address the problem before shipping the code.' + value: 'STOPSHIP:' + - reason: 'Forbidden TODO todo marker in comment, please do the changes.' + value: 'TODO:' + allowedPatterns: '' + ForbiddenImport: + active: false + imports: [] + forbiddenPatterns: '' + ForbiddenMethodCall: + active: false + methods: + - reason: 'print does not allow you to configure the output stream. Use a logger instead.' + value: 'kotlin.io.print' + - reason: 'println does not allow you to configure the output stream. Use a logger instead.' + value: 'kotlin.io.println' + ForbiddenSuppress: + active: false + rules: [] + ForbiddenVoid: + active: true + ignoreOverridden: false + ignoreUsageInGenerics: false + FunctionOnlyReturningConstant: + active: true + ignoreOverridableFunction: true + ignoreActualFunction: true + excludedFunctions: [] + LoopWithTooManyJumpStatements: + active: true + maxJumpCount: 1 + MagicNumber: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/*.kts'] + ignoreNumbers: + - '-1' + - '0' + - '1' + - '2' + ignoreHashCodeFunction: true + ignorePropertyDeclaration: false + ignoreLocalVariableDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + ignoreRanges: false + ignoreExtensionFunctions: true + MandatoryBracesLoops: + active: false + MaxChainedCallsOnSameLine: + active: false + maxChainedCalls: 5 + MaxLineLength: + active: true + maxLineLength: 120 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: false + excludeRawStrings: true + MayBeConst: + active: true + ModifierOrder: + active: true + MultilineLambdaItParameter: + active: false + MultilineRawStringIndentation: + active: false + indentSize: 4 + trimmingMethods: + - 'trimIndent' + - 'trimMargin' + NestedClassesVisibility: + active: true + NewLineAtEndOfFile: + active: true + NoTabs: + active: false + NullableBooleanCheck: + active: false + ObjectLiteralToLambda: + active: true + OptionalAbstractKeyword: + active: true + OptionalUnit: + active: false + PreferToOverPairSyntax: + active: false + ProtectedMemberInFinalClass: + active: true + RedundantExplicitType: + active: false + RedundantHigherOrderMapUsage: + active: true + RedundantVisibilityModifierRule: + active: false + ReturnCount: + active: true + max: 2 + excludedFunctions: + - 'equals' + excludeLabeled: false + excludeReturnFromLambda: true + excludeGuardClauses: false + SafeCast: + active: true + SerialVersionUIDInSerializableClass: + active: true + SpacingBetweenPackageAndImports: + active: false + StringShouldBeRawString: + active: false + maxEscapedCharacterCount: 2 + ignoredCharacters: [] + ThrowsCount: + active: true + max: 2 + excludeGuardClauses: false + TrailingWhitespace: + active: false + TrimMultilineRawString: + active: false + trimmingMethods: + - 'trimIndent' + - 'trimMargin' + UnderscoresInNumericLiterals: + active: false + acceptableLength: 4 + allowNonStandardGrouping: false + UnnecessaryAbstractClass: + active: true + UnnecessaryAnnotationUseSiteTarget: + active: false + UnnecessaryApply: + active: true + UnnecessaryBackticks: + active: false + UnnecessaryBracesAroundTrailingLambda: + active: false + UnnecessaryFilter: + active: true + UnnecessaryInheritance: + active: true + UnnecessaryInnerClass: + active: false + UnnecessaryLet: + active: false + UnnecessaryParentheses: + active: false + allowForUnclearPrecedence: false + UntilInsteadOfRangeTo: + active: false + UnusedImports: + active: false + UnusedParameter: + active: true + allowedNames: 'ignored|expected' + UnusedPrivateClass: + active: true + UnusedPrivateMember: + active: true + allowedNames: '' + UnusedPrivateProperty: + active: true + allowedNames: '_|ignored|expected|serialVersionUID' + UseAnyOrNoneInsteadOfFind: + active: true + UseArrayLiteralsInAnnotations: + active: true + UseCheckNotNull: + active: true + UseCheckOrError: + active: true + UseDataClass: + active: false + allowVars: false + UseEmptyCounterpart: + active: false + UseIfEmptyOrIfBlank: + active: false + UseIfInsteadOfWhen: + active: false + ignoreWhenContainingVariableDeclaration: false + UseIsNullOrEmpty: + active: true + UseLet: + active: false + UseOrEmpty: + active: true + UseRequire: + active: true + UseRequireNotNull: + active: true + UseSumOfInsteadOfFlatMapSize: + active: false + UselessCallOnNotNull: + active: true + UtilityClassWithPublicConstructor: + active: true + VarCouldBeVal: + active: true + ignoreLateinitVar: false + WildcardImport: + active: true + excludeImports: + - 'java.util.*' diff --git a/gradle.properties b/gradle.properties index fd818b03..3466a81e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,17 +15,14 @@ kotlin.mpp.stability.nowarn=true kotlin.code.style=official # Native kotlin.native.ignoreIncorrectDependencies=true -kotlin.mpp.enableCompatibilityMetadataVariant=true kotlin.mpp.enableCInteropCommonization=true kotlin.native.cacheKind=none -kotlin.native.osVersionMin.ios_x64=14.0 -kotlin.native.osVersionMin.ios_arm64=14.0 -kotlin.native.osVersionMin.ios_arm32=14.0 -kotlin.native.osVersionMin.ios_simulator_arm64=14.0 -kotlin.native.binary.memoryModel=experimental +kotlin.native.osVersionMin.ios_x64=15.0 +kotlin.native.osVersionMin.ios_arm64=15.0 +kotlin.native.osVersionMin.ios_arm32=15.0 +kotlin.native.osVersionMin.ios_simulator_arm64=15.0 # Android android.useAndroidX=true android.enableJetifier=false -android.disableAutomaticComponentCreation=true # see: https://github.com/robolectric/robolectric/issues/6521 android.jetifier.ignorelist=bcprov diff --git a/gradle/package.json b/gradle/package.json index 2973cb06..411ea750 100644 --- a/gradle/package.json +++ b/gradle/package.json @@ -7,7 +7,7 @@ "devDependencies": {}, "dependencies": {}, "peerDependencies": { - "@js-joda/timezone": "~2.11.1" + "@js-joda/timezone": "~2.18.2" }, "optionalDependencies": {} } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832..7f93135c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5a..8838ba97 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index f127cfd4..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/ktx-datetime/api/android/ktx-datetime.api b/ktx-datetime/api/android/ktx-datetime.api index 44a3f7d9..13e61292 100644 --- a/ktx-datetime/api/android/ktx-datetime.api +++ b/ktx-datetime/api/android/ktx-datetime.api @@ -1,10 +1,3 @@ -public final class tech/antibytes/kfixture/ktx/datetime/BuildConfig { - public static final field BUILD_TYPE Ljava/lang/String; - public static final field DEBUG Z - public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; - public fun ()V -} - public final class tech/antibytes/kfixture/ktx/datetime/DefaultPredicateKt { public static final fun defaultPredicate (Ljava/lang/Object;)Z } diff --git a/ktx-datetime/build.gradle.kts b/ktx-datetime/build.gradle.kts index 32d22fd4..291b9474 100644 --- a/ktx-datetime/build.gradle.kts +++ b/ktx-datetime/build.gradle.kts @@ -10,9 +10,7 @@ import tech.antibytes.gradle.coverage.api.JacocoVerificationRule import tech.antibytes.gradle.coverage.CoverageApiContract.JacocoCounter import tech.antibytes.gradle.coverage.CoverageApiContract.JacocoMeasurement import tech.antibytes.gradle.configuration.apple.ensureAppleDeviceCompatibility - import tech.antibytes.gradle.configuration.sourcesets.appleWithLegacy -import tech.antibytes.gradle.configuration.sourcesets.setupAndroidTest import tech.antibytes.gradle.dependency.helper.nodePeerPackage import tech.antibytes.gradle.dependency.helper.nodeProductionPackage import tech.antibytes.gradle.kfixture.config.publishing.FixtureKtxDateTimeConfiguration @@ -85,7 +83,7 @@ android { } kotlin { - android() + androidTarget() js(IR) { nodejs() @@ -136,9 +134,7 @@ kotlin { } } - setupAndroidTest() - - val androidTest by getting { + val androidUnitTest by getting { dependencies { implementation(antibytesCatalog.jvm.test.kotlin.core) implementation(antibytesCatalog.jvm.test.kotlin.junit4) diff --git a/ktx-datetime/src/androidTest/kotlin/tech/antibytes/kfixture/ktx/datetime/generator/TimeZoneGeneratorSpec.kt b/ktx-datetime/src/androidUnitTest/kotlin/tech/antibytes/kfixture/ktx/datetime/generator/TimeZoneGeneratorSpec.kt similarity index 100% rename from ktx-datetime/src/androidTest/kotlin/tech/antibytes/kfixture/ktx/datetime/generator/TimeZoneGeneratorSpec.kt rename to ktx-datetime/src/androidUnitTest/kotlin/tech/antibytes/kfixture/ktx/datetime/generator/TimeZoneGeneratorSpec.kt diff --git a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/Setup.kt b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/Setup.kt index a58be72e..82fa8e0b 100644 --- a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/Setup.kt +++ b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/Setup.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture.ktx.datetime import kotlinx.datetime.DatePeriod diff --git a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/DateTimeFixture.kt b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/DateTimeFixture.kt index 2e9136a0..faeb3011 100644 --- a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/DateTimeFixture.kt +++ b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/DateTimeFixture.kt @@ -1,11 +1,10 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ -@file:Suppress("OPT_IN_USAGE") +@file:Suppress("OPT_IN_USAGE", "ktlint:standard:filename") package tech.antibytes.kfixture.ktx.datetime.fixture diff --git a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixture.kt b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixture.kt index 58c5b996..c6812a18 100644 --- a/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixture.kt +++ b/ktx-datetime/src/commonMain/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixture.kt @@ -1,10 +1,11 @@ -/* ktlint-disable filename */ /* * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. * * Use of this source code is governed by Apache v2.0 */ +@file:Suppress("ktlint:standard:filename") + package tech.antibytes.kfixture.ktx.datetime.fixture import kotlin.jvm.JvmName diff --git a/ktx-datetime/src/commonTest/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixtureSpec.kt b/ktx-datetime/src/commonTest/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixtureSpec.kt index 2cfcab26..c51c953f 100644 --- a/ktx-datetime/src/commonTest/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixtureSpec.kt +++ b/ktx-datetime/src/commonTest/kotlin/tech/antibytes/kfixture/ktx/datetime/fixture/InstantFixtureSpec.kt @@ -55,7 +55,8 @@ class InstantFixtureSpec { RangeType, PublicApi.Qualifier?, Function1, - FixtureType,> { + FixtureType, + > { return when (FixtureType::class) { Instant::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture( @@ -76,7 +77,8 @@ class InstantFixtureSpec { RangeType, PublicApi.Qualifier?, Function1, - FixtureType?,> { + FixtureType?, + > { return when (FixtureType::class) { Instant::class -> { fixture, from, to, qualifier, predicate -> fixture.fixture( @@ -641,7 +643,8 @@ class InstantFixtureSpec { ClosedRange>, PublicApi.Qualifier?, Function1, - FixtureType,> { + FixtureType, + > { return when (FixtureType::class) { Instant::class -> { fixture, range, qualifier, predicate -> fixture.fixture( @@ -660,7 +663,8 @@ class InstantFixtureSpec { ClosedRange>, PublicApi.Qualifier?, Function1, - FixtureType?,> { + FixtureType?, + > { return when (FixtureType::class) { Instant::class -> { fixture, range, qualifier, predicate -> fixture.fixture( diff --git a/ktx-datetime/src/jsTest/kotlin/tech/antibytes/kfixture/ktx/datetime/JsJodaTimeZoneModule.kt b/ktx-datetime/src/jsTest/kotlin/tech/antibytes/kfixture/ktx/datetime/JsJodaTimeZoneModule.kt index 8540649d..33208a01 100644 --- a/ktx-datetime/src/jsTest/kotlin/tech/antibytes/kfixture/ktx/datetime/JsJodaTimeZoneModule.kt +++ b/ktx-datetime/src/jsTest/kotlin/tech/antibytes/kfixture/ktx/datetime/JsJodaTimeZoneModule.kt @@ -10,4 +10,5 @@ package tech.antibytes.kfixture.ktx.datetime @JsNonModule external object JsJodaTimeZoneModule +@Suppress("unused") private val jsJodaTz = JsJodaTimeZoneModule diff --git a/settings.gradle.kts b/settings.gradle.kts index 7182e259..0f1f5d29 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,6 +6,8 @@ import tech.antibytes.gradle.dependency.node.nodeToDependencyCatalog import tech.antibytes.gradle.dependency.settings.localGithub +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + pluginManagement { repositories { val antibytesPlugins = "^tech\\.antibytes\\.[\\.a-z\\-]+" @@ -28,7 +30,7 @@ pluginManagement { } plugins { - id("tech.antibytes.gradle.dependency.settings") version "0e82305" + id("tech.antibytes.gradle.dependency.settings") version "cfd6317" } includeBuild("setup") @@ -45,7 +47,7 @@ dependencyResolutionManagement { include( ":core", ":ktx-datetime", - ":docs" + ":docs", ) buildCache { diff --git a/setup/settings.gradle.kts b/setup/settings.gradle.kts index f964cb36..0c707f22 100644 --- a/setup/settings.gradle.kts +++ b/setup/settings.gradle.kts @@ -25,5 +25,7 @@ pluginManagement { } plugins { - id("tech.antibytes.gradle.dependency.settings") version "0e82305" + id("tech.antibytes.gradle.dependency.settings") version "cfd6317" } + +rootProject.name = "setup"