Skip to content

AndroidPoet/compose-guard

Repository files navigation

ComposeGuard

JetBrains Plugin Downloads License Profile Android Weekly

Catch Jetpack Compose mistakes as you type β€” 37 best-practice rules from the Compose Rules guidelines, surfaced live in Android Studio & IntelliJ IDEA with inline highlights, gutter icons, and one-click fixes.


Preview

ComposeGuard Preview

Why ComposeGuard?

The Compose Rules catch the subtle mistakes that hurt Compose code β€” missing Modifier parameters, un-remembered state, unstable collections, reused modifiers, and dozens more. ComposeGuard brings those checks into the editor, so you fix them while the code is still fresh instead of discovering them in a build log or a code review.

  • ⚑ Instant β€” analysis runs as you type; no build, no Gradle task, no CI round-trip.
  • 🎯 Accurate β€” rules are PSI-based and tuned to avoid false positives on valid patterns (overrides, scoped slots, mutually-exclusive branches, run-once effects, …).
  • πŸ›  Actionable β€” most violations come with a quick fix (Alt+Enter) and a detailed explanation of why it matters.
  • 🎚 Configurable β€” enable/disable any rule or whole category, or suppress per declaration.

Table of Contents

Features

  • Real-time highlighting β€” violations appear as colored underlines while you edit.
  • Gutter icons β€” a color-coded dot per @Composable summarizes its status at a glance:
    • πŸ”΄ Error Β Β  🟠 Warning Β Β  βšͺ Weak warning Β Β  πŸ”΅ Info
  • Inline hints β€” compact badges next to function names show rule violations.
  • Hover tooltips β€” every violation explains the problem, the reasoning, and the fix.
  • Quick fixes β€” rename, add a modifier parameter, wrap in remember, switch to a type-specific state, make a preview private, swap to an immutable collection, and more.
  • 37 rules across 6 categories β€” see the full Rule Reference.

Installation

Install from Marketplace

  1. Open Android Studio or IntelliJ IDEA.
  2. Go to Settings β†’ Plugins β†’ Marketplace.
  3. Search for ComposeGuard.
  4. Click Install and restart when prompted.

Or install directly from the JetBrains Marketplace.

Quick Start

Once installed, ComposeGuard automatically analyzes any Kotlin file containing @Composable functions β€” no configuration required. Here are a few things it catches:

// 🟠 Naming: Unit-returning composables should be PascalCase
@Composable
fun userCard(user: User) { }              // β†’ rename to "UserCard"

// 🟠 Modifier: public UI composables should expose a Modifier
@Composable
fun ProductCard(product: Product) {       // β†’ add `modifier: Modifier = Modifier`
    Column { Text(product.name) }
}

// πŸ”΄ State: state must be remembered
@Composable
fun Counter() {
    val count = mutableStateOf(0)         // β†’ wrap in remember { }
}

// 🟠 Stricter: prefer stable collections
@Composable
fun ItemList(items: List<Item>) { }       // β†’ use ImmutableList<Item>

Hover any highlight for the full explanation, or press Alt+Enter to apply a fix.

Suppressing Rules

To intentionally allow a violation, annotate the declaration with @Suppress using the rule id (the same id shown in the warning, e.g. ModifierRequired). The quick fix can insert this for you:

@Suppress("ModifierRequired")
@Composable
fun SplashLogo() {
    Image(painterResource(R.drawable.logo), contentDescription = null)
}

// Multiple rules at once:
@Suppress("ModifierRequired", "ComposableNaming")
@Composable
fun splash() { /* ... */ }

Suppression works at the function, property, or class level. To turn rules off project-wide instead, use Configuration.

Rule Reference

ComposeGuard ships 37 rules based on the Compose Rules guidelines. Severity legend: πŸ”΄ Error Β· 🟠 Warning Β· βšͺ Weak warning Β· πŸ”΅ Info.

Naming

Rule id Checks Severity
ComposableNaming Unit-returning composables use PascalCase; value-returning use camelCase 🟠
CompositionLocalNaming CompositionLocal properties are prefixed with Local 🟠
PreviewNaming @Preview functions reference Preview in their name βšͺ
MultipreviewNaming Multipreview annotation classes reference Preview βšͺ
ComposableAnnotationNaming @ComposableTargetMarker annotations end with Composable βšͺ
EventParameterNaming Event lambdas use present tense (onClick, not onClicked) βšͺ

Modifiers

