Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions MiniMods/PrettyPrint/PrettyPrintMinimod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@

namespace Minimod.PrettyPrint
{
internal class FrameStack
{
private object head;
private FrameStack tail;

public static FrameStack Empty = new FrameStack();

private FrameStack() {}

public FrameStack(object obj, FrameStack rest)
{
head = obj;
tail = rest;
}

public bool Contains(object obj)
{
var current = this;
while (current != Empty)
{
if (current.head == obj) return true;
current = current.tail;
}
return false;
}
}

/// <summary>
/// <h1>Minimod.PrettyPrint, Version 1.0.1, Copyright � Lars Corneliussen 2011</h1>
/// <para>Creates nice textual representations of any objects. Mostly meant for debug/informational output.</para>
Expand Down Expand Up @@ -405,12 +432,22 @@ public static string PrettyPrint(this object anyObject, Type declaredType, Func<
}

public static string PrettyPrint(this object anyObject, Type declaredType, Settings settings)
{
return PrettyPrint(anyObject, declaredType, settings, FrameStack.Empty);
}

internal static string PrettyPrint(object anyObject, Type declaredType, Settings settings, FrameStack printing)
{
if (anyObject == null)
{
return "<null" + (declaredType != typeof(object) ? ", " + declaredType.GetPrettyName() : "") + ">";
}

if (printing.Contains(anyObject))
{
return "<" + anyObject.GetType().GetPrettyName() + " - referenced earlier>";
}

var formatter = settings.GetCustomFormatter(anyObject);
if (formatter != null)
{
Expand All @@ -434,22 +471,22 @@ public static string PrettyPrint(this object anyObject, Type declaredType, Setti

if (anyObject is IEnumerable)
{
return enumerable(anyObject as IEnumerable, declaredType, settings);
return enumerable(anyObject as IEnumerable, declaredType, settings, new FrameStack(anyObject, printing));
}

if (declaredType.IsEnum && Enum.IsDefined(declaredType, anyObject))
{
return String.Format("<{0}.{1} = {2}>", declaredType.Name, Enum.GetName(declaredType, anyObject), (int)anyObject);
}

return GenericFormatter.Format(actualType, anyObject, settings);
return GenericFormatter.Format(actualType, anyObject, settings, new FrameStack(anyObject, printing));
}

#endregion

private static string enumerable(IEnumerable objects, Type declaredType, Settings settings)
private static string enumerable(IEnumerable objects, Type declaredType, Settings settings, FrameStack printing)
{
string[] items = objects.Cast<object>().Select(_ => _.PrettyPrint(settings)).ToArray();
string[] items = objects.Cast<object>().Select(x => PrettyPrint(x, x.GetType(), settings, printing)).ToArray();

if (settings.PrefersMultiline
?? (
Expand Down Expand Up @@ -502,13 +539,18 @@ public class MemberDetails
}

public static string Format(Type actualType, object anyObject, Settings settings)
{
return Format(actualType, anyObject, settings, FrameStack.Empty);
}

internal static string Format(Type actualType, object anyObject, Settings settings, FrameStack printing)
{
if (actualType == null) throw new ArgumentNullException("actualType");
if (anyObject == null) throw new ArgumentNullException("anyObject");
if (settings == null) throw new ArgumentNullException("settings");

var members =
findAndFormatMembers(anyObject, settings, actualType)
findAndFormatMembers(anyObject, settings, actualType, printing)
.Where(m => m.Value != null || (settings.OmitsNullMembers ?? false))
.ToArray();

Expand Down Expand Up @@ -538,7 +580,7 @@ private static bool mayFormatKeyValuePairs(MemberDetails[] members, out string f
}

private static IEnumerable<MemberDetails> findAndFormatMembers(object anyObject, Settings settings,
Type actualType)
Type actualType, FrameStack printing)
{
var properties =
from prop in actualType.GetMembers().OfType<PropertyInfo>()
Expand Down Expand Up @@ -581,7 +623,7 @@ from prop in actualType.GetMembers().OfType<FieldInfo>()
{
pretty = hasCustomFormatter
? propFormatter(m.value, m.name, anyObject, settings)
: m.value.PrettyPrint(m.type, settings);
: PrettyPrint(m.value, m.type, settings, printing);
}
else
{
Expand Down
51 changes: 51 additions & 0 deletions MiniMods/PrettyPrint/PrettyPrintMinimodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,57 @@ public void Sample2_UglyArray()
Console.WriteLine(value);
Console.WriteLine(value.PrettyPrint());
}

class A
{
public int i;
public A a;
}

[Test]
public void PrettyPrintRecursiveTypes()
{
var tail = new A { i = 0 };
var head = new A { a = tail, i = 1 };
tail.a = head;

Console.WriteLine(head.PrettyPrint());
Console.WriteLine(tail.PrettyPrint());
}

[Test]
public void PrettyPrintDeepRecusion()
{
var tail = new A { i = 0 };
var head = tail;

for (var i = 1; i < 100; ++i)
{
head = new A { a = head, i = i };
}

tail.a = head;

Console.WriteLine(head.PrettyPrint());
Console.WriteLine(tail.PrettyPrint());
}

class B
{
public int i;
public IEnumerable<B> bs;
}

[Test]
public void PrettyPrintEnumerable()
{
var tail = new B { i = 0 };
var head = new B { i = 1, bs = new B[] { tail } };
tail.bs = new [] { head };

Console.WriteLine(head.PrettyPrint());
Console.WriteLine(tail.PrettyPrint());
}
}

[TestFixture]
Expand Down