diff --git a/.golden/kotlinSumOfProductWithTypeParameterSpec/golden b/.golden/kotlinSumOfProductWithTypeParameterSpec/golden
new file mode 100644
index 0000000..c041f65
--- /dev/null
+++ b/.golden/kotlinSumOfProductWithTypeParameterSpec/golden
@@ -0,0 +1,11 @@
+@JsonClassDiscriminator("direction")
+@Serializable
+sealed class CursorInput {
+ @Serializable
+ @SerialName("nextPage")
+ data class NextPage(val key: A?) : CursorInput()
+
+ @Serializable
+ @SerialName("previousPage")
+ data class PreviousPage(val key: A) : CursorInput()
+}
\ No newline at end of file
diff --git a/.golden/swiftSumOfProductWithTypeParameterSpec/golden b/.golden/swiftSumOfProductWithTypeParameterSpec/golden
new file mode 100644
index 0000000..31a552c
--- /dev/null
+++ b/.golden/swiftSumOfProductWithTypeParameterSpec/golden
@@ -0,0 +1,4 @@
+enum CursorInput: CaseIterable, Hashable, Codable {
+ case nextPage(A?)
+ case previousPage(A)
+}
\ No newline at end of file
diff --git a/moat.cabal b/moat.cabal
index 95ef219..1e064a8 100644
--- a/moat.cabal
+++ b/moat.cabal
@@ -94,6 +94,7 @@ test-suite spec
SumOfProductWithTaggedObjectAndNonConcreteCasesSpec
SumOfProductWithTaggedObjectAndSingleNullarySpec
SumOfProductWithTaggedObjectStyleSpec
+ SumOfProductWithTypeParameterSpec
TypeVariableSpec
Moat
Moat.Class
diff --git a/src/Moat/Pretty/Kotlin.hs b/src/Moat/Pretty/Kotlin.hs
index 85e6a3a..f889491 100644
--- a/src/Moat/Pretty/Kotlin.hs
+++ b/src/Moat/Pretty/Kotlin.hs
@@ -224,12 +224,14 @@ prettyApp t1 t2 =
-- error is restricted
prettyTaggedObject ::
String ->
+ [String] ->
[Annotation] ->
+ [Interface] ->
[EnumCase] ->
String ->
SumOfProductEncodingOptions ->
String
-prettyTaggedObject parentName anns cases indents SumOfProductEncodingOptions {..} =
+prettyTaggedObject parentName tyVars anns ifaces cases indents SumOfProductEncodingOptions {..} =
intercalate
"\n\n"
( cases <&> \case
@@ -238,22 +240,22 @@ prettyTaggedObject parentName anns cases indents SumOfProductEncodingOptions {..
++ prettyAnnotations (Just caseNm) indents anns
++ indents
++ "data class "
- ++ toUpperFirst caseNm
+ ++ caseTypeHeader caseNm
++ "(val "
++ contentsFieldName
++ ": "
++ prettyMoatType caseTy
++ ") : "
- ++ parentName
+ ++ parentTypeHeader
++ "()"
EnumCase caseNm caseDoc [] ->
prettyTypeDoc indents caseDoc []
++ prettyAnnotations (Just caseNm) indents anns
++ indents
++ "data object "
- ++ toUpperFirst caseNm
+ ++ caseTypeHeader caseNm
++ " : "
- ++ parentName
+ ++ parentTypeHeader
++ "()"
EnumCase caseNm _ _ ->
error $
@@ -261,6 +263,12 @@ prettyTaggedObject parentName anns cases indents SumOfProductEncodingOptions {..
<> caseNm
<> " can have zero or one concrete type constructor!"
)
+ where
+ caseTypeHeader :: String -> String
+ caseTypeHeader name = prettyMoatTypeHeader (toUpperFirst name) (addTyVarBounds tyVars ifaces)
+
+ parentTypeHeader :: String
+ parentTypeHeader = prettyMoatTypeHeader parentName tyVars
prettyEnum ::
() =>
@@ -325,7 +333,7 @@ prettyEnum doc anns ifaces name tyVars cases sop@SumOfProductEncodingOptions {..
++ classTyp
++ prettyInterfaces ifaces
++ " {\n"
- ++ prettyTaggedObject name anns cases indents sop
+ ++ prettyTaggedObject name tyVars anns ifaces cases indents sop
++ "\n}"
where
isCEnum :: [EnumCase] -> Bool
diff --git a/test/SumOfProductWithTypeParameterSpec.hs b/test/SumOfProductWithTypeParameterSpec.hs
new file mode 100644
index 0000000..18b19ae
--- /dev/null
+++ b/test/SumOfProductWithTypeParameterSpec.hs
@@ -0,0 +1,38 @@
+module SumOfProductWithTypeParameterSpec where
+
+import Common
+import Data.List (stripPrefix)
+import Data.Maybe
+import Moat
+import Test.Hspec
+import Test.Hspec.Golden
+import Prelude hiding (Enum)
+
+data CursorInput a
+ = CursorInputNextPage (Maybe a)
+ | CursorInputPreviousPage a
+
+mobileGenWith
+ ( defaultOptions
+ { constructorModifier = \body -> fromMaybe body (stripPrefix "CursorInput" body)
+ , dataAnnotations = [Serializable, SerialName]
+ , dataProtocols = [OtherProtocol "CaseIterable", Hashable, Codable]
+ , sumOfProductEncodingOptions =
+ SumOfProductEncodingOptions
+ { encodingStyle = TaggedObjectStyle
+ , sumAnnotations = [RawAnnotation "JsonClassDiscriminator(\"direction\")"]
+ , contentsFieldName = "key"
+ , tagFieldName = "direction"
+ }
+ }
+ )
+ ''CursorInput
+
+spec :: Spec
+spec =
+ describe "stays golden" $ do
+ let moduleName = "SumOfProductWithTypeParameterSpec"
+ it "kotlin" $
+ defaultGolden ("kotlin" <> moduleName) (showKotlin @(CursorInput _))
+ it "swift" $
+ defaultGolden ("swift" <> moduleName) (showSwift @(CursorInput _))