Skip to content

Commit

Permalink
Merge pull request #19 from bonsai-rx/feature-dev
Browse files Browse the repository at this point in the history
Generate ToString override with member formatting
  • Loading branch information
glopesdev authored Jan 7, 2024
2 parents 809b422 + c1575cf commit 2b332c7
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 0 deletions.
77 changes: 77 additions & 0 deletions Bonsai.Sgen.Tests/ToStringGenerationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NJsonSchema;
using System.Threading.Tasks;

namespace Bonsai.Sgen.Tests
{
[TestClass]
public class ToStringGenerationTests
{
private static Task<JsonSchema> CreateTestSchema()
{
return JsonSchema.FromJsonAsync(@"
{
""$schema"": ""http://json-schema.org/draft-04/schema#"",
""type"": ""object"",
""title"": ""Container"",
""properties"": {
""BaseType"": {
""oneOf"": [
{
""$ref"": ""#/definitions/BaseType""
},
{
""type"": ""null""
}
]
}
},
""definitions"": {
""DerivedType"": {
""type"": ""object"",
""properties"": {
""Bar"": {
""type"": [
""null"",
""string""
]
},
""Baz"": {
""type"": [
""null"",
""integer""
]
}
},
""allOf"": [
{
""$ref"": ""#/definitions/BaseType""
}
]
},
""EmptyDerivedType"": {
""type"": ""object"",
""allOf"": [
{
""$ref"": ""#/definitions/BaseType""
}
]
},
""BaseType"": {
""type"": ""object""
}
}
}
");
}

[TestMethod]
public async Task GenerateToStringOverride_FormatMultipleProperties()
{
var schema = await CreateTestSchema();
var generator = TestHelper.CreateGenerator(schema);
var code = generator.GenerateFile();
CompilerTestHelper.CompileFromSource(code);
}
}
}
77 changes: 77 additions & 0 deletions Bonsai.Sgen/CSharpClassTemplate.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.CodeDom;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Text;
using System.Xml.Serialization;
using Newtonsoft.Json;
using NJsonSchema.Converters;
Expand Down Expand Up @@ -67,8 +68,10 @@ public override void BuildType(CodeTypeDeclaration type)
new CodeAttributeArgument(new CodePrimitiveExpression(Model.Description))));
}

var propertyCount = 0;
foreach (var property in Model.Properties)
{
propertyCount++;
Model.Schema.ActualProperties.TryGetValue(property.Name, out var propertySchema);
var isPrimitive = PrimitiveTypes.TryGetValue(property.Type, out string? underlyingType);
var fieldDeclaration = new CodeMemberField(
Expand Down Expand Up @@ -216,6 +219,80 @@ public override void BuildType(CodeTypeDeclaration type)
new CodeTypeReferenceExpression("Bonsai.ElementCategory"),
"Source"))));
}

const string PrintMembersMethodName = "PrintMembers";
const string AppendMethodName = nameof(StringBuilder.Append);
var stringBuilderParameter = new CodeParameterDeclarationExpression(typeof(StringBuilder), "stringBuilder");
var stringBuilderVariable = new CodeVariableReferenceExpression(stringBuilderParameter.Name);
var printMembersMethod = new CodeMemberMethod
{
Name = PrintMembersMethodName,
Attributes = Model.BaseClass != null
? MemberAttributes.Family | MemberAttributes.Override
: MemberAttributes.Family,
Parameters = { stringBuilderParameter },
ReturnType = new CodeTypeReference(typeof(bool))
};
if (Model.BaseClass != null && propertyCount == 0)
{
printMembersMethod.Statements.Add(new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), PrintMembersMethodName, stringBuilderVariable)));
}
else
{
if (Model.BaseClass != null)
{
printMembersMethod.Statements.Add(new CodeConditionStatement(
new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), PrintMembersMethodName, stringBuilderVariable),
new CodeExpressionStatement(
new CodeMethodInvokeExpression(stringBuilderVariable, AppendMethodName, new CodePrimitiveExpression(", ")))));
}

var propertyIndex = 0;
foreach (var property in Model.Properties)
{
printMembersMethod.Statements.Add(new CodeMethodInvokeExpression(
stringBuilderVariable,
AppendMethodName,
new CodeSnippetExpression(
$"\"{property.Name} = \" + {property.FieldName}" +
(++propertyIndex < propertyCount ? " + \", \"" : string.Empty))));
}
printMembersMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(propertyCount > 0)));
}

type.Members.Add(printMembersMethod);
if (Model.BaseClass == null)
{
var toStringMethod = new CodeMemberMethod
{
Name = nameof(ToString),
Attributes = MemberAttributes.Public | MemberAttributes.Override,
ReturnType = new CodeTypeReference(typeof(string)),
Statements =
{
new CodeVariableDeclarationStatement(
stringBuilderParameter.Type,
stringBuilderParameter.Name,
new CodeObjectCreateExpression(stringBuilderParameter.Type)),
new CodeMethodInvokeExpression(
stringBuilderVariable,
AppendMethodName,
new CodePropertyReferenceExpression(
new CodeMethodInvokeExpression(null, nameof(GetType)),
nameof(Type.Name))),
new CodeMethodInvokeExpression(stringBuilderVariable, AppendMethodName, new CodePrimitiveExpression(" { ")),
new CodeConditionStatement(
new CodeMethodInvokeExpression(null, printMembersMethod.Name, stringBuilderVariable),
new CodeExpressionStatement(
new CodeMethodInvokeExpression(stringBuilderVariable, AppendMethodName, new CodePrimitiveExpression(" ")))),
new CodeMethodInvokeExpression(stringBuilderVariable, AppendMethodName, new CodePrimitiveExpression("}")),
new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(stringBuilderVariable, nameof(ToString)))
}
};
type.Members.Add(toStringMethod);
}
}

static readonly Dictionary<string, string> PrimitiveTypes = new()
Expand Down

0 comments on commit 2b332c7

Please sign in to comment.