Skip to content

Commit 492e479

Browse files
authored
Merge pull request #27 from skydoves/feature/windowstool
Introduce tool windows for the compose stability analysis
2 parents 65b595c + a604da5 commit 492e479

File tree

19 files changed

+1341
-87
lines changed

19 files changed

+1341
-87
lines changed

app/src/main/kotlin/com/skydoves/myapplication/MainActivity.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fun Card(
152152
elevation: CardElevation = CardDefaults.cardElevation(),
153153
func: @Composable () -> UnstableUser,
154154
func2: suspend () -> UnstableUser,
155+
func3: suspend () -> StableUser,
155156
content: @Composable ColumnScope.() -> Unit,
156157
) {
157158
}
@@ -280,6 +281,10 @@ sealed class MySealed {
280281
class Child : MySealed()
281282

282283
class Child2 : MySealed()
284+
285+
data class Child3(val stableUser: StableUser) : MySealed()
286+
287+
data class Child4(val unstableUser: UnstableUser) : MySealed()
283288
}
284289

285290
@JvmInline
@@ -292,8 +297,12 @@ value class TestValueClass(val test: String)
292297
@Composable
293298
fun <T> GenericDisplay(
294299
item: T,
300+
fontWeight4: FontWeight,
295301
mySealed: MySealed,
296302
child2: MySealed.Child2,
303+
child3: MySealed.Child3,
304+
child4: MySealed.Child4,
305+
child: MySealed.Child,
297306
fontWeight: FontWeight,
298307
fontWeight2: FontWeight?,
299308
values: kotlin.String,
@@ -354,3 +363,4 @@ fun DebugInfoPanel() {
354363
}
355364
}
356365
}
366+
// Force recompile

app/stability/app.stability

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public fun com.skydoves.myapplication.ActionButton(text: kotlin.String, onClick:
1313
- onClick: STABLE (function type)
1414

1515
@Composable
16-
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
16+
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
1717
skippable: false
1818
restartable: true
1919
params:
@@ -23,6 +23,7 @@ public fun com.skydoves.myapplication.Card(modifier: androidx.compose.ui.Modifie
2323
- elevation: STABLE (marked @Stable or @Immutable)
2424
- func: STABLE (function type)
2525
- func2: RUNTIME (requires runtime check)
26+
- func3: RUNTIME (requires runtime check)
2627
- content: STABLE (function type)
2728

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

4748
@Composable
48-
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
49+
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
4950
skippable: false
5051
restartable: true
5152
params:
5253
- item: RUNTIME (requires runtime check)
54+
- fontWeight4: STABLE (marked @Stable or @Immutable)
5355
- mySealed: STABLE
5456
- child2: STABLE
57+
- child3: STABLE
58+
- child4: UNSTABLE (has mutable properties or unstable members)
59+
- child: STABLE
5560
- fontWeight: STABLE (marked @Stable or @Immutable)
5661
- fontWeight2: STABLE (marked @Stable or @Immutable)
5762
- values: STABLE (String is immutable)
@@ -131,12 +136,13 @@ public fun com.skydoves.myapplication.Test(stableUser2: com.skydoves.myapplicati
131136
- stableUser2: STABLE
132137

133138
@Composable
134-
public fun com.skydoves.myapplication.Test(myClass2: com.skydoves.myapplication.models.MyClass2, normalClass: com.skydoves.myapplication.models.NormalClass): kotlin.Unit
139+
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
135140
skippable: false
136141
restartable: true
137142
params:
138143
- myClass2: UNSTABLE (has mutable properties or unstable members)
139144
- normalClass: STABLE
145+
- immutableList: STABLE (known stable type)
140146

141147
@Composable
142148
public fun com.skydoves.myapplication.Test(name: kotlin.String, king: kotlin.Float): kotlin.Unit

compose-stability-analyzer-idea/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to the IntelliJ IDEA plugin will be documented in this file.
55
## [Unreleased]
66

77
### Added
8+
- **New Compose Stability Tool Window** - View all composables in your project at a glance (Issue #14)
9+
- Tree view grouped by module -> package -> file
10+
- Color-coded stability indicators (green for stable, red for unstable)
11+
- Stability counts at each level shown as (total: XS, YU, ZR) where S=Stable, U=Unstable, R=Runtime
12+
- Details pane showing composable information and parameter stability
13+
- Double-click navigation to source code location
14+
- Filter buttons to show All, Skippable, or Unskippable composables
15+
- Refresh button to re-analyze the project
16+
- Appears as a dedicated tool window on the right side of the IDE with custom icon
17+
- Access via View -> Tool Windows -> Compose Stability or click the icon on the right toolbar
818
- New setting: "Show in test source sets" for gutter icons (Issue #21)
919
- Gutter icons are now hidden in test directories by default (can be enabled in settings)
1020
- Support for reading @StabilityInferred annotation parameters for cross-module stability detection (Issue #18)

compose-stability-analyzer-idea/api/compose-stability-analyzer-idea.api

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,172 @@ public final class com/skydoves/compose/stability/idea/settings/StabilitySetting
134134
public final fun getInstance ()Lcom/skydoves/compose/stability/idea/settings/StabilitySettingsState;
135135
}
136136

137+
public final class com/skydoves/compose/stability/idea/toolwindow/ComposableInfo {
138+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZZLjava/util/List;)V
139+
public final fun component1 ()Ljava/lang/String;
140+
public final fun component10 ()Ljava/util/List;
141+
public final fun component2 ()Ljava/lang/String;
142+
public final fun component3 ()Ljava/lang/String;
143+
public final fun component4 ()Ljava/lang/String;
144+
public final fun component5 ()Ljava/lang/String;
145+
public final fun component6 ()I
146+
public final fun component7 ()Z
147+
public final fun component8 ()Z
148+
public final fun component9 ()Z
149+
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;
150+
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;
151+
public fun equals (Ljava/lang/Object;)Z
152+
public final fun getFileName ()Ljava/lang/String;
153+
public final fun getFilePath ()Ljava/lang/String;
154+
public final fun getFunctionName ()Ljava/lang/String;
155+
public final fun getLine ()I
156+
public final fun getModuleName ()Ljava/lang/String;
157+
public final fun getPackageName ()Ljava/lang/String;
158+
public final fun getParameters ()Ljava/util/List;
159+
public fun hashCode ()I
160+
public final fun isRestartable ()Z
161+
public final fun isRuntime ()Z
162+
public final fun isSkippable ()Z
163+
public fun toString ()Ljava/lang/String;
164+
}
165+
166+
public final class com/skydoves/compose/stability/idea/toolwindow/ComposableStabilityCollector {
167+
public fun <init> (Lcom/intellij/openapi/project/Project;)V
168+
public final fun collectAll ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;
169+
}
170+
171+
public final class com/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults {
172+
public fun <init> (Ljava/util/List;Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;)V
173+
public final fun component1 ()Ljava/util/List;
174+
public final fun component2 ()Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
175+
public final fun copy (Ljava/util/List;Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;)Lcom/skydoves/compose/stability/idea/toolwindow/ComposableStabilityResults;
176+
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;
177+
public fun equals (Ljava/lang/Object;)Z
178+
public final fun getComposables ()Ljava/util/List;
179+
public final fun getStats ()Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
180+
public fun hashCode ()I
181+
public fun toString ()Ljava/lang/String;
182+
}
183+
184+
public final class com/skydoves/compose/stability/idea/toolwindow/ParameterInfo {
185+
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZ)V
186+
public final fun component1 ()Ljava/lang/String;
187+
public final fun component2 ()Ljava/lang/String;
188+
public final fun component3 ()Z
189+
public final fun component4 ()Z
190+
public final fun copy (Ljava/lang/String;Ljava/lang/String;ZZ)Lcom/skydoves/compose/stability/idea/toolwindow/ParameterInfo;
191+
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;
192+
public fun equals (Ljava/lang/Object;)Z
193+
public final fun getName ()Ljava/lang/String;
194+
public final fun getType ()Ljava/lang/String;
195+
public fun hashCode ()I
196+
public final fun isRuntime ()Z
197+
public final fun isStable ()Z
198+
public fun toString ()Ljava/lang/String;
199+
}
200+
201+
public abstract class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
202+
}
203+
204+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
205+
public fun <init> (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;)V
206+
public final fun component1 ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
207+
public final fun copy (Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Composable;
208+
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;
209+
public fun equals (Ljava/lang/Object;)Z
210+
public final fun getInfo ()Lcom/skydoves/compose/stability/idea/toolwindow/ComposableInfo;
211+
public fun hashCode ()I
212+
public fun toString ()Ljava/lang/String;
213+
}
214+
215+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
216+
public fun <init> (Ljava/lang/String;)V
217+
public final fun component1 ()Ljava/lang/String;
218+
public final fun copy (Ljava/lang/String;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$EmptyMessage;
219+
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;
220+
public fun equals (Ljava/lang/Object;)Z
221+
public final fun getMessage ()Ljava/lang/String;
222+
public fun hashCode ()I
223+
public fun toString ()Ljava/lang/String;
224+
}
225+
226+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
227+
public fun <init> (Ljava/lang/String;II)V
228+
public final fun component1 ()Ljava/lang/String;
229+
public final fun component2 ()I
230+
public final fun component3 ()I
231+
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$File;
232+
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;
233+
public fun equals (Ljava/lang/Object;)Z
234+
public final fun getName ()Ljava/lang/String;
235+
public final fun getSkippableCount ()I
236+
public final fun getUnskippableCount ()I
237+
public fun hashCode ()I
238+
public fun toString ()Ljava/lang/String;
239+
}
240+
241+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
242+
public fun <init> (Ljava/lang/String;II)V
243+
public final fun component1 ()Ljava/lang/String;
244+
public final fun component2 ()I
245+
public final fun component3 ()I
246+
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Module;
247+
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;
248+
public fun equals (Ljava/lang/Object;)Z
249+
public final fun getName ()Ljava/lang/String;
250+
public final fun getSkippableCount ()I
251+
public final fun getUnskippableCount ()I
252+
public fun hashCode ()I
253+
public fun toString ()Ljava/lang/String;
254+
}
255+
256+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package : com/skydoves/compose/stability/idea/toolwindow/StabilityNodeData {
257+
public fun <init> (Ljava/lang/String;II)V
258+
public final fun component1 ()Ljava/lang/String;
259+
public final fun component2 ()I
260+
public final fun component3 ()I
261+
public final fun copy (Ljava/lang/String;II)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityNodeData$Package;
262+
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;
263+
public fun equals (Ljava/lang/Object;)Z
264+
public final fun getName ()Ljava/lang/String;
265+
public final fun getSkippableCount ()I
266+
public final fun getUnskippableCount ()I
267+
public fun hashCode ()I
268+
public fun toString ()Ljava/lang/String;
269+
}
270+
271+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityStats {
272+
public fun <init> ()V
273+
public fun <init> (III)V
274+
public synthetic fun <init> (IIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
275+
public final fun component1 ()I
276+
public final fun component2 ()I
277+
public final fun component3 ()I
278+
public final fun copy (III)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
279+
public static synthetic fun copy$default (Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;IIIILjava/lang/Object;)Lcom/skydoves/compose/stability/idea/toolwindow/StabilityStats;
280+
public fun equals (Ljava/lang/Object;)Z
281+
public final fun getSkippableCount ()I
282+
public final fun getTotalCount ()I
283+
public final fun getUnskippableCount ()I
284+
public fun hashCode ()I
285+
public fun toString ()Ljava/lang/String;
286+
}
287+
288+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityToolWindow {
289+
public fun <init> (Lcom/intellij/openapi/project/Project;)V
290+
public final fun getContent ()Ljavax/swing/JComponent;
291+
}
292+
293+
public final class com/skydoves/compose/stability/idea/toolwindow/StabilityToolWindowFactory : com/intellij/openapi/wm/ToolWindowFactory {
294+
public fun <init> ()V
295+
public fun createToolWindowContent (Lcom/intellij/openapi/project/Project;Lcom/intellij/openapi/wm/ToolWindow;)V
296+
public fun getAnchor ()Lcom/intellij/openapi/wm/ToolWindowAnchor;
297+
public fun getIcon ()Ljavax/swing/Icon;
298+
public fun init (Lcom/intellij/openapi/wm/ToolWindow;)V
299+
public fun isApplicable (Lcom/intellij/openapi/project/Project;)Z
300+
public fun isApplicableAsync (Lcom/intellij/openapi/project/Project;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
301+
public fun isDoNotActivateOnStart ()Z
302+
public fun manage (Lcom/intellij/openapi/wm/ToolWindow;Lcom/intellij/openapi/wm/ToolWindowManager;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
303+
public fun shouldBeAvailable (Lcom/intellij/openapi/project/Project;)Z
304+
}
305+

0 commit comments

Comments
 (0)