diff --git a/CHANGELOG.md b/CHANGELOG.md index 90077aa..49cc732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 2.2.1 + +### Fixes + +- Added trailing newline in Kotlin output + ## 2.2.0 ### Added diff --git a/gotyno-hs.cabal b/gotyno-hs.cabal index 6068d74..5d9e94d 100644 --- a/gotyno-hs.cabal +++ b/gotyno-hs.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: gotyno-hs -version: 2.2.0 +version: 2.2.1 synopsis: A type definition compiler supporting multiple output languages. description: Compiles type definitions into F#, TypeScript and Python, with validators, decoders and encoders. category: Compiler diff --git a/package.yaml b/package.yaml index ed52e64..3374070 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: gotyno-hs -version: 2.2.0 +version: 2.2.1 synopsis: A type definition compiler supporting multiple output languages. description: Compiles type definitions into F#, TypeScript and Python, with validators, decoders and encoders. license: BSD2 diff --git a/src/CodeGeneration/Kotlin.hs b/src/CodeGeneration/Kotlin.hs index a2040f5..4ec458a 100644 --- a/src/CodeGeneration/Kotlin.hs +++ b/src/CodeGeneration/Kotlin.hs @@ -50,7 +50,7 @@ outputModule module' = moduleClassOutput, definitionOutput, "\n", - "}" + "}\n" ] modulePrelude :: Text diff --git a/test/ParsingSpec.hs b/test/ParsingSpec.hs index c64e837..2e8958b 100644 --- a/test/ParsingSpec.hs +++ b/test/ParsingSpec.hs @@ -50,7 +50,14 @@ data PythonReferenceOutput = PythonReferenceOutput } data KotlinReferenceOutput = KotlinReferenceOutput - { basic :: !Text, + { basicStruct :: !Text, + basicUnion :: !Text, + genericStruct :: !Text, + genericUnion :: !Text, + basicEnumeration :: !Text, + basicImport :: !Text, + basicOptional :: !Text, + basic :: !Text, import' :: !Text, hasGeneric :: !Text, generics :: !Text, @@ -121,12 +128,33 @@ fSharpReferenceOutput = do kotlinReferenceOutput :: IO KotlinReferenceOutput kotlinReferenceOutput = do + basicStruct <- basicStructReferenceOutput "kt" + basicUnion <- basicUnionReferenceOutput "kt" + genericStruct <- genericStructReferenceOutput "kt" + genericUnion <- genericUnionReferenceOutput "kt" + basicEnumeration <- basicEnumerationReferenceOutput "kt" + basicImport <- basicImportReferenceOutput "kt" + basicOptional <- basicOptionalReferenceOutput "kt" basic <- basicReferenceOutput "kt" import' <- importReferenceOutput "kt" hasGeneric <- hasGenericReferenceOutput "kt" generics <- genericsReferenceOutput "kt" gitHub <- gitHubReferenceOutput "kt" - pure KotlinReferenceOutput {basic, import', hasGeneric, generics, gitHub} + pure + KotlinReferenceOutput + { basicStruct, + basicUnion, + genericStruct, + genericUnion, + basicEnumeration, + basicImport, + basicOptional, + basic, + import', + hasGeneric, + generics, + gitHub + } dLangReferenceOutput :: IO DLangReferenceOutput dLangReferenceOutput = do @@ -236,7 +264,20 @@ spec (HaskellReferenceOutput hsBasic hsImport hsHasGeneric hsGenerics hsGitHub) (FSharpReferenceOutput fsBasic fsImport fsHasGeneric fsGenerics fsGitHub) (PythonReferenceOutput pyPython pyBasic pyGenerics) - (KotlinReferenceOutput ktBasic ktImport ktHasGeneric ktGenerics ktGitHub) + ( KotlinReferenceOutput + ktBasicStruct + ktBasicUnion + ktGenericStruct + ktGenericUnion + ktBasicEnumeration + ktBasicImport + ktBasicOptional + ktBasic + ktImport + ktHasGeneric + ktGenerics + ktGitHub + ) ( DLangReferenceOutput dBasicStruct dBasicUnion @@ -555,30 +596,35 @@ spec basicStructModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/basicStruct.gotyno"] TypeScript.outputModule basicStructModule `shouldBe` tsBasicStruct + Kotlin.outputModule basicStructModule `shouldBe` ktBasicStruct DLang.outputModule basicStructModule `shouldBe` dBasicStruct it "Mirrors reference output for `basicUnion.gotyno`" $ do basicUnionModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/basicUnion.gotyno"] TypeScript.outputModule basicUnionModule `shouldBe` tsBasicUnion + Kotlin.outputModule basicUnionModule `shouldBe` ktBasicUnion DLang.outputModule basicUnionModule `shouldBe` dBasicUnion it "Mirrors reference output for `genericStruct.gotyno`" $ do genericStructModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/genericStruct.gotyno"] TypeScript.outputModule genericStructModule `shouldBe` tsGenericStruct + Kotlin.outputModule genericStructModule `shouldBe` ktGenericStruct DLang.outputModule genericStructModule `shouldBe` dGenericStruct it "Mirrors reference output for `genericUnion.gotyno`" $ do genericUnionModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/genericUnion.gotyno"] TypeScript.outputModule genericUnionModule `shouldBe` tsGenericUnion + Kotlin.outputModule genericUnionModule `shouldBe` ktGenericUnion DLang.outputModule genericUnionModule `shouldBe` dGenericUnion it "Mirrors reference output for `basicEnumeration.gotyno`" $ do enumerationModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/basicEnumeration.gotyno"] TypeScript.outputModule enumerationModule `shouldBe` tsBasicEnumeration + Kotlin.outputModule enumerationModule `shouldBe` ktBasicEnumeration DLang.outputModule enumerationModule `shouldBe` dBasicEnumeration it "Mirrors reference output for `basicImport.gotyno`" $ do @@ -586,12 +632,14 @@ spec (getRight >>> PartialList.last) <$> parseModules ["examples/basicStruct.gotyno", "examples/basicImport.gotyno"] TypeScript.outputModule basicImportModule `shouldBe` tsBasicImport + Kotlin.outputModule basicImportModule `shouldBe` ktBasicImport DLang.outputModule basicImportModule `shouldBe` dBasicImport it "Mirrors reference output for `basicOptional.gotyno`" $ do basicOptionalModule <- (getRight >>> PartialList.head) <$> parseModules ["examples/basicOptional.gotyno"] TypeScript.outputModule basicOptionalModule `shouldBe` tsBasicOptional + Kotlin.outputModule basicOptionalModule `shouldBe` ktBasicOptional DLang.outputModule basicOptionalModule `shouldBe` dBasicOptional it "Mirrors reference output for `basic.gotyno`" $ do diff --git a/test/reference-output/basic.kt b/test/reference-output/basic.kt index 29e866d..7e119e3 100644 --- a/test/reference-output/basic.kt +++ b/test/reference-output/basic.kt @@ -232,4 +232,4 @@ sealed class EmbeddedEvent : java.io.Serializable { } } } -} \ No newline at end of file +} diff --git a/test/reference-output/basicEnumeration.kt b/test/reference-output/basicEnumeration.kt new file mode 100644 index 0000000..f367ec9 --- /dev/null +++ b/test/reference-output/basicEnumeration.kt @@ -0,0 +1,31 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class BasicEnumeration { +enum class StringValues(val data: String) : java.io.Serializable { + @JsonProperty("first") FIRST("first"), + @JsonProperty("second") SECOND("second"), + @JsonProperty("Third") THIRD("Third"), + @JsonProperty("Fourth") FOURTH("Fourth"); + + companion object {} +} + +enum class IntValues(val data: Int) : java.io.Serializable { + @JsonProperty(1) FIRST(1), + @JsonProperty(2) SECOND(2), + @JsonProperty(3) THIRD(3), + @JsonProperty(4) FOURTH(4); + + companion object {} +} +} diff --git a/test/reference-output/basicImport.kt b/test/reference-output/basicImport.kt new file mode 100644 index 0000000..c1e5f23 --- /dev/null +++ b/test/reference-output/basicImport.kt @@ -0,0 +1,35 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +import org.gotynoOutput.BasicStruct + +class BasicImport { +@Serializable +data class StructUsingImport( + @get:JsonProperty("field") + val field: BasicStruct.BasicStruct +) : java.io.Serializable + +@Serializable +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type" +) +sealed class UnionUsingImport : java.io.Serializable { + @Serializable + @JsonTypeName("ConstructorWithPayload") + data class ConstructorWithPayload(val data: BasicStruct.BasicStruct) : UnionUsingImport(), java.io.Serializable { + val type = "ConstructorWithPayload" + } +} +} diff --git a/test/reference-output/basicOptional.kt b/test/reference-output/basicOptional.kt new file mode 100644 index 0000000..62d5831 --- /dev/null +++ b/test/reference-output/basicOptional.kt @@ -0,0 +1,49 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class BasicOptional { +@Serializable +data class HasOptionalString( + @get:JsonProperty("stringField") + val stringField: String?, + @get:JsonProperty("optionalArrayField") + val optionalArrayField: ArrayList?, + @get:JsonProperty("arrayOfOptionalField") + val arrayOfOptionalField: ArrayList +) : java.io.Serializable + +@Serializable +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type" +) +sealed class HasOptionalConstructor : java.io.Serializable { + @Serializable + @JsonTypeName("DoesNot") + data class DoesNot(val data: Int) : HasOptionalConstructor(), java.io.Serializable { + val type = "DoesNot" + } + + @Serializable + @JsonTypeName("Does") + data class Does(val data: Int?) : HasOptionalConstructor(), java.io.Serializable { + val type = "Does" + } + + @Serializable + @JsonTypeName("HasOptionalStruct") + data class HasOptionalStruct(val data: HasOptionalString?) : HasOptionalConstructor(), java.io.Serializable { + val type = "HasOptionalStruct" + } +} +} diff --git a/test/reference-output/basicStruct.kt b/test/reference-output/basicStruct.kt new file mode 100644 index 0000000..87217c0 --- /dev/null +++ b/test/reference-output/basicStruct.kt @@ -0,0 +1,21 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class BasicStruct { +@Serializable +data class BasicStruct( + @get:JsonProperty("field1") + val field1: Int, + @get:JsonProperty("field2") + val field2: String +) : java.io.Serializable +} diff --git a/test/reference-output/basicUnion.kt b/test/reference-output/basicUnion.kt new file mode 100644 index 0000000..1f4ef5b --- /dev/null +++ b/test/reference-output/basicUnion.kt @@ -0,0 +1,53 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class BasicUnion { +@Serializable +data class PayloadStruct( + @get:JsonProperty("field1") + val field1: Int +) : java.io.Serializable + +@Serializable +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type" +) +sealed class BasicUnion : java.io.Serializable { + @Serializable + @JsonTypeName("HasStringPayload") + data class HasStringPayload(val data: String) : BasicUnion(), java.io.Serializable { + val type = "HasStringPayload" + } + + @Serializable + @JsonTypeName("HasPayload") + data class HasPayload(val data: PayloadStruct) : BasicUnion(), java.io.Serializable { + val type = "HasPayload" + } + + @Serializable + @JsonTypeName("HasNoPayload") + class HasNoPayload : BasicUnion(), java.io.Serializable { + val type = "HasNoPayload" + + override fun equals(other: Any?): Boolean { + return other is HasNoPayload + } + + override fun hashCode(): Int { + return 0 + } + } +} +} diff --git a/test/reference-output/genericStruct.kt b/test/reference-output/genericStruct.kt new file mode 100644 index 0000000..15ba81f --- /dev/null +++ b/test/reference-output/genericStruct.kt @@ -0,0 +1,19 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class GenericStruct { +@Serializable +data class GenericStruct( + @get:JsonProperty("field") + val field: T +) : java.io.Serializable +} diff --git a/test/reference-output/genericUnion.kt b/test/reference-output/genericUnion.kt new file mode 100644 index 0000000..ebaf4ec --- /dev/null +++ b/test/reference-output/genericUnion.kt @@ -0,0 +1,41 @@ +package org.gotynoOutput + +import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.module.kotlin.* +import com.fasterxml.jackson.databind.annotation.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.deser.std.* +import java.text.ParseException +import java.math.BigInteger +import kotlinx.serialization.Serializable + +class GenericUnion { +@Serializable +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type" +) +sealed class GenericUnion : java.io.Serializable { + @Serializable + @JsonTypeName("HasTPayload") + data class HasTPayload(val data: T) : GenericUnion(), java.io.Serializable { + val type = "HasTPayload" + } + + @Serializable + @JsonTypeName("HasNoPayload") + class HasNoPayload : GenericUnion(), java.io.Serializable { + val type = "HasNoPayload" + + override fun equals(other: Any?): Boolean { + return other is HasNoPayload<*> + } + + override fun hashCode(): Int { + return 0 + } + } +} +} diff --git a/test/reference-output/generics.kt b/test/reference-output/generics.kt index d71dc78..91e662d 100644 --- a/test/reference-output/generics.kt +++ b/test/reference-output/generics.kt @@ -161,4 +161,4 @@ sealed class KnownForEmbeddedWithUpperCase : java.io.Serializable { val media_type = "Tv" } } -} \ No newline at end of file +} diff --git a/test/reference-output/github.kt b/test/reference-output/github.kt index 73f0066..284b3a5 100644 --- a/test/reference-output/github.kt +++ b/test/reference-output/github.kt @@ -286,4 +286,4 @@ data class RepositorySearchData( @get:JsonProperty("items") val items: ArrayList ) : java.io.Serializable -} \ No newline at end of file +} diff --git a/test/reference-output/hasGeneric.kt b/test/reference-output/hasGeneric.kt index 53942da..5c3bb2b 100644 --- a/test/reference-output/hasGeneric.kt +++ b/test/reference-output/hasGeneric.kt @@ -66,4 +66,4 @@ sealed class HasGenericEvent : java.io.Serializable { val type = "GenericEvent" } } -} \ No newline at end of file +} diff --git a/test/reference-output/importExample.kt b/test/reference-output/importExample.kt index d22263d..f94c614 100644 --- a/test/reference-output/importExample.kt +++ b/test/reference-output/importExample.kt @@ -58,4 +58,4 @@ data class AllConcrete( @get:JsonProperty("field") val field: HoldsSomething, UnionUsingImport>> ) : java.io.Serializable -} \ No newline at end of file +}