Skip to content

Commit 6332305

Browse files
committed
Enables object notation formatter in visualizer
1 parent 4bf26ae commit 6332305

6 files changed

Lines changed: 324 additions & 127 deletions

File tree

Shared/ObjectNotationFormatter.cs

Lines changed: 95 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -61,108 +61,94 @@ public ObjectNotationFormatter(object o, string language, out Dictionary<string,
6161
typeof(TryExpression)
6262
};
6363

64-
private void WriteObjectCreation(object o, int depth=0) {
65-
if (!o.GetType().InheritsFromOrImplementsAny(PropertyTypes) && !o.GetType().InheritsFromOrImplementsAny(NodeTypes)) {
66-
Write(RenderLiteral(o, language));
64+
private void WriteObjectCreation(object o) {
65+
var type = writeNew(o);
66+
var preferredOrder = preferredPropertyOrders.FirstOrDefault(x => x.Item1.IsAssignableFrom(o.GetType())).Item2;
67+
var properties = type.GetProperties().Where(x => {
68+
if (x.Name.In("CanReduce", "TailCall", "CanReduce", "IsLifted", "IsLiftedToNull", "ArgumentCount")) { return false; }
69+
if (x.Name == "NodeType" && hideNodeType.Contains(type)) { return false; }
70+
return true;
71+
}).ToList();
72+
73+
if (properties.None()) {
74+
if (language == CSharp) { Write("()"); }
6775
return;
6876
}
6977

70-
Write(
71-
language == CSharp ? "new " :
72-
language == VisualBasic ? "New " :
73-
""
74-
);
78+
if (language == VisualBasic) { Write(" With"); }
79+
Write(" {");
80+
Indent();
81+
WriteEOL();
7582

76-
var type = o.GetType().BaseTypes(false, true).First(x => x.IsPublic && !x.IsInterface);
77-
var typename = type.FriendlyName(language);
78-
Write(typename);
79-
80-
if (o is IEnumerable enumerable) {
81-
// use collection initializer
82-
bool hasItems = false;
83-
enumerable.Cast<object>().ForEach((x, index) => {
84-
if (index == 0) {
85-
hasItems = true;
86-
if (language == VisualBasic) { Write(" From"); }
87-
Write(" {");
88-
Indent();
89-
} else if (index > 0) {
90-
Write(",");
91-
}
83+
properties.OrderBy(x => {
84+
if (x.Name.In("NodeType", "Type")) { return -2; }
85+
if (preferredOrder == null) { return -1; }
86+
var indexOf = Array.IndexOf(preferredOrder, x.Name);
87+
if (indexOf == -1) { return 1000; }
88+
return indexOf;
89+
})
90+
.ThenBy(x => x.Name)
91+
.Select(x => {
92+
object value;
93+
try {
94+
value = x.GetValue(o);
95+
} catch (Exception ex) {
96+
value = ex.Message;
97+
}
98+
return (x, value);
99+
})
100+
.WhereT((_, value) => {
101+
if (value == null) { return false; }
102+
if (value is IEnumerable seq && seq.None()) { return false; }
103+
return true;
104+
})
105+
.ForEachT((x, value, index) => {
106+
if (index > 0) {
107+
Write(",");
92108
WriteEOL();
93-
WriteObjectCreation(x, depth+1);
94-
});
95-
if (hasItems) {
96-
WriteEOL(true);
97-
Write("}");
98109
}
99-
} else {
100-
//use object initializer
101-
var preferredOrder = preferredPropertyOrders.FirstOrDefault(x => x.Item1.IsAssignableFrom(o.GetType())).Item2;
102-
var properties = type.GetProperties().Where(x => {
103-
if (x.Name.In("CanReduce", "TailCall", "CanReduce", "IsLifted", "IsLiftedToNull", "ArgumentCount")) { return false; }
104-
if (x.Name == "NodeType" && hideNodeType.Contains(type)) { return false; }
105-
return true;
106-
}).ToList();
107-
if (properties.None()) {
108-
if (language == CSharp) { Write("()"); }
109-
return;
110+
if (language == VisualBasic) { Write("."); }
111+
Write(x.Name);
112+
Write(" = ");
113+
114+
if (x.PropertyType.InheritsFromOrImplementsAny(PropertyTypes)) {
115+
WriteCollection(value as IEnumerable, x.Name);
116+
} else if (x.PropertyType.InheritsFromOrImplementsAny(NodeTypes)) {
117+
WriteNode(x.Name, value);
118+
} else {
119+
Write(RenderLiteral(value, language));
110120
}
121+
});
111122

112-
if (language == VisualBasic) { Write(" With"); }
113-
Write(" {");
114-
Indent();
115-
WriteEOL();
116-
117-
var values = properties
118-
.Where(x => x.Name.NotIn("TailCall","CanReduce", "IsLifted", "IsLiftedToNull"))
119-
.OrderBy(x => {
120-
if (x.Name.In("NodeType", "Type")) { return -2; }
121-
if (preferredOrder == null) { return -1; }
122-
var indexOf = Array.IndexOf(preferredOrder, x.Name);
123-
if (indexOf == -1) { return 1000; }
124-
return indexOf;
125-
}).ThenBy(x => x.Name)
126-
.Select(x => {
127-
object value;
128-
try {
129-
value = x.GetValue(o);
130-
} catch (Exception ex) {
131-
value = ex.Message;
132-
}
133-
return (x, value);
134-
})
135-
.WhereT((instance, value) => {
136-
if (value == null) { return false; }
137-
if (!(value is IEnumerable enumerable1)) { return true; }
138-
if (enumerable1.None()) { return false; }
139-
return true;
140-
})
141-
.ForEachT((x, value, index) => {
142-
if (index > 0) {
143-
Write(",");
144-
WriteEOL();
145-
}
146-
if (language == VisualBasic) { Write("."); }
147-
Write(x.Name);
148-
Write(" = ");
149-
150-
var (success, literal) = TryRenderLiteral(value, language);
151-
if (success) {
152-
Write(literal);
153-
return;
154-
}
155-
if (value.GetType() == o.GetType()) {
156-
Write("<potential recursion>");
157-
return;
158-
}
159-
160-
WriteObjectCreation(value, depth+1);
161-
});
162-
163-
WriteEOL(true);
164-
Write("}");
123+
WriteEOL(true);
124+
Write("}");
125+
}
126+
127+
private void WriteCollection(IEnumerable seq, string pathSegment) {
128+
writeNew(seq);
129+
var items = seq.Cast<object>().ToList();
130+
if (items.None() ) {
131+
if (language==CSharp) { Write("()"); }
132+
return;
165133
}
134+
if (language == VisualBasic) { Write(" From"); }
135+
Write(" {");
136+
Indent();
137+
WriteEOL();
138+
WriteNodes(pathSegment, items, true);
139+
WriteEOL(true);
140+
Write("}");
141+
}
142+
143+
private Type writeNew(object o) {
144+
Write(
145+
language == CSharp ? "new " :
146+
language == VisualBasic ? "New " :
147+
""
148+
);
149+
var t = o.GetType().BaseTypes(false, true).First(x => x.IsPublic && !x.IsInterface);
150+
Write(t.FriendlyName(language));
151+
return t;
166152
}
167153

168154
protected override void WriteBinary(BinaryExpression expr) => WriteObjectCreation(expr);
@@ -194,18 +180,22 @@ private void WriteObjectCreation(object o, int depth=0) {
194180
protected override void WriteSwitchCase(SwitchCase switchCase) => WriteObjectCreation(switchCase);
195181
protected override void WriteCatchBlock(CatchBlock catchBlock) => WriteObjectCreation(catchBlock);
196182
protected override void WriteLabelTarget(LabelTarget labelTarget) => WriteObjectCreation(labelTarget);
197-
protected override void WriteBinaryOperationBinder(BinaryOperationBinder binaryOperationBinder, IList<Expression> args) => WriteObjectCreation(binaryOperationBinder);
198-
protected override void WriteConvertBinder(ConvertBinder convertBinder, IList<Expression> args) => WriteObjectCreation(convertBinder);
199-
protected override void WriteCreateInstanceBinder(CreateInstanceBinder createInstanceBinder, IList<Expression> args) => WriteObjectCreation(createInstanceBinder);
200-
protected override void WriteDeleteIndexBinder(DeleteIndexBinder deleteIndexBinder, IList<Expression> args) => WriteObjectCreation(deleteIndexBinder);
201-
protected override void WriteDeleteMemberBinder(DeleteMemberBinder deleteMemberBinder, IList<Expression> args) => WriteObjectCreation(deleteMemberBinder);
202-
protected override void WriteGetIndexBinder(GetIndexBinder getIndexBinder, IList<Expression> args) => WriteObjectCreation(getIndexBinder);
203-
protected override void WriteGetMemberBinder(GetMemberBinder getMemberBinder, IList<Expression> args) => WriteObjectCreation(getMemberBinder);
204-
protected override void WriteInvokeBinder(InvokeBinder invokeBinder, IList<Expression> args) => WriteObjectCreation(invokeBinder);
205-
protected override void WriteInvokeMemberBinder(InvokeMemberBinder invokeMemberBinder, IList<Expression> args) => WriteObjectCreation(invokeMemberBinder);
206-
protected override void WriteSetIndexBinder(SetIndexBinder setIndexBinder, IList<Expression> args) => WriteObjectCreation(setIndexBinder);
207-
protected override void WriteSetMemberBinder(SetMemberBinder setMemberBinder, IList<Expression> args) => WriteObjectCreation(setMemberBinder);
208-
protected override void WriteUnaryOperationBinder(UnaryOperationBinder unaryOperationBinder, IList<Expression> args) => WriteObjectCreation(unaryOperationBinder);
183+
184+
protected override void WriteDynamic(DynamicExpression expr) => WriteObjectCreation(expr);
185+
186+
protected override void WriteBinaryOperationBinder(BinaryOperationBinder binaryOperationBinder, IList<Expression> args) => throw new NotImplementedException();
187+
protected override void WriteConvertBinder(ConvertBinder convertBinder, IList<Expression> args) => throw new NotImplementedException();
188+
protected override void WriteCreateInstanceBinder(CreateInstanceBinder createInstanceBinder, IList<Expression> args) => throw new NotImplementedException();
189+
protected override void WriteDeleteIndexBinder(DeleteIndexBinder deleteIndexBinder, IList<Expression> args) => throw new NotImplementedException();
190+
protected override void WriteDeleteMemberBinder(DeleteMemberBinder deleteMemberBinder, IList<Expression> args) => throw new NotImplementedException();
191+
protected override void WriteGetIndexBinder(GetIndexBinder getIndexBinder, IList<Expression> args) => throw new NotImplementedException();
192+
protected override void WriteGetMemberBinder(GetMemberBinder getMemberBinder, IList<Expression> args) => throw new NotImplementedException();
193+
protected override void WriteInvokeBinder(InvokeBinder invokeBinder, IList<Expression> args) => throw new NotImplementedException();
194+
protected override void WriteInvokeMemberBinder(InvokeMemberBinder invokeMemberBinder, IList<Expression> args) => throw new NotImplementedException();
195+
protected override void WriteSetIndexBinder(SetIndexBinder setIndexBinder, IList<Expression> args) => throw new NotImplementedException();
196+
protected override void WriteSetMemberBinder(SetMemberBinder setMemberBinder, IList<Expression> args) => throw new NotImplementedException();
197+
protected override void WriteUnaryOperationBinder(UnaryOperationBinder unaryOperationBinder, IList<Expression> args) => throw new NotImplementedException();
198+
209199
protected override void WriteParameterDeclarationImpl(ParameterExpression prm) => WriteObjectCreation(prm);
210200
}
211201
}

Shared/WriterBase.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ protected void WriteNodes<T>(string pathSegment, IEnumerable<T> items, string de
352352
protected abstract void WriteSwitchCase(SwitchCase switchCase);
353353
protected abstract void WriteCatchBlock(CatchBlock catchBlock);
354354
protected abstract void WriteLabelTarget(LabelTarget labelTarget);
355-
//protected abstract void WriteIArgumentProvider(IArgumentProvider iArgumentProvider);
356355

357356
// binders
358357
protected abstract void WriteBinaryOperationBinder(BinaryOperationBinder binaryOperationBinder, IList<Expression> args);

Tests.DotNetCore/Runner.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
using Pather.CSharp;
77
using ExpressionToString.Util;
88
using System;
9-
using System.IO;
109
using static ExpressionToString.Tests.Functions;
11-
using static ExpressionToString.Util.Functions;
1210
using static System.Environment;
1311

1412
namespace ExpressionToString.Tests {
@@ -110,15 +108,15 @@ public static void RunTest(object o, string objectName, ExpectedDataFixture allE
110108
}
111109

112110
var selector =
113-
formatter == FactoryMethods ? x => x :
111+
formatter == ObjectNotation ? x => x :
114112
(Func<string,string>)(x => x.Replace("_0", ""));
115113

116114
var paths = pathSpans.Keys.Select(selector).ToHashSet();
117115

118116
return (formatter, (singleResult, paths));
119117
}).ToDictionary();
120118

121-
var expectedPaths = actual[FactoryMethods].paths;
119+
var expectedPaths = actual[ObjectNotation].paths;
122120

123121
// check that all the expected paths can resolve against the original object
124122
var resolver = new Resolver();
@@ -132,9 +130,8 @@ public static void RunTest(object o, string objectName, ExpectedDataFixture allE
132130
Assert.Equal(expected, actualSingle);
133131

134132
if (formatter != FactoryMethods) { // we're using the paths of the FactoryMethodsFormatter as reference paths
135-
var referencePaths = actual[FactoryMethods].paths;
136133
var actualPaths = actual[formatter].paths;
137-
Assert.True(referencePaths.IsSupersetOf(actualPaths));
134+
Assert.True(expectedPaths.IsSupersetOf(actualPaths));
138135
}
139136
}
140137
}

0 commit comments

Comments
 (0)