All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Recomposition Profiler: Timing measurement (Issue #89)
@TraceRecompositionnow measures composable recomposition duration viaSystem.nanoTime()IR injection- Duration displayed in logcat output:
[Recomposition #3] UserCard (2.30ms) - Compiler plugin wraps composable body in try-finally for accurate timing even on exceptions
RecompositionEvent.durationNanosfield added for custom logger consumption- KMP-compatible via
expect/actual currentNanoTime()(Android/JVM supported, other platforms gracefully skip)
- Heatmap Tooltip — Hover over recomposition count inlay in the editor to see:
- Last recomposition duration
- Parameter changes with old/new values
- State changes with old/new values
- Unstable parameter summary
- Cumulative total recomposition count and duration
- Heatmap logcat parser updates — Parses
[param]and[state]prefixed lines and duration from log output
- Shadow plugin upgraded to 9.0.0-beta12 for Gradle 9.x compatibility (plugin ID changed from
com.github.johnrengelman.shadowtocom.gradleup.shadow)
- Stability configuration file support for
stabilityDump(Issue #130, PR #105)stabilityConfigurationFilesnow applies to bothstabilityDumpandstabilityChecktasks- Types matching configuration patterns are overridden to STABLE in the baseline file
- Composable
skippableflag is recalculated based on resolved parameter stability
unstableOnlyoption for stability baseline (Issue #128)- New
unstableOnlyoption: when enabled, only unstable composables are included in the baseline file - Reduces baseline file size in large projects and focuses on stability issues
- New
- New composable diff now includes parameter-level stability details (PR #105)
stabilityCheckoutput for new composables shows each parameter's stability status
- Internal state change tracking for
@TraceRecomposition(Issue #89)- New
traceStatesannotation parameter:@TraceRecomposition(traceStates = true) - Tracks
mutableStateOf,mutableIntStateOf,derivedStateOfand other Compose state changes - Compiler plugin detects delegated state variables via
IrLocalDelegatedPropertyIR analysis - Logs state changes with
[state]prefix, parameter changes with[param]prefix - Only changed states are logged to reduce noise
- New
ignoredPackagesnow consistently respected duringstabilityCheck(Issue #129)- Previously, composables in ignored packages were excluded from
stabilityDumpbut still detected as "new composable" duringstabilityCheck - Now both tasks apply the same package/class filtering
- Previously, composables in ignored packages were excluded from
@Optionalannotation added tostabilityConfigurationFilestask input (PR #105)- Prevents Gradle task validation failure when configuration files are not set
- ADB not found on Windows (Issue #139)
- Fixed
adb.exedetection on Windows for the Heatmap feature - Added Windows default SDK path (
%LOCALAPPDATA%\Android\Sdk) - Uses
wherecommand instead ofwhichon Windows for PATH lookup
- Fixed
- Tool window actions always visible — Toggle Heatmap, Clear Data, Settings, and GitHub icons moved from hover-only title bar to content toolbar across all tabs
- Tool window icon updated — Changed from monochrome gray to blue color matching the plugin icon
- Stability comparison logic extracted to
StabilityComparison.kt(PR #105) - Stability configuration parser added as
StabilityConfigParser.kt(PR #105)
- Fixed Kotlin 2.3.20 compatibility (Issue #133)
- Resolved
NoSuchMethodErrorforIrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUBandDEFINEDconstants - Used reflection-based origin lookups to support Kotlin's changed return types in 2.3.20
- Migrated
ComposableStabilityCheckerfromFirSimpleFunctionCheckertoFirCallableDeclarationCheckerto handleFirSimpleFunction→FirNamedFunctionrename
- Resolved
- Upgraded to Kotlin 2.3.20
- Recomposition Cascade Visualizer (PR #119)
- Right-click any
@Composablefunction and select "Analyze Recomposition Cascade" to trace downstream composables affected by recomposition - Tree view showing each downstream composable with stability status (skippable vs. non-skippable)
- Summary statistics: total downstream count, skippable/unskippable counts, and max depth
- Cycle detection and configurable depth limits (max 10) prevent infinite analysis
- Double-click any node to navigate directly to its source code
- Available via editor right-click context menu
- New "Cascade" tab in the Compose Stability Analyzer tool window
- Right-click any
- Live Recomposition Heatmap (PR #120, #121)
- Real-time recomposition counts from a connected device overlaid directly above composable functions in the editor
- Reads
@TraceRecompositionevents from ADB logcat and aggregates per-composable data - Color-coded severity: green (< 10 recompositions), yellow (10-50), red (50+)
- Click any recomposition count to open the Heatmap tab with detailed event logs and parameter change history
- Start/Stop toggle button in the tool window title bar and Code menu
- Multi-device support with device picker when multiple ADB devices are connected
- Flicker-free rendering using deterministic pre-baked inlay renderers
- Heatmap enabled by default in plugin settings
- Configurable severity thresholds in Settings > Tools > Compose Stability Analyzer
- New "Heatmap" tab in the Compose Stability Analyzer tool window
- Plugin Verifier integration (PR #118)
- Extended IDE compatibility to build 261 (IntelliJ IDEA 2026.1)
- Added
runPluginVerifiertask for automated compatibility testing
- Tool window now has three tabs: Explorer, Cascade, and Heatmap
- Start/Stop Recomposition Heatmap button moved to tool window title bar for visibility across all tabs
- K2-safe reference resolution using
runCatchingpattern in cascade analyzer - Cancellation support in cascade background analysis via
ProgressIndicator.checkCanceled()
- Android variant-specific stability tasks (Issue #85, PR #101)
- Gradle plugin now creates per-variant tasks (e.g.,
debugStabilityDump,releaseStabilityCheck) for Android projects - Allows running stability analysis on a single variant without compiling others
- Aggregate tasks (
stabilityDump,stabilityCheck) still available for all variants - Improved build cache compatibility for Kotlin compile output registration
- Gradle plugin now creates per-variant tasks (e.g.,
- Non-regressive change filtering for stability validation (Issue #82, PR #104)
- New
ignoreNonRegressiveChangesoption: only flag stability regressions, ignore non-regressive changes (e.g., new stable parameters) - New
allowMissingBaselineoption: allow stability checks to run even without an existing baseline file - With both flags enabled, the Gradle plugin reports all unstable composables found in the module
- New
- Stability configuration file wildcard support (Issue #108, PR #110)
- Implemented
stabilityPatternToRegexto support*and**wildcard syntax in stability configuration files - Matches the format used by the official Compose compiler stability configuration
- Example:
com.datalayer.*,com.example.**
- Implemented
@StabilityInferredannotation now supported in Gradle plugin (Issue #102, PR #112)- Immutable classes from other modules annotated with
@StabilityInferred(parameters=0)are now correctly treated as stable duringstabilityDump/stabilityCheck - Previously, cross-module classes with
@StabilityInferredwere incorrectly marked as UNSTABLE - Aligns Gradle plugin behavior with the IDEA plugin, which already handled this correctly
- Immutable classes from other modules annotated with
- Skip analysis for
@NonRestartableComposableand@NonSkippableComposable(Issue #103, PR #111)- Composable functions annotated with
@NonRestartableComposableor@NonSkippableComposableare now excluded from stability analysis - These functions are not subject to recomposition skipping, so stability analysis is not applicable
- Composable functions annotated with
- Improved typealias handling in IDEA plugin (Issue #16, PR #106)
- Parameters using a typealias to a function type (e.g.,
typealias ComposableAction = @Composable () -> Unit) are now correctly recognized as stable - Added typealias expansion support across PSI fallback, K1, and K2 analysis paths
- Includes circular alias recursion guard to prevent infinite loops
- Parameters using a typealias to a function type (e.g.,
- Replaced internal
nj2k.descendantsOfTypewith stablePsiTreeUtilAPI (PR #109)- Implemented intelligent caching mechanism for typealias resolution with automatic expiration
- Streamlined function-type detection and composability checking logic
- Improved IDE responsiveness during analysis
- Fixed stabilityDump task incorrectly marked as UP-TO-DATE
- Task now properly tracks the
stability-info.jsoninput file for up-to-date checks - Changed from
@Internalto@InputFilesannotation on input file property - Ensures stability files are regenerated when compiler output changes
- Fixes issue where running
./gradlew stabilityDumpwould skip execution even when stability files were missing - Task now correctly runs after
cleanor when stability output is deleted
- Task now properly tracks the
- Quiet mode for stability validation (Issue #83)
- New
quietCheck: Boolean = falseoption instabilityValidationconfiguration - Suppresses "✅ Stability check passed." messages for modules that pass checks
- Reduces log noise in multi-module projects where many modules pass validation
- Errors and warnings still shown normally
- Example:
stabilityValidation { quietCheck.set(true) }
- New
- Upgraded to Kotlin 2.3.0
- Fixed "Wrong plugin option format: null" compilation error (Issue #87)
- Changed cross-module detection to use file-based approach instead of string-based SubpluginOption
- Project dependencies now written to
build/stability/project-dependencies.txt(one package per line) - Compiler plugin reads dependencies from file instead of parsing comma-separated string
- Resolves build failures in multi-module projects introduced in 0.6.3
- Users experiencing compilation errors with 0.6.3 should upgrade to 0.6.4
- More robust cross-module dependency passing mechanism
- Better handling of empty dependency lists
- Follows common patterns used by other Kotlin compiler plugins
- Cross-module stability detection - Classes from other Gradle modules now require explicit stability annotations
- Compiler plugin: Detects cross-module types via IR origins and package matching
- Gradle plugin: Automatically collects all subproject packages for cross-module detection
- IDE plugin: Uses IntelliJ module system to identify cross-module boundaries
- Classes from different modules marked as UNSTABLE unless annotated with @Stable/@Immutable/@StabilityInferred
- Prevents accidentally assuming stability for types where implementation details aren't visible
- Provides consistent behavior across compiler plugin, IDE plugin, and stability validation
- Fixed Gradle compatibility issues
- Removed deprecated
getDependencyProject()usage for broader Gradle version compatibility - Implemented portable dependency collection that works across all Gradle versions
- Removed deprecated
- Fixed compiler tests compatibility
- Updated StabilityTestConfigurator to pass new projectDependencies parameter
- All compiler tests now passing with cross-module detection enabled
- Fixed property source file location and navigation in tool window (Issue #67)
- Tool window now correctly identifies source file for composable properties
- Properties no longer show "Unknown.kt" as file name
- Double-clicking on property names navigates to correct source location
- Enhanced tool window handling of ignored type patterns (Issue #74)
- Ignored parameters displayed as stable instead of hidden
- Composable skippability recalculated based on processed parameters
- Better visibility of composable signatures while respecting ignore patterns
- Compacted code comments for better readability across all cross-module detection implementations
- Fixed property source file location and navigation in tool window (Issue #67)
- Tool window now correctly identifies source file for composable properties
- Properties no longer show "Unknown.kt" as file name
- Double-clicking on property names navigates to correct source location
- Extended source location search to include
KtPropertydeclarations
- Enhanced tool window handling of ignored type patterns (Issue #74)
- Ignored parameters now displayed as stable instead of being hidden completely
- Composable skippability is recalculated based on processed parameters
- Provides better visibility of composable signatures while respecting ignore patterns
- Settings icon in IDE plugin tool window toolbar for quick access to configuration
- Support for ignored type patterns in tool window
- Tool window now respects ignored type patterns (Issue #74)
- WASM build failures with Gradle task dependencies (Issue #70)
- Property name display showing as
<get-propertyName>(Issue #67)
- Updated tool window icon to monochrome style
- Updated dependencies (Android Lint, Nexus Plugin, AGP, Compose BOM)
- Per-project stability configuration file support (Issue #60)
- Runtime gutter icon for runtime-only composables
- Generic type argument inference at compile time
- Enhanced tooltip information for runtime parameters
- Better visual distinction between unstable and runtime stability
- iOS native compilation with kotlinx.serialization (Issue #48)
- Gradle Configuration Cache compatibility (Issue #41)
- APK size increase in release builds (Issue #39)
- Optimized ProGuard rules to reduce APK size
- wasmJs target support for Kotlin Multiplatform
- Sealed class stability inheritance (Issue #31)
- Minimum IDE version updated to IntelliJ IDEA 2024.2+ (build 242+)
- New Compose Stability Tool Window (Issue #14)
- Interactive empty state guide
- Show in test source sets setting (Issue #21)
- @StabilityInferred annotation parameter support (Issue #18)
- Enhanced UI/UX for Tool Window
- Performance optimization using pre-computed JSON files
- Added IntelliJ Plugin Verifier integration
- PluginException in IntelliJ IDEA 2025.2.4 (Issue #33)
- Typealias detection for Composable function types (Issue #16)
- ImmutableList/Set/Map detection in test code (Issue #21)
- @Parcelize data classes stability detection (Issue #3)
- StackOverflowError with recursive types (Issue #11)
- Compose shape types stability analysis
- Stability analysis for Compose shape types
- StackOverflowError with recursive types
- False positive warnings for @Parcelize classes
- ProGuard consumer rules for R8/ProGuard compatibility
- Comprehensive compiler-tests module
- Enhanced documentation for stability validation
- @TraceRecomposition visualization
- Stability analysis for complex generics
- @IgnoreStabilityReport annotation
- Runtime and Gradle module unit tests
- Stability validation workflow (stabilityDump and stabilityCheck tasks)
- IDE quick fixes for @TraceRecomposition
- Compiler test compatibility with Kotlin 2.2.21
- Unified maven publishing configuration
- K2 API compatibility for Android Studio AI-243
- Graceful fallback to PSI analyzer
- K2 Analysis API support
- Enhanced @Preview detection
- IntelliJ IDEA 2025.2 support
- Initial release
- Hover documentation
- Gutter icons
- Inline hints
- Code inspections and quick fixes
- Added - New features
- Changed - Changes in existing functionality
- Deprecated - Soon-to-be removed features
- Removed - Removed features
- Fixed - Bug fixes
- Improved - Enhancements to existing features
- Security - Security-related changes
- Breaking Changes - Breaking changes requiring migration