diff --git a/idealingua-v1/idealingua-v1-model/src/main/scala/izumi/idealingua/model/common/TypeId.scala b/idealingua-v1/idealingua-v1-model/src/main/scala/izumi/idealingua/model/common/TypeId.scala index 8f1ff6e8..cf0100b5 100644 --- a/idealingua-v1/idealingua-v1-model/src/main/scala/izumi/idealingua/model/common/TypeId.scala +++ b/idealingua-v1/idealingua-v1-model/src/main/scala/izumi/idealingua/model/common/TypeId.scala @@ -186,6 +186,13 @@ object Primitive { override def aliases: List[TypeName] = List("tsz", "datetimez", "dtz") } + /** + * Date, Time and Offset + */ + case object TTsO extends Primitive with TimeTypeId { + override def aliases: List[TypeName] = List("tso", "datetimeo", "dto") + } + /** * Date, Time and Timezone, but Timezone is always set to UTC */ @@ -246,6 +253,7 @@ object Primitive { , TDate , TTsTz , TTsU + , TTsO , TTs , TBLOB , @@ -316,5 +324,3 @@ object Generic { .flatMap(tpe => tpe.aliases.map(a => a -> tpe)) .toMap } - - diff --git a/idealingua-v1/idealingua-v1-runtime-rpc-csharp/src/main/resources/runtime/csharp/IRT/Marshaller/JsonNetMarshaller.cs b/idealingua-v1/idealingua-v1-runtime-rpc-csharp/src/main/resources/runtime/csharp/IRT/Marshaller/JsonNetMarshaller.cs index dc357890..4e1ed57c 100644 --- a/idealingua-v1/idealingua-v1-runtime-rpc-csharp/src/main/resources/runtime/csharp/IRT/Marshaller/JsonNetMarshaller.cs +++ b/idealingua-v1/idealingua-v1-runtime-rpc-csharp/src/main/resources/runtime/csharp/IRT/Marshaller/JsonNetMarshaller.cs @@ -55,7 +55,7 @@ public O Unmarshal(string data) { if (to == typeof(WebSocketRequestMessageJson) || to == typeof(WebSocketResponseMessageJson)) { return JsonConvert.DeserializeObject(data, webSocketConverters); } - + return JsonConvert.DeserializeObject(data, settings); } @@ -81,7 +81,7 @@ public override InterfaceMarshalWorkaround ReadJson(JsonReader reader, System.Ty throw new Exception("Should not be used for Reading, workaround only for writing."); } } - + private class WebSocketMessageBase_JsonNetConverter: JsonNetConverter { public override void WriteJson(JsonWriter writer, WebSocketMessageBase holder, JsonSerializer serializer) { throw new Exception("WebSocketMessageBase should never be serialized."); @@ -90,34 +90,34 @@ public override void WriteJson(JsonWriter writer, WebSocketMessageBase holder, J public override WebSocketMessageBase ReadJson(JsonReader reader, System.Type objectType, WebSocketMessageBase existingValue, bool hasExistingValue, JsonSerializer serializer) { var json = JObject.Load(reader); var kind = json["kind"].Value(); - + var res = hasExistingValue ? existingValue : new WebSocketMessageBase(kind); res.Kind = kind; return res; } } - + private class WebSocketFailureMessage_JsonNetConverter: JsonNetConverter { public override void WriteJson(JsonWriter writer, WebSocketFailureMessage holder, JsonSerializer serializer) { writer.WriteStartObject(); // Kind writer.WritePropertyName("kind"); writer.WriteValue(holder.Kind); - + // Cause writer.WritePropertyName("cause"); writer.WriteValue(holder.Cause); - + // Data writer.WritePropertyName("data"); writer.WriteValue(holder.Data); - + writer.WriteEndObject(); } public override WebSocketFailureMessage ReadJson(JsonReader reader, System.Type objectType, WebSocketFailureMessage existingValue, bool hasExistingValue, JsonSerializer serializer) { var json = JObject.Load(reader); - + var kind = json["kind"].Value(); var res = hasExistingValue ? existingValue : new WebSocketFailureMessage(); res.Kind = kind; @@ -133,29 +133,29 @@ public override void WriteJson(JsonWriter writer, WebSocketRequestMessageJson ho // Kind writer.WritePropertyName("kind"); writer.WriteValue(holder.Kind); - + // ID writer.WritePropertyName("id"); writer.WriteValue(holder.ID); - + // Service if (!string.IsNullOrEmpty(holder.Service)) { writer.WritePropertyName("service"); writer.WriteValue(holder.Service); } - + // Method if (!string.IsNullOrEmpty(holder.Method)) { writer.WritePropertyName("method"); writer.WriteValue(holder.Method); } - + // Headers if (holder.Headers != null && holder.Headers.Count > 0) { writer.WritePropertyName("headers"); writer.WriteValue(holder.Headers); } - + // Data if (!string.IsNullOrEmpty(holder.Data)) { writer.WritePropertyName("data"); @@ -167,7 +167,7 @@ public override void WriteJson(JsonWriter writer, WebSocketRequestMessageJson ho public override WebSocketRequestMessageJson ReadJson(JsonReader reader, System.Type objectType, WebSocketRequestMessageJson existingValue, bool hasExistingValue, JsonSerializer serializer) { var json = JObject.Load(reader); - + var kind = json["kind"].Value(); var res = hasExistingValue ? existingValue : new WebSocketRequestMessageJson(kind); @@ -184,18 +184,18 @@ public override WebSocketRequestMessageJson ReadJson(JsonReader reader, System.T return res; } } - + private class WebSocketResponseMessage_JsonNetConverter: JsonNetConverter { public override void WriteJson(JsonWriter writer, WebSocketResponseMessageJson holder, JsonSerializer serializer) { writer.WriteStartObject(); // Kind writer.WritePropertyName("kind"); writer.WriteValue(holder.Kind); - + // Ref writer.WritePropertyName("ref"); writer.WriteValue(holder.Ref); - + // Data if (!string.IsNullOrEmpty(holder.Data)) { writer.WritePropertyName("data"); @@ -207,7 +207,7 @@ public override void WriteJson(JsonWriter writer, WebSocketResponseMessageJson h public override WebSocketResponseMessageJson ReadJson(JsonReader reader, System.Type objectType, WebSocketResponseMessageJson existingValue, bool hasExistingValue, JsonSerializer serializer) { var json = JObject.Load(reader); var kind = json["kind"].Value(); - + var res = hasExistingValue ? existingValue : new WebSocketResponseMessageJson(kind); res.Kind = kind; res.Ref = json["ref"].Value(); @@ -221,7 +221,7 @@ public override WebSocketResponseMessageJson ReadJson(JsonReader reader, System. if (reader.Value != null) { if (reader.TokenType == JsonToken.PropertyName) { Console.WriteLine("Found: " + reader.Value); - + switch (reader.Value) { case "ref": res.Ref = reader.ReadAsString(); break; @@ -306,6 +306,8 @@ public static class JsonNetTimeFormats { public static readonly string TsuDefault = "yyyy-MM-ddTHH:mm:ss.fffZ"; public static readonly string[] Tsu = JsonNetTimeFormats.Tsz; + public static readonly string TsoDefault = JsonNetTimeFormats.TszDefault; + public static readonly string[] Tso = JsonNetTimeFormats.Tsz; } class JsonNetDateConverter : IsoDateTimeConverter { @@ -331,4 +333,4 @@ public JsonNetDateTimeZonedConverter() { base.DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffzzz"; } } -} \ No newline at end of file +} diff --git a/idealingua-v1/idealingua-v1-runtime-rpc-go/src/main/resources/runtime/go/irt/formatter.go b/idealingua-v1/idealingua-v1-runtime-rpc-go/src/main/resources/runtime/go/irt/formatter.go index 9687f8bd..a74c4a96 100644 --- a/idealingua-v1/idealingua-v1-runtime-rpc-go/src/main/resources/runtime/go/irt/formatter.go +++ b/idealingua-v1/idealingua-v1-runtime-rpc-go/src/main/resources/runtime/go/irt/formatter.go @@ -120,3 +120,11 @@ func ReadUTCDateTime(value string) (time.Time, error) { func WriteUTCDateTime(value time.Time) string { return value.UTC().Format("2006-01-02T15:04:05.000Z") } + +func ReadOffsetDateTime(value string) (time.Time, error) { + return ReadDateTime(value, false) +} + +func WriteOffsetDateTime(value time.Time) string { + return value.Format("2006-01-02T15:04:05.000-07:00") +} diff --git a/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/formatter.ts b/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/formatter.ts index 373f989f..5d5c1802 100644 --- a/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/formatter.ts +++ b/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/formatter.ts @@ -75,4 +75,12 @@ export class Formatter { public static writeUTCDateTime(value: Date): string { return moment(value).utc().format('YYYY-MM-DDTHH:mm:ss.SSSZ'); } + + public static readOffsetDateTime(value: string): Date { + return Formatter.readDateTime(value, false); + } + + public static writeOffsetDateTime(value: Date): string { + return moment(value).format('YYYY-MM-DDTHH:mm:ss.SSSZ'); + } } diff --git a/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/introspector.ts b/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/introspector.ts index 255bc1ee..f931efe6 100644 --- a/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/introspector.ts +++ b/idealingua-v1/idealingua-v1-runtime-rpc-typescript/src/main/resources/runtime/typescript/irt/introspector.ts @@ -32,6 +32,7 @@ export enum IntrospectorTypes { Tsz, Tsl, Tsu, + Tso, Time, Date } @@ -143,4 +144,4 @@ export class Introspector { public static all(): IIntrospectorObject[] { return Introspector.knownTypesList; } -} \ No newline at end of file +} diff --git a/idealingua-v1/idealingua-v1-test-defs/src/main/resources/defs/any/izumi/test/domain01.domain b/idealingua-v1/idealingua-v1-test-defs/src/main/resources/defs/any/izumi/test/domain01.domain index 7d650ad3..61b3bc27 100644 --- a/idealingua-v1/idealingua-v1-test-defs/src/main/resources/defs/any/izumi/test/domain01.domain +++ b/idealingua-v1/idealingua-v1-test-defs/src/main/resources/defs/any/izumi/test/domain01.domain @@ -77,6 +77,7 @@ mixin AllTypes { ts : tsz tslocal : tsl tsuni : tsu + tsofs : tso time : time date : date @@ -210,6 +211,10 @@ data TsuData { since: tsu } +data TsoData { + since: tso +} + mixin CommonFailure { code: i32 } diff --git a/idealingua-v1/idealingua-v1-transpilers/.jvm/src/test/scala/izumi/idealingua/IDLTestTools.scala b/idealingua-v1/idealingua-v1-transpilers/.jvm/src/test/scala/izumi/idealingua/IDLTestTools.scala index 88f0886b..c72fd116 100644 --- a/idealingua-v1/idealingua-v1-transpilers/.jvm/src/test/scala/izumi/idealingua/IDLTestTools.scala +++ b/idealingua-v1/idealingua-v1-transpilers/.jvm/src/test/scala/izumi/idealingua/IDLTestTools.scala @@ -89,14 +89,15 @@ object IDLTestTools { val manifest = mf.copy(layout = ScalaProjectLayout.SBT, sbt = mf.sbt.copy(projectNaming = mf.sbt.projectNaming.copy(dropFQNSegments = Some(1)))) val out = compiles(id, domains, CompilerOptions(IDLLanguage.Scala, extensions, manifest)) val classpath: String = IzJvm.safeClasspath() + val safeClasspath = s"\"$classpath\"" val cmd = layout match { case ScalaProjectLayout.PLAIN => // it's hard to map volumes on CI agent bcs our build runs in docker but all the mounts happens on the docker host if (useDockerForLocalTest && hasDocker && !isCI) { - dockerRun(out, classpath, scala213 = true) + dockerRun(out, safeClasspath, scala213 = true) } else { - directRun(out, classpath) + directRun(out, safeClasspath) } case ScalaProjectLayout.SBT => diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/CSharpImports.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/CSharpImports.scala index 543c745b..6241218f 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/CSharpImports.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/CSharpImports.scala @@ -1,13 +1,13 @@ package izumi.idealingua.translator.tocsharp import izumi.fundamentals.platform.language.Quirks -import izumi.idealingua.model.common.TypeId._ -import izumi.idealingua.model.common.{Generic, Package, Primitive, TypeId} -import izumi.idealingua.model.problems.IDLException +import izumi.idealingua.model.common.TypeId.* +import izumi.idealingua.model.common.{Generic, Package, Primitive, PrimitiveId, ScalarId, StructureId, TypeId} import izumi.idealingua.model.il.ast.typed.DefMethod.Output.{Algebraic, Alternative, Singular, Struct, Void} import izumi.idealingua.model.il.ast.typed.DefMethod.RPCMethod -import izumi.idealingua.model.il.ast.typed.TypeDef._ +import izumi.idealingua.model.il.ast.typed.TypeDef.* import izumi.idealingua.model.il.ast.typed.{Buzzer, DefMethod, Service, TypeDef} +import izumi.idealingua.model.problems.IDLException import izumi.idealingua.model.typespace.Typespace import izumi.idealingua.translator.tocsharp.types.CSharpType @@ -75,8 +75,11 @@ object CSharpImports { case Primitive.TTs => return Seq("System", "IRT", "System.Globalization") case Primitive.TTsTz => return Seq("System", "IRT", "System.Globalization") case Primitive.TTsU => return Seq("System", "IRT", "System.Globalization") + case Primitive.TTsO => return Seq("System", "IRT", "System.Globalization") case Primitive.TDate => return Seq("System") case Primitive.TUUID => return Seq("System") + case Primitive.TFloat => + case Primitive.TDouble => case Primitive.TBLOB => ??? case g: Generic => g match { case _: Generic.TOption => return Seq("System") @@ -84,8 +87,11 @@ object CSharpImports { case _: Generic.TList => return Seq("System.Collections", "System.Collections.Generic") case _: Generic.TSet => return Seq("System.Collections", "System.Collections.Generic") } - case _: Primitive => return Seq.empty - case _ => + case _: PrimitiveId => + case _: StructureId => + case _: ScalarId => + case _: AdtId => + case _: AliasId => } if (t.path.toPackage.isEmpty) { diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/extensions/JsonNetExtension.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/extensions/JsonNetExtension.scala index e2f68ee8..3d389951 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/extensions/JsonNetExtension.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/extensions/JsonNetExtension.scala @@ -1,13 +1,13 @@ package izumi.idealingua.translator.tocsharp.extensions import izumi.fundamentals.platform.language.Quirks.discard -import izumi.fundamentals.platform.strings.IzString._ -import izumi.idealingua.model.common.TypeId._ -import izumi.idealingua.model.common.{Generic, Primitive, TypeId} +import izumi.fundamentals.platform.strings.IzString.* +import izumi.idealingua.model.common.TypeId.* +import izumi.idealingua.model.common.{Generic, Primitive, TimeTypeId, TypeId} import izumi.idealingua.model.problems.IDLException import izumi.idealingua.model.il.ast.typed.DefMethod import izumi.idealingua.model.il.ast.typed.DefMethod.Output.{Alternative, Singular} -import izumi.idealingua.model.il.ast.typed.TypeDef._ +import izumi.idealingua.model.il.ast.typed.TypeDef.* import izumi.idealingua.model.typespace.Typespace import izumi.idealingua.translator.tocsharp.types.{CSharpClass, CSharpField, CSharpType} import izumi.idealingua.translator.tocsharp.{CSTContext, CSharpImports} @@ -171,6 +171,7 @@ object JsonNetExtension extends CSharpTranslatorExtension { case Primitive.TDate => s"""writer.WriteValue($src.ToString("yyyy-MM-dd"));""" case Primitive.TTs => s"""writer.WriteValue($src.ToString(JsonNetTimeFormats.TslDefault, CultureInfo.InvariantCulture));""" case Primitive.TTsTz => s"""writer.WriteValue($src.ToString($src.Kind == DateTimeKind.Utc ? JsonNetTimeFormats.TsuDefault : JsonNetTimeFormats.TszDefault, CultureInfo.InvariantCulture));""" + case Primitive.TTsO => s"""writer.WriteValue($src.ToString($src.Kind == DateTimeKind.Utc ? JsonNetTimeFormats.TsuDefault : JsonNetTimeFormats.TsoDefault, CultureInfo.InvariantCulture));""" case Primitive.TTsU => s"""writer.WriteValue($src.ToUniversalTime().ToString(JsonNetTimeFormats.TsuDefault, CultureInfo.InvariantCulture));""" } @@ -210,11 +211,7 @@ object JsonNetExtension extends CSharpTranslatorExtension { case Primitive.TFloat => false case Primitive.TDouble => false case Primitive.TUUID => false - case Primitive.TTime => false - case Primitive.TDate => false - case Primitive.TTs => false - case Primitive.TTsTz => false - case Primitive.TTsU => false + case _: TimeTypeId => false case Primitive.TBLOB => ??? } case c => c match { @@ -323,6 +320,7 @@ object JsonNetExtension extends CSharpTranslatorExtension { case Primitive.TDate => s"DateTime.Parse($src.Value())" case Primitive.TTs => s"DateTime.ParseExact($src.Value(), JsonNetTimeFormats.Tsl, CultureInfo.InvariantCulture, DateTimeStyles.None)" case Primitive.TTsTz => s"DateTime.ParseExact($src.Value(), JsonNetTimeFormats.Tsz, CultureInfo.InvariantCulture, DateTimeStyles.None)" + case Primitive.TTsO => s"DateTime.ParseExact($src.Value(), JsonNetTimeFormats.Tso, CultureInfo.InvariantCulture, DateTimeStyles.None)" case Primitive.TTsU => s"DateTime.ParseExact($src.Value(), JsonNetTimeFormats.Tsu, CultureInfo.InvariantCulture, DateTimeStyles.None)" } case _ => t.id match { diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/types/CSharpType.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/types/CSharpType.scala index 1488d3c1..5058c712 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/types/CSharpType.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/tocsharp/types/CSharpType.scala @@ -43,6 +43,7 @@ final case class CSharpType ( case Primitive.TDate => false case Primitive.TTs => false case Primitive.TTsTz => false + case Primitive.TTsO => false case Primitive.TTsU => false case Primitive.TBLOB => ??? } @@ -81,6 +82,7 @@ final case class CSharpType ( case Primitive.TDate => true case Primitive.TTs => true case Primitive.TTsTz => true + case Primitive.TTsO => true case Primitive.TTsU => true case Primitive.TBLOB => true } @@ -119,6 +121,7 @@ final case class CSharpType ( case Primitive.TDate => "0" case Primitive.TTs => "0" case Primitive.TTsTz => "0" + case Primitive.TTsO => "0" case Primitive.TTsU => "0" case Primitive.TBLOB => "null" } @@ -157,6 +160,7 @@ final case class CSharpType ( case Primitive.TDate => None case Primitive.TTs => None case Primitive.TTsTz => None + case Primitive.TTsO => None case Primitive.TTsU => None case Primitive.TBLOB => None } @@ -198,6 +202,7 @@ final case class CSharpType ( case Primitive.TDate => s"""System.DateTime.Parse(string.Format("{0:D4}-{1:D2}-{2:D2}", ${1984 + rnd.nextInt(20)}, ${1 + rnd.nextInt(12)}, ${1 + rnd.nextInt(28)}))""" case Primitive.TTs => s"""System.DateTime.ParseExact(string.Format("{0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}.{6:D3}", ${1984 + rnd.nextInt(20)}, ${1 + rnd.nextInt(12)}, ${1 + rnd.nextInt(28)}, ${rnd.nextInt(24)}, ${rnd.nextInt(60)}, ${rnd.nextInt(60)}, ${100 + rnd.nextInt(100)}), JsonNetTimeFormats.Tsl, CultureInfo.InvariantCulture, DateTimeStyles.None)""" case Primitive.TTsTz => s"""System.DateTime.ParseExact(string.Format("{0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}.{6:D3}+10:00", ${1984 + rnd.nextInt(20)}, ${1 + rnd.nextInt(12)}, ${1 + rnd.nextInt(28)}, ${rnd.nextInt(24)}, ${rnd.nextInt(60)}, ${rnd.nextInt(60)}, ${100 + rnd.nextInt(100)}), JsonNetTimeFormats.Tsz, CultureInfo.InvariantCulture, DateTimeStyles.None)""" + case Primitive.TTsO => s"""System.DateTime.ParseExact(string.Format("{0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}.{6:D3}+10:00", ${1984 + rnd.nextInt(20)}, ${1 + rnd.nextInt(12)}, ${1 + rnd.nextInt(28)}, ${rnd.nextInt(24)}, ${rnd.nextInt(60)}, ${rnd.nextInt(60)}, ${100 + rnd.nextInt(100)}), JsonNetTimeFormats.Tsz, CultureInfo.InvariantCulture, DateTimeStyles.None)""" case Primitive.TTsU => s"""System.DateTime.ParseExact(string.Format("{0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}.{6:D3}Z", ${1984 + rnd.nextInt(20)}, ${1 + rnd.nextInt(12)}, ${1 + rnd.nextInt(28)}, ${rnd.nextInt(24)}, ${rnd.nextInt(60)}, ${rnd.nextInt(60)}, ${100 + rnd.nextInt(100)}), JsonNetTimeFormats.Tsu, CultureInfo.InvariantCulture, DateTimeStyles.None)""" } case _ => id match { @@ -341,6 +346,7 @@ final case class CSharpType ( case Primitive.TDate => "DateTime" // Could be Date case Primitive.TTs => "DateTime" case Primitive.TTsTz => "DateTime" + case Primitive.TTsO => "DateTime" case Primitive.TTsU => "DateTime" } diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangField.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangField.scala index f86ba24c..eb4c7e53 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangField.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangField.scala @@ -1,10 +1,10 @@ package izumi.idealingua.translator.togolang.types -import izumi.fundamentals.platform.strings.IzString._ -import izumi.idealingua.model.common.TypeId._ -import izumi.idealingua.model.common.{Generic, Primitive, TypeId} -import izumi.idealingua.model.problems.IDLException +import izumi.fundamentals.platform.strings.IzString.* +import izumi.idealingua.model.common.TypeId.* +import izumi.idealingua.model.common.* import izumi.idealingua.model.il.ast.typed.TypeDef.Alias +import izumi.idealingua.model.problems.IDLException import izumi.idealingua.model.typespace.Typespace final case class GoLangField( @@ -53,6 +53,14 @@ final case class GoLangField( else s"""$dest := irt.WriteDate($src)""".stripMargin + case Primitive.TTsO => + if (forOption) + s"""_$dest := irt.WriteOffsetDateTime($src) + |$dest = &_$dest + """.stripMargin + else + s"""$dest := irt.WriteOffsetDateTime($src)""".stripMargin + case Primitive.TTsU => if (forOption) s"""_$dest := irt.WriteUTCDateTime($src) @@ -106,9 +114,11 @@ final case class GoLangField( |$dest ${if(forOption) "" else ":"}= ${if(forOption) "&" else ""}_$dest """.stripMargin - case al: AliasId => renderPolymorphSerialized(ts.dealias(al), dest, srcOriginal, forOption) + case al: AliasId => + renderPolymorphSerialized(ts.dealias(al), dest, srcOriginal, forOption) - case _ => throw new IDLException(s"Should not get into renderPolymorphSerialized ${id.name} dest: $dest src: $srcOriginal") + case _: StructureId | _: PrimitiveId | Primitive.TFloat | Primitive.TDouble | _: EnumId | _: IdentifierId | _: Generic => + throw new IDLException(s"Should not get into renderPolymorphSerialized ${id.name} dest: $dest src: $srcOriginal") } } @@ -120,8 +130,8 @@ final case class GoLangField( case _: InterfaceId | _: AdtId | _: IdentifierId | _: DTOId | _: EnumId => renderPolymorphSerialized(id, dest, src) - case Primitive.TDate | Primitive.TTime | Primitive.TTsTz | Primitive.TTs | Primitive.TTsU => - renderPolymorphSerialized(id, dest, src) + case _: TimeTypeId => + renderPolymorphSerialized(id, dest, src) case g: Generic => g match { case go: Generic.TOption => @@ -135,7 +145,7 @@ final case class GoLangField( |} """.stripMargin - case _: Generic.TList | _: Generic.TSet => { + case _: Generic.TList | _: Generic.TSet => val vt = g match { case gl: Generic.TList => gl.valueType case gs: Generic.TSet => gs.valueType @@ -158,9 +168,8 @@ final case class GoLangField( |} |$dest := $tempVal """.stripMargin - } - case gm: Generic.TMap => { + case gm: Generic.TMap => val vt = GoLangType(gm.valueType, im, ts) val tempVal = s"_$dest" @@ -180,10 +189,10 @@ final case class GoLangField( |} |$dest := $tempVal """.stripMargin - } } - case _ => throw new IDLException("Should never get into renderPolymorphSerializedVar with other types... " + id.name + " " + id.getClass().getName()) + case _: StructureId | Primitive.TBLOB | Primitive.TBool | Primitive.TDouble | Primitive.TFloat | Primitive.TInt16 | Primitive.TInt32 | Primitive.TInt64 | Primitive.TInt8 | Primitive.TString | Primitive.TTsO | Primitive.TUInt16 | Primitive.TUInt32 | Primitive.TUInt64 | Primitive.TUInt8 | Primitive.TUUID => + throw new IDLException("Should never get into renderPolymorphSerializedVar with other types... " + id.name + " " + id.getClass.getName) } } @@ -193,19 +202,18 @@ final case class GoLangField( def renderSerializedVar(): String = { tp.id match { - case Primitive.TTsTz => renderMemberName(true) + "AsString()" - case Primitive.TTs => renderMemberName(true) + "AsString()" - case Primitive.TTsU => renderMemberName(true) + "AsString()" - case Primitive.TDate => renderMemberName(true) + "AsString()" - case Primitive.TTime => renderMemberName(true) + "AsString()" + case _: TimeTypeId => + renderMemberName(true) + "AsString()" case g: Generic => g match { case go: Generic.TOption => go.valueType match { - case Primitive.TTsTz | Primitive.TTs | Primitive.TTsU | Primitive.TDate | Primitive.TTime => renderMemberName(true) + "AsString()" + case _: TimeTypeId => + renderMemberName(true) + "AsString()" case _ => renderMemberName(false) } case _ => renderMemberName(false) } - case _ => renderMemberName(false) + case _: StructureId | _: ScalarId | _: AdtId | _: AliasId => + renderMemberName(false) } } @@ -226,13 +234,14 @@ final case class GoLangField( case Primitive.TDate => toDateField() case Primitive.TTs => toTimeStampField(local = true) case Primitive.TTsTz => toTimeStampField(local = false) + case Primitive.TTsO => toTimeStampField(local = false) case Primitive.TTsU => toTimeStampField(local = false, utc = true) case g: Generic => g match { case go: Generic.TOption => go.valueType match { case Primitive.TTime => toTimeField(optional = true) case Primitive.TDate => toDateField(optional = true) case Primitive.TTs => toTimeStampField(local = true, optional = true) - case Primitive.TTsTz => toTimeStampField(local = false, optional = true) + case Primitive.TTsO => toTimeStampField(local = false, optional = true) case Primitive.TTsU => toTimeStampField(local = false, optional = true, utc = true) case _ => toGenericField() } @@ -379,6 +388,13 @@ final case class GoLangField( |} """.stripMargin + case Primitive.TTsO => + s"""$dest, err := irt.ReadOffsetDateTime($src) + |if err != nil { + | return err + |} + """.stripMargin + case Primitive.TTsU => s"""$dest, err := irt.ReadUTCDateTime($src) |if err != nil { @@ -518,13 +534,13 @@ final case class GoLangField( """.stripMargin } } - case Primitive.TTsTz | Primitive.TTs | Primitive.TTsU | Primitive.TTime | Primitive.TDate => + case _: TimeTypeId => s"""if err := $struct.Set${renderMemberName(true)}FromString(${if (optional) "*" else ""}$variable); err != nil { | return err |} """.stripMargin - case _ => assignVar + case _: StructureId | _: ScalarId => assignVar } } else { val res = id match { diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangImports.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangImports.scala index 61a662ad..6b14d39e 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangImports.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangImports.scala @@ -65,6 +65,7 @@ object GoLangImports { case Primitive.TTime => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) case Primitive.TTs => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) case Primitive.TTsTz => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) + case Primitive.TTsO => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) case Primitive.TTsU => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) case Primitive.TDate => return if (forTest) Seq(Seq("time")) else Seq(Seq("time"), Seq("irt")) case Primitive.TUUID => return if (forTest) Seq.empty else Seq(Seq("regexp")) diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangType.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangType.scala index e5aee7a5..ac0707ef 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangType.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/togolang/types/GoLangType.scala @@ -1,12 +1,11 @@ package izumi.idealingua.translator.togolang.types import izumi.fundamentals.platform.language.Quirks -import izumi.idealingua.model.common.TypeId._ -import izumi.idealingua.model.common.{Generic, Primitive, TypeId} +import izumi.idealingua.model.common.TypeId.* +import izumi.idealingua.model.common.* +import izumi.idealingua.model.il.ast.typed.TypeDef.{Alias, Enumeration} import izumi.idealingua.model.problems.IDLException -import izumi.idealingua.model.il.ast.typed.TypeDef.Alias import izumi.idealingua.model.typespace.Typespace -import izumi.idealingua.model.il.ast.typed.TypeDef.Enumeration final case class GoLangType ( id: TypeId, @@ -80,15 +79,7 @@ final case class GoLangType ( } def isPolymorph(id: TypeId): Boolean = id match { - case p: Primitive => p match { -// case Primitive.TUUID => true - case Primitive.TTsU => true - case Primitive.TTs => true - case Primitive.TTsTz => true - case Primitive.TDate => true - case Primitive.TTime => true - case _ => false - } + case _: TimeTypeId => true case _: DTOId => true case _: IdentifierId => true case _: AdtId => true @@ -101,7 +92,7 @@ final case class GoLangType ( case gs: Generic.TSet => isPolymorph(gs.valueType) case gm: Generic.TMap => isPolymorph(gm.valueType) } - case _ => false + case _: PrimitiveId | Primitive.TDouble | Primitive.TFloat => false } protected def renderPrimitiveType(primitive: Primitive, serialized: Boolean = false): String = primitive match { @@ -126,6 +117,7 @@ final case class GoLangType ( case Primitive.TDate => if (serialized) "string" else "time.Time" case Primitive.TTs => if (serialized) "string" else "time.Time" case Primitive.TTsTz => if (serialized) "string" else "time.Time" + case Primitive.TTsO => if (serialized) "string" else "time.Time" case Primitive.TTsU => if (serialized) "string" else "time.Time" } @@ -269,6 +261,7 @@ final case class GoLangType ( case Primitive.TDate => "\"0000-00-00\"" case Primitive.TTs => "\"0000-00-00T00:00:00.00000\"" case Primitive.TTsTz => "\"0000-00-00T00:00:00.00000+10:00[Australia/Sydney]\"" + case Primitive.TTsO => "\"0000-00-00T00:00:00.00000+10:00\"" case Primitive.TTsU => "\"0000-00-00T00:00:00.00000Z[UTC]\"" case g: Generic => g match { case gm: Generic.TMap => s"map[${GoLangType(gm.keyType, im, ts).renderType(forMap = true)}]${GoLangType(gm.valueType, im, ts).renderType()}{}" @@ -278,9 +271,8 @@ final case class GoLangType ( } case al: AliasId => GoLangType(ts(al).asInstanceOf[Alias].target, im, ts).defaultValue() case e: EnumId => ts(e).asInstanceOf[Enumeration].members.head.value - case _: IdentifierId | _: DTOId => "nil" + case _: IdentifierId | _: DTOId | _: AdtId => "nil" case _: InterfaceId => "nil" - case _ => "nil" } def testValue(): String = id match { @@ -302,6 +294,7 @@ final case class GoLangType ( case Primitive.TDate => "time.Now()" // "\"2010-12-01\"" case Primitive.TTs => "time.Now()" // "\"2010-12-01T15:10:10.10001\"" case Primitive.TTsTz => "time.Now()" // "\"2010-12-01T15:10:10.10001+10:00[Australia/Sydney]\"" + case Primitive.TTsO => "time.Now()" // "\"2010-12-01T15:10:10.10001+10:00[Australia/Sydney]\"" case Primitive.TTsU => "time.Now()" // "\"2010-12-01T15:10:10.10001Z[UTC]\"" case g: Generic => g match { case gm: Generic.TMap => s"map[${GoLangType(gm.keyType, im, ts).renderType(forMap = true)}]${GoLangType(gm.valueType, im, ts).renderType()}{}" @@ -317,16 +310,17 @@ final case class GoLangType ( case _: IdentifierId | _: DTOId | _: EnumId => s"${im.withImport(id)}NewTest${id.name}()" case i: InterfaceId => s"${im.withImport(id)}NewTest${i.name + ts.tools.implId(i).name}()" case ad: AdtId => s"${im.withImport(id)}NewTest${ad.name}()" - case _ => "nil" } def testValuePackage(): List[String] = id match { - case Primitive.TTime | Primitive.TDate | Primitive.TTsTz | Primitive.TTs | Primitive.TTsU => List("time") + case Primitive.TTime | Primitive.TDate | Primitive.TTsTz | Primitive.TTs | Primitive.TTsO | Primitive.TTsU => + List("time") // TODO For testing we might want to import from other packages... // case al: AliasId => GoLangType(ts(al).asInstanceOf[Alias].target, im, ts).testValuePackage() // case _: IdentifierId | _: DTOId | _: EnumId => s"NewTest${id.name}()" // case i: InterfaceId => s"NewTest${i.name + ts.implId(i).name}()" - case _ => List.empty + case _: StructureId | _: AdtId | _: AliasId | _: EnumId | _: IdentifierId | _: Generic | _: PrimitiveId | Primitive.TFloat | Primitive.TDouble => + List.empty } } diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toprotobuf/types/ProtobufTypeConverter.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toprotobuf/types/ProtobufTypeConverter.scala index 07659690..3f8236ea 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toprotobuf/types/ProtobufTypeConverter.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toprotobuf/types/ProtobufTypeConverter.scala @@ -1,6 +1,6 @@ package izumi.idealingua.translator.toprotobuf.types -import izumi.idealingua.model.common.{DomainId, Generic, Primitive, TypeId} +import izumi.idealingua.model.common.{DomainId, Generic, Primitive, PrimitiveId, TimeTypeId, TypeId} import izumi.idealingua.model.il.ast.typed import izumi.idealingua.model.problems.IDLException @@ -53,10 +53,10 @@ class ProtobufTypeConverter(domain: DomainId) { case Primitive.TUUID => throw new IDLException(s"[$domain] Protobuf does not support UUIDs as map key parameters. Parameter: ${t.path}#${t.name}") - case Primitive.TTsTz | Primitive.TTsU | Primitive.TTs | Primitive.TTime | Primitive.TDate => + case _: TimeTypeId => throw new IDLException(s"[$domain] Protobuf does not support Time units as map key parameters. Parameter: ${t.path}#${t.name}") - case _ => + case _: PrimitiveId => } case _ => @@ -116,7 +116,7 @@ class ProtobufTypeConverter(domain: DomainId) { case Primitive.TUUID => ProtobufType(Seq("idl", "types"), "PUUID") - case Primitive.TTsTz | Primitive.TTsU | Primitive.TTs | Primitive.TTime | Primitive.TDate => + case Primitive.TTsTz | Primitive.TTsO | Primitive.TTsU | Primitive.TTs | Primitive.TTime | Primitive.TDate => ProtobufType(Seq("idl", "types"), "PTimestamp") } } diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toscala/types/ScalaTypeConverter.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toscala/types/ScalaTypeConverter.scala index 3c38a408..688179c7 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toscala/types/ScalaTypeConverter.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/toscala/types/ScalaTypeConverter.scala @@ -1,15 +1,14 @@ package izumi.idealingua.translator.toscala.types -import java.time.{LocalDate, LocalDateTime, LocalTime, ZonedDateTime} +import java.time.{LocalDate, LocalDateTime, LocalTime, OffsetDateTime, ZonedDateTime} import java.util.UUID - import izumi.idealingua.model import izumi.idealingua.model.JavaType -import izumi.idealingua.model.common.{DomainId, _} +import izumi.idealingua.model.common.{DomainId, *} import izumi.idealingua.model.problems.IDLException import izumi.idealingua.model.typespace.structures.{PlainStruct, Struct} -import scala.meta._ +import scala.meta.* import scala.reflect.{ClassTag, classTag} @@ -129,6 +128,8 @@ class ScalaTypeConverter(domain: DomainId) { JavaType.get[UUID] case Primitive.TTsTz => JavaType.get[ZonedDateTime] + case Primitive.TTsO => + JavaType.get[OffsetDateTime] case Primitive.TTsU => JavaType.get[ZonedDateTime] case Primitive.TTs => diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/TypeScriptImports.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/TypeScriptImports.scala index d174ffb9..3482d041 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/TypeScriptImports.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/TypeScriptImports.scala @@ -86,6 +86,7 @@ object TypeScriptImports { } case p: Primitive => p match { case Primitive.TTs => return Seq(s"import { Formatter } from '${scopeRoot}irt';") + case Primitive.TTsO => return Seq(s"import { Formatter } from '${scopeRoot}irt';") case Primitive.TTsU => return Seq(s"import { Formatter } from '${scopeRoot}irt';") case Primitive.TTsTz => return Seq(s"import { Formatter } from '${scopeRoot}irt';") case Primitive.TTime => return Seq(s"import { Formatter } from '${scopeRoot}irt';") diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/extensions/IntrospectionExtension.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/extensions/IntrospectionExtension.scala index 589ba2e7..abcb37ec 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/extensions/IntrospectionExtension.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/extensions/IntrospectionExtension.scala @@ -31,6 +31,7 @@ object IntrospectionExtension extends TypeScriptTranslatorExtension { case Primitive.TDate => "{intro: IntrospectorTypes.Date}" case Primitive.TTs => "{intro: IntrospectorTypes.Tsl}" case Primitive.TTsTz => "{intro: IntrospectorTypes.Tsz}" + case Primitive.TTsO => "{intro: IntrospectorTypes.Tso}" case Primitive.TTsU => "{intro: IntrospectorTypes.Tsu}" case g: Generic => g match { case gm: Generic.TMap => s"{intro: IntrospectorTypes.Map, key: ${unwindType(gm.keyType)}, value: ${unwindType(gm.valueType)}} as IIntrospectorMapType" diff --git a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/types/TypeScriptTypeConverter.scala b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/types/TypeScriptTypeConverter.scala index d66aeccf..06931562 100644 --- a/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/types/TypeScriptTypeConverter.scala +++ b/idealingua-v1/idealingua-v1-transpilers/src/main/scala/izumi/idealingua/translator/totypescript/types/TypeScriptTypeConverter.scala @@ -32,6 +32,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => "Date.parse(" + value + ")" case Primitive.TTs => "Date.parse(" + value + ")" case Primitive.TTsTz => "Date.parse(" + value + ")" + case Primitive.TTsO => "Date.parse(" + value + ")" case Primitive.TTsU => "Date.parse(" + value + ")" case id: IdentifierId => s"new ${id.name}($value)" case en: EnumId => s"${en.name}[$value]" @@ -72,6 +73,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => name + "AsString" case Primitive.TTs => name + "AsString" case Primitive.TTsTz => name + "AsString" + case Primitive.TTsO => name + "AsString" case Primitive.TTsU => name + "AsString" case o: Generic.TOption => deserializeName(name, o.valueType) case _ => name @@ -97,6 +99,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => variable case Primitive.TTs => variable case Primitive.TTsTz => variable + case Primitive.TTsO => variable case Primitive.TTsU => variable case g: Generic => deserializeGenericType(variable, g, ts, asAny) case _ => deserializeCustomType(variable, target, ts, asAny) @@ -182,6 +185,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => if (forSerialized) "string" else "Date" case Primitive.TTs => if (forSerialized) "string" else "Date" case Primitive.TTsTz => if (forSerialized) "string" else "Date" + case Primitive.TTsO => if (forSerialized) "string" else "Date" case Primitive.TTsU => if (forSerialized) "string" else "Date" } @@ -227,6 +231,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => if(nonMember) s"Formatter.writeDate($name)" else s"${name}AsString"; case Primitive.TTs => if(nonMember) s"Formatter.writeLocalDateTime($name)" else s"${name}AsString"; case Primitive.TTsTz => if(nonMember) s"Formatter.writeZoneDateTime($name)" else s"${name}AsString"; + case Primitive.TTsO => if(nonMember) s"Formatter.writeOffsetDateTime($name)" else s"${name}AsString"; case Primitive.TTsU => if(nonMember) s"Formatter.writeUTCDateTime($name)" else s"${name}AsString"; } @@ -274,6 +279,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => toDateField(name, optional) case Primitive.TTs => toDateTimeField(name, local = true, optional) case Primitive.TTsTz => toDateTimeField(name, local = false, optional) + case Primitive.TTsO => toDateTimeField(name, local = false, optional) case Primitive.TTsU => toDateTimeField(name, local = false, optional, utc = true) case _ => s"""public get ${safeName(name)}(): ${toNativeType(id, ts)}${if (optional) " | undefined" else ""} { @@ -317,6 +323,7 @@ class TypeScriptTypeConverter() { case Primitive.TDate => toPrivateMember(name, "Date") case Primitive.TTs => toPrivateMember(name, "Date") case Primitive.TTsTz => toPrivateMember(name, "Date") + case Primitive.TTsO => toPrivateMember(name, "Date") case Primitive.TTsU => toPrivateMember(name, "Date") case _ => toPrivateMember(name, toNativeType(id, ts)) }