Wire ktlint-gradle 14.2.0 and detekt 2.0.0-alpha.5 (the only detekt line with Gradle 9 support) through the version catalog. - .editorconfig: official Kotlin style, 120-col limit, @Composable exempt from function-naming. - config/detekt/detekt.yml: slim overrides on detekt's defaults — @Composable exemptions for the OOP-era metrics, sane ReturnCount / ThrowsCount / TooManyFunctions thresholds, and TooGenericExceptionCaught off at the resilient network/push boundaries (which now log). Findings fixed in code (behaviour-preserving; 81 unit tests still pass): - SwallowedException: SendWorker / IdleService now log the caught exception. - roleOf (Folder) and extractBody (ImapClient) split into named helpers. - MailSyncer: hoisted a 4-condition `if` into a named val. - TopDest extracted to its own file; ~14 magic numbers -> named constants. The remainder is the ktlint auto-format across the module. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
56 lines
2.5 KiB
YAML
56 lines
2.5 KiB
YAML
# Project overrides merged onto detekt's bundled defaults (buildUponDefaultConfig = true in
|
|
# app/build.gradle.kts). Only rules that need tuning for this project appear here.
|
|
#
|
|
# Guiding principle: Compose UI intentionally breaks several OOP-era metrics, and a few default
|
|
# thresholds are stricter than this project's chosen style. Those are relaxed here with a reason.
|
|
# Genuine smells (swallowed exceptions, an over-complex condition, a misnamed file) are fixed in
|
|
# the code, not silenced.
|
|
|
|
complexity:
|
|
LongMethod:
|
|
# Declarative @Composable functions are read top-to-bottom and are legitimately long.
|
|
ignoreAnnotated: ['Composable']
|
|
CyclomaticComplexMethod:
|
|
# Branchy layout code (when/if inside a UI tree) isn't algorithmic complexity.
|
|
ignoreAnnotated: ['Composable']
|
|
TooManyFunctions:
|
|
# Screen files group many small @Composable helpers next to their screen. The data layer
|
|
# (repositories, DAOs, mappers) and complex mailbox screen/ViewModel are intentionally
|
|
# operation-rich cohesive APIs; detekt's default of 11 is far too low for them. Files past
|
|
# ~40 functions still flag as genuinely bloated.
|
|
ignoreAnnotated: ['Composable']
|
|
allowedFunctionsPerFile: 40
|
|
allowedFunctionsPerClass: 40
|
|
allowedFunctionsPerInterface: 40
|
|
|
|
naming:
|
|
FunctionNaming:
|
|
# @Composable functions are PascalCase by Compose convention.
|
|
ignoreAnnotated: ['Composable']
|
|
|
|
style:
|
|
MagicNumber:
|
|
# dp / sp / duration literals are idiomatic inline in Compose.
|
|
ignoreAnnotated: ['Composable']
|
|
ignorePropertyDeclaration: true
|
|
ignoreNamedArgument: true
|
|
ReturnCount:
|
|
# Allow guard-clause-style early returns; detekt's default of 2 is overly strict.
|
|
max: 4
|
|
LoopWithTooManyJumpStatements:
|
|
# Clear early-continue / early-return loops (e.g. MIME-part walking) read fine; default 1 is strict.
|
|
maxJumpCount: 3
|
|
ThrowsCount:
|
|
# Guard-clause throws don't count; allow a few more for functions validating several
|
|
# preconditions (e.g. the OAuth token exchange checks response, auth code, and email).
|
|
excludeGuardClauses: true
|
|
max: 3
|
|
|
|
exceptions:
|
|
TooGenericExceptionCaught:
|
|
# Background sync, the push service, and the IMAP client intentionally catch broadly at their
|
|
# boundaries to stay resilient to arbitrary mail-library/network failures; each catch is logged
|
|
# and handled (retry with backoff, or SMTP fallback). The SwallowedException rule stays active
|
|
# (exceptions are logged, not dropped).
|
|
active: false
|