diff --git a/StatePrinter.Tests/IntegrationTests/ObjectGraphsTest.cs b/StatePrinter.Tests/IntegrationTests/ObjectGraphsTest.cs
index 5917ce6..c9aff46 100644
--- a/StatePrinter.Tests/IntegrationTests/ObjectGraphsTest.cs
+++ b/StatePrinter.Tests/IntegrationTests/ObjectGraphsTest.cs
@@ -17,6 +17,7 @@
// specific language governing permissions and limitations
// under the License.
+using System;
using System.Collections.Generic;
using NUnit.Framework;
using StatePrinting.OutputFormatters;
@@ -36,7 +37,12 @@ public void Setup()
{
printer = TestHelper.CreateTestPrinter();
- car = new Car(new SteeringWheel(new FoamGrip("Plastic"))) { Brand = "Toyota" };
+ car = new Car(new SteeringWheel(new FoamGrip("Plastic")))
+ {
+ Brand = "Toyota",
+ Wheels = new [] { new Wheel(), new Wheel(), new Wheel(), new Wheel() }, // testing populated collection
+ Passengers = new Passenger[0] // testing empty collection
+ };
course = new Course();
course.Members.Add(new Student("Stan", course));
@@ -45,7 +51,7 @@ public void Setup()
}
[Test]
- public void ThreeLinkedGraph()
+ public void ThreeLinkedGraph_curly()
{
var expected =
@"new Car()
@@ -61,11 +67,75 @@ public void ThreeLinkedGraph()
Weight = 525
}
Brand = ""Toyota""
+ Wheels = new Wheel[]()
+ {
+ [0] = new Wheel()
+ {
+ Diameter = 0
+ }
+ [1] = new Wheel()
+ {
+ Diameter = 0
+ }
+ [2] = new Wheel()
+ {
+ Diameter = 0
+ }
+ [3] = new Wheel()
+ {
+ Diameter = 0
+ }
+ }
+ Passengers = new Passenger[]()
+ {
+ }
}";
printer.Assert.PrintEquals(expected, car);
}
+ [Test]
+ public void ThreeLinkedGraph_strictCSharp()
+ {
+ printer.Configuration.OutputFormatter = new StrictCSharpStyle(printer.Configuration);
+
+ var expected =
+ @"new Car()
+{
+ StereoAmplifiers = null,
+ steeringWheel = new SteeringWheel()
+ {
+ Size = 3,
+ Grip = new FoamGrip()
+ {
+ Material = ""Plastic"",
+ },
+ Weight = 525,
+ },
+ Brand = ""Toyota"",
+ Wheels = new Wheel[]
+ {
+ new Wheel()
+ {
+ Diameter = 0,
+ },
+ new Wheel()
+ {
+ Diameter = 0,
+ },
+ new Wheel()
+ {
+ Diameter = 0,
+ },
+ new Wheel()
+ {
+ Diameter = 0,
+ },
+ },
+}";
+ printer.Assert.PrintEquals(expected, car);
+ }
+
[Test]
public void ThreeLinkedGraph_json()
{
@@ -80,7 +150,22 @@ public void ThreeLinkedGraph_json()
},
""Weight"": 525
},
- ""Brand"": ""Toyota""
+ ""Brand"": ""Toyota"",
+ ""Wheels"": [
+ {
+ ""Diameter"": 0
+ },
+ {
+ ""Diameter"": 0
+ },
+ {
+ ""Diameter"": 0
+ },
+ {
+ ""Diameter"": 0
+ }
+ ],
+ ""Passengers"": []
}";
printer.Assert.PrintEquals(expected, car);
@@ -101,6 +186,22 @@ public void ThreeLinkedGraph_xmlstyle()
525
Toyota
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
";
printer.Assert.PrintEquals(expected, car);
@@ -129,7 +230,13 @@ public void CyclicGraph_curly()
printer.Assert.PrintEquals(expected, course);
}
-
+ [Test]
+ public void CyclicGraph_strictCSharp()
+ {
+ printer.Configuration.OutputFormatter = new StrictCSharpStyle(printer.Configuration);
+ Assert.Throws(() => printer.PrintObject(course));
+ }
+
[Test]
public void CyclicGraph_Json()
{
@@ -307,18 +414,30 @@ public void CyclicGraph_xmlstyle()
}
}
+ internal class Passenger
+ {
+ }
+
#region car
class Car
{
protected int? StereoAmplifiers = null;
private SteeringWheel steeringWheel;
public string Brand { get; set; }
+ public Wheel[] Wheels { get; set; }
+ public Passenger[] Passengers { get; set; }
+
public Car(SteeringWheel steeringWheel)
{
this.steeringWheel = steeringWheel;
}
}
+ internal class Wheel
+ {
+ public decimal Diameter { get; set; }
+ }
+
internal class SteeringWheel
{
internal int Size = 3;
diff --git a/StatePrinter/OutputFormatters/StrictCSharpStyle.cs b/StatePrinter/OutputFormatters/StrictCSharpStyle.cs
new file mode 100644
index 0000000..e72b93f
--- /dev/null
+++ b/StatePrinter/OutputFormatters/StrictCSharpStyle.cs
@@ -0,0 +1,135 @@
+// Copyright 2014 Kasper B. Graversen
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using StatePrinting.Configurations;
+using StatePrinting.Introspection;
+
+namespace StatePrinting.OutputFormatters
+{
+ ///
+ /// Formatting the tokens to a compilable C# representation.
+ ///
+ /// Circular refereces are not supported, as this would lead to infinte loops.
+ ///
+ public class StrictCSharpStyle : IOutputFormatter
+ {
+ Configuration configuration;
+
+ public StrictCSharpStyle(Configuration configuration)
+ {
+ this.configuration = configuration;
+ }
+
+ public string Print(List tokens)
+ {
+ var filter = new UnusedReferencesTokenFilter();
+ var processed = filter.FilterUnusedReferences(tokens);
+
+ return MakeString(processed);
+ }
+
+ string MakeString(IList tokens)
+ {
+ var sb = new IndentingStringBuilder(configuration);
+
+ for (var i = 0; i < tokens.Count; i++)
+ {
+ var token = tokens[i];
+ MakeTokenString(token, sb);
+ }
+
+ sb.TrimLast();
+ var result = sb.ToString();
+
+ // remove final superfluous trailing comma - very hacky, could probably be done better
+ return result.Remove(result.Length - 1);
+ }
+
+ void MakeTokenString(Token token, IndentingStringBuilder sb)
+ {
+ switch (token.Tokenkind)
+ {
+ case TokenType.StartScope:
+ case TokenType.StartList:
+ case TokenType.StartDict:
+ sb.AppendFormatLine("{{");
+ sb.Indent();
+ break;
+
+ case TokenType.EndScope:
+ case TokenType.EndList:
+ case TokenType.EndDict:
+ sb.DeIndent();
+ sb.AppendFormatLine("}},");
+ break;
+
+ case TokenType.SimpleFieldValue:
+ sb.AppendFormatLine("{0}", MakeFieldValue(token, token.Value));
+ break;
+
+ case TokenType.SeenBeforeWithReference:
+ throw CreateCyclicalObjectGraphException();
+
+ case TokenType.FieldnameWithTypeAndReference:
+ if (token.ReferenceNo != null)
+ {
+ throw CreateCyclicalObjectGraphException();
+ }
+
+ var fieldType = OutputFormatterHelpers.MakeReadable(token.FieldType);
+
+ string value = string.Format("new {0}{1}", fieldType, token.FieldType.IsArray ? "" : "()");
+ sb.AppendFormatLine("{0}", MakeFieldValue(token, value));
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ string MakeFieldValue(Token token, string value, Token nextToken = null)
+ {
+ if (token.Field == null)
+ return string.Format("{0}", value);
+
+ if (token.Field.Index.HasValue)
+ return string.Format("{0}", value);
+
+ if (token.Field.Key != null)
+ return string.Format("[{0}] = {1}", token.Field.Key, value);
+
+ if (!string.IsNullOrEmpty(token.Field.Name))
+ {
+ var isEnumerable = token.FieldType != null && token.FieldType.IsAssignableFrom(typeof(IEnumerable));
+ return string.Format("{0} = {1}{2}", token.Field.Name, value, isEnumerable ? "" : ",");
+ }
+
+ return string.Format("{0}", value);
+ }
+
+ NotSupportedException CreateCyclicalObjectGraphException()
+ {
+ return new NotSupportedException("Cyclical object graphs are not supported in StrictCSharp style.");
+ }
+ }
+}
diff --git a/StatePrinter/StatePrinter.csproj b/StatePrinter/StatePrinter.csproj
index 4004082..3c6a831 100644
--- a/StatePrinter/StatePrinter.csproj
+++ b/StatePrinter/StatePrinter.csproj
@@ -80,6 +80,7 @@
+