Этап 1: detekt (статанализ + ktlint-форматирование) с baseline
CI / verify (push) Has been cancelled
CI / release (push) Has been cancelled

- detekt 1.23.8 применён ко всем НАШИМ модулям (vendor-форк исключён),
  +formatting-ruleset (обёртка ktlint). Совместим с Kotlin 2.3 (проверено).
- config/detekt/detekt.yml — настройки под наш код (LongMethod 120, MaxLine 140,
  MagicNumber off — dp/цвета отдельно, FunctionNaming off — @Composable Заглавные).
- detekt-baseline.xml по модулям: ~403 текущих замечаний зафиксированы →
  detekt зелёный, дальше ловит только НОВЫЕ. detekt в CI (ci.yml verify).

Проверено: detektBaseline + detekt BUILD SUCCESSFUL.
This commit is contained in:
b-dev-mobile
2026-07-07 23:36:40 +00:00
parent ab8fa70e51
commit ac438269c5
17 changed files with 549 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>ArgumentListWrapping:MailComposeScreen.kt$(hour, minute)</ID>
<ID>ArgumentListWrapping:MailComposeScreen.kt$(updatedDate, java.time.LocalTime.of(hour, minute))</ID>
<ID>ArgumentListWrapping:MailModels.kt$("""^\s*&lt;(?:!DOCTYPE|html|head|body|table|div|p|span|br|meta)\b""", RegexOption.IGNORE_CASE)</ID>
<ID>ArgumentListWrapping:MailScreen.kt$(context, it.message ?: "Ошибка загрузки", Toast.LENGTH_SHORT)</ID>
<ID>ComplexCondition:MailComposeActivity.kt$MailComposeActivity$username.isBlank() || serverUrl.isBlank() || accountId &lt;= 0 || accountEmail.isBlank()</ID>
<ID>ComplexCondition:MailRepository.kt$MailRepository$configured != null &amp;&amp; (role != "sent" || configured.specialRole != "inbox" &amp;&amp; !configured.isInbox)</ID>
<ID>CyclomaticComplexMethod:MailScreen.kt$@Composable fun MailScreen( session: AuthSession, modifier: Modifier = Modifier, openMessageId: Int? = null, openMailboxId: Int? = null, pushRefreshRequest: Int = 0, sidebarOpen: Boolean = false, onSidebarOpenChange: (Boolean) -&gt; Unit = {}, settingsOpen: Boolean = false, onSettingsOpenChange: (Boolean) -&gt; Unit = {}, onOpenMessageConsumed: () -&gt; Unit = {}, onMessageOpenStateChange: (Boolean) -&gt; Unit = {}, onUnauthorized: () -&gt; Unit = {}, )</ID>
<ID>ImportOrdering:MailComponents.kt$import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Checkbox import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.IconButton import androidx.compose.material3.MenuDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.DialogProperties import coil.compose.AsyncImage import kotlin.OptIn import ru.forbion.f7cloud.core.designsystem.F7Colors import ru.forbion.f7cloud.core.designsystem.F7ListCard import ru.forbion.f7cloud.core.designsystem.F7OutlinedField import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton import ru.forbion.f7cloud.core.designsystem.f7SwipeFromRightToDismiss import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date import java.util.Locale import kotlin.math.abs import android.app.DatePickerDialog</ID>
<ID>ImportOrdering:MailScreen.kt$import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.compose.viewModel import ru.forbion.f7cloud.core.auth.AuthSession import androidx.activity.compose.BackHandler import ru.forbion.f7cloud.core.designsystem.F7Colors import ru.forbion.f7cloud.core.designsystem.F7OverlayDismissHandler import ru.forbion.f7cloud.core.designsystem.f7SwipeFromRightToDismiss import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import ru.forbion.f7cloud.core.network.NetworkFactory import ru.forbion.f7cloud.feature.files.LocalFileOpener import kotlinx.coroutines.flow.distinctUntilChanged import java.io.File</ID>
<ID>Indentation:MailScreen.kt$ </ID>
<ID>LargeClass:MailRepository.kt$MailRepository</ID>
<ID>LargeClass:MailViewModel.kt$MailViewModel : ViewModel</ID>
<ID>LongMethod:MailComponents.kt$@Composable fun MailMessageSenderCard( fromName: String, fromEmail: String, subject: String, to: String, cc: String, dateInt: Long, flagged: Boolean, seen: Boolean, important: Boolean, serverUrl: String, onReply: () -&gt; Unit, onToggleStar: () -&gt; Unit, onMarkUnread: () -&gt; Unit, onDelete: () -&gt; Unit, onToggleImportant: () -&gt; Unit, onForward: () -&gt; Unit, onMarkSpam: () -&gt; Unit, onEditTags: () -&gt; Unit, onMove: () -&gt; Unit, onSnooze: () -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongMethod:MailComponents.kt$@Composable fun MailNavigationSidebar( serverUrl: String, visible: Boolean, accounts: List&lt;MailAccount&gt;, folders: List&lt;MailFolderEntry&gt;, selected: MailFolderEntry?, collapsedAccountIds: Set&lt;Int&gt;, onDismiss: () -&gt; Unit, onComposeClick: () -&gt; Unit, onRefreshClick: () -&gt; Unit, onFolderClick: (MailFolderEntry) -&gt; Unit, onToggleAccountCollapsed: (Int) -&gt; Unit, onPriorityInboxClick: () -&gt; Unit, onOutboxClick: () -&gt; Unit, )</ID>
<ID>LongMethod:MailComponents.kt$@Composable fun MailSearchParamsSheet( visible: Boolean, params: MailSearchParams, onDismiss: () -&gt; Unit, onSearch: (MailSearchParams) -&gt; Unit, onClear: () -&gt; Unit, )</ID>
<ID>LongMethod:MailComposeScreen.kt$@Composable fun MailComposeScreen( session: AuthSession, launch: MailComposeLaunch, vm: MailComposeViewModel, onClose: () -&gt; Unit, onUnauthorized: () -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongMethod:MailFilesPickerActivity.kt$@Composable private fun MailFilesPickerScreen( session: AuthSession, title: String, onCancel: () -&gt; Unit, onUnauthorized: () -&gt; Unit, onFileSelected: (FileItem) -&gt; Unit, )</ID>
<ID>LongMethod:MailScreen.kt$@Composable fun MailScreen( session: AuthSession, modifier: Modifier = Modifier, openMessageId: Int? = null, openMailboxId: Int? = null, pushRefreshRequest: Int = 0, sidebarOpen: Boolean = false, onSidebarOpenChange: (Boolean) -&gt; Unit = {}, settingsOpen: Boolean = false, onSettingsOpenChange: (Boolean) -&gt; Unit = {}, onOpenMessageConsumed: () -&gt; Unit = {}, onMessageOpenStateChange: (Boolean) -&gt; Unit = {}, onUnauthorized: () -&gt; Unit = {}, )</ID>
<ID>LongMethod:MailScreen.kt$@Composable private fun MailInboxScreen( session: AuthSession, modifier: Modifier = Modifier, selectedFolder: MailFolderEntry?, loading: Boolean, loadingMore: Boolean, error: String?, searchQuery: String, searchParams: MailSearchParams, isOutbox: Boolean, messages: List&lt;MailMessage&gt;, outboxMessages: List&lt;MailOutboxMessage&gt;, nextCursor: Long?, onSearchChange: (String) -&gt; Unit, onQuickFilterToggle: (MailQuickFilter) -&gt; Unit, onComposeClick: () -&gt; Unit, onFilterClick: () -&gt; Unit, onMessageClick: (Int) -&gt; Unit, onOutboxRetry: (Int) -&gt; Unit, onOutboxDelete: (Int) -&gt; Unit, onLoadMore: () -&gt; Unit, )</ID>
<ID>LongMethod:MailScreen.kt$@Composable private fun MailMessageDetailView( session: AuthSession, detail: MailMessageDetail?, loading: Boolean, httpClient: okhttp3.OkHttpClient, modifier: Modifier = Modifier, showHeader: Boolean = true, htmlBodyExternal: Boolean = false, onAttachmentClick: (MailAttachment) -&gt; Unit, )</ID>
<ID>LongMethod:MailSettingsScreens.kt$@Composable private fun MailAccountSettingsScreen( settings: MailAccountSettings?, loading: Boolean, saving: Boolean, mailboxes: List&lt;MailMailbox&gt;, onBack: () -&gt; Unit, onSave: (MailAccountSettings) -&gt; Unit, )</ID>
<ID>LongMethod:MailSettingsScreens.kt$@Composable private fun MailAppSettingsScreen( serverUrl: String, accounts: List&lt;MailAccount&gt;, appSettings: MailAppSettings?, loading: Boolean, saving: Boolean, onAccountClick: (Int) -&gt; Unit, onShowThreadedChange: (Boolean) -&gt; Unit, onHighlightExternalChange: (Boolean) -&gt; Unit, onRemoveTrustedSender: (MailTrustedSender) -&gt; Unit, onCreateTextBlock: (String, String) -&gt; Unit, onDeleteTextBlock: (Int) -&gt; Unit, onDismiss: () -&gt; Unit, )</ID>
<ID>LoopWithTooManyJumpStatements:MailCacheRepository.kt$MailCacheRepository$for</ID>
<ID>LoopWithTooManyJumpStatements:MailRepository.kt$MailRepository$for</ID>
<ID>LoopWithTooManyJumpStatements:MailRepository.kt$MailRepository$while</ID>
<ID>MatchingDeclarationName:MailRichTextEditor.kt$MailRichTextEditorController</ID>
<ID>MaximumLineLength:MailComposeActivity.kt$MailComposeActivity.Companion$ </ID>
<ID>MaximumLineLength:MailComposeScreen.kt$ </ID>
<ID>MaximumLineLength:MailComposeViewModel.kt$MailComposeViewModel$ </ID>
<ID>MaximumLineLength:MailModels.kt$private</ID>
<ID>MaximumLineLength:MailScreen.kt$ </ID>
<ID>MaximumLineLength:MailViewModel.kt$MailViewModel$ </ID>
<ID>NestedBlockDepth:MailRepository.kt$MailRepository$private fun parseMailboxes(data: Any): List&lt;MailMailbox&gt;</ID>
<ID>NoUnusedImports:MailComponents.kt$ru.forbion.f7cloud.feature.mail.MailComponents.kt</ID>
<ID>NoUnusedImports:MailComposeScreen.kt$ru.forbion.f7cloud.feature.mail.MailComposeScreen.kt</ID>
<ID>NoUnusedImports:MailRepository.kt$ru.forbion.f7cloud.feature.mail.MailRepository.kt</ID>
<ID>PropertyWrapping:MailModels.kt$private val HTML_BODY_HINT = Regex("""^\s*&lt;(?:!DOCTYPE|html|head|body|table|div|p|span|br|meta)\b""", RegexOption.IGNORE_CASE)</ID>
<ID>UnusedParameter:MailRepository.kt$MailRepository$serverUrl: String</ID>
<ID>UnusedPrivateMember:MailComponents.kt$@Composable private fun MailTagChip(tag: MailTag)</ID>
<ID>UnusedPrivateProperty:MailComponents.kt$private val StarColor = Color(0xFFF9CF3D)</ID>
</CurrentIssues>
</SmellBaseline>