From 48f210f9cbdacdb8095156e4ed792df45b59fb26 Mon Sep 17 00:00:00 2001 From: nenoNaninu Date: Sat, 17 Sep 2022 18:06:28 +0900 Subject: [PATCH 1/4] support DateTimeOffset --- src/Tapper/DefaultTypeMapperProvider.cs | 3 ++- src/Tapper/TypeMappers/DateTimeTypeMapper.cs | 28 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Tapper/DefaultTypeMapperProvider.cs b/src/Tapper/DefaultTypeMapperProvider.cs index 551a6c9..7ab00d3 100644 --- a/src/Tapper/DefaultTypeMapperProvider.cs +++ b/src/Tapper/DefaultTypeMapperProvider.cs @@ -19,6 +19,7 @@ public DefaultTypeMapperProvider(Compilation compilation, bool includeReferenced _tupleTypeMapper = new TupleTypeMapper(); var dateTimeTypeMapper = new DateTimeTypeMapper(compilation); + var dateTimeOffsetTypeMapper = new DateTimeOffsetTypeMapper(compilation); var nullableStructTypeMapper = new NullableStructTypeMapper(compilation); var primitiveTypeMappers = PrimitiveTypeMappers.Create(compilation); @@ -31,7 +32,7 @@ public DefaultTypeMapperProvider(Compilation compilation, bool includeReferenced var typeMappers = sourceTypeMapper.Concat(primitiveTypeMappers) .Concat(collectionTypeTypeMappers) .Concat(dictionaryTypeMappers) - .Concat(new ITypeMapper[] { dateTimeTypeMapper, nullableStructTypeMapper }); + .Concat(new ITypeMapper[] { dateTimeTypeMapper, dateTimeOffsetTypeMapper, nullableStructTypeMapper }); _mappers = typeMappers.ToDictionary(x => x.Assign, SymbolEqualityComparer.Default); } diff --git a/src/Tapper/TypeMappers/DateTimeTypeMapper.cs b/src/Tapper/TypeMappers/DateTimeTypeMapper.cs index a03e00a..9d84fb9 100644 --- a/src/Tapper/TypeMappers/DateTimeTypeMapper.cs +++ b/src/Tapper/TypeMappers/DateTimeTypeMapper.cs @@ -29,3 +29,31 @@ public string MapTo(ITypeSymbol typeSymbol, ITranspilationOptions options) throw new InvalidOperationException($"DateTimeTypeMapper is not support {typeSymbol.ToDisplayString()}."); } } + +internal class DateTimeOffsetTypeMapper : ITypeMapper +{ + public ITypeSymbol Assign { get; } + + public DateTimeOffsetTypeMapper(Compilation compilation) + { + Assign = compilation.GetTypeByMetadataName("System.DateTimeOffset")!; + } + + public string MapTo(ITypeSymbol typeSymbol, ITranspilationOptions options) + { + if (SymbolEqualityComparer.Default.Equals(typeSymbol, Assign)) + { + if (options.SerializerOption == SerializerOption.MessagePack) + { + return "[Date, number]"; + } + else + { + return "(Date | string)"; + } + } + + throw new InvalidOperationException($"DateTimeOffsetTypeMapper is not support {typeSymbol.ToDisplayString()}."); + } +} + From f2abf8f7765a9e55cb77787932d334291e0641ed Mon Sep 17 00:00:00 2001 From: nenoNaninu Date: Sat, 17 Sep 2022 18:08:38 +0900 Subject: [PATCH 2/4] update Analyzer --- src/Tapper.Analyzer/TapperAnalyzer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tapper.Analyzer/TapperAnalyzer.cs b/src/Tapper.Analyzer/TapperAnalyzer.cs index cb1b293..7f73478 100644 --- a/src/Tapper.Analyzer/TapperAnalyzer.cs +++ b/src/Tapper.Analyzer/TapperAnalyzer.cs @@ -77,6 +77,7 @@ public override void Initialize(AnalysisContext context) typeof(Uri), typeof(Guid), typeof(DateTime), + typeof(DateTimeOffset), typeof(Nullable<>), // Collection typeof(Array), From 5f1441471bf5dc62dc20dfa599fda4ceeba13a00 Mon Sep 17 00:00:00 2001 From: nenoNaninu Date: Sat, 17 Sep 2022 18:10:43 +0900 Subject: [PATCH 3/4] add tests for transpiling DateTimeOffset --- .../Controllers/TapperController.cs | 13 +++++++++++ tests/Tapper.Tests.Server/Models/Models.cs | 3 +++ tests/TypeScriptTest/src/fetch.json.test.ts | 15 +++++++++++-- tests/TypeScriptTest/src/fetch.json.ts | 20 ++++++++++++++++- .../TypeScriptTest/src/fetch.msgpack.test.ts | 15 +++++++++++-- tests/TypeScriptTest/src/fetch.msgpack.ts | 22 ++++++++++++++++++- 6 files changed, 82 insertions(+), 6 deletions(-) diff --git a/tests/Tapper.Tests.Server/Controllers/TapperController.cs b/tests/Tapper.Tests.Server/Controllers/TapperController.cs index 3a12d83..d13a228 100644 --- a/tests/Tapper.Tests.Server/Controllers/TapperController.cs +++ b/tests/Tapper.Tests.Server/Controllers/TapperController.cs @@ -101,4 +101,17 @@ public int Test0() return null; } + + [HttpPost] + public Type7? Test7(Type7 type7) + { + var ans = DateTimeOffset.Parse("2022-09-17T16:29:55.2260000+09:00"); + + if (type7.DateTimeOffset == ans) + { + return new Type7(DateTimeOffset.Parse("2022-09-17T16:51:00.4600000+09:00")); + } + + return null; + } } diff --git a/tests/Tapper.Tests.Server/Models/Models.cs b/tests/Tapper.Tests.Server/Models/Models.cs index 8c4d74d..20dba05 100644 --- a/tests/Tapper.Tests.Server/Models/Models.cs +++ b/tests/Tapper.Tests.Server/Models/Models.cs @@ -66,3 +66,6 @@ public record Type5(char Value); [TranspilationSource] public record Type6(byte[] Binary); + +[TranspilationSource] +public record Type7(DateTimeOffset DateTimeOffset); diff --git a/tests/TypeScriptTest/src/fetch.json.test.ts b/tests/TypeScriptTest/src/fetch.json.test.ts index f1587cb..7dd1f9d 100644 --- a/tests/TypeScriptTest/src/fetch.json.test.ts +++ b/tests/TypeScriptTest/src/fetch.json.test.ts @@ -1,5 +1,5 @@ -import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6 } from './fetch.json' -import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/json/Tapper.Tests.Server.Models' +import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6, fetchType7 } from './fetch.json' +import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/json/Tapper.Tests.Server.Models' test('fetch1.json', async () => { const res = await fetchType2(); @@ -53,3 +53,14 @@ test('fetch6.json', async () => { expect(res).toEqual(gt); }); + +test('fetch7.json', async () => { + const res = await fetchType7(); + + const gt: Type7 = + { + dateTimeOffset: new Date("2022-09-17T16:51:00.4600000+09:00") + } + + expect(res).toEqual(gt); +}); diff --git a/tests/TypeScriptTest/src/fetch.json.ts b/tests/TypeScriptTest/src/fetch.json.ts index 649de5f..a7ab71b 100644 --- a/tests/TypeScriptTest/src/fetch.json.ts +++ b/tests/TypeScriptTest/src/fetch.json.ts @@ -1,4 +1,4 @@ -import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/json/Tapper.Tests.Server.Models'; +import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/json/Tapper.Tests.Server.Models'; import { randomUUID } from 'crypto'; import fetch from 'node-fetch'; @@ -84,3 +84,21 @@ export const fetchType6 = async () => { return ret; } + +export const fetchType7 = async () => { + const obj: Type7 = { + dateTimeOffset: new Date("2022-09-17T16:29:55.2260000+09:00") + } + + const response = await fetch("http://localhost:5100/tapper/test7", { + method: "POST", + body: JSON.stringify(obj), + headers: { 'Content-Type': 'application/json' }, + }); + + const ret = await response.json() as Type7; + + ret.dateTimeOffset = typeof ret.dateTimeOffset === 'string' ? new Date(ret.dateTimeOffset) : ret.dateTimeOffset; + + return ret; +} diff --git a/tests/TypeScriptTest/src/fetch.msgpack.test.ts b/tests/TypeScriptTest/src/fetch.msgpack.test.ts index abe8cc2..e2d295a 100644 --- a/tests/TypeScriptTest/src/fetch.msgpack.test.ts +++ b/tests/TypeScriptTest/src/fetch.msgpack.test.ts @@ -1,5 +1,5 @@ -import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6 } from './fetch.msgpack' -import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/msgpack/Tapper.Tests.Server.Models' +import { fetchType2, fetchType3, fetchType4, fetchType5, fetchType6, fetchType7 } from './fetch.msgpack' +import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/msgpack/Tapper.Tests.Server.Models' test('fetch1.msgpack', async () => { const res = await fetchType2(); @@ -56,3 +56,14 @@ test('fetch6.msgpack', async () => { expect(res).toEqual(gt); }); + +test('fetch7.msgpack', async () => { + const res = await fetchType7(); + + const gt: Type7 = + { + DateTimeOffset: [new Date("2022-09-17T16:51:00.46Z"), 540] + } + + expect(res).toEqual(gt); +}); diff --git a/tests/TypeScriptTest/src/fetch.msgpack.ts b/tests/TypeScriptTest/src/fetch.msgpack.ts index b8f7dc2..ce8fdd3 100644 --- a/tests/TypeScriptTest/src/fetch.msgpack.ts +++ b/tests/TypeScriptTest/src/fetch.msgpack.ts @@ -1,4 +1,4 @@ -import { MyEnum, Type2, Type3, Type4, Type5, Type6 } from './generated/msgpack/Tapper.Tests.Server.Models'; +import { MyEnum, Type2, Type3, Type4, Type5, Type6, Type7 } from './generated/msgpack/Tapper.Tests.Server.Models'; import { randomUUID } from 'crypto'; import { encode, decode } from "@msgpack/msgpack"; import fetch from 'node-fetch'; @@ -108,3 +108,23 @@ export const fetchType6 = async () => { return ret; } + +export const fetchType7 = async () => { + const obj: Type7 = { + DateTimeOffset: [new Date("2022-09-17T16:29:55.226Z"), 540], + } + + const response = await fetch("http://localhost:5100/tapper/test7", { + method: "POST", + body: encode(obj), + headers: { + 'Content-Type': 'application/x-msgpack', + 'Accept': 'application/x-msgpack' + }, + }); + + const buf = await response.buffer() + const ret = decode(buf) as Type7; + + return ret; +} From 7294c187dda3e9153f7182cf8211b742a56e78a2 Mon Sep 17 00:00:00 2001 From: nenoNaninu Date: Sat, 17 Sep 2022 18:40:54 +0900 Subject: [PATCH 4/4] update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 67f67e7..2ee77bf 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,8 @@ When transpiling class, struct, and record, only `public` fields and properties | string | string | | Uri | string | | Guid | string | Compatible with TypeScript's `crypto.randomUUID()`. | -| DateTime | (Date \| string) or Date | Json: `(Date \| string)`, MessagePack: `Date`. | +| DateTime | `(Date \| string)` or `Date` | Json: `(Date \| string)`, MessagePack: `Date`. | +| DateTimeOffset | `(Date \| string)` or `[Date, number]` | Json: `(Date \| string)`, MessagePack: `[Date, number]`. note [#41](https://github.com/nenoNaninu/Tapper/pull/41) | | System.Nullable\| (T \| undefined) | | byte[] | string or Uint8Array | JSON: `string` (base64), MessagePack `Uint8Array`. | | T[] | T[] |