diff --git a/src/DendroDocs.Shared/Descriptions/InvocationDescription.cs b/src/DendroDocs.Shared/Descriptions/InvocationDescription.cs index e1368b3..956de51 100644 --- a/src/DendroDocs.Shared/Descriptions/InvocationDescription.cs +++ b/src/DendroDocs.Shared/Descriptions/InvocationDescription.cs @@ -1,3 +1,5 @@ +using DendroDocs.Json; + namespace DendroDocs; /// @@ -6,6 +8,20 @@ namespace DendroDocs; [DebuggerDisplay("Invocation \"{ContainingType,nq}.{Name,nq}\"")] public class InvocationDescription(string containingType, string name) : Statement { + /// + /// Initializes a new instance of the class with arguments. + /// + /// The type that contains the invoked method or constructor. + /// The name of the invoked method or constructor. + /// The collection of arguments passed to the invocation. + [Newtonsoft.Json.JsonConstructor] + [JsonConstructor] + public InvocationDescription(string containingType, string name, List? arguments) + : this(containingType, name) + { + if (arguments is not null) this.Arguments.AddRange(arguments); + } + /// /// Gets the type that contains the invoked method or constructor. /// @@ -19,5 +35,7 @@ public class InvocationDescription(string containingType, string name) : Stateme /// /// Gets the collection of arguments passed to the invocation. /// + [Newtonsoft.Json.JsonProperty(ItemTypeNameHandling = Newtonsoft.Json.TypeNameHandling.None)] + [Newtonsoft.Json.JsonConverter(typeof(ConcreteTypeConverter>))] public List Arguments { get; } = []; } diff --git a/tests/DendroDocs.Shared.Tests/Serialization/NewtonsoftDeserializationTests.cs b/tests/DendroDocs.Shared.Tests/Serialization/NewtonsoftDeserializationTests.cs index 09a0969..03b7975 100644 --- a/tests/DendroDocs.Shared.Tests/Serialization/NewtonsoftDeserializationTests.cs +++ b/tests/DendroDocs.Shared.Tests/Serialization/NewtonsoftDeserializationTests.cs @@ -485,4 +485,100 @@ public void ConstructorParameters_Should_BeDeserializedCorrectly() secondParameter.Name.ShouldBe("value"); secondParameter.Attributes.Count.ShouldBe(0); } + + [TestMethod] + public void InvocationArguments_Should_BeDeserializedCorrectly_Newtonsoft() + { + // Assign + var json = """ + [{ + "FullName": "Test.Controller", + "Methods": [{ + "Name": "TestMethod", + "Statements": [{ + "$type": "DendroDocs.InvocationDescription, DendroDocs.Shared", + "ContainingType": "Test.Service", + "Name": "PublishMessageAsync", + "Arguments": [{ + "Type": "string", + "Text": "e.MessageType" + }, { + "Type": "Test.Event", + "Text": "e" + }] + }] + }] + }] + """; + + // Act + var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings())!; + + // Assert + types.Count.ShouldBe(1); + types[0].Methods.Count.ShouldBe(1); + types[0].Methods[0].Statements.Count.ShouldBe(1); + + var invocation = types[0].Methods[0].Statements[0].ShouldBeOfType(); + invocation.ContainingType.ShouldBe("Test.Service"); + invocation.Name.ShouldBe("PublishMessageAsync"); + invocation.Arguments.Count.ShouldBe(2); + + invocation.Arguments[0].Type.ShouldBe("string"); + invocation.Arguments[0].Text.ShouldBe("e.MessageType"); + + invocation.Arguments[1].Type.ShouldBe("Test.Event"); + invocation.Arguments[1].Text.ShouldBe("e"); + } + + [TestMethod] + public void InvocationArguments_Should_BeDeserializedCorrectly_ComplexExample_Newtonsoft() + { + // Test case based on the original issue's JSON + var json = """ + [{ + "FullName": "Pitstop.Application.CustomerManagementAPI.Controllers.CustomersController", + "Methods": [{ + "Name": "RegisterAsync", + "Statements": [{ + "$type": "DendroDocs.InvocationDescription, DendroDocs.Shared", + "ContainingType": "Pitstop.Infrastructure.Messaging.IMessagePublisher", + "Name": "PublishMessageAsync", + "Arguments": [{ + "Type": "string", + "Text": "e.MessageType" + }, { + "Type": "Pitstop.CustomerManagementAPI.Events.CustomerRegistered", + "Text": "e" + }, { + "Type": "string", + "Text": "" + }] + }] + }] + }] + """; + + // Act + var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings())!; + + // Assert + types.Count.ShouldBe(1); + types[0].Methods.Count.ShouldBe(1); + types[0].Methods[0].Statements.Count.ShouldBe(1); + + var invocation = types[0].Methods[0].Statements[0].ShouldBeOfType(); + invocation.ContainingType.ShouldBe("Pitstop.Infrastructure.Messaging.IMessagePublisher"); + invocation.Name.ShouldBe("PublishMessageAsync"); + invocation.Arguments.Count.ShouldBe(3); + + invocation.Arguments[0].Type.ShouldBe("string"); + invocation.Arguments[0].Text.ShouldBe("e.MessageType"); + + invocation.Arguments[1].Type.ShouldBe("Pitstop.CustomerManagementAPI.Events.CustomerRegistered"); + invocation.Arguments[1].Text.ShouldBe("e"); + + invocation.Arguments[2].Type.ShouldBe("string"); + invocation.Arguments[2].Text.ShouldBe(""); + } } diff --git a/tests/DendroDocs.Shared.Tests/Serialization/TextJsonDeserializationTests.cs b/tests/DendroDocs.Shared.Tests/Serialization/TextJsonDeserializationTests.cs index 9201b42..3668bbd 100644 --- a/tests/DendroDocs.Shared.Tests/Serialization/TextJsonDeserializationTests.cs +++ b/tests/DendroDocs.Shared.Tests/Serialization/TextJsonDeserializationTests.cs @@ -580,4 +580,100 @@ public void ConstructorParameters_Should_BeDeserializedCorrectly() secondParameter.Name.ShouldBe("value"); secondParameter.Attributes.Count.ShouldBe(0); } + + [TestMethod] + public void InvocationArguments_Should_BeDeserializedCorrectly_TextJson() + { + // Assign + var json = """ + [{ + "FullName": "Test.Controller", + "Methods": [{ + "Name": "TestMethod", + "Statements": [{ + "$type": "DendroDocs.InvocationDescription, DendroDocs.Shared", + "ContainingType": "Test.Service", + "Name": "PublishMessageAsync", + "Arguments": [{ + "Type": "string", + "Text": "e.MessageType" + }, { + "Type": "Test.Event", + "Text": "e" + }] + }] + }] + }] + """; + + // Act + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; + + // Assert + types.Count.ShouldBe(1); + types[0].Methods.Count.ShouldBe(1); + types[0].Methods[0].Statements.Count.ShouldBe(1); + + var invocation = types[0].Methods[0].Statements[0].ShouldBeOfType(); + invocation.ContainingType.ShouldBe("Test.Service"); + invocation.Name.ShouldBe("PublishMessageAsync"); + invocation.Arguments.Count.ShouldBe(2); + + invocation.Arguments[0].Type.ShouldBe("string"); + invocation.Arguments[0].Text.ShouldBe("e.MessageType"); + + invocation.Arguments[1].Type.ShouldBe("Test.Event"); + invocation.Arguments[1].Text.ShouldBe("e"); + } + + [TestMethod] + public void InvocationArguments_Should_BeDeserializedCorrectly_ComplexExample_TextJson() + { + // Test case based on the original issue's JSON + var json = """ + [{ + "FullName": "Pitstop.Application.CustomerManagementAPI.Controllers.CustomersController", + "Methods": [{ + "Name": "RegisterAsync", + "Statements": [{ + "$type": "DendroDocs.InvocationDescription, DendroDocs.Shared", + "ContainingType": "Pitstop.Infrastructure.Messaging.IMessagePublisher", + "Name": "PublishMessageAsync", + "Arguments": [{ + "Type": "string", + "Text": "e.MessageType" + }, { + "Type": "Pitstop.CustomerManagementAPI.Events.CustomerRegistered", + "Text": "e" + }, { + "Type": "string", + "Text": "" + }] + }] + }] + }] + """; + + // Act + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; + + // Assert + types.Count.ShouldBe(1); + types[0].Methods.Count.ShouldBe(1); + types[0].Methods[0].Statements.Count.ShouldBe(1); + + var invocation = types[0].Methods[0].Statements[0].ShouldBeOfType(); + invocation.ContainingType.ShouldBe("Pitstop.Infrastructure.Messaging.IMessagePublisher"); + invocation.Name.ShouldBe("PublishMessageAsync"); + invocation.Arguments.Count.ShouldBe(3); + + invocation.Arguments[0].Type.ShouldBe("string"); + invocation.Arguments[0].Text.ShouldBe("e.MessageType"); + + invocation.Arguments[1].Type.ShouldBe("Pitstop.CustomerManagementAPI.Events.CustomerRegistered"); + invocation.Arguments[1].Text.ShouldBe("e"); + + invocation.Arguments[2].Type.ShouldBe("string"); + invocation.Arguments[2].Text.ShouldBe(""); + } }