diff --git a/Linguini.Serialization.Test/AttributeSerializerTest.cs b/Linguini.Serialization.Test/AttributeSerializerTest.cs deleted file mode 100644 index a19774b..0000000 --- a/Linguini.Serialization.Test/AttributeSerializerTest.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Text; -using System.Text.Json; -using Linguini.Serialization.Converters; -using Linguini.Syntax.Ast; -using NUnit.Framework; -using Attribute = Linguini.Syntax.Ast.Attribute; - -namespace Linguini.Serialization.Test; - -[TestFixture] -public class AttributeSerializerTest -{ - [Test] - [TestOf(typeof(AttributeSerializer))] - [Parallelizable] - public void TestAttributeSerializer() - { - string attributeJson = @" -{ - ""type"": ""Attribute"", - ""id"": { - ""type"": ""Identifier"", - ""name"": ""desc"" - }, - ""value"": { - ""type"": ""Pattern"", - ""elements"": [ - { - ""type"": ""StringLiteral"", - ""value"": ""description"" - } - ] - } -}"; - Attribute expected = new Attribute("desc", new PatternBuilder("description")); - Attribute? actual = JsonSerializer.Deserialize(attributeJson, TestUtil.Options); - Assert.That(actual, Is.EqualTo(expected)); - } - - [Test] - [TestOf(typeof(AttributeSerializer))] - [Parallelizable] - public void Serde() - { - Attribute start = new Attribute("desc", new PatternBuilder("d1")); - var text = ""; - using (var memoryStream = new MemoryStream()) - { - JsonSerializer.Serialize(memoryStream, start, TestUtil.Options); - text = Encoding.UTF8.GetString(memoryStream.ToArray()); - } - - Attribute deserialized = JsonSerializer.Deserialize(text, TestUtil.Options)!; - Assert.That(deserialized, Is.EqualTo(start)); - } -} \ No newline at end of file diff --git a/Linguini.Serialization.Test/CallArgumentsSerializerTest.cs b/Linguini.Serialization.Test/CallArgumentsSerializerTest.cs deleted file mode 100644 index 40441b6..0000000 --- a/Linguini.Serialization.Test/CallArgumentsSerializerTest.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Text; -using System.Text.Json; -using Linguini.Serialization.Converters; -using Linguini.Syntax.Ast; -using NUnit.Framework; - -namespace Linguini.Serialization.Test; - -[TestFixture] -public class CallArgumentsSerializerTest -{ - [Test] - [TestOf(typeof(CallArgumentsSerializer))] - [Parallelizable] - public void TestCallSerializer() - { - string callJson = @" -{ - ""type"": ""CallArguments"", - ""positional"": [ - { - ""type"": ""MessageReference"", - ""id"": { - ""type"": ""Identifier"", - ""name"": ""x"" - }, - ""attribute"": null - } - ], - ""named"": [ - { - ""type"": ""NamedArgument"", - ""name"": { - ""type"": ""Identifier"", - ""name"": ""y"" - }, - ""value"": { - ""value"": ""3"", - ""type"": ""NumberLiteral"" - } - } - ] -}"; - var expected = new CallArgumentsBuilder() - .AddPositionalArg(InlineExpressionBuilder.CreateMessageReference("x")) - .AddNamedArg("y", 3) - .Build(); - CallArguments? actual = JsonSerializer.Deserialize(callJson, TestUtil.Options); - Assert.That(actual, Is.EqualTo(expected)); - } - - [Test] - [TestOf(typeof(CallArgumentsSerializer))] - [Parallelizable] - public void Serde() - { - var start = new CallArgumentsBuilder() - .AddNamedArg("x", 3) - .AddPositionalArg(InlineExpressionBuilder.CreateTermReference("x", "y")) - .Build(); - var text = ""; - using (var memoryStream = new MemoryStream()) - { - JsonSerializer.Serialize(memoryStream, start, TestUtil.Options); - text = Encoding.UTF8.GetString(memoryStream.ToArray()); - } - - CallArguments deserialized = JsonSerializer.Deserialize(text, TestUtil.Options); - Assert.That(deserialized, Is.EqualTo(start)); - } -} \ No newline at end of file diff --git a/Linguini.Serialization.Test/DynamicReferenceSerializerTest.cs b/Linguini.Serialization.Test/DynamicReferenceSerializerTest.cs deleted file mode 100644 index ad8c191..0000000 --- a/Linguini.Serialization.Test/DynamicReferenceSerializerTest.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Text; -using System.Text.Json; -using Linguini.Serialization.Converters; -using Linguini.Syntax.Ast; -using NUnit.Framework; - -namespace Linguini.Serialization.Test; - -[TestFixture] -public class DynamicReferenceSerializerTest -{ - [Test] - [TestOf(typeof(DynamicReferenceSerializer))] - [Parallelizable] - public void TestDynamicReference() - { - string dynamicReference = @" -{ - ""type"": ""DynamicReference"", - ""id"": { - ""type"": ""Identifier"", - ""name"": ""dyn"" - }, - ""attribute"": { - ""type"": ""Identifier"", - ""name"": ""attr"" - }, - ""arguments"": { - ""type"": ""CallArguments"", - ""positional"": [ - { - ""type"": ""MessageReference"", - ""id"": { - ""type"": ""Identifier"", - ""name"": ""x"" - }, - ""attribute"": null - } - ], - ""named"": [ - { - ""type"": ""NamedArgument"", - ""name"": { - ""type"": ""Identifier"", - ""name"": ""y"" - }, - ""value"": { - ""value"": ""3"", - ""type"": ""NumberLiteral"" - } - } - ] - } -}"; - var callArgs = new CallArgumentsBuilder() - .AddPositionalArg(InlineExpressionBuilder.CreateMessageReference("x")) - .AddNamedArg("y", 3); - var expected = new DynamicReference("dyn", "attr", callArgs); - DynamicReference? actual = JsonSerializer.Deserialize(dynamicReference, TestUtil.Options); - Assert.That(actual, Is.EqualTo(expected)); - } - - [Test] - [TestOf(typeof(DynamicReferenceSerializer))] - [Parallelizable] - public void Serde() - { - var callArgs = new CallArgumentsBuilder() - .AddPositionalArg(InlineExpressionBuilder.CreateMessageReference("x")) - .AddNamedArg("y", 3) - .AddPositionalArg("z") - .AddNamedArg("om", InlineExpressionBuilder.CreateMessageReference("a", "z")); - var start = new DynamicReference("dyn", "attr", callArgs); - var text = ""; - using (var memoryStream = new MemoryStream()) - { - JsonSerializer.Serialize(memoryStream, start, TestUtil.Options); - text = Encoding.UTF8.GetString(memoryStream.ToArray()); - } - - DynamicReference deserialized = JsonSerializer.Deserialize(text, TestUtil.Options)!; - Assert.That(deserialized, Is.EqualTo(start)); - } -} \ No newline at end of file diff --git a/Linguini.Serialization.Test/SerializeAndDeserializeTest.cs b/Linguini.Serialization.Test/SerializeAndDeserializeTest.cs new file mode 100644 index 0000000..7f18b67 --- /dev/null +++ b/Linguini.Serialization.Test/SerializeAndDeserializeTest.cs @@ -0,0 +1,86 @@ +using System.Diagnostics; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; +using Linguini.Serialization.Converters; +using Linguini.Syntax.Ast; +using NUnit.Framework; +using Attribute = Linguini.Syntax.Ast.Attribute; + + +namespace Linguini.Serialization.Test; + +[TestFixture] +public class SerializeAndDeserializeTest +{ + [Test] + [TestCaseSource(nameof(AstExamples))] + [Parallelizable] + public void SerializeDeserializeTest(object x) + { + SerializeAndDeserializeTest.SerializeDeserializeTest(x); + } + + public static IEnumerable AstExamples() + { + yield return new CallArgumentsBuilder() + .AddPositionalArg(InlineExpressionBuilder.CreateMessageReference("x")) + .AddNamedArg("y", 3) + .Build(); + yield return new Attribute("desc", new PatternBuilder("description")); + yield return new DynamicReference("dyn", "attr", new CallArgumentsBuilder() + .AddPositionalArg(InlineExpressionBuilder.CreateMessageReference("x")) + .AddNamedArg("y", 3)); + yield return new FunctionReference("foo", new CallArgumentsBuilder() + .AddPositionalArg(3) + .AddNamedArg("test", InlineExpressionBuilder.CreateTermReference("x", "y")) + .Build() + ); + yield return new Identifier("test"); + } + + private static void SerializeDeserializeTest(T expected) + { + // Serialize the object to JSON string. + var jsonString = JsonSerializer.Serialize(expected, Options); + + // Deserialize the JSON string back into an object. + Debug.Assert(expected != null, nameof(expected) + " != null"); + var deserializedObject = JsonSerializer.Deserialize(jsonString, expected.GetType(), Options); + + // Now you have a 'deserializedObject' which should be equivalent to the original 'expected' object. + Assert.That(deserializedObject, Is.Not.Null); + Assert.That(deserializedObject, Is.EqualTo(expected)); + } + + private static readonly JsonSerializerOptions Options = new() + { + IgnoreReadOnlyFields = false, + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + Converters = + { + new AttributeSerializer(), + new CallArgumentsSerializer(), + new CommentSerializer(), + new FunctionReferenceSerializer(), + new IdentifierSerializer(), + new JunkSerializer(), + new MessageReferenceSerializer(), + new MessageSerializer(), + new DynamicReferenceSerializer(), + new NamedArgumentSerializer(), + new ParseErrorSerializer(), + new PatternSerializer(), + new PlaceableSerializer(), + new ResourceSerializer(), + new PlaceableSerializer(), + new SelectExpressionSerializer(), + new TermReferenceSerializer(), + new TermSerializer(), + new VariantSerializer(), + new VariableReferenceSerializer(), + } + }; +} \ No newline at end of file diff --git a/Linguini.Serialization.Test/TestUtil.cs b/Linguini.Serialization.Test/TestUtil.cs index 41455da..35c2f15 100644 --- a/Linguini.Serialization.Test/TestUtil.cs +++ b/Linguini.Serialization.Test/TestUtil.cs @@ -2,40 +2,15 @@ using System.Text.Json; using System.Text.Json.Serialization; using Linguini.Serialization.Converters; +using NUnit.Framework; namespace Linguini.Serialization.Test { public static class TestUtil { - public static readonly JsonSerializerOptions Options = new() - { - IgnoreReadOnlyFields = false, - WriteIndented = true, - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - Converters = - { - new AttributeSerializer(), - new CallArgumentsSerializer(), - new CommentSerializer(), - new FunctionReferenceSerializer(), - new IdentifierSerializer(), - new JunkSerializer(), - new MessageReferenceSerializer(), - new MessageSerializer(), - new DynamicReferenceSerializer(), - new NamedArgumentSerializer(), - new ParseErrorSerializer(), - new PatternSerializer(), - new PlaceableSerializer(), - new ResourceSerializer(), - new PlaceableSerializer(), - new SelectExpressionSerializer(), - new TermReferenceSerializer(), - new TermSerializer(), - new VariantSerializer(), - new VariableReferenceSerializer(), - } - }; + + + + } } \ No newline at end of file diff --git a/Linguini.Serialization/Converters/DynamicReferenceSerializer.cs b/Linguini.Serialization/Converters/DynamicReferenceSerializer.cs index f54ca72..d7d4198 100644 --- a/Linguini.Serialization/Converters/DynamicReferenceSerializer.cs +++ b/Linguini.Serialization/Converters/DynamicReferenceSerializer.cs @@ -11,7 +11,8 @@ public class DynamicReferenceSerializer : JsonConverter public override DynamicReference? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - throw new NotImplementedException(); + var el = JsonSerializer.Deserialize(ref reader, options); + return ProcessDynamicReference(el, options); } public override void Write(Utf8JsonWriter writer, DynamicReference dynRef, JsonSerializerOptions options) @@ -40,9 +41,8 @@ public override void Write(Utf8JsonWriter writer, DynamicReference dynRef, JsonS public static DynamicReference ProcessDynamicReference(JsonElement el, JsonSerializerOptions options) { - Identifier? identifier = null; - if (!el.TryGetProperty("id", out var jsonId) && - !IdentifierSerializer.TryGetIdentifier(jsonId, options, out identifier)) + if (!el.TryGetProperty("id", out var jsonId) || + !IdentifierSerializer.TryGetIdentifier(jsonId, options, out var identifier)) { throw new JsonException("Dynamic reference must contain at least `id` field"); } @@ -59,7 +59,7 @@ public static DynamicReference ProcessDynamicReference(JsonElement el, CallArgumentsSerializer.TryGetCallArguments(jsonArgs, options, out arguments); } - return new DynamicReference(identifier!, attribute, arguments); + return new DynamicReference(identifier, attribute, arguments); } } } \ No newline at end of file diff --git a/Linguini.Serialization/Converters/FunctionReferenceSerializer.cs b/Linguini.Serialization/Converters/FunctionReferenceSerializer.cs index 639a671..5e7f7c7 100644 --- a/Linguini.Serialization/Converters/FunctionReferenceSerializer.cs +++ b/Linguini.Serialization/Converters/FunctionReferenceSerializer.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; using Linguini.Syntax.Ast; @@ -11,7 +10,8 @@ public class FunctionReferenceSerializer : JsonConverter public override FunctionReference Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - throw new NotImplementedException(); + var el = JsonSerializer.Deserialize(ref reader, options); + return ProcessFunctionReference(el, options); } public override void Write(Utf8JsonWriter writer, FunctionReference value, JsonSerializerOptions options) @@ -29,23 +29,22 @@ public override void Write(Utf8JsonWriter writer, FunctionReference value, JsonS public static FunctionReference ProcessFunctionReference(JsonElement el, JsonSerializerOptions options) { - Identifier? ident = null; - if (!el.TryGetProperty("id", out JsonElement value) && - !IdentifierSerializer.TryGetIdentifier(value, options, out ident)) + if (!el.TryGetProperty("id", out JsonElement value) || + !IdentifierSerializer.TryGetIdentifier(value, options, out var ident)) { throw new JsonException("Function reference must contain `id` field"); } CallArguments? arguments = null; - if (!el.TryGetProperty("arguments", out var jsonArguments) && - CallArgumentsSerializer.TryGetCallArguments(jsonArguments, options, out arguments) + if (!el.TryGetProperty("arguments", out var jsonArguments) || + !CallArgumentsSerializer.TryGetCallArguments(jsonArguments, options, out arguments) ) { throw new JsonException("Function reference must contain `arguments` field"); } - return new FunctionReference(ident!, arguments!.Value); + return new FunctionReference(ident, arguments.Value); } } } \ No newline at end of file diff --git a/Linguini.Syntax.Tests/Parser/LinguiniTestDetailedErrors.cs b/Linguini.Syntax.Tests/Parser/LinguiniTestDetailedErrors.cs index d437bb7..d7581fd 100644 --- a/Linguini.Syntax.Tests/Parser/LinguiniTestDetailedErrors.cs +++ b/Linguini.Syntax.Tests/Parser/LinguiniTestDetailedErrors.cs @@ -1,8 +1,6 @@ using System; -using Linguini.Syntax.Ast; using Linguini.Syntax.Parser; using NUnit.Framework; -using NUnit.Framework.Legacy; namespace Linguini.Syntax.Tests.Parser { diff --git a/Linguini.Syntax/Ast/Expression.cs b/Linguini.Syntax/Ast/Expression.cs index 3b25f2f..3fe907c 100644 --- a/Linguini.Syntax/Ast/Expression.cs +++ b/Linguini.Syntax/Ast/Expression.cs @@ -155,14 +155,14 @@ public bool Equals(MessageReference? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return Id.Equals(other.Id) && Equals(Attribute, other.Attribute); + return Id.Equals(other.Id) && Identifier.Comparator.Equals(Attribute, other.Attribute); } public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj.GetType() != GetType()) return false; return Equals((MessageReference)obj); } @@ -217,7 +217,7 @@ public bool Equals(DynamicReference? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return Id.Equals(other.Id) && Equals(Attribute, other.Attribute) && + return Id.Equals(other.Id) && Identifier.Comparator.Equals(Attribute, other.Attribute) && Nullable.Equals(Arguments, other.Arguments); } @@ -342,16 +342,6 @@ public Placeable(IExpression expression) Expression = expression; } - public bool Equals(IPatternElement? other) - { - if (other is Placeable otherPlaceable) - { - return Expression == otherPlaceable.Expression; - } - - return false; - } - public bool Equals(Placeable? other) { if (ReferenceEquals(null, other)) return false; diff --git a/PluralRules.Test/Cldr/CldrParserTest.cs b/PluralRules.Test/Cldr/CldrParserTest.cs index 3b3c28b..7339254 100644 --- a/PluralRules.Test/Cldr/CldrParserTest.cs +++ b/PluralRules.Test/Cldr/CldrParserTest.cs @@ -60,8 +60,8 @@ public void ParseEmpty() [Parallelizable] [TestCase("n is 12 @integer 0, 5, 7~20", new[] {"0", "5", "7~20"}, new string[] { })] [TestCase("n is 12 @integer 0, 5, 7~20 @decimal 1, 3~6,...", new[] {"0", "5", "7~20"}, - new string[] {"1", "3~6"})] - [TestCase("@integer 0, 11~25, 100, 1000, …", new string[] {"0", "11~25", "100", "1000"}, new string[] { })] + new[] {"1", "3~6"})] + [TestCase("@integer 0, 11~25, 100, 1000, …", new[] {"0", "11~25", "100", "1000"}, new string[] { })] public void ParseSamples(string input, string[] expIntRangeList, string[] expDecRangeList) { var rule = new CldrParser(input).ParseRule();