Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/src/main/kotlin/com/skydoves/myapplication/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ fun Card(
elevation: CardElevation = CardDefaults.cardElevation(),
func: @Composable () -> UnstableUser,
func2: suspend () -> UnstableUser,
func3: suspend () -> StableUser,
content: @Composable ColumnScope.() -> Unit,
) {
}
Expand Down Expand Up @@ -280,6 +281,10 @@ sealed class MySealed {
class Child : MySealed()

class Child2 : MySealed()

data class Child3(val stableUser: StableUser) : MySealed()

data class Child4(val unstableUser: UnstableUser) : MySealed()
}

@JvmInline
Expand All @@ -292,8 +297,12 @@ value class TestValueClass(val test: String)
@Composable
fun <T> GenericDisplay(
item: T,
fontWeight4: FontWeight,
mySealed: MySealed,
child2: MySealed.Child2,
child3: MySealed.Child3,
child4: MySealed.Child4,
child: MySealed.Child,
fontWeight: FontWeight,
fontWeight2: FontWeight?,
values: kotlin.String,
Expand Down Expand Up @@ -354,3 +363,4 @@ fun DebugInfoPanel() {
}
}
}
// Force recompile
12 changes: 9 additions & 3 deletions app/stability/app.stability
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public fun com.skydoves.myapplication.ActionButton(text: kotlin.String, onClick:
- onClick: STABLE (function type)

@Composable
public fun com.skydoves.myapplication.Card(modifier: androidx.compose.ui.Modifier?, shape: androidx.compose.ui.graphics.Shape?, colors: androidx.compose.material3.CardColors?, elevation: androidx.compose.material3.CardElevation?, func: kotlin.Function2<androidx.compose.runtime.Composer, kotlin.Int, com.skydoves.myapplication.models.UnstableUser>, func2: kotlin.coroutines.SuspendFunction0<com.skydoves.myapplication.models.UnstableUser>, content: @[ExtensionFunctionType] kotlin.Function3<androidx.compose.foundation.layout.ColumnScope, androidx.compose.runtime.Composer, kotlin.Int, kotlin.Unit>): kotlin.Unit
public fun com.skydoves.myapplication.Card(modifier: androidx.compose.ui.Modifier?, shape: androidx.compose.ui.graphics.Shape?, colors: androidx.compose.material3.CardColors?, elevation: androidx.compose.material3.CardElevation?, func: kotlin.Function2<androidx.compose.runtime.Composer, kotlin.Int, com.skydoves.myapplication.models.UnstableUser>, func2: kotlin.coroutines.SuspendFunction0<com.skydoves.myapplication.models.UnstableUser>, func3: kotlin.coroutines.SuspendFunction0<com.skydoves.myapplication.models.StableUser>, content: @[ExtensionFunctionType] kotlin.Function3<androidx.compose.foundation.layout.ColumnScope, androidx.compose.runtime.Composer, kotlin.Int, kotlin.Unit>): kotlin.Unit
skippable: false
restartable: true
params:
Expand All @@ -23,6 +23,7 @@ public fun com.skydoves.myapplication.Card(modifier: androidx.compose.ui.Modifie
- elevation: STABLE (marked @Stable or @Immutable)
- func: STABLE (function type)
- func2: RUNTIME (requires runtime check)
- func3: RUNTIME (requires runtime check)
- content: STABLE (function type)

@Composable
Expand All @@ -45,13 +46,17 @@ public fun com.skydoves.myapplication.CounterDisplay(count: com.skydoves.myappli
- count: STABLE

@Composable
public fun com.skydoves.myapplication.GenericDisplay(item: T of com.skydoves.myapplication.GenericDisplay, mySealed: com.skydoves.myapplication.MySealed, child2: com.skydoves.myapplication.MySealed.Child2, fontWeight: androidx.compose.ui.text.font.FontWeight, fontWeight2: androidx.compose.ui.text.font.FontWeight?, values: kotlin.String, value: kotlin.Int?, testValueClass: com.skydoves.myapplication.TestValueClass, textAlign: androidx.compose.ui.text.style.TextAlign, textAlign2: androidx.compose.ui.text.style.TextAlign?, displayText: kotlin.Function1<T of com.skydoves.myapplication.GenericDisplay, kotlin.String>): kotlin.Unit
public fun com.skydoves.myapplication.GenericDisplay(item: T of com.skydoves.myapplication.GenericDisplay, fontWeight4: androidx.compose.ui.text.font.FontWeight, mySealed: com.skydoves.myapplication.MySealed, child2: com.skydoves.myapplication.MySealed.Child2, child3: com.skydoves.myapplication.MySealed.Child3, child4: com.skydoves.myapplication.MySealed.Child4, child: com.skydoves.myapplication.MySealed.Child, fontWeight: androidx.compose.ui.text.font.FontWeight, fontWeight2: androidx.compose.ui.text.font.FontWeight?, values: kotlin.String, value: kotlin.Int?, testValueClass: com.skydoves.myapplication.TestValueClass, textAlign: androidx.compose.ui.text.style.TextAlign, textAlign2: androidx.compose.ui.text.style.TextAlign?, displayText: kotlin.Function1<T of com.skydoves.myapplication.GenericDisplay, kotlin.String>): kotlin.Unit
skippable: false
restartable: true
params:
- item: RUNTIME (requires runtime check)
- fontWeight4: STABLE (marked @Stable or @Immutable)
- mySealed: STABLE
- child2: STABLE
- child3: STABLE
- child4: UNSTABLE (has mutable properties or unstable members)
- child: STABLE
- fontWeight: STABLE (marked @Stable or @Immutable)
- fontWeight2: STABLE (marked @Stable or @Immutable)
- values: STABLE (String is immutable)
Expand Down Expand Up @@ -131,12 +136,13 @@ public fun com.skydoves.myapplication.Test(stableUser2: com.skydoves.myapplicati
- stableUser2: STABLE

@Composable
public fun com.skydoves.myapplication.Test(myClass2: com.skydoves.myapplication.models.MyClass2, normalClass: com.skydoves.myapplication.models.NormalClass): kotlin.Unit
public fun com.skydoves.myapplication.Test(myClass2: com.skydoves.myapplication.models.MyClass2, normalClass: com.skydoves.myapplication.models.NormalClass, immutableList: kotlinx.collections.immutable.ImmutableList<kotlin.String>): kotlin.Unit
skippable: false
restartable: true
params:
- myClass2: UNSTABLE (has mutable properties or unstable members)
- normalClass: STABLE
- immutableList: STABLE (known stable type)

@Composable
public fun com.skydoves.myapplication.Test(name: kotlin.String, king: kotlin.Float): kotlin.Unit
Expand Down
10 changes: 10 additions & 0 deletions compose-stability-analyzer-idea/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to the IntelliJ IDEA plugin will be documented in this file.
## [Unreleased]

### Added
- **New Compose Stability Tool Window** - View all composables in your project at a glance (Issue #14)
- Tree view grouped by module -> package -> file
- Color-coded stability indicators (green for stable, red for unstable)
- Stability counts at each level shown as (total: XS, YU, ZR) where S=Stable, U=Unstable, R=Runtime
- Details pane showing composable information and parameter stability
- Double-click navigation to source code location
- Filter buttons to show All, Skippable, or Unskippable composables
- Refresh button to re-analyze the project
- Appears as a dedicated tool window on the right side of the IDE with custom icon
- Access via View -> Tool Windows -> Compose Stability or click the icon on the right toolbar
- New setting: "Show in test source sets" for gutter icons (Issue #21)
- Gutter icons are now hidden in test directories by default (can be enabled in settings)
- Support for reading @StabilityInferred annotation parameters for cross-module stability detection (Issue #18)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,172 @@ public final class com/skydoves/compose/stability/idea/settings/StabilitySetting
public final fun getInstance ()Lcom/skydoves/compose/stability/idea/settings/StabilitySettingsState;
}

public final class com/skydoves/compose/stability/idea/toolwindow/ComposableInfo {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZZLjava/util/List;)V
public final fun component1 ()Ljava/lang/String;
public final fun component10 ()Ljava/util/List;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Ljava/lang/String;
public final fun component6 ()I
public final fun component7 ()Z
public final fun component8 ()Z
public final fun component9 ()Z
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZZLjava/util/List;)Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZZLjava/util/List;ILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
public fun equals (Ljava/lang/Object;)Z
public final fun getFileName ()Ljava/lang/String;
public final fun getFilePath ()Ljava/lang/String;
public final fun getFunctionName ()Ljava/lang/String;
public final fun getLine ()I
public final fun getModuleName ()Ljava/lang/String;
public final fun getPackageName ()Ljava/lang/String;
public final fun getParameters ()Ljava/util/List;
public fun hashCode ()I
public final fun isRestartable ()Z
public final fun isRuntime ()Z
public final fun isSkippable ()Z
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/ComposableStabilityCollector {
public fun <init> (Lcom/intellij/openapi/project/Project;)V
public final fun collectAll ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;
}

public final class com/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults {
public fun <init> (Ljava/util/List;Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;)V
public final fun component1 ()Ljava/util/List;
public final fun component2 ()Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
public final fun copy (Ljava/util/List;Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;)Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;Ljava/util/List;Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;ILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;
public fun equals (Ljava/lang/Object;)Z
public final fun getComposables ()Ljava/util/List;
public final fun getStats ()Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/ParameterInfo {
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZ)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Z
public final fun component4 ()Z
public final fun copy (Ljava/lang/String;Ljava/lang/String;ZZ)Lcom/skydoves/compose/stability/idea/toolwindow/ParameterInfo;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/ParameterInfo;Ljava/lang/String;Ljava/lang/String;ZZILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/ParameterInfo;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getType ()Ljava/lang/String;
public fun hashCode ()I
public final fun isRuntime ()Z
public final fun isStable ()Z
public fun toString ()Ljava/lang/String;
}

public abstract class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
public fun <init> (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;)V
public final fun component1 ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
public final fun copy (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable;Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;ILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable;
public fun equals (Ljava/lang/Object;)Z
public final fun getInfo ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage;Ljava/lang/String;ILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage;
public fun equals (Ljava/lang/Object;)Z
public final fun getMessage ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
public fun <init> (Ljava/lang/String;II)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()I
public final fun component3 ()I
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File;Ljava/lang/String;IIILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getSkippableCount ()I
public final fun getUnskippableCount ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
public fun <init> (Ljava/lang/String;II)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()I
public final fun component3 ()I
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module;Ljava/lang/String;IIILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getSkippableCount ()I
public final fun getUnskippableCount ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
public fun <init> (Ljava/lang/String;II)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()I
public final fun component3 ()I
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package;Ljava/lang/String;IIILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getSkippableCount ()I
public final fun getUnskippableCount ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityStats {
public fun <init> ()V
public fun <init> (III)V
public synthetic fun <init> (IIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()I
public final fun component2 ()I
public final fun component3 ()I
public final fun copy (III)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;IIIILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
public fun equals (Ljava/lang/Object;)Z
public final fun getSkippableCount ()I
public final fun getTotalCount ()I
public final fun getUnskippableCount ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityToolWindow {
public fun <init> (Lcom/intellij/openapi/project/Project;)V
public final fun getContent ()Ljavax/swing/JComponent;
}

public final class com/skydoves/compose/stability/idea/toolwindow/StabilityToolWindowFactory : com/intellij/openapi/wm/ToolWindowFactory {
public fun <init> ()V
public fun createToolWindowContent (Lcom/intellij/openapi/project/Project;Lcom/intellij/openapi/wm/ToolWindow;)V
public fun getAnchor ()Lcom/intellij/openapi/wm/ToolWindowAnchor;
public fun getIcon ()Ljavax/swing/Icon;
public fun init (Lcom/intellij/openapi/wm/ToolWindow;)V
public fun isApplicable (Lcom/intellij/openapi/project/Project;)Z
public fun isApplicableAsync (Lcom/intellij/openapi/project/Project;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun isDoNotActivateOnStart ()Z
public fun manage (Lcom/intellij/openapi/wm/ToolWindow;Lcom/intellij/openapi/wm/ToolWindowManager;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun shouldBeAvailable (Lcom/intellij/openapi/project/Project;)Z
}

Loading