Using with detekt
When using the detekt Gradle Plugin, you can specify the dependency on this set of rules by using detektPlugins
.
dependencies {
detektPlugins "io.nlopez.compose.rules:detekt:<VERSION>"
}
Using with detekt CLI / detekt IDE plugin¶
The releases page contains an uber jar for each version release that can be used to run with the CLI version of detekt.
detekt -p detekt-compose-<VERSION>-all.jar -c your/config/detekt.yml
For the IDE plugin, you'll need to add the uber jar to the list of custom plugins in its configuration, and don't forget to also enable the rules in the yml config provided to the plugin for it to work.
Enabling rules¶
For the rules to be picked up, you will need to enable them in your detekt.yml
configuration file.
Compose:
ComposableAnnotationNaming:
active: true
ComposableNaming:
active: true
# -- You can optionally disable the checks in this rule for regex matches against the composable name (e.g. molecule presenters)
# allowedComposableFunctionNames: .*Presenter,.*MoleculePresenter
ComposableParamOrder:
active: true
# -- You can optionally have a list of types to be treated as lambdas (e.g. typedefs or fun interfaces not picked up automatically)
# treatAsLambda: MyLambdaType
CompositionLocalAllowlist:
active: true
# -- You can optionally define a list of CompositionLocals that are allowed here
# allowedCompositionLocals: LocalSomething,LocalSomethingElse
CompositionLocalNaming:
active: true
ContentEmitterReturningValues:
active: true
# -- You can optionally add your own composables here
# contentEmitters: MyComposable,MyOtherComposable
ContentTrailingLambda:
active: true
# -- You can optionally have a list of types to be treated as lambdas (e.g. typedefs or fun interfaces not picked up automatically)
# treatAsLambda: MyLambdaType
# -- You can optionally have a list of types to be treated as composable lambdas (e.g. typedefs or fun interfaces not picked up automatically).
# -- The difference with treatAsLambda is that those need `@Composable` MyLambdaType in the definition, while these won't.
# treatAsComposableLambda: MyComposableLambdaType
ContentSlotReused:
active: true
# -- You can optionally have a list of types to be treated as composable lambdas (e.g. typedefs or fun interfaces not picked up automatically).
# -- The difference with treatAsLambda is that those need `@Composable` MyLambdaType in the definition, while these won't.
# treatAsComposableLambda: MyComposableLambdaType
DefaultsVisibility:
active: true
LambdaParameterEventTrailing:
active: true
# -- You can optionally add your own composables here
# contentEmitters: MyComposable,MyOtherComposable
# -- You can add composables here that you don't want to count as content emitters (e.g. custom dialogs or modals)
# contentEmittersDenylist: MyNonEmitterComposable
LambdaParameterInRestartableEffect:
active: true
# -- You can optionally have a list of types to be treated as lambdas (e.g. typedefs or fun interfaces not picked up automatically)
# treatAsLambda: MyLambdaType
Material2:
active: false # Opt-in, disabled by default. Turn on if you want to disallow Material 2 usages.
# -- You can optionally allow parts of it, if you are in the middle of a migration.
# allowedFromM2: icons.Icons,TopAppBar
ModifierClickableOrder:
active: true
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierComposable:
active: true
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierComposed:
active: true
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierMissing:
active: true
# -- You can optionally control the visibility of which composables to check for here
# -- Possible values are: `only_public`, `public_and_internal` and `all` (default is `only_public`)
# checkModifiersForVisibility: only_public
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
# -- You can suppress this check in functions annotated with these annotations
# ignoreAnnotated: ['Potato', 'Banana']
ModifierNaming:
active: true
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierNotUsedAtRoot:
active: true
# -- You can optionally add your own composables here
# contentEmitters: MyComposable,MyOtherComposable
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierReused:
active: true
# -- You can optionally add your own Modifier types
# customModifiers: BananaModifier,PotatoModifier
ModifierWithoutDefault:
active: true
MultipleEmitters:
active: true
# -- You can optionally add your own composables here that will count as content emitters
# contentEmitters: MyComposable,MyOtherComposable
# -- You can add composables here that you don't want to count as content emitters (e.g. custom dialogs or modals)
# contentEmittersDenylist: MyNonEmitterComposable
MutableParams:
active: true
MutableStateAutoboxing:
active: true
MutableStateParam:
active: true
ParameterNaming:
active: true
# -- You can optionally have a list of types to be treated as lambdas (e.g. typedefs or fun interfaces not picked up automatically)
# treatAsLambda: MyLambdaType
PreviewAnnotationNaming:
active: true
PreviewNaming:
active: false # Opt-in, disabled by default.
# -- You can optionally configure the naming strategy for previews.
# -- Possible values are: `suffix`, `prefix`, `anywhere`. By default, it will be `suffix`.
# previewNamingStrategy: suffix
PreviewPublic:
active: true
RememberMissing:
active: true
RememberContentMissing:
active: true
UnstableCollections:
active: false # Opt-in, disabled by default. Turn on if you want to enforce this (e.g. you have strong skipping disabled)
ViewModelForwarding:
active: true
# -- You can optionally use this rule on things other than types ending in "ViewModel" or "Presenter" (which are the defaults). You can add your own via a regex here:
# allowedStateHolderNames: .*ViewModel,.*Presenter
# -- You can optionally add an allowlist for Composable names that won't be affected by this rule
# allowedForwarding: .*Content,.*FancyStuff
# -- You can optionally add an allowlist for ViewModel/StateHolder names that won't be affected by this rule
# allowedForwardingOfTypes: PotatoViewModel,(Apple|Banana)ViewModel,.*FancyViewModel
ViewModelInjection:
active: true
# -- You can optionally add your own ViewModel factories here
# viewModelFactories: hiltViewModel,potatoViewModel
Disabling a specific rule¶
To disable a rule you have to follow the instructions from the detekt documentation, and use the id of the rule you want to disable.
For example, to disable ComposableNaming
in a particular method, you can suppress it.
@Suppress("ComposableNaming")
@Composable
fun myNameIsWrong() { }
You can also disable rules altogether by changing the active: true
to active: false
in your detekt configuration yml file.