From 29327e23c17b7727740657ddc98f2e41147baa6e Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Wed, 5 Nov 2025 23:06:37 +0530 Subject: [PATCH 1/6] - Configure detekt plugin on core module - Run detekt on PR actions like opened, reopened, synchronised - baseline for detekt has been setup --- .github/workflows/pr_tests.yml | 19 +- build.gradle.kts | 1 + core/build.gradle.kts | 31 +- core/detekt-baseline.xml | 249 +++++++++++ detekt.yml | 786 +++++++++++++++++++++++++++++++++ gradle/libs.versions.toml | 4 +- 6 files changed, 1087 insertions(+), 3 deletions(-) create mode 100644 core/detekt-baseline.xml create mode 100644 detekt.yml diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index 5e7d0660..7005b102 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -2,7 +2,7 @@ name: PR Unit Tests on: pull_request: - types: [opened, reopened, synchronize] + types: [ opened, reopened, synchronize ] permissions: contents: read @@ -35,6 +35,23 @@ jobs: - name: Run unit tests run: ./gradlew --no-daemon jvmTest + - name: Run Detekt (core module) + run: ./gradlew --no-daemon --console=plain :core:detekt + + - name: Show Detekt summary + if: always() + run: | + SUMMARY_MD=core/build/reports/detekt/detekt.md + SUMMARY_TXT=core/build/reports/detekt/detekt.txt + if [ -f "$SUMMARY_MD" ]; then + echo "Detekt summary (markdown):" + cat "$SUMMARY_MD" + elif [ -f "$SUMMARY_TXT" ]; then + echo "Detekt summary (text):" + cat "$SUMMARY_TXT" + else + echo "Detekt report not found." + fi - name: Verify test reports exist run: | diff --git a/build.gradle.kts b/build.gradle.kts index e72c5f78..cee4737b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.android.library).apply(false) alias(libs.plugins.compose.hotreload) apply false alias(libs.plugins.nexus.publish) + alias(libs.plugins.detekt).apply(false) } nexusPublishing { diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 3b6a5143..95fa970d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,6 +1,7 @@ @file:Suppress("UnstableApiUsage") @file:OptIn(ExperimentalKotlinGradlePluginApi::class) +import io.gitlab.arturbosch.detekt.Detekt import org.jetbrains.compose.internal.utils.getLocalProperty import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -12,6 +13,8 @@ plugins { alias(libs.plugins.compose.hotreload) alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.library) + alias(libs.plugins.detekt) + id("maven-publish") id("signing") } @@ -124,7 +127,33 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } } - +val detektSourceDirs = listOf( + "src/commonMain/kotlin", + "src/cmpMain/kotlin", + "src/androidMain/kotlin", + "src/jvmMain/kotlin", + "src/iosMain/kotlin", + "src/webMain/kotlin" +).map(::file).filter(File::exists) + +detekt { + buildUponDefaultConfig = true + config.setFrom(files(rootProject.file("detekt.yml"))) + ignoreFailures = true + parallel = true + source.setFrom(detektSourceDirs) + baseline = file("$projectDir/detekt-baseline.xml") +} +// +tasks.withType().configureEach { + jvmTarget = JvmTarget.JVM_17.target + reports { + html.required.set(true) + xml.required.set(true) + txt.required.set(true) + sarif.required.set(false) + } +} val javadocJar = tasks.create("javadocJar") { archiveClassifier.set("javadoc") duplicatesStrategy = DuplicatesStrategy.EXCLUDE diff --git a/core/detekt-baseline.xml b/core/detekt-baseline.xml new file mode 100644 index 00000000..610d59b4 --- /dev/null +++ b/core/detekt-baseline.xml @@ -0,0 +1,249 @@ + + + + + ComplexCondition:ScrollArea.kt$<no name provided>$isOverscrollTop || isOverscrollBottom || isOverscrollLeft || isOverscrollRight + ConstructorParameterNaming:Dialog.kt$DialogState$____deprecated_constructor: Unit + CyclomaticComplexMethod:BottomSheet.kt$@Composable fun BottomSheetScope.DragIndication( modifier: Modifier = Modifier, indication: Indication = LocalIndication.current, interactionSource: MutableInteractionSource? = null, ) + CyclomaticComplexMethod:ColoredIndication.kt$ColoredIndication.ColoredIndicationInstance$override fun onAttach() + CyclomaticComplexMethod:Slider.kt$private fun Modifier.sliderKeyboardInteractions(enabled: Boolean, state: SliderState): Modifier + CyclomaticComplexMethod:TabGroup.kt$@Composable fun TabList( modifier: Modifier = Modifier, shape: Shape = RectangleShape, backgroundColor: Color = Color.Unspecified, contentColor: Color = Color.Unspecified, contentPadding: PaddingValues = NoPadding, orientation: Orientation = Orientation.Horizontal, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalAlignment: Alignment.Vertical = Alignment.Top, content: @Composable RowScope.() -> Unit ) + CyclomaticComplexMethod:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") @Composable fun TextField( value: String, onValueChange: (String) -> Unit, editable: Boolean = true, modifier: Modifier = Modifier, contentPadding: PaddingValues = NoPadding, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, placeholder: String = "", contentColor: Color = LocalContentColor.current, disabledColor: Color = contentColor.copy(0.66f), backgroundColor: Color = Color.Unspecified, borderWidth: Dp = 1.dp, borderColor: Color = Color.Unspecified, shape: Shape = RectangleShape, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign = TextAlign.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, singleLine: Boolean = false, minLines: Int = 1, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource? = null, spacing: Dp = 8.dp, visualTransformation: VisualTransformation = VisualTransformation.None, verticalAlignment: Alignment.Vertical = Alignment.CenterVertically, ) + CyclomaticComplexMethod:Tooltip.kt$@Composable fun TooltipPanel( modifier: Modifier = Modifier, arrow: @Composable (TooltipArrowDirection) -> Unit, enter: EnterTransition = AppearInstantly, exit: ExitTransition = DisappearInstantly, content: @Composable () -> Unit ) + CyclomaticComplexMethod:deprecated.TabGroup.kt$@Composable fun TabGroupScope.TabList( modifier: Modifier = Modifier, shape: Shape = RectangleShape, backgroundColor: Color = Color.Unspecified, contentColor: Color = Color.Unspecified, contentPadding: PaddingValues = NoPadding, orientation: Orientation = Orientation.Horizontal, activateOnFocus: Boolean = true, content: @Composable RowScope.() -> Unit ) + EmptyFunctionBlock:AnchoredDraggable.kt$AnchoredDraggableNode${ } + ExplicitItLambdaParameter:TextField.kt${ it -> if (scope.isTrailingFocused.not() && scope.isLeadingFocused.not()) { // block any value changes, unless the actual text input is focused // this guards for cases where the onValueChange(it.text) textRange = it.selection } } + ForbiddenComment:ObjectFloatMap.kt$MutableObjectFloatMap$// TODO: We could just mark the entry as empty if there's a group + ForbiddenComment:ScatterMap.kt$// TODO: We could further reduce the work we do by always copying index 0 to + ForbiddenComment:ScatterMap.kt$MutableScatterMap$// TODO: We could just mark the entry as empty if there's a group + ForbiddenComment:ScatterMap.kt$MutableScatterMap.MutableMapWrapper$// TODO: See TODO on `MapWrapper` + ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: @Suppress required because of a lint check issue (b/294130025) + ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: While not mandatory, it would be pertinent to throw a + ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: the proliferation of inner classes causes unnecessary code to be + ForbiddenComment:ScatterSet.kt$MutableScatterSet$// TODO: We could just mark the element as empty if there's a group + InvalidPackageDeclaration:AnchoredDraggable.kt$package com.composables.core.androidx.compose.foundation.gestures + InvalidPackageDeclaration:BottomSheet.kt$package com.composables.core + InvalidPackageDeclaration:ContainerHelpers.kt$package com.composables.core.androidx.collection.internal + InvalidPackageDeclaration:Dialog.kt$package com.composables.core + InvalidPackageDeclaration:DragGestureDetector.kt$package com.composables.core.androidx.compose.foundation.gestures + InvalidPackageDeclaration:Draggable.kt$package com.composables.core.androidx.compose.foundation.gestures + InvalidPackageDeclaration:FloatRange.kt$package com.composables.core.androidx.annotation + InvalidPackageDeclaration:FloatSet.kt$package com.composables.core.androidx.collection + InvalidPackageDeclaration:FocusRingIndication.kt$package com.composables.core + InvalidPackageDeclaration:Icon.kt$package com.composables.core + InvalidPackageDeclaration:IntRange.kt$package com.composables.core.androidx.annotation + InvalidPackageDeclaration:LongClickable.android.kt$package core.com.composeunstyled + InvalidPackageDeclaration:LongClickable.cmp.kt$package core.com.composeunstyled + InvalidPackageDeclaration:LongClickable.kt$package core.com.composeunstyled + InvalidPackageDeclaration:ModalBottomSheet.kt$package com.composables.core + InvalidPackageDeclaration:ObjectFloatMap.kt$package com.composables.core.androidx.collection + InvalidPackageDeclaration:RuntimeHelpers.kt$package com.composables.core.androidx.collection.internal + InvalidPackageDeclaration:ScatterMap.kt$package com.composables.core.androidx.collection + InvalidPackageDeclaration:ScatterSet.kt$package com.composables.core.androidx.collection + InvalidPackageDeclaration:ScrollArea.kt$package com.composables.core + InvalidPackageDeclaration:Separators.kt$package com.composables.core + InvalidPackageDeclaration:deprecated.Menu.kt$package com.composables.core + LongMethod:BottomSheet.kt$@Composable fun BottomSheetScope.DragIndication( modifier: Modifier = Modifier, indication: Indication = LocalIndication.current, interactionSource: MutableInteractionSource? = null, ) + LongMethod:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") @Composable fun TextField( value: String, onValueChange: (String) -> Unit, editable: Boolean = true, modifier: Modifier = Modifier, contentPadding: PaddingValues = NoPadding, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, placeholder: String = "", contentColor: Color = LocalContentColor.current, disabledColor: Color = contentColor.copy(0.66f), backgroundColor: Color = Color.Unspecified, borderWidth: Dp = 1.dp, borderColor: Color = Color.Unspecified, shape: Shape = RectangleShape, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign = TextAlign.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, singleLine: Boolean = false, minLines: Int = 1, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource? = null, spacing: Dp = 8.dp, visualTransformation: VisualTransformation = VisualTransformation.None, verticalAlignment: Alignment.Vertical = Alignment.CenterVertically, ) + LoopWithTooManyJumpStatements:LongClickable.kt$while + LoopWithTooManyJumpStatements:ObjectFloatMap.kt$MutableObjectFloatMap$while + LoopWithTooManyJumpStatements:ScatterMap.kt$MutableScatterMap$while + LoopWithTooManyJumpStatements:ScatterSet.kt$MutableScatterSet$while + LoopWithTooManyJumpStatements:ScrollArea.kt$while + MatchingDeclarationName:ProgressIndicator.kt$ProgressIndicatorScope + MatchingDeclarationName:Slider.kt$SliderState + MaxLineLength:BottomSheet.kt$* + MaxLineLength:BottomSheet.kt$@Deprecated("This will go away in 2.0. Instead of use the overload that does not use the RingIndication as indication argument. Instead, style the focus ring yourself using the Modifier.focusRing().") + MaxLineLength:BottomSheet.kt$BottomSheetState$"Cannot set targetDetent to a detent (${value.identifier}) that is not part of the detents of the sheet's state. Current detents are: ${innerDetents.joinToString()}" + MaxLineLength:BottomSheet.kt$BottomSheetState$"Detent identifiers need to be unique, but you passed the following detents multiple times: ${duplicates.joinToString { it }}." + MaxLineLength:BottomSheet.kt$BottomSheetState$"The initialDetent ${initialDetent.identifier} was not part of the included detents while creating the sheet's state." + MaxLineLength:BottomSheet.kt$BottomSheetState$"Tried to create a bottom sheet without any detents. Make sure to pass at least one detent when creating your sheet's state." + MaxLineLength:BottomSheet.kt$BottomSheetState$"Tried to set currentDetent to an unknown detent with identifier ${value.identifier}. Make sure that the detent is passed to the list of detents when instantiating the sheet's state." + MaxLineLength:BottomSheet.kt$BottomSheetState$// If anchors haven't been initialized yet (offset is NaN), always use currentDetent to establish the starting position + MaxLineLength:BottomSheet.kt$SheetDetent$* + MaxLineLength:Button.kt$* + MaxLineLength:ComposeUnstyledFlags.kt$ComposeUnstyledFlags$* + MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.CenterStart, DropdownPanelAnchor.CenterEnd -> anchorBounds.top - popupContentSize.height / 2 + MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.TopEnd, DropdownPanelAnchor.CenterEnd, DropdownPanelAnchor.BottomEnd -> anchorBounds.right - popupContentSize.width + MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.TopStart, DropdownPanelAnchor.CenterStart, DropdownPanelAnchor.BottomStart -> anchorBounds.left + MaxLineLength:FloatingContent.kt$* + MaxLineLength:FocusRingIndication.kt$@Deprecated("This will go away in 2.0. Use the new focusRing() modifier instead that does not force you to override your theme's indication") + MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(imageBitmap,contentDescription,modifier,tint)")) + MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(imageVector,contentDescription,modifier,tint)")) + MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(painter,contentDescription,modifier,tint)")) + MaxLineLength:MinimumComponentInteractiveSize.kt$* + MaxLineLength:Modal.android.kt$* + MaxLineLength:Modal.android.kt$?: + MaxLineLength:Modal.android.kt$error("CompositionLocal LocalModalWindow not present – did you try to access the modal window without a modal visible on the screen?") + MaxLineLength:Modal.kt$* + MaxLineLength:ModalBottomSheet.kt$* + MaxLineLength:ProgressIndicator.kt$* + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Left || it == OverscrollSides.Horizontal } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.y) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Bottom || it == OverscrollSides.Vertical } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.x) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Left || it == OverscrollSides.Horizontal } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } + MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Bottom || it == OverscrollSides.Vertical } + MaxLineLength:ScrollArea.kt$LazyGridScrollAreaScrollAreaState$scrollState.layoutInfo.visibleItemsInfo.distinctBy { if (orientation == Orientation.Vertical) it.column else it.row } + MaxLineLength:ScrollArea.kt$LazyLineContentScrollAreaState$return averageVisibleLineSize * totalLineCount + lineSpacing * (totalLineCount - 1).coerceAtLeast(0) + contentPadding() + MaxLineLength:Stack.kt$* + MaxLineLength:TabGroup.kt$&& + MaxLineLength:TabGroup.kt$?: + MaxLineLength:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") + MaxLineLength:TextField.kt$@Deprecated("This will go to 2.0. Stateless TextFields in Compose do not work correctly in all languages and cause duplication characters and unexpected behaviors") + MaxLineLength:Theme.kt$@Deprecated("This function will go away in 2.0. Use ProvideTextStyle or ProvideContentColor instead which affects themable components instead of overriding your theme") + MaxLineLength:Theme.kt$ComponentInteractiveSize$* + MaxLineLength:Theme.kt$Theme$"There is no ${property.name} property in the ${theme.name} theme. To fix this: 1. Create a design property: val ${property.name} = ThemeProperty<Type>(\"${property.name}\"), 2. Pass it to your theme definition: buildTheme { properties[${property.name}] = mapOf(${property.name} to TODO(\"Give ${property.name} a value\")) }" + MaxLineLength:Theme.kt$ThemeBuilder$@Deprecated("This will go away in 2.0. Use defaultComponentInteractiveSize instead for specifying the size for touch and non-touch targets instead.") + MaxLineLength:Theme.kt$ThemeValues$error("Tried to access the value of the token called ${token.name}, but no tokens with that name are defined within the $propertyName property. You probably forgot to set a ${token.name} token in your theme definition. The resolved theme was $themeName") + MaxLineLength:Theme.kt$staticCompositionLocalOf<ResolvedTheme> { error("No theme was set. In order to use the Theme object you need to wrap your content with a theme @Composable returned by the buildTheme {} function.") } + MaxLineLength:ToggleSwitch.kt$* + MaxLineLength:deprecated.Menu.kt$* + NestedBlockDepth:BottomSheet.kt$private fun UnstyledDraggableAnchors<SheetDetent>.closestDetent( offset: Float, searchUpwards: Boolean ): SheetDetent? + NestedBlockDepth:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, orientation: Orientation?, onPointerSlopReached: (PointerInputChange, Offset) -> Unit, ): PointerInputChange? + NestedBlockDepth:ObjectFloatMap.kt$ObjectFloatMap$@PublishedApi internal inline fun forEachIndexed(block: (index: Int) -> Unit) + NestedBlockDepth:ScatterMap.kt$ScatterMap$@PublishedApi internal inline fun forEachIndexed(block: (index: Int) -> Unit) + NestedBlockDepth:ScatterSet.kt$ScatterSet$@PublishedApi internal inline fun forEachIndex(block: (index: Int) -> Unit) + NewLineAtEndOfFile:BuildModifier.kt$com.composeunstyled.BuildModifier.kt + NewLineAtEndOfFile:Button.kt$com.composeunstyled.Button.kt + NewLineAtEndOfFile:ColoredIndication.kt$com.composeunstyled.theme.ColoredIndication.kt + NewLineAtEndOfFile:ComposeUnstyledFlags.kt$com.composeunstyled.ComposeUnstyledFlags.kt + NewLineAtEndOfFile:ContainerSize.cmp.kt$com.composeunstyled.ContainerSize.cmp.kt + NewLineAtEndOfFile:EscapeHandler.android.kt$com.composeunstyled.EscapeHandler.android.kt + NewLineAtEndOfFile:EscapeHandler.cmp.kt$com.composeunstyled.EscapeHandler.cmp.kt + NewLineAtEndOfFile:EscapeHandler.kt$com.composeunstyled.EscapeHandler.kt + NewLineAtEndOfFile:KeyEventObserver.ios.kt$com.composeunstyled.KeyEventObserver.ios.kt + NewLineAtEndOfFile:KeyEventObserver.kt$com.composeunstyled.KeyEventObserver.kt + NewLineAtEndOfFile:LongClickable.cmp.kt$core.com.composeunstyled.LongClickable.cmp.kt + NewLineAtEndOfFile:Modal.android.kt$com.composeunstyled.Modal.android.kt + NewLineAtEndOfFile:Modal.kt$com.composeunstyled.Modal.kt + NewLineAtEndOfFile:ModalBottomSheet.kt$com.composables.core.ModalBottomSheet.kt + NewLineAtEndOfFile:NoIndication.kt$com.composeunstyled.theme.NoIndication.kt + NewLineAtEndOfFile:ScrollArea.android.kt$com.composables.core.ScrollArea.android.kt + NewLineAtEndOfFile:ScrollArea.cmp.kt$com.composables.core.ScrollArea.cmp.kt + NewLineAtEndOfFile:Separators.kt$com.composables.core.Separators.kt + NewLineAtEndOfFile:Theme.kt$com.composeunstyled.theme.Theme.kt + NewLineAtEndOfFile:Utils.android.kt$com.composeunstyled.Utils.android.kt + NewLineAtEndOfFile:Utils.apple.kt$com.composeunstyled.Utils.apple.kt + NewLineAtEndOfFile:Utils.jvm.kt$com.composeunstyled.Utils.jvm.kt + NewLineAtEndOfFile:Utils.kt$com.composeunstyled.Utils.kt + NewLineAtEndOfFile:Utils.web .kt$com.composeunstyled.Utils.web .kt + ReturnCount:DragGestureDetector.kt$internal suspend inline fun AwaitPointerEventScope.drag( pointerId: PointerId, onDrag: (PointerInputChange) -> Unit, orientation: Orientation?, motionConsumed: (PointerInputChange) -> Boolean ): PointerInputChange? + ReturnCount:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitDragOrUp( pointerId: PointerId, hasDragged: (PointerInputChange) -> Boolean ): PointerInputChange? + ReturnCount:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, orientation: Orientation?, onPointerSlopReached: (PointerInputChange, Offset) -> Unit, ): PointerInputChange? + ReturnCount:DragGestureDetector.kt$suspend fun AwaitPointerEventScope.awaitLongPressOrCancellation( pointerId: PointerId ): PointerInputChange? + SwallowedException:AnchoredDraggable.kt$anchoredDragFinished: AnchoredDragFinishedSignal + SwallowedException:Draggable.kt$DragGestureNode$c: CancellationException + TooManyFunctions:AnchoredDraggable.kt$AnchoredDraggableNode<T> : DragGestureNode + TooManyFunctions:AnchoredDraggable.kt$com.composables.core.androidx.compose.foundation.gestures.AnchoredDraggable.kt + TooManyFunctions:DragGestureDetector.kt$com.composables.core.androidx.compose.foundation.gestures.DragGestureDetector.kt + TooManyFunctions:Draggable.kt$DragGestureNode : DelegatingNodePointerInputModifierNodeCompositionLocalConsumerModifierNode + TooManyFunctions:ObjectFloatMap.kt$MutableObjectFloatMap<K> : ObjectFloatMap + TooManyFunctions:ObjectFloatMap.kt$ObjectFloatMap<K> + TooManyFunctions:ObjectFloatMap.kt$com.composables.core.androidx.collection.ObjectFloatMap.kt + TooManyFunctions:ScatterMap.kt$MutableScatterMap<K, V> : ScatterMap + TooManyFunctions:ScatterMap.kt$ScatterMap<K, V> + TooManyFunctions:ScatterMap.kt$com.composables.core.androidx.collection.ScatterMap.kt + TooManyFunctions:ScatterSet.kt$MutableScatterSet<E> : ScatterSet + TooManyFunctions:ScatterSet.kt$ScatterSet<E> + TooManyFunctions:ScatterSet.kt$com.composables.core.androidx.collection.ScatterSet.kt + TooManyFunctions:ScrollArea.kt$LazyGridScrollAreaScrollAreaState : LazyLineContentScrollAreaState + TooManyFunctions:ScrollArea.kt$com.composables.core.ScrollArea.kt + TooManyFunctions:XmlTheme.kt$com.composeunstyled.theme.XmlTheme.kt + TopLevelPropertyNaming:ScatterMap.kt$// C1 constant from MurmurHash implementation: https://en.wikipedia.org/wiki/MurmurHash#Algorithm internal const val MurmurHashC1: Int = 0xcc9e2d51.toInt() + TopLevelPropertyNaming:ScatterMap.kt$// Capacity to use as the first bump when capacity is initially 0 // We choose 6 so that the "unloaded" capacity maps to 7 internal const val DefaultScatterCapacity = 6 + TopLevelPropertyNaming:ScatterMap.kt$// Indicates that all the slot in a [Group] are empty // 0x8080808080808080UL, see explanation in [BitmaskMsb] internal const val AllEmpty = -0x7f7f7f7f_7f7f7f80L + TopLevelPropertyNaming:ScatterMap.kt$// Least significant bits in the bitmask, one for each metadata in the group @PublishedApi internal const val BitmaskLsb: Long = 0x01010101_01010101L + TopLevelPropertyNaming:ScatterMap.kt$// Most significant bits in the bitmask, one for each metadata in the group // // NOTE: Ideally we'd use a ULong here, defined as 0x8080808080808080UL but // using ULong/UByte makes us take a ~10% performance hit on get/set compared to // a Long. And since Kotlin hates signed constants, we have to use // -0x7f7f7f7f7f7f7f80L instead of the more sensible 0x8080808080808080L (and // 0x8080808080808080UL.toLong() isn't considered a constant) @PublishedApi internal const val BitmaskMsb: Long = -0x7f7f7f7f_7f7f7f80L // srsly Kotlin @#! + TopLevelPropertyNaming:ScatterMap.kt$// Number of metadata present both at the beginning and at the end of // the metadata array so we can use a [GroupWidth] probing window from // any index in the table. internal const val ClonedMetadataCount = GroupWidth - 1 + TopLevelPropertyNaming:ScatterMap.kt$// Used to mark the end of the actual storage, used to end iterations @PublishedApi internal const val Sentinel: Long = 0b11111111L + TopLevelPropertyNaming:ScatterMap.kt$// Width of a group, in bytes. Since we can only use types as large as // Long we must fit our metadata bytes in a 64-bit word or smaller, which // means we can only store up to 8 slots in a group. Ideally we could use // 128-bit data types to benefit from NEON/SSE instructions and manipulate // groups of 16 slots at a time. internal const val GroupWidth = 8 + TopLevelPropertyNaming:ScatterMap.kt$internal const val Deleted = 0b11111110L + TopLevelPropertyNaming:ScatterMap.kt$internal const val Empty = 0b10000000L + TopLevelPropertyNaming:ScrollArea.kt$/** * The delay between each subsequent (after the 2nd) scroll while the scrollbar track is pressed * outside the thumb. */ internal const val DelayBetweenScrollsOnTrackPress: Long = 100L + TopLevelPropertyNaming:ScrollArea.kt$/** * The delay between the 1st and 2nd scroll while the scrollbar track is pressed outside the thumb. */ internal const val DelayBeforeSecondScrollOnTrackPress: Long = 300L + UnusedImports:CheckBox.kt$import androidx.compose.runtime.remember + UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.dialog + UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.semantics + UnusedImports:Dialog.kt$import androidx.compose.ui.unit.dp + UnusedImports:Icon.kt$import com.composeunstyled.LocalContentColor + UnusedImports:KeyEventObserver.jvm.kt$import androidx.compose.runtime.currentComposer + UnusedImports:deprecated.TabGroup.kt$import androidx.compose.ui.unit.dp + UnusedParameter:BottomSheet.kt$onClickLabel: String? = "Toggle sheet" + UnusedPrivateMember:LongClickable.kt$private suspend fun AwaitPointerEventScope.awaitSecondDown( firstUp: PointerInputChange ): PointerInputChange? + UnusedPrivateProperty:Dialog.kt$DialogState$____deprecated_constructor: Unit + UnusedPrivateProperty:Draggable.kt$DragGestureNode$// Use wrapper lambdas here to make sure that if these properties are updated while we suspend, // we point to the new reference when we invoke them. startDragImmediately is a lambda since we // need the most recent value passed to it from Scrollable. private val _canDrag: (PointerInputChange) -> Boolean = { this.canDrag(it) } + UnusedPrivateProperty:LongClickable.kt$private val NoPressGesture: suspend PressGestureScope.(Offset) -> Unit = {} + UnusedPrivateProperty:LongClickable.kt$val cancelOrReleaseJob: Job? + VariableNaming:ObjectFloatMap.kt$ObjectFloatMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @Suppress("PropertyName") @JvmField internal var _capacity: Int = 0 + VariableNaming:ObjectFloatMap.kt$ObjectFloatMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @Suppress("PropertyName") @JvmField internal var _size: Int = 0 + VariableNaming:ScatterMap.kt$ScatterMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @JvmField internal var _capacity: Int = 0 + VariableNaming:ScatterMap.kt$ScatterMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @JvmField internal var _size: Int = 0 + VariableNaming:ScatterSet.kt$ScatterSet$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @JvmField internal var _capacity: Int = 0 + VariableNaming:ScatterSet.kt$ScatterSet$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @JvmField internal var _size: Int = 0 + WildcardImport:BottomSheet.kt$import androidx.compose.foundation.* + WildcardImport:BottomSheet.kt$import androidx.compose.foundation.layout.* + WildcardImport:BottomSheet.kt$import androidx.compose.runtime.* + WildcardImport:BottomSheet.kt$import androidx.compose.ui.semantics.* + WildcardImport:BottomSheet.kt$import androidx.compose.ui.unit.* + WildcardImport:BottomSheet.kt$import com.composables.core.androidx.compose.foundation.gestures.* + WildcardImport:Button.kt$import androidx.compose.foundation.* + WildcardImport:Button.kt$import androidx.compose.foundation.layout.* + WildcardImport:ColoredIndication.kt$import androidx.compose.foundation.interaction.* + WildcardImport:Dialog.kt$import androidx.compose.runtime.* + WildcardImport:Dialog.kt$import androidx.compose.ui.input.key.* + WildcardImport:Disclosure.kt$import androidx.compose.runtime.* + WildcardImport:Disclosure.kt$import androidx.compose.ui.semantics.* + WildcardImport:DropdownMenu.kt$import androidx.compose.foundation.layout.* + WildcardImport:DropdownMenu.kt$import androidx.compose.ui.input.key.* + WildcardImport:DropdownMenu.kt$import androidx.compose.ui.unit.* + WildcardImport:FloatingContent.kt$import androidx.compose.ui.unit.* + WildcardImport:FocusRingIndication.kt$import androidx.compose.ui.geometry.* + WildcardImport:LongClickable.kt$import androidx.compose.ui.input.pointer.* + WildcardImport:LongClickable.kt$import kotlinx.coroutines.* + WildcardImport:Modal.android.kt$import androidx.compose.runtime.* + WildcardImport:ModalBottomSheet.kt$import androidx.compose.runtime.* + WildcardImport:ModalBottomSheet.kt$import com.composeunstyled.* + WildcardImport:Outline.kt$import androidx.compose.ui.graphics.* + WildcardImport:ProgressIndicator.kt$import androidx.compose.runtime.* + WildcardImport:RadioGroup.kt$import androidx.compose.foundation.layout.* + WildcardImport:RadioGroup.kt$import androidx.compose.runtime.* + WildcardImport:ScrollArea.kt$import androidx.compose.foundation.* + WildcardImport:ScrollArea.kt$import androidx.compose.foundation.gestures.* + WildcardImport:ScrollArea.kt$import androidx.compose.foundation.interaction.* + WildcardImport:ScrollArea.kt$import androidx.compose.runtime.* + WildcardImport:ScrollArea.kt$import androidx.compose.ui.unit.* + WildcardImport:ScrollArea.kt$import kotlinx.coroutines.* + WildcardImport:Separators.kt$import androidx.compose.foundation.layout.* + WildcardImport:Slider.kt$import androidx.compose.foundation.gestures.* + WildcardImport:Slider.kt$import androidx.compose.runtime.* + WildcardImport:Slider.kt$import androidx.compose.ui.input.pointer.* + WildcardImport:Stack.kt$import androidx.compose.foundation.layout.* + WildcardImport:TabGroup.kt$import androidx.compose.foundation.layout.* + WildcardImport:TabGroup.kt$import androidx.compose.runtime.* + WildcardImport:TabGroup.kt$import androidx.compose.ui.focus.* + WildcardImport:TextField.kt$import androidx.compose.foundation.* + WildcardImport:TextField.kt$import androidx.compose.foundation.layout.* + WildcardImport:TextField.kt$import androidx.compose.runtime.* + WildcardImport:TextField.kt$import androidx.compose.ui.graphics.* + WildcardImport:Theme.kt$import androidx.compose.runtime.* + WildcardImport:ToggleSwitch.kt$import androidx.compose.foundation.layout.* + WildcardImport:ToggleSwitch.kt$import androidx.compose.runtime.* + WildcardImport:Tooltip.kt$import androidx.compose.foundation.layout.* + WildcardImport:Tooltip.kt$import androidx.compose.runtime.* + WildcardImport:XmlTheme.kt$import androidx.compose.runtime.* + WildcardImport:deprecated.Menu.kt$import androidx.compose.foundation.layout.* + WildcardImport:deprecated.Menu.kt$import androidx.compose.runtime.* + WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.focus.* + WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.input.key.* + WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.unit.* + WildcardImport:deprecated.Menu.kt$import com.composeunstyled.* + WildcardImport:deprecated.RadioGroup.kt$import androidx.compose.foundation.layout.* + WildcardImport:deprecated.RadioGroup.kt$import androidx.compose.runtime.* + WildcardImport:deprecated.TabGroup.kt$import androidx.compose.foundation.layout.* + WildcardImport:deprecated.TabGroup.kt$import androidx.compose.runtime.* + WildcardImport:deprecated.TabGroup.kt$import androidx.compose.ui.focus.* + + diff --git a/detekt.yml b/detekt.yml new file mode 100644 index 00000000..263ed61e --- /dev/null +++ b/detekt.yml @@ -0,0 +1,786 @@ +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: 100 + LongParameterList: + active: false + functionThreshold: 12 + constructorThreshold: 10 + 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-zA-Z][a-zA-Z0-9]*' + excludeClassPattern: '$^' + FunctionParameterNaming: + active: true + parameterPattern: '[a-zA-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]*)*' + excludes: + - '**/generated/**' + 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: false + 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: true + 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/libs.versions.toml b/gradle/libs.versions.toml index 4b5be895..90b7a8ca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,6 +6,7 @@ compose = "1.9.0" hot-reload = "1.0.0-rc01" nexusPublishPlugin = "2.0.0-rc-1" +detekt = "1.23.8" activity-core = "1.10.1" lucide = "1.0.0" window = "1.4.0" @@ -39,4 +40,5 @@ compose-hotreload = { id = "org.jetbrains.compose.hot-reload", version.ref = "ho kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } -nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublishPlugin" } \ No newline at end of file +nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublishPlugin" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } \ No newline at end of file From 4480f228a938dd6f0b48a2f226fb9cc2c4291761 Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Thu, 6 Nov 2025 17:50:55 +0530 Subject: [PATCH 2/6] Refactor: Clean up and simplify Detekt configuration - Simplified the `detekt.yml` configuration by removing many commented-out and default rules, focusing on a stricter, more relevant ruleset. - Increased `maxIssues` to 10. - Disabled several complexity and naming rules (e.g., `LongMethod`, `LongParameterList`, `FunctionNaming`) that are less applicable to Jetpack Compose code. - Updated the Detekt baseline to reflect the new configuration. - Streamlined the Detekt step in the `pr_tests.yml` GitHub workflow. --- .github/workflows/pr_tests.yml | 8 +- core/build.gradle.kts | 2 +- core/detekt-baseline.xml | 95 +++-- detekt.yml | 756 +-------------------------------- 4 files changed, 71 insertions(+), 790 deletions(-) diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index 7005b102..744c524f 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -35,20 +35,16 @@ jobs: - name: Run unit tests run: ./gradlew --no-daemon jvmTest - - name: Run Detekt (core module) - run: ./gradlew --no-daemon --console=plain :core:detekt + - name: Run Detekt + run: ./gradlew --no-daemon --console=plain :core:detekt - name: Show Detekt summary if: always() run: | SUMMARY_MD=core/build/reports/detekt/detekt.md - SUMMARY_TXT=core/build/reports/detekt/detekt.txt if [ -f "$SUMMARY_MD" ]; then echo "Detekt summary (markdown):" cat "$SUMMARY_MD" - elif [ -f "$SUMMARY_TXT" ]; then - echo "Detekt summary (text):" - cat "$SUMMARY_TXT" else echo "Detekt report not found." fi diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 95fa970d..b7b57014 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -144,7 +144,7 @@ detekt { source.setFrom(detektSourceDirs) baseline = file("$projectDir/detekt-baseline.xml") } -// + tasks.withType().configureEach { jvmTarget = JvmTarget.JVM_17.target reports { diff --git a/core/detekt-baseline.xml b/core/detekt-baseline.xml index 610d59b4..564d5162 100644 --- a/core/detekt-baseline.xml +++ b/core/detekt-baseline.xml @@ -43,41 +43,67 @@ InvalidPackageDeclaration:ScrollArea.kt$package com.composables.core InvalidPackageDeclaration:Separators.kt$package com.composables.core InvalidPackageDeclaration:deprecated.Menu.kt$package com.composables.core - LongMethod:BottomSheet.kt$@Composable fun BottomSheetScope.DragIndication( modifier: Modifier = Modifier, indication: Indication = LocalIndication.current, interactionSource: MutableInteractionSource? = null, ) - LongMethod:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") @Composable fun TextField( value: String, onValueChange: (String) -> Unit, editable: Boolean = true, modifier: Modifier = Modifier, contentPadding: PaddingValues = NoPadding, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, placeholder: String = "", contentColor: Color = LocalContentColor.current, disabledColor: Color = contentColor.copy(0.66f), backgroundColor: Color = Color.Unspecified, borderWidth: Dp = 1.dp, borderColor: Color = Color.Unspecified, shape: Shape = RectangleShape, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign = TextAlign.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, singleLine: Boolean = false, minLines: Int = 1, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource? = null, spacing: Dp = 8.dp, visualTransformation: VisualTransformation = VisualTransformation.None, verticalAlignment: Alignment.Vertical = Alignment.CenterVertically, ) LoopWithTooManyJumpStatements:LongClickable.kt$while LoopWithTooManyJumpStatements:ObjectFloatMap.kt$MutableObjectFloatMap$while LoopWithTooManyJumpStatements:ScatterMap.kt$MutableScatterMap$while LoopWithTooManyJumpStatements:ScatterSet.kt$MutableScatterSet$while LoopWithTooManyJumpStatements:ScrollArea.kt$while + MagicNumber:AnchoredDraggable.kt$UnstyledAnchoredDraggableState$0.5f + MagicNumber:AnchoredDraggable.kt$UnstyledAnchoredDraggableState$1e-6f + MagicNumber:ContainerHelpers.kt$12 + MagicNumber:ContainerHelpers.kt$31 + MagicNumber:ContainerHelpers.kt$4 + MagicNumber:ContainerHelpers.kt$8 + MagicNumber:Dialog.kt$0.6f + MagicNumber:ModalBottomSheet.kt$0.6f + MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$0x00ffffff_ffffffffL + MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$3 + MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$56 + MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$7 + MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$0xFFL + MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$3 + MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$31 + MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$8 + MagicNumber:ScatterMap.kt$0x00ffffff_ffffffffL + MagicNumber:ScatterMap.kt$0x7 + MagicNumber:ScatterMap.kt$0x7f + MagicNumber:ScatterMap.kt$0x80L + MagicNumber:ScatterMap.kt$0xff + MagicNumber:ScatterMap.kt$0xffL + MagicNumber:ScatterMap.kt$16 + MagicNumber:ScatterMap.kt$3 + MagicNumber:ScatterMap.kt$56 + MagicNumber:ScatterMap.kt$6 + MagicNumber:ScatterMap.kt$63 + MagicNumber:ScatterMap.kt$64 + MagicNumber:ScatterMap.kt$7 + MagicNumber:ScatterMap.kt$8 + MagicNumber:ScatterMap.kt$MutableScatterMap$3 + MagicNumber:ScatterMap.kt$MutableScatterMap$7 + MagicNumber:ScatterMap.kt$ScatterMap$0xffL + MagicNumber:ScatterMap.kt$ScatterMap$3 + MagicNumber:ScatterMap.kt$ScatterMap$31 + MagicNumber:ScatterMap.kt$ScatterMap$8 + MagicNumber:ScatterSet.kt$3 + MagicNumber:ScatterSet.kt$MutableScatterSet$0x00ffffff_ffffffffL + MagicNumber:ScatterSet.kt$MutableScatterSet$3 + MagicNumber:ScatterSet.kt$MutableScatterSet$56 + MagicNumber:ScatterSet.kt$MutableScatterSet$7 + MagicNumber:ScatterSet.kt$ScatterSet$0xFFL + MagicNumber:ScatterSet.kt$ScatterSet$3 + MagicNumber:ScatterSet.kt$ScatterSet$31 + MagicNumber:ScatterSet.kt$ScatterSet$8 + MagicNumber:Slider.kt$0.01f + MagicNumber:Slider.kt$1000 + MagicNumber:TextField.kt$0.66f MatchingDeclarationName:ProgressIndicator.kt$ProgressIndicatorScope MatchingDeclarationName:Slider.kt$SliderState MaxLineLength:BottomSheet.kt$* MaxLineLength:BottomSheet.kt$@Deprecated("This will go away in 2.0. Instead of use the overload that does not use the RingIndication as indication argument. Instead, style the focus ring yourself using the Modifier.focusRing().") MaxLineLength:BottomSheet.kt$BottomSheetState$"Cannot set targetDetent to a detent (${value.identifier}) that is not part of the detents of the sheet's state. Current detents are: ${innerDetents.joinToString()}" - MaxLineLength:BottomSheet.kt$BottomSheetState$"Detent identifiers need to be unique, but you passed the following detents multiple times: ${duplicates.joinToString { it }}." - MaxLineLength:BottomSheet.kt$BottomSheetState$"The initialDetent ${initialDetent.identifier} was not part of the included detents while creating the sheet's state." - MaxLineLength:BottomSheet.kt$BottomSheetState$"Tried to create a bottom sheet without any detents. Make sure to pass at least one detent when creating your sheet's state." MaxLineLength:BottomSheet.kt$BottomSheetState$"Tried to set currentDetent to an unknown detent with identifier ${value.identifier}. Make sure that the detent is passed to the list of detents when instantiating the sheet's state." - MaxLineLength:BottomSheet.kt$BottomSheetState$// If anchors haven't been initialized yet (offset is NaN), always use currentDetent to establish the starting position - MaxLineLength:BottomSheet.kt$SheetDetent$* - MaxLineLength:Button.kt$* MaxLineLength:ComposeUnstyledFlags.kt$ComposeUnstyledFlags$* - MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.CenterStart, DropdownPanelAnchor.CenterEnd -> anchorBounds.top - popupContentSize.height / 2 - MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.TopEnd, DropdownPanelAnchor.CenterEnd, DropdownPanelAnchor.BottomEnd -> anchorBounds.right - popupContentSize.width - MaxLineLength:DropdownMenu.kt$MenuContentPositionProvider$DropdownPanelAnchor.TopStart, DropdownPanelAnchor.CenterStart, DropdownPanelAnchor.BottomStart -> anchorBounds.left - MaxLineLength:FloatingContent.kt$* - MaxLineLength:FocusRingIndication.kt$@Deprecated("This will go away in 2.0. Use the new focusRing() modifier instead that does not force you to override your theme's indication") - MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(imageBitmap,contentDescription,modifier,tint)")) - MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(imageVector,contentDescription,modifier,tint)")) - MaxLineLength:Icon.kt$@Deprecated("Use Icon from the com.composeunstyled package", ReplaceWith("com.composeunstyled.Icon(painter,contentDescription,modifier,tint)")) - MaxLineLength:MinimumComponentInteractiveSize.kt$* - MaxLineLength:Modal.android.kt$* MaxLineLength:Modal.android.kt$?: - MaxLineLength:Modal.android.kt$error("CompositionLocal LocalModalWindow not present – did you try to access the modal window without a modal visible on the screen?") - MaxLineLength:Modal.kt$* - MaxLineLength:ModalBottomSheet.kt$* - MaxLineLength:ProgressIndicator.kt$* MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Left || it == OverscrollSides.Horizontal } MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } @@ -86,21 +112,13 @@ MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Bottom || it == OverscrollSides.Vertical } - MaxLineLength:ScrollArea.kt$LazyGridScrollAreaScrollAreaState$scrollState.layoutInfo.visibleItemsInfo.distinctBy { if (orientation == Orientation.Vertical) it.column else it.row } - MaxLineLength:ScrollArea.kt$LazyLineContentScrollAreaState$return averageVisibleLineSize * totalLineCount + lineSpacing * (totalLineCount - 1).coerceAtLeast(0) + contentPadding() MaxLineLength:Stack.kt$* - MaxLineLength:TabGroup.kt$&& - MaxLineLength:TabGroup.kt$?: - MaxLineLength:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") MaxLineLength:TextField.kt$@Deprecated("This will go to 2.0. Stateless TextFields in Compose do not work correctly in all languages and cause duplication characters and unexpected behaviors") MaxLineLength:Theme.kt$@Deprecated("This function will go away in 2.0. Use ProvideTextStyle or ProvideContentColor instead which affects themable components instead of overriding your theme") - MaxLineLength:Theme.kt$ComponentInteractiveSize$* MaxLineLength:Theme.kt$Theme$"There is no ${property.name} property in the ${theme.name} theme. To fix this: 1. Create a design property: val ${property.name} = ThemeProperty<Type>(\"${property.name}\"), 2. Pass it to your theme definition: buildTheme { properties[${property.name}] = mapOf(${property.name} to TODO(\"Give ${property.name} a value\")) }" MaxLineLength:Theme.kt$ThemeBuilder$@Deprecated("This will go away in 2.0. Use defaultComponentInteractiveSize instead for specifying the size for touch and non-touch targets instead.") MaxLineLength:Theme.kt$ThemeValues$error("Tried to access the value of the token called ${token.name}, but no tokens with that name are defined within the $propertyName property. You probably forgot to set a ${token.name} token in your theme definition. The resolved theme was $themeName") MaxLineLength:Theme.kt$staticCompositionLocalOf<ResolvedTheme> { error("No theme was set. In order to use the Theme object you need to wrap your content with a theme @Composable returned by the buildTheme {} function.") } - MaxLineLength:ToggleSwitch.kt$* - MaxLineLength:deprecated.Menu.kt$* NestedBlockDepth:BottomSheet.kt$private fun UnstyledDraggableAnchors<SheetDetent>.closestDetent( offset: Float, searchUpwards: Boolean ): SheetDetent? NestedBlockDepth:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, orientation: Orientation?, onPointerSlopReached: (PointerInputChange, Offset) -> Unit, ): PointerInputChange? NestedBlockDepth:ObjectFloatMap.kt$ObjectFloatMap$@PublishedApi internal inline fun forEachIndexed(block: (index: Int) -> Unit) @@ -137,33 +155,16 @@ SwallowedException:AnchoredDraggable.kt$anchoredDragFinished: AnchoredDragFinishedSignal SwallowedException:Draggable.kt$DragGestureNode$c: CancellationException TooManyFunctions:AnchoredDraggable.kt$AnchoredDraggableNode<T> : DragGestureNode - TooManyFunctions:AnchoredDraggable.kt$com.composables.core.androidx.compose.foundation.gestures.AnchoredDraggable.kt TooManyFunctions:DragGestureDetector.kt$com.composables.core.androidx.compose.foundation.gestures.DragGestureDetector.kt TooManyFunctions:Draggable.kt$DragGestureNode : DelegatingNodePointerInputModifierNodeCompositionLocalConsumerModifierNode TooManyFunctions:ObjectFloatMap.kt$MutableObjectFloatMap<K> : ObjectFloatMap TooManyFunctions:ObjectFloatMap.kt$ObjectFloatMap<K> - TooManyFunctions:ObjectFloatMap.kt$com.composables.core.androidx.collection.ObjectFloatMap.kt TooManyFunctions:ScatterMap.kt$MutableScatterMap<K, V> : ScatterMap TooManyFunctions:ScatterMap.kt$ScatterMap<K, V> TooManyFunctions:ScatterMap.kt$com.composables.core.androidx.collection.ScatterMap.kt TooManyFunctions:ScatterSet.kt$MutableScatterSet<E> : ScatterSet TooManyFunctions:ScatterSet.kt$ScatterSet<E> - TooManyFunctions:ScatterSet.kt$com.composables.core.androidx.collection.ScatterSet.kt TooManyFunctions:ScrollArea.kt$LazyGridScrollAreaScrollAreaState : LazyLineContentScrollAreaState - TooManyFunctions:ScrollArea.kt$com.composables.core.ScrollArea.kt - TooManyFunctions:XmlTheme.kt$com.composeunstyled.theme.XmlTheme.kt - TopLevelPropertyNaming:ScatterMap.kt$// C1 constant from MurmurHash implementation: https://en.wikipedia.org/wiki/MurmurHash#Algorithm internal const val MurmurHashC1: Int = 0xcc9e2d51.toInt() - TopLevelPropertyNaming:ScatterMap.kt$// Capacity to use as the first bump when capacity is initially 0 // We choose 6 so that the "unloaded" capacity maps to 7 internal const val DefaultScatterCapacity = 6 - TopLevelPropertyNaming:ScatterMap.kt$// Indicates that all the slot in a [Group] are empty // 0x8080808080808080UL, see explanation in [BitmaskMsb] internal const val AllEmpty = -0x7f7f7f7f_7f7f7f80L - TopLevelPropertyNaming:ScatterMap.kt$// Least significant bits in the bitmask, one for each metadata in the group @PublishedApi internal const val BitmaskLsb: Long = 0x01010101_01010101L - TopLevelPropertyNaming:ScatterMap.kt$// Most significant bits in the bitmask, one for each metadata in the group // // NOTE: Ideally we'd use a ULong here, defined as 0x8080808080808080UL but // using ULong/UByte makes us take a ~10% performance hit on get/set compared to // a Long. And since Kotlin hates signed constants, we have to use // -0x7f7f7f7f7f7f7f80L instead of the more sensible 0x8080808080808080L (and // 0x8080808080808080UL.toLong() isn't considered a constant) @PublishedApi internal const val BitmaskMsb: Long = -0x7f7f7f7f_7f7f7f80L // srsly Kotlin @#! - TopLevelPropertyNaming:ScatterMap.kt$// Number of metadata present both at the beginning and at the end of // the metadata array so we can use a [GroupWidth] probing window from // any index in the table. internal const val ClonedMetadataCount = GroupWidth - 1 - TopLevelPropertyNaming:ScatterMap.kt$// Used to mark the end of the actual storage, used to end iterations @PublishedApi internal const val Sentinel: Long = 0b11111111L - TopLevelPropertyNaming:ScatterMap.kt$// Width of a group, in bytes. Since we can only use types as large as // Long we must fit our metadata bytes in a 64-bit word or smaller, which // means we can only store up to 8 slots in a group. Ideally we could use // 128-bit data types to benefit from NEON/SSE instructions and manipulate // groups of 16 slots at a time. internal const val GroupWidth = 8 - TopLevelPropertyNaming:ScatterMap.kt$internal const val Deleted = 0b11111110L - TopLevelPropertyNaming:ScatterMap.kt$internal const val Empty = 0b10000000L - TopLevelPropertyNaming:ScrollArea.kt$/** * The delay between each subsequent (after the 2nd) scroll while the scrollbar track is pressed * outside the thumb. */ internal const val DelayBetweenScrollsOnTrackPress: Long = 100L - TopLevelPropertyNaming:ScrollArea.kt$/** * The delay between the 1st and 2nd scroll while the scrollbar track is pressed outside the thumb. */ internal const val DelayBeforeSecondScrollOnTrackPress: Long = 300L UnusedImports:CheckBox.kt$import androidx.compose.runtime.remember UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.dialog UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.semantics diff --git a/detekt.yml b/detekt.yml index 263ed61e..4abec819 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,786 +1,70 @@ build: - maxIssues: 0 + maxIssues: 10 # Change number of issues allowed as per need excludeCorrectable: false weights: - # complexity: 2 - # LongParameterList: 1 - # style: 1 - # comments: 1 + complexity: 2 + LongParameterList: 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: 100 - LongParameterList: - active: false - functionThreshold: 12 - constructorThreshold: 10 - 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: +style: + MaxLineLength: active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**' ] - exceptions: - - 'ArrayIndexOutOfBoundsException' - - 'Exception' - - 'IllegalArgumentException' - - 'IllegalMonitorStateException' - - 'IllegalStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - ThrowingNewInstanceOfSameException: + maxLineLength: 150 + WildcardImport: active: true - TooGenericExceptionCaught: + UnusedImports: active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**' ] - exceptionNames: - - 'ArrayIndexOutOfBoundsException' - - 'Error' - - 'Exception' - - 'IllegalMonitorStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - allowedExceptionNameRegex: '_|(ignore|expected).*' - TooGenericExceptionThrown: + NewLineAtEndOfFile: 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: + PackageNaming: 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-zA-Z][a-zA-Z0-9]*' - excludeClassPattern: '$^' - FunctionParameterNaming: - active: true - parameterPattern: '[a-zA-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 # Composables often start with uppercase + TopLevelPropertyNaming: 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]*)*' - excludes: - - '**/generated/**' - 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: + +complexity: + LongMethod: + active: false # Disable, Compose UIs can be long + LongParameterList: + active: false # Compose often uses many params + TooManyFunctions: active: true - variablePattern: '[a-z][A-Za-z0-9]*' - privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' + thresholdInFiles: 20 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: false - 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: true - 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.*' From b3a7f5a77abe5fe2dfef8d5868fbf1241acf60ca Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Thu, 6 Nov 2025 22:59:08 +0530 Subject: [PATCH 3/6] Refactor: Rename pr_tests.yml to ci.yml and fix report output Renamed the `pr_tests.yml` workflow file to `ci.yml` for clarity. Also, corrected the Detekt summary output to properly format it as a markdown code block in the workflow log. --- .github/workflows/{pr_tests.yml => ci.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{pr_tests.yml => ci.yml} (97%) diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/ci.yml similarity index 97% rename from .github/workflows/pr_tests.yml rename to .github/workflows/ci.yml index 744c524f..f18f6816 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: SUMMARY_MD=core/build/reports/detekt/detekt.md if [ -f "$SUMMARY_MD" ]; then echo "Detekt summary (markdown):" - cat "$SUMMARY_MD" + cat "```markdown\n$SUMMARY_MD\n```" else echo "Detekt report not found." fi From 4eacdef4088ac4f8f9a278c5252aabdb10ef5fb1 Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Thu, 6 Nov 2025 23:04:03 +0530 Subject: [PATCH 4/6] Move unit tests after Detekt Moves the `Run unit tests` step to execute after the Detekt analysis steps to reject the PR early if it has any code smells. --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f18f6816..bf52f653 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,9 +33,6 @@ jobs: restore-keys: | gradle-${{ runner.os }}- - - name: Run unit tests - run: ./gradlew --no-daemon jvmTest - - name: Run Detekt run: ./gradlew --no-daemon --console=plain :core:detekt - name: Show Detekt summary @@ -49,6 +46,9 @@ jobs: echo "Detekt report not found." fi + - name: Run unit tests + run: ./gradlew --no-daemon jvmTest + - name: Verify test reports exist run: | set -e From e69144c76b10a1807a268e7665a5a0eabe0690a2 Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Thu, 6 Nov 2025 23:08:37 +0530 Subject: [PATCH 5/6] feat: Output Detekt report to GitHub Step Summary The Detekt summary is now outputted to the GitHub Step Summary for better visibility in the workflow run. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf52f653..fbe76393 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: run: | SUMMARY_MD=core/build/reports/detekt/detekt.md if [ -f "$SUMMARY_MD" ]; then - echo "Detekt summary (markdown):" - cat "```markdown\n$SUMMARY_MD\n```" + echo -e "## Detekt Report\n" >> "$GITHUB_STEP_SUMMARY" + cat "$SUMMARY_MD" >> "$GITHUB_STEP_SUMMARY" else echo "Detekt report not found." fi From e5b640d8d20d2de7a0ae65d2789c27b11b706887 Mon Sep 17 00:00:00 2001 From: Raghav Satyadev Date: Fri, 7 Nov 2025 15:00:04 +0530 Subject: [PATCH 6/6] Simplify detekt configuration Removes most of the custom detekt configuration, opting for detekt's defaults. The maximum issue count is increased to 500 to allow the build to pass, and the baseline file has been cleared. --- core/detekt-baseline.xml | 245 +-------------------------------------- detekt.yml | 77 ++++-------- 2 files changed, 22 insertions(+), 300 deletions(-) diff --git a/core/detekt-baseline.xml b/core/detekt-baseline.xml index 564d5162..119a7fd5 100644 --- a/core/detekt-baseline.xml +++ b/core/detekt-baseline.xml @@ -2,249 +2,6 @@ - ComplexCondition:ScrollArea.kt$<no name provided>$isOverscrollTop || isOverscrollBottom || isOverscrollLeft || isOverscrollRight - ConstructorParameterNaming:Dialog.kt$DialogState$____deprecated_constructor: Unit - CyclomaticComplexMethod:BottomSheet.kt$@Composable fun BottomSheetScope.DragIndication( modifier: Modifier = Modifier, indication: Indication = LocalIndication.current, interactionSource: MutableInteractionSource? = null, ) - CyclomaticComplexMethod:ColoredIndication.kt$ColoredIndication.ColoredIndicationInstance$override fun onAttach() - CyclomaticComplexMethod:Slider.kt$private fun Modifier.sliderKeyboardInteractions(enabled: Boolean, state: SliderState): Modifier - CyclomaticComplexMethod:TabGroup.kt$@Composable fun TabList( modifier: Modifier = Modifier, shape: Shape = RectangleShape, backgroundColor: Color = Color.Unspecified, contentColor: Color = Color.Unspecified, contentPadding: PaddingValues = NoPadding, orientation: Orientation = Orientation.Horizontal, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalAlignment: Alignment.Vertical = Alignment.Top, content: @Composable RowScope.() -> Unit ) - CyclomaticComplexMethod:TextField.kt$@Deprecated("This overload will go away in 2.0. Use the overload of TextField that provides slots for better styling capabilities") @Composable fun TextField( value: String, onValueChange: (String) -> Unit, editable: Boolean = true, modifier: Modifier = Modifier, contentPadding: PaddingValues = NoPadding, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, placeholder: String = "", contentColor: Color = LocalContentColor.current, disabledColor: Color = contentColor.copy(0.66f), backgroundColor: Color = Color.Unspecified, borderWidth: Dp = 1.dp, borderColor: Color = Color.Unspecified, shape: Shape = RectangleShape, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign = TextAlign.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, singleLine: Boolean = false, minLines: Int = 1, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource? = null, spacing: Dp = 8.dp, visualTransformation: VisualTransformation = VisualTransformation.None, verticalAlignment: Alignment.Vertical = Alignment.CenterVertically, ) - CyclomaticComplexMethod:Tooltip.kt$@Composable fun TooltipPanel( modifier: Modifier = Modifier, arrow: @Composable (TooltipArrowDirection) -> Unit, enter: EnterTransition = AppearInstantly, exit: ExitTransition = DisappearInstantly, content: @Composable () -> Unit ) - CyclomaticComplexMethod:deprecated.TabGroup.kt$@Composable fun TabGroupScope.TabList( modifier: Modifier = Modifier, shape: Shape = RectangleShape, backgroundColor: Color = Color.Unspecified, contentColor: Color = Color.Unspecified, contentPadding: PaddingValues = NoPadding, orientation: Orientation = Orientation.Horizontal, activateOnFocus: Boolean = true, content: @Composable RowScope.() -> Unit ) - EmptyFunctionBlock:AnchoredDraggable.kt$AnchoredDraggableNode${ } - ExplicitItLambdaParameter:TextField.kt${ it -> if (scope.isTrailingFocused.not() && scope.isLeadingFocused.not()) { // block any value changes, unless the actual text input is focused // this guards for cases where the onValueChange(it.text) textRange = it.selection } } - ForbiddenComment:ObjectFloatMap.kt$MutableObjectFloatMap$// TODO: We could just mark the entry as empty if there's a group - ForbiddenComment:ScatterMap.kt$// TODO: We could further reduce the work we do by always copying index 0 to - ForbiddenComment:ScatterMap.kt$MutableScatterMap$// TODO: We could just mark the entry as empty if there's a group - ForbiddenComment:ScatterMap.kt$MutableScatterMap.MutableMapWrapper$// TODO: See TODO on `MapWrapper` - ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: @Suppress required because of a lint check issue (b/294130025) - ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: While not mandatory, it would be pertinent to throw a - ForbiddenComment:ScatterMap.kt$ScatterMap.MapWrapper$// TODO: the proliferation of inner classes causes unnecessary code to be - ForbiddenComment:ScatterSet.kt$MutableScatterSet$// TODO: We could just mark the element as empty if there's a group - InvalidPackageDeclaration:AnchoredDraggable.kt$package com.composables.core.androidx.compose.foundation.gestures - InvalidPackageDeclaration:BottomSheet.kt$package com.composables.core - InvalidPackageDeclaration:ContainerHelpers.kt$package com.composables.core.androidx.collection.internal - InvalidPackageDeclaration:Dialog.kt$package com.composables.core - InvalidPackageDeclaration:DragGestureDetector.kt$package com.composables.core.androidx.compose.foundation.gestures - InvalidPackageDeclaration:Draggable.kt$package com.composables.core.androidx.compose.foundation.gestures - InvalidPackageDeclaration:FloatRange.kt$package com.composables.core.androidx.annotation - InvalidPackageDeclaration:FloatSet.kt$package com.composables.core.androidx.collection - InvalidPackageDeclaration:FocusRingIndication.kt$package com.composables.core - InvalidPackageDeclaration:Icon.kt$package com.composables.core - InvalidPackageDeclaration:IntRange.kt$package com.composables.core.androidx.annotation - InvalidPackageDeclaration:LongClickable.android.kt$package core.com.composeunstyled - InvalidPackageDeclaration:LongClickable.cmp.kt$package core.com.composeunstyled - InvalidPackageDeclaration:LongClickable.kt$package core.com.composeunstyled - InvalidPackageDeclaration:ModalBottomSheet.kt$package com.composables.core - InvalidPackageDeclaration:ObjectFloatMap.kt$package com.composables.core.androidx.collection - InvalidPackageDeclaration:RuntimeHelpers.kt$package com.composables.core.androidx.collection.internal - InvalidPackageDeclaration:ScatterMap.kt$package com.composables.core.androidx.collection - InvalidPackageDeclaration:ScatterSet.kt$package com.composables.core.androidx.collection - InvalidPackageDeclaration:ScrollArea.kt$package com.composables.core - InvalidPackageDeclaration:Separators.kt$package com.composables.core - InvalidPackageDeclaration:deprecated.Menu.kt$package com.composables.core - LoopWithTooManyJumpStatements:LongClickable.kt$while - LoopWithTooManyJumpStatements:ObjectFloatMap.kt$MutableObjectFloatMap$while - LoopWithTooManyJumpStatements:ScatterMap.kt$MutableScatterMap$while - LoopWithTooManyJumpStatements:ScatterSet.kt$MutableScatterSet$while - LoopWithTooManyJumpStatements:ScrollArea.kt$while - MagicNumber:AnchoredDraggable.kt$UnstyledAnchoredDraggableState$0.5f - MagicNumber:AnchoredDraggable.kt$UnstyledAnchoredDraggableState$1e-6f - MagicNumber:ContainerHelpers.kt$12 - MagicNumber:ContainerHelpers.kt$31 - MagicNumber:ContainerHelpers.kt$4 - MagicNumber:ContainerHelpers.kt$8 - MagicNumber:Dialog.kt$0.6f - MagicNumber:ModalBottomSheet.kt$0.6f - MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$0x00ffffff_ffffffffL - MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$3 - MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$56 - MagicNumber:ObjectFloatMap.kt$MutableObjectFloatMap$7 - MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$0xFFL - MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$3 - MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$31 - MagicNumber:ObjectFloatMap.kt$ObjectFloatMap$8 - MagicNumber:ScatterMap.kt$0x00ffffff_ffffffffL - MagicNumber:ScatterMap.kt$0x7 - MagicNumber:ScatterMap.kt$0x7f - MagicNumber:ScatterMap.kt$0x80L - MagicNumber:ScatterMap.kt$0xff - MagicNumber:ScatterMap.kt$0xffL - MagicNumber:ScatterMap.kt$16 - MagicNumber:ScatterMap.kt$3 - MagicNumber:ScatterMap.kt$56 - MagicNumber:ScatterMap.kt$6 - MagicNumber:ScatterMap.kt$63 - MagicNumber:ScatterMap.kt$64 - MagicNumber:ScatterMap.kt$7 - MagicNumber:ScatterMap.kt$8 - MagicNumber:ScatterMap.kt$MutableScatterMap$3 - MagicNumber:ScatterMap.kt$MutableScatterMap$7 - MagicNumber:ScatterMap.kt$ScatterMap$0xffL - MagicNumber:ScatterMap.kt$ScatterMap$3 - MagicNumber:ScatterMap.kt$ScatterMap$31 - MagicNumber:ScatterMap.kt$ScatterMap$8 - MagicNumber:ScatterSet.kt$3 - MagicNumber:ScatterSet.kt$MutableScatterSet$0x00ffffff_ffffffffL - MagicNumber:ScatterSet.kt$MutableScatterSet$3 - MagicNumber:ScatterSet.kt$MutableScatterSet$56 - MagicNumber:ScatterSet.kt$MutableScatterSet$7 - MagicNumber:ScatterSet.kt$ScatterSet$0xFFL - MagicNumber:ScatterSet.kt$ScatterSet$3 - MagicNumber:ScatterSet.kt$ScatterSet$31 - MagicNumber:ScatterSet.kt$ScatterSet$8 - MagicNumber:Slider.kt$0.01f - MagicNumber:Slider.kt$1000 - MagicNumber:TextField.kt$0.66f - MatchingDeclarationName:ProgressIndicator.kt$ProgressIndicatorScope - MatchingDeclarationName:Slider.kt$SliderState - MaxLineLength:BottomSheet.kt$* - MaxLineLength:BottomSheet.kt$@Deprecated("This will go away in 2.0. Instead of use the overload that does not use the RingIndication as indication argument. Instead, style the focus ring yourself using the Modifier.focusRing().") - MaxLineLength:BottomSheet.kt$BottomSheetState$"Cannot set targetDetent to a detent (${value.identifier}) that is not part of the detents of the sheet's state. Current detents are: ${innerDetents.joinToString()}" - MaxLineLength:BottomSheet.kt$BottomSheetState$"Tried to set currentDetent to an unknown detent with identifier ${value.identifier}. Make sure that the detent is passed to the list of detents when instantiating the sheet's state." - MaxLineLength:ComposeUnstyledFlags.kt$ComposeUnstyledFlags$* - MaxLineLength:Modal.android.kt$?: - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Left || it == OverscrollSides.Horizontal } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingBackwards(available.y) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Bottom || it == OverscrollSides.Vertical } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.x) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Left || it == OverscrollSides.Horizontal } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.x) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Right || it == OverscrollSides.Horizontal } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollBackwards.not() && overscrollEffectSides.any { it == OverscrollSides.Top || it == OverscrollSides.Vertical } - MaxLineLength:ScrollArea.kt$<no name provided>$isMovingForward(available.y) && canScrollForward.not() && overscrollEffectSides.any { it == OverscrollSides.Bottom || it == OverscrollSides.Vertical } - MaxLineLength:Stack.kt$* - MaxLineLength:TextField.kt$@Deprecated("This will go to 2.0. Stateless TextFields in Compose do not work correctly in all languages and cause duplication characters and unexpected behaviors") - MaxLineLength:Theme.kt$@Deprecated("This function will go away in 2.0. Use ProvideTextStyle or ProvideContentColor instead which affects themable components instead of overriding your theme") - MaxLineLength:Theme.kt$Theme$"There is no ${property.name} property in the ${theme.name} theme. To fix this: 1. Create a design property: val ${property.name} = ThemeProperty<Type>(\"${property.name}\"), 2. Pass it to your theme definition: buildTheme { properties[${property.name}] = mapOf(${property.name} to TODO(\"Give ${property.name} a value\")) }" - MaxLineLength:Theme.kt$ThemeBuilder$@Deprecated("This will go away in 2.0. Use defaultComponentInteractiveSize instead for specifying the size for touch and non-touch targets instead.") - MaxLineLength:Theme.kt$ThemeValues$error("Tried to access the value of the token called ${token.name}, but no tokens with that name are defined within the $propertyName property. You probably forgot to set a ${token.name} token in your theme definition. The resolved theme was $themeName") - MaxLineLength:Theme.kt$staticCompositionLocalOf<ResolvedTheme> { error("No theme was set. In order to use the Theme object you need to wrap your content with a theme @Composable returned by the buildTheme {} function.") } - NestedBlockDepth:BottomSheet.kt$private fun UnstyledDraggableAnchors<SheetDetent>.closestDetent( offset: Float, searchUpwards: Boolean ): SheetDetent? - NestedBlockDepth:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, orientation: Orientation?, onPointerSlopReached: (PointerInputChange, Offset) -> Unit, ): PointerInputChange? - NestedBlockDepth:ObjectFloatMap.kt$ObjectFloatMap$@PublishedApi internal inline fun forEachIndexed(block: (index: Int) -> Unit) - NestedBlockDepth:ScatterMap.kt$ScatterMap$@PublishedApi internal inline fun forEachIndexed(block: (index: Int) -> Unit) - NestedBlockDepth:ScatterSet.kt$ScatterSet$@PublishedApi internal inline fun forEachIndex(block: (index: Int) -> Unit) - NewLineAtEndOfFile:BuildModifier.kt$com.composeunstyled.BuildModifier.kt - NewLineAtEndOfFile:Button.kt$com.composeunstyled.Button.kt - NewLineAtEndOfFile:ColoredIndication.kt$com.composeunstyled.theme.ColoredIndication.kt - NewLineAtEndOfFile:ComposeUnstyledFlags.kt$com.composeunstyled.ComposeUnstyledFlags.kt - NewLineAtEndOfFile:ContainerSize.cmp.kt$com.composeunstyled.ContainerSize.cmp.kt - NewLineAtEndOfFile:EscapeHandler.android.kt$com.composeunstyled.EscapeHandler.android.kt - NewLineAtEndOfFile:EscapeHandler.cmp.kt$com.composeunstyled.EscapeHandler.cmp.kt - NewLineAtEndOfFile:EscapeHandler.kt$com.composeunstyled.EscapeHandler.kt - NewLineAtEndOfFile:KeyEventObserver.ios.kt$com.composeunstyled.KeyEventObserver.ios.kt - NewLineAtEndOfFile:KeyEventObserver.kt$com.composeunstyled.KeyEventObserver.kt - NewLineAtEndOfFile:LongClickable.cmp.kt$core.com.composeunstyled.LongClickable.cmp.kt - NewLineAtEndOfFile:Modal.android.kt$com.composeunstyled.Modal.android.kt - NewLineAtEndOfFile:Modal.kt$com.composeunstyled.Modal.kt - NewLineAtEndOfFile:ModalBottomSheet.kt$com.composables.core.ModalBottomSheet.kt - NewLineAtEndOfFile:NoIndication.kt$com.composeunstyled.theme.NoIndication.kt - NewLineAtEndOfFile:ScrollArea.android.kt$com.composables.core.ScrollArea.android.kt - NewLineAtEndOfFile:ScrollArea.cmp.kt$com.composables.core.ScrollArea.cmp.kt - NewLineAtEndOfFile:Separators.kt$com.composables.core.Separators.kt - NewLineAtEndOfFile:Theme.kt$com.composeunstyled.theme.Theme.kt - NewLineAtEndOfFile:Utils.android.kt$com.composeunstyled.Utils.android.kt - NewLineAtEndOfFile:Utils.apple.kt$com.composeunstyled.Utils.apple.kt - NewLineAtEndOfFile:Utils.jvm.kt$com.composeunstyled.Utils.jvm.kt - NewLineAtEndOfFile:Utils.kt$com.composeunstyled.Utils.kt - NewLineAtEndOfFile:Utils.web .kt$com.composeunstyled.Utils.web .kt - ReturnCount:DragGestureDetector.kt$internal suspend inline fun AwaitPointerEventScope.drag( pointerId: PointerId, onDrag: (PointerInputChange) -> Unit, orientation: Orientation?, motionConsumed: (PointerInputChange) -> Boolean ): PointerInputChange? - ReturnCount:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitDragOrUp( pointerId: PointerId, hasDragged: (PointerInputChange) -> Boolean ): PointerInputChange? - ReturnCount:DragGestureDetector.kt$private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, orientation: Orientation?, onPointerSlopReached: (PointerInputChange, Offset) -> Unit, ): PointerInputChange? - ReturnCount:DragGestureDetector.kt$suspend fun AwaitPointerEventScope.awaitLongPressOrCancellation( pointerId: PointerId ): PointerInputChange? - SwallowedException:AnchoredDraggable.kt$anchoredDragFinished: AnchoredDragFinishedSignal - SwallowedException:Draggable.kt$DragGestureNode$c: CancellationException - TooManyFunctions:AnchoredDraggable.kt$AnchoredDraggableNode<T> : DragGestureNode - TooManyFunctions:DragGestureDetector.kt$com.composables.core.androidx.compose.foundation.gestures.DragGestureDetector.kt - TooManyFunctions:Draggable.kt$DragGestureNode : DelegatingNodePointerInputModifierNodeCompositionLocalConsumerModifierNode - TooManyFunctions:ObjectFloatMap.kt$MutableObjectFloatMap<K> : ObjectFloatMap - TooManyFunctions:ObjectFloatMap.kt$ObjectFloatMap<K> - TooManyFunctions:ScatterMap.kt$MutableScatterMap<K, V> : ScatterMap - TooManyFunctions:ScatterMap.kt$ScatterMap<K, V> - TooManyFunctions:ScatterMap.kt$com.composables.core.androidx.collection.ScatterMap.kt - TooManyFunctions:ScatterSet.kt$MutableScatterSet<E> : ScatterSet - TooManyFunctions:ScatterSet.kt$ScatterSet<E> - TooManyFunctions:ScrollArea.kt$LazyGridScrollAreaScrollAreaState : LazyLineContentScrollAreaState - UnusedImports:CheckBox.kt$import androidx.compose.runtime.remember - UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.dialog - UnusedImports:Dialog.kt$import androidx.compose.ui.semantics.semantics - UnusedImports:Dialog.kt$import androidx.compose.ui.unit.dp - UnusedImports:Icon.kt$import com.composeunstyled.LocalContentColor - UnusedImports:KeyEventObserver.jvm.kt$import androidx.compose.runtime.currentComposer - UnusedImports:deprecated.TabGroup.kt$import androidx.compose.ui.unit.dp - UnusedParameter:BottomSheet.kt$onClickLabel: String? = "Toggle sheet" - UnusedPrivateMember:LongClickable.kt$private suspend fun AwaitPointerEventScope.awaitSecondDown( firstUp: PointerInputChange ): PointerInputChange? - UnusedPrivateProperty:Dialog.kt$DialogState$____deprecated_constructor: Unit - UnusedPrivateProperty:Draggable.kt$DragGestureNode$// Use wrapper lambdas here to make sure that if these properties are updated while we suspend, // we point to the new reference when we invoke them. startDragImmediately is a lambda since we // need the most recent value passed to it from Scrollable. private val _canDrag: (PointerInputChange) -> Boolean = { this.canDrag(it) } - UnusedPrivateProperty:LongClickable.kt$private val NoPressGesture: suspend PressGestureScope.(Offset) -> Unit = {} - UnusedPrivateProperty:LongClickable.kt$val cancelOrReleaseJob: Job? - VariableNaming:ObjectFloatMap.kt$ObjectFloatMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @Suppress("PropertyName") @JvmField internal var _capacity: Int = 0 - VariableNaming:ObjectFloatMap.kt$ObjectFloatMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @Suppress("PropertyName") @JvmField internal var _size: Int = 0 - VariableNaming:ScatterMap.kt$ScatterMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @JvmField internal var _capacity: Int = 0 - VariableNaming:ScatterMap.kt$ScatterMap$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @JvmField internal var _size: Int = 0 - VariableNaming:ScatterSet.kt$ScatterSet$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the capacity @JvmField internal var _capacity: Int = 0 - VariableNaming:ScatterSet.kt$ScatterSet$// We use a backing field for capacity to avoid invokevirtual calls // every time we need to look at the size @JvmField internal var _size: Int = 0 - WildcardImport:BottomSheet.kt$import androidx.compose.foundation.* - WildcardImport:BottomSheet.kt$import androidx.compose.foundation.layout.* - WildcardImport:BottomSheet.kt$import androidx.compose.runtime.* - WildcardImport:BottomSheet.kt$import androidx.compose.ui.semantics.* - WildcardImport:BottomSheet.kt$import androidx.compose.ui.unit.* - WildcardImport:BottomSheet.kt$import com.composables.core.androidx.compose.foundation.gestures.* - WildcardImport:Button.kt$import androidx.compose.foundation.* - WildcardImport:Button.kt$import androidx.compose.foundation.layout.* - WildcardImport:ColoredIndication.kt$import androidx.compose.foundation.interaction.* - WildcardImport:Dialog.kt$import androidx.compose.runtime.* - WildcardImport:Dialog.kt$import androidx.compose.ui.input.key.* - WildcardImport:Disclosure.kt$import androidx.compose.runtime.* - WildcardImport:Disclosure.kt$import androidx.compose.ui.semantics.* - WildcardImport:DropdownMenu.kt$import androidx.compose.foundation.layout.* - WildcardImport:DropdownMenu.kt$import androidx.compose.ui.input.key.* - WildcardImport:DropdownMenu.kt$import androidx.compose.ui.unit.* - WildcardImport:FloatingContent.kt$import androidx.compose.ui.unit.* - WildcardImport:FocusRingIndication.kt$import androidx.compose.ui.geometry.* - WildcardImport:LongClickable.kt$import androidx.compose.ui.input.pointer.* - WildcardImport:LongClickable.kt$import kotlinx.coroutines.* - WildcardImport:Modal.android.kt$import androidx.compose.runtime.* - WildcardImport:ModalBottomSheet.kt$import androidx.compose.runtime.* - WildcardImport:ModalBottomSheet.kt$import com.composeunstyled.* - WildcardImport:Outline.kt$import androidx.compose.ui.graphics.* - WildcardImport:ProgressIndicator.kt$import androidx.compose.runtime.* - WildcardImport:RadioGroup.kt$import androidx.compose.foundation.layout.* - WildcardImport:RadioGroup.kt$import androidx.compose.runtime.* - WildcardImport:ScrollArea.kt$import androidx.compose.foundation.* - WildcardImport:ScrollArea.kt$import androidx.compose.foundation.gestures.* - WildcardImport:ScrollArea.kt$import androidx.compose.foundation.interaction.* - WildcardImport:ScrollArea.kt$import androidx.compose.runtime.* - WildcardImport:ScrollArea.kt$import androidx.compose.ui.unit.* - WildcardImport:ScrollArea.kt$import kotlinx.coroutines.* - WildcardImport:Separators.kt$import androidx.compose.foundation.layout.* - WildcardImport:Slider.kt$import androidx.compose.foundation.gestures.* - WildcardImport:Slider.kt$import androidx.compose.runtime.* - WildcardImport:Slider.kt$import androidx.compose.ui.input.pointer.* - WildcardImport:Stack.kt$import androidx.compose.foundation.layout.* - WildcardImport:TabGroup.kt$import androidx.compose.foundation.layout.* - WildcardImport:TabGroup.kt$import androidx.compose.runtime.* - WildcardImport:TabGroup.kt$import androidx.compose.ui.focus.* - WildcardImport:TextField.kt$import androidx.compose.foundation.* - WildcardImport:TextField.kt$import androidx.compose.foundation.layout.* - WildcardImport:TextField.kt$import androidx.compose.runtime.* - WildcardImport:TextField.kt$import androidx.compose.ui.graphics.* - WildcardImport:Theme.kt$import androidx.compose.runtime.* - WildcardImport:ToggleSwitch.kt$import androidx.compose.foundation.layout.* - WildcardImport:ToggleSwitch.kt$import androidx.compose.runtime.* - WildcardImport:Tooltip.kt$import androidx.compose.foundation.layout.* - WildcardImport:Tooltip.kt$import androidx.compose.runtime.* - WildcardImport:XmlTheme.kt$import androidx.compose.runtime.* - WildcardImport:deprecated.Menu.kt$import androidx.compose.foundation.layout.* - WildcardImport:deprecated.Menu.kt$import androidx.compose.runtime.* - WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.focus.* - WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.input.key.* - WildcardImport:deprecated.Menu.kt$import androidx.compose.ui.unit.* - WildcardImport:deprecated.Menu.kt$import com.composeunstyled.* - WildcardImport:deprecated.RadioGroup.kt$import androidx.compose.foundation.layout.* - WildcardImport:deprecated.RadioGroup.kt$import androidx.compose.runtime.* - WildcardImport:deprecated.TabGroup.kt$import androidx.compose.foundation.layout.* - WildcardImport:deprecated.TabGroup.kt$import androidx.compose.runtime.* - WildcardImport:deprecated.TabGroup.kt$import androidx.compose.ui.focus.* + diff --git a/detekt.yml b/detekt.yml index 4abec819..33ff64f3 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,70 +1,35 @@ build: - maxIssues: 10 # Change number of issues allowed as per need - excludeCorrectable: false - weights: - complexity: 2 - LongParameterList: 1 + maxIssues: 500 # Change number of issues allowed as per need config: validation: true warningsAsErrors: false checkExhaustiveness: false - excludes: '' + # when writing own rules with new properties, exclude the property path e.g.: ['my_rule_set', '.*>.*>[my_property]'] processors: active: true exclude: - 'DetektProgressListener' + # - 'KtFileCountProcessor' + # - 'PackageCountProcessor' + # - 'ClassCountProcessor' + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ProjectComplexityProcessor' + # - 'ProjectCognitiveComplexityProcessor' + # - 'ProjectLLOCProcessor' + # - 'ProjectCLOCProcessor' + # - 'ProjectLOCProcessor' + # - 'ProjectSLOCProcessor' + # - 'LicenseHeaderLoaderExtension' console-reports: active: true - exclude: - - 'ProjectStatisticsReport' - - 'ComplexityReport' - -output-reports: - active: true - -style: - MaxLineLength: - active: true - maxLineLength: 150 - WildcardImport: - active: true - UnusedImports: - active: true - NewLineAtEndOfFile: - active: true - -naming: - PackageNaming: - active: true - FunctionNaming: - active: false # Composables often start with uppercase - TopLevelPropertyNaming: - active: false - ObjectPropertyNaming: - active: true - -complexity: - LongMethod: - active: false # Disable, Compose UIs can be long - LongParameterList: - active: false # Compose often uses many params - TooManyFunctions: - active: true - thresholdInFiles: 20 - -performance: - ForEachOnRange: - active: true - SpreadOperator: - active: true - -potential-bugs: - EqualsAlwaysReturnsTrueOrFalse: - active: true - IteratorHasNextCallsNextMethod: - active: true - UnsafeCast: - active: true + # exclude: + # - 'ProjectStatisticsReport' + # - 'ComplexityReport' + # - 'NotificationReport' + # - 'IssuesReport' + # - 'FileBasedIssuesReport' + # - 'LiteIssuesReport'