Rule id Checks Severity
ModifierRequired Public, UI-emitting composables expose a Modifier parameter 🟠
ModifierDefaultValue modifier parameters default to Modifier 🟠
ModifierNaming The main modifier is named modifier; others follow xModifier βšͺ
ModifierTopMost The modifier is applied to the root-most layout 🟠
ModifierReuse The same modifier isn't applied to multiple live nodes 🟠
ModifierOrder Modifier chain order is intentional (e.g. padding before clickable) 🟠
AvoidComposed Prefer Modifier.Node over the deprecated composed { } factory 🟠

State

Rule id Checks Severity
RememberState mutableStateOf and friends are wrapped in remember { } πŸ”΄
TypeSpecificState Primitives use mutableIntStateOf / mutableFloatStateOf / … 🟠
DerivedStateOfCandidate Values computed from state use derivedStateOf 🟠
FrequentRecomposition Hot observable sources use lifecycle-aware collection 🟠
DeferStateReads Fast-changing state reads are deferred to lambda modifiers 🟠
HoistState State is hoisted to the appropriate level πŸ”΅
MutableStateParameter Pass value + callback instead of a MutableState parameter 🟠

Parameters

Rule id Checks Severity
ParameterOrdering Order is required β†’ modifier β†’ optional β†’ trailing content βšͺ
TrailingLambda The content slot is the trailing lambda; event handlers are not βšͺ
MutableParameter Avoid inherently mutable types (MutableList, ArrayList, …) as parameters 🟠
ExplicitDependencies Make injected ViewModels explicit parameters βšͺ
ViewModelForwarding Don't forward a ViewModel into another composable 🟠

Composables & Effects

Rule id Checks Severity
ContentEmission A composable emits content or returns a value, not both 🟠
MultipleContentEmitters A composable emits a single piece of content 🟠
ContentSlotReused A content slot isn't invoked more than once on the same pass 🟠
EffectKeys Changing captured values are passed as effect keys 🟠
LambdaParameterInEffect Lambda parameters used in effects are wrapped in rememberUpdatedState 🟠
MovableContent movableContentOf is remembered πŸ”΄
PreviewVisibility @Preview composables are private 🟠
ComponentDefaultsVisibility A <Component>Defaults object matches its composable's visibility 🟠
LazyListMissingKey Lazy list items provide a stable key 🟠
LazyListContentType Heterogeneous lazy lists set a contentType πŸ”΅

Stricter

Rule id Checks Severity
UnstableCollections Prefer ImmutableList / PersistentList over List, Set, Map 🟠
Material2Usage Migrate androidx.compose.material (M2) imports to Material 3 πŸ”΅

Suppress any rule with @Suppress("<RuleId>"), or toggle it in Settings β†’ Tools β†’ ComposeGuard.

Statistics Dashboard

ComposeGuard includes a tool window that tracks rule violations across your project.

ComposeGuard Statistics Dashboard

  • Real-time statistics β€” violation counts update as you code.
  • Category breakdown β€” see violations grouped by rule category.
  • Rule-level details β€” drill into specific rules.
  • Project overview β€” track overall code-quality trends.

Open it from View β†’ Tool Windows β†’ ComposeGuard Statistics.

Configuration

Configure ComposeGuard at Settings β†’ Tools β†’ ComposeGuard.

ComposeGuard Settings - Disable Rules

  • Enable ComposeGuard β€” master toggle for the whole plugin.
  • Display options β€” toggle gutter icons and inlay hints.
  • Rule configuration β€” enable/disable individual rules or entire categories.

Adopting ComposeGuard in an existing codebase

Adding the plugin to a large legacy project? Roll it out gradually instead of facing every warning at once:

  1. Start with the Stricter category off (Material2Usage, UnstableCollections).
  2. Enable categories one at a time as you refactor β€” the category checkbox toggles the whole group.
  3. Use @Suppress("<RuleId>") for individual, intentional exceptions.

Requirements & Compatibility

  • IntelliJ IDEA 2024.2+ or Android Studio Ladybug (2024.2)+
  • The bundled Kotlin plugin (enabled by default)
ComposeGuard Supported IDE builds
1.2.x 2024.2 – 2026.2

Contributing

Contributions are welcome β€” issues and pull requests both.

  1. Fork the repository.
  2. Create a feature branch: git checkout -b feature/amazing-feature.
  3. Make your change and add tests (./gradlew :compose-guard:test).
  4. Commit and push, then open a Pull Request.

Credits

Built on the excellent Compose Rules guidelines by Nacho Lopez (mrmans0n).

License

Designed and developed by 2025 androidpoet (Ranbir Singh)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Made with ❀️ by androidpoet

About

Real-time detection of Jetpack Compose best practices and rule violations directly in Android Studio.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors

Languages