-
-
Notifications
You must be signed in to change notification settings - Fork 24
Validate a subclass of a sealed type class #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -395,20 +395,25 @@ public class StabilityAnalyzerTransformer( | |
| } | ||
|
|
||
| // 16. Abstract classes - cannot determine (RUNTIME) | ||
| // EXCEPT sealed classes which are handled by property analysis | ||
| // EXCEPT: sealed classes with @Stable/@Immutable annotations | ||
| // Issue #31: @Immutable sealed classes should be trusted as stable | ||
| if (clazz.modality == org.jetbrains.kotlin.descriptors.Modality.ABSTRACT) { | ||
| // Check if this is a sealed class (sealed classes are abstract but stable if no mutable props) | ||
| // Check if this is a sealed class (sealed classes are abstract but stable if annotated) | ||
| val isSealed = try { | ||
| clazz.sealedSubclasses.isNotEmpty() | ||
| } catch (e: Exception) { | ||
| false | ||
| } | ||
|
|
||
| // Only mark as RUNTIME if it's NOT a sealed class | ||
| if (!isSealed) { | ||
| // Check if it has @Stable or @Immutable annotation | ||
| val hasStabilityAnnotation = clazz.hasAnnotation(stableFqName) || | ||
| clazz.hasAnnotation(immutableFqName) | ||
|
|
||
| // Only mark as RUNTIME if it's NOT a sealed class AND doesn't have stability annotation | ||
| if (!isSealed && !hasStabilityAnnotation) { | ||
| return ParameterStability.RUNTIME | ||
| } | ||
| // Sealed classes continue to property analysis | ||
| // Sealed classes and annotated abstract classes continue to property analysis | ||
| } | ||
|
|
||
| // 18. Regular classes - analyze properties first before checking @StabilityInferred | ||
|
|
@@ -434,6 +439,29 @@ public class StabilityAnalyzerTransformer( | |
| * Matches K2 implementation logic. | ||
| */ | ||
| private fun analyzeClassProperties(clazz: IrClass, fqName: String?): ParameterStability { | ||
| // Issue #31: Check if parent sealed class has @Immutable/@Stable | ||
| val parentHasStabilityAnnotation = clazz.superTypes.any { superType -> | ||
| val superClassSymbol = superType.classOrNull | ||
| if (superClassSymbol != null) { | ||
| val superClass = superClassSymbol.owner | ||
| // Check if superclass is sealed AND has stability annotation | ||
| val isSealed = try { | ||
| superClass.sealedSubclasses.isNotEmpty() | ||
| } catch (e: Exception) { | ||
| false | ||
| } | ||
| val hasAnnotation = superClass.hasAnnotation(stableFqName) || | ||
| superClass.hasAnnotation(immutableFqName) | ||
| isSealed && hasAnnotation | ||
| } else { | ||
| false | ||
| } | ||
| } | ||
|
|
||
| if (parentHasStabilityAnnotation) { | ||
| return ParameterStability.STABLE | ||
| } | ||
|
Comment on lines
+443
to
+463
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mirror the IDE fix for all stable annotations. Here we only check 🧰 Tools🪛 detekt (1.23.8)[warning] 450-450: The caught exception is swallowed. The original exception could be lost. (detekt.exceptions.SwallowedException) |
||
|
|
||
| // Check superclass stability first (matches IDE plugin logic) | ||
| val superClassStability = analyzeSuperclassStability(clazz) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Propagate all stable markers, not just
@Stable/@Immutable.Line 435 only matches Compose’s two annotations. Because
hasStableAnnotation()already recognizes@StableForAnalysis(and other stable markers), sealed subclasses of those annotations still get downgraded to runtime stability. That breaks the promise we make for custom stable markers. Please reusesuperClassSymbol.hasStableAnnotation()(or the same constant set) so every annotation we treat as stable elsewhere also propagates through sealed parents. This keeps IDE inference consistent with the rest of the analyzer.🤖 Prompt for AI Agents