Skip to content

Commit aef3132

Browse files
committed
Visualizer -- resolve UnaryExpression and BinaryExpression factory methods based on NodeType
1 parent c128469 commit aef3132

4 files changed

Lines changed: 148 additions & 140 deletions

File tree

Shared/FactoryMethodsFormatter.cs

Lines changed: 2 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Linq.Expressions;
77
using static ExpressionToString.Globals;
88
using static ExpressionToString.Util.Functions;
9-
using static System.Linq.Expressions.ExpressionType;
109
using static ExpressionToString.FormatterNames;
1110
using static System.Linq.Expressions.Expression;
1211
using System.Collections;
@@ -145,101 +144,13 @@ private void WriteMethodCall(Expression<Action> expr) {
145144
WriteMethodCall(callExpr.Method.Name, pairs.ToList());
146145
}
147146

148-
static Dictionary<ExpressionType, string> binaryUnaryMethods = new Dictionary<ExpressionType, string>() {
149-
{ ExpressionType.Add, "Add" },
150-
{ ExpressionType.AddAssign, "AddAssign" },
151-
{ ExpressionType.AddAssignChecked, "AddAssignChecked" },
152-
{ ExpressionType.AddChecked, "AddChecked" },
153-
{ ExpressionType.And, "And" },
154-
{ ExpressionType.AndAlso, "AndAlso" },
155-
{ ExpressionType.AndAssign, "AndAssign" },
156-
{ ExpressionType.ArrayIndex, "ArrayIndex" },
157-
{ ExpressionType.ArrayLength, "ArrayLength" },
158-
{ ExpressionType.Assign, "Assign" },
159-
{ ExpressionType.Block, "Block" },
160-
{ ExpressionType.Call, "Call" },
161-
{ ExpressionType.Coalesce, "Coalesce" },
162-
{ Conditional, "Conditional" },
163-
{ ExpressionType.Constant, "Constant" },
164-
{ ExpressionType.Convert, "Convert" },
165-
{ ExpressionType.ConvertChecked, "ConvertChecked" },
166-
{ ExpressionType.DebugInfo, "DebugInfo" },
167-
{ ExpressionType.Decrement, "Decrement" },
168-
{ ExpressionType.Default, "Default" },
169-
{ ExpressionType.Divide, "Divide" },
170-
{ ExpressionType.DivideAssign, "DivideAssign" },
171-
{ ExpressionType.Dynamic, "Dynamic" },
172-
{ ExpressionType.Equal, "Equal" },
173-
{ ExpressionType.ExclusiveOr, "ExclusiveOr" },
174-
{ ExpressionType.ExclusiveOrAssign, "ExclusiveOrAssign" },
175-
{ Extension, "Extension" },
176-
{ ExpressionType.Goto, "Goto" },
177-
{ ExpressionType.GreaterThan, "GreaterThan" },
178-
{ ExpressionType.GreaterThanOrEqual, "GreaterThanOrEqual" },
179-
{ ExpressionType.Increment, "Increment" },
180-
{ Index, "Index" },
181-
{ ExpressionType.Invoke, "Invoke" },
182-
{ ExpressionType.IsFalse, "IsFalse" },
183-
{ ExpressionType.IsTrue, "IsTrue" },
184-
{ ExpressionType.Label, "Label" },
185-
{ ExpressionType.Lambda, "Lambda" },
186-
{ ExpressionType.LeftShift, "LeftShift" },
187-
{ ExpressionType.LeftShiftAssign, "LeftShiftAssign" },
188-
{ ExpressionType.LessThan, "LessThan" },
189-
{ ExpressionType.LessThanOrEqual, "LessThanOrEqual" },
190-
{ ExpressionType.ListInit, "ListInit" },
191-
{ ExpressionType.Loop, "Loop" },
192-
{ MemberAccess, "MemberAccess" },
193-
{ ExpressionType.MemberInit, "MemberInit" },
194-
{ ExpressionType.Modulo, "Modulo" },
195-
{ ExpressionType.ModuloAssign, "ModuloAssign" },
196-
{ ExpressionType.Multiply, "Multiply" },
197-
{ ExpressionType.MultiplyAssign, "MultiplyAssign" },
198-
{ ExpressionType.MultiplyAssignChecked, "MultiplyAssignChecked" },
199-
{ ExpressionType.MultiplyChecked, "MultiplyChecked" },
200-
{ ExpressionType.Negate, "Negate" },
201-
{ ExpressionType.NegateChecked, "NegateChecked" },
202-
{ ExpressionType.New, "New" },
203-
{ ExpressionType.NewArrayBounds, "NewArrayBounds" },
204-
{ ExpressionType.NewArrayInit, "NewArrayInit" },
205-
{ ExpressionType.Not, "Not" },
206-
{ ExpressionType.NotEqual, "NotEqual" },
207-
{ ExpressionType.OnesComplement, "OnesComplement" },
208-
{ ExpressionType.Or, "Or" },
209-
{ ExpressionType.OrAssign, "OrAssign" },
210-
{ ExpressionType.OrElse, "OrElse" },
211-
{ ExpressionType.Parameter, "Parameter" },
212-
{ ExpressionType.PostDecrementAssign, "PostDecrementAssign" },
213-
{ ExpressionType.PostIncrementAssign, "PostIncrementAssign" },
214-
{ ExpressionType.Power, "Power" },
215-
{ ExpressionType.PowerAssign, "PowerAssign" },
216-
{ ExpressionType.PreDecrementAssign, "PreDecrementAssign" },
217-
{ ExpressionType.PreIncrementAssign, "PreIncrementAssign" },
218-
{ ExpressionType.Quote, "Quote" },
219-
{ ExpressionType.RightShift, "RightShift" },
220-
{ ExpressionType.RightShiftAssign, "RightShiftAssign" },
221-
{ ExpressionType.RuntimeVariables, "RuntimeVariables" },
222-
{ ExpressionType.Subtract, "Subtract" },
223-
{ ExpressionType.SubtractAssign, "SubtractAssign" },
224-
{ ExpressionType.SubtractAssignChecked, "SubtractAssignChecked" },
225-
{ ExpressionType.SubtractChecked, "SubtractChecked" },
226-
{ ExpressionType.Switch, "Switch" },
227-
{ ExpressionType.Throw, "Throw" },
228-
{ Try, "Try" },
229-
{ ExpressionType.TypeAs, "TypeAs" },
230-
{ ExpressionType.TypeEqual, "TypeEqual" },
231-
{ ExpressionType.TypeIs, "TypeIs" },
232-
{ ExpressionType.UnaryPlus, "UnaryPlus" },
233-
{ ExpressionType.Unbox, "Unbox" },
234-
};
235-
236147
protected override void WriteBinary(BinaryExpression expr) {
237-
if (!binaryUnaryMethods.TryGetValue(expr.NodeType, out var name)) { throw new InvalidOperationException($"Method not found for '{expr.NodeType}' node type"); }
148+
if (!BinaryUnaryMethods.TryGetValue(expr.NodeType, out var name)) { throw new InvalidOperationException($"Method not found for '{expr.NodeType}' node type"); }
238149
WriteMethodCall(name, new[] { ("Left", expr.Left), ("Right", expr.Right) });
239150
}
240151

241152
protected override void WriteUnary(UnaryExpression expr) {
242-
if (!binaryUnaryMethods.TryGetValue(expr.NodeType, out var name)) { throw new InvalidOperationException($"Method not found for '{expr.NodeType}' node type"); }
153+
if (!BinaryUnaryMethods.TryGetValue(expr.NodeType, out var name)) { throw new InvalidOperationException($"Method not found for '{expr.NodeType}' node type"); }
243154
switch (expr.NodeType) {
244155
case ExpressionType.Convert:
245156
case ExpressionType.ConvertChecked:

Shared/Util/Globals.cs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System.Linq;
55
using System.Linq.Expressions;
66
using System.Reflection;
7-
using System.Runtime.CompilerServices;
7+
using static System.Linq.Expressions.ExpressionType;
88

99
namespace ExpressionToString {
1010
public static class FormatterNames {
@@ -47,5 +47,94 @@ static Globals() {
4747
};
4848

4949
public static List<Type> PropertyTypes = NodeTypes.Select(x => typeof(IEnumerable<>).MakeGenericType(x)).ToList();
50+
51+
public static Dictionary<ExpressionType, string> BinaryUnaryMethods = new Dictionary<ExpressionType, string>() {
52+
{ Add, "Add" },
53+
{ AddAssign, "AddAssign" },
54+
{ AddAssignChecked, "AddAssignChecked" },
55+
{ AddChecked, "AddChecked" },
56+
{ And, "And" },
57+
{ AndAlso, "AndAlso" },
58+
{ AndAssign, "AndAssign" },
59+
{ ArrayIndex, "ArrayIndex" },
60+
{ ArrayLength, "ArrayLength" },
61+
{ Assign, "Assign" },
62+
{ Block, "Block" },
63+
{ Call, "Call" },
64+
{ Coalesce, "Coalesce" },
65+
{ Conditional, "Conditional" },
66+
{ Constant, "Constant" },
67+
{ ExpressionType.Convert, "Convert" },
68+
{ ConvertChecked, "ConvertChecked" },
69+
{ DebugInfo, "DebugInfo" },
70+
{ Decrement, "Decrement" },
71+
{ Default, "Default" },
72+
{ Divide, "Divide" },
73+
{ DivideAssign, "DivideAssign" },
74+
{ Dynamic, "Dynamic" },
75+
{ Equal, "Equal" },
76+
{ ExclusiveOr, "ExclusiveOr" },
77+
{ ExclusiveOrAssign, "ExclusiveOrAssign" },
78+
{ Extension, "Extension" },
79+
{ Goto, "Goto" },
80+
{ GreaterThan, "GreaterThan" },
81+
{ GreaterThanOrEqual, "GreaterThanOrEqual" },
82+
{ Increment, "Increment" },
83+
{ Index, "Index" },
84+
{ Invoke, "Invoke" },
85+
{ IsFalse, "IsFalse" },
86+
{ IsTrue, "IsTrue" },
87+
{ Label, "Label" },
88+
{ Lambda, "Lambda" },
89+
{ LeftShift, "LeftShift" },
90+
{ LeftShiftAssign, "LeftShiftAssign" },
91+
{ LessThan, "LessThan" },
92+
{ LessThanOrEqual, "LessThanOrEqual" },
93+
{ ListInit, "ListInit" },
94+
{ Loop, "Loop" },
95+
{ MemberAccess, "MemberAccess" },
96+
{ MemberInit, "MemberInit" },
97+
{ Modulo, "Modulo" },
98+
{ ModuloAssign, "ModuloAssign" },
99+
{ Multiply, "Multiply" },
100+
{ MultiplyAssign, "MultiplyAssign" },
101+
{ MultiplyAssignChecked, "MultiplyAssignChecked" },
102+
{ MultiplyChecked, "MultiplyChecked" },
103+
{ Negate, "Negate" },
104+
{ NegateChecked, "NegateChecked" },
105+
{ New, "New" },
106+
{ NewArrayBounds, "NewArrayBounds" },
107+
{ NewArrayInit, "NewArrayInit" },
108+
{ Not, "Not" },
109+
{ NotEqual, "NotEqual" },
110+
{ OnesComplement, "OnesComplement" },
111+
{ Or, "Or" },
112+
{ OrAssign, "OrAssign" },
113+
{ OrElse, "OrElse" },
114+
{ Parameter, "Parameter" },
115+
{ PostDecrementAssign, "PostDecrementAssign" },
116+
{ PostIncrementAssign, "PostIncrementAssign" },
117+
{ Power, "Power" },
118+
{ PowerAssign, "PowerAssign" },
119+
{ PreDecrementAssign, "PreDecrementAssign" },
120+
{ PreIncrementAssign, "PreIncrementAssign" },
121+
{ Quote, "Quote" },
122+
{ RightShift, "RightShift" },
123+
{ RightShiftAssign, "RightShiftAssign" },
124+
{ RuntimeVariables, "RuntimeVariables" },
125+
{ Subtract, "Subtract" },
126+
{ SubtractAssign, "SubtractAssign" },
127+
{ SubtractAssignChecked, "SubtractAssignChecked" },
128+
{ SubtractChecked, "SubtractChecked" },
129+
{ Switch, "Switch" },
130+
{ Throw, "Throw" },
131+
{ Try, "Try" },
132+
{ TypeAs, "TypeAs" },
133+
{ TypeEqual, "TypeEqual" },
134+
{ TypeIs, "TypeIs" },
135+
{ UnaryPlus, "UnaryPlus" },
136+
{ Unbox, "Unbox" },
137+
};
138+
50139
}
51140
}

Visualizer.Shared/VisualizerData.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,16 @@ internal ExpressionNodeData(object o, (string aggregatePath, string pathFromPare
288288
baseTypes[o.GetType()] = _baseTypes;
289289
}
290290

291-
var publicType = o.GetType().BaseTypes(false, true).FirstOrDefault(x => !x.IsInterface && x.IsPublic);
292-
factoryMethods.TryGetValue(publicType, out _factoryMethodNames);
291+
string factoryMethodName = null;
292+
if (o is BinaryExpression || o is UnaryExpression) {
293+
BinaryUnaryMethods.TryGetValue(((Expression)o).NodeType, out factoryMethodName);
294+
}
295+
if (factoryMethodName.IsNullOrWhitespace()) {
296+
var publicType = o.GetType().BaseTypes(false, true).FirstOrDefault(x => !x.IsInterface && x.IsPublic);
297+
factoryMethods.TryGetValue(publicType, out _factoryMethodNames);
298+
} else {
299+
_factoryMethodNames = new[] { factoryMethodName };
300+
}
293301
}
294302

295303
private static List<(Type, string[])> preferredPropertyOrders = new List<(Type, string[])> {

_visualizerTests/Program.cs

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ static void Main(string[] args) {
5656
//var expr = foo.GetExpression();
5757

5858
//var i = 5;
59-
Expression<Func<int>> expr1 = () => 5;
60-
Expression<Func<Expression<Func<int>>>> expr = () => expr1;
59+
//Expression<Func<int>> expr1 = () => 5;
60+
//Expression<Func<Expression<Func<int>>>> expr = () => expr1;
6161

6262
//Expression<Func<string>> expr = Lambda<Func<string>>(
6363
// MakeMemberAccess(
@@ -86,50 +86,50 @@ static void Main(string[] args) {
8686
//IQueryable<Person> personSource = null;
8787
//Expression<Func<Person, bool>> expr = person => person.LastName.StartsWith("A");
8888

89-
//var hour = Variable(typeof(int), "hour");
90-
//var msg = Variable(typeof(string), "msg");
91-
//var block = Block(
92-
// // specify the variables available within the block
93-
// new[] { hour, msg },
94-
// // hour =
95-
// Assign(hour,
96-
// // DateTime.Now.Hour
97-
// MakeMemberAccess(
98-
// MakeMemberAccess(
99-
// null,
100-
// typeof(DateTime).GetMember("Now").Single()
101-
// ),
102-
// typeof(DateTime).GetMember("Hour").Single()
103-
// )
104-
// ),
105-
// // if ( ... ) { ... } else { ... }
106-
// IfThenElse(
107-
// // ... && ...
108-
// AndAlso(
109-
// // hour >= 6
110-
// GreaterThanOrEqual(
111-
// hour,
112-
// Constant(6)
113-
// ),
114-
// // hour <= 18
115-
// LessThanOrEqual(
116-
// hour,
117-
// Constant(18)
118-
// )
119-
// ),
120-
// // msg = "Good day"
121-
// Assign(msg, Constant("Good day")),
122-
// // msg = Good night"
123-
// Assign(msg, Constant("Good night"))
124-
// ),
125-
// // Console.WriteLine(msg);
126-
// Call(
127-
// typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }),
128-
// msg
129-
// ),
130-
// hour
131-
//);
132-
//Expression<Action> expr = Lambda<Action>(block);
89+
var hour = Variable(typeof(int), "hour");
90+
var msg = Variable(typeof(string), "msg");
91+
var block = Block(
92+
// specify the variables available within the block
93+
new[] { hour, msg },
94+
// hour =
95+
Assign(hour,
96+
// DateTime.Now.Hour
97+
MakeMemberAccess(
98+
MakeMemberAccess(
99+
null,
100+
typeof(DateTime).GetMember("Now").Single()
101+
),
102+
typeof(DateTime).GetMember("Hour").Single()
103+
)
104+
),
105+
// if ( ... ) { ... } else { ... }
106+
IfThenElse(
107+
// ... && ...
108+
AndAlso(
109+
// hour >= 6
110+
GreaterThanOrEqual(
111+
hour,
112+
Constant(6)
113+
),
114+
// hour <= 18
115+
LessThanOrEqual(
116+
hour,
117+
Constant(18)
118+
)
119+
),
120+
// msg = "Good day"
121+
Assign(msg, Constant("Good day")),
122+
// msg = Good night"
123+
Assign(msg, Constant("Good night"))
124+
),
125+
// Console.WriteLine(msg);
126+
Call(
127+
typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }),
128+
msg
129+
),
130+
hour
131+
);
132+
Expression<Action> expr = Lambda<Action>(block);
133133

134134
//var constant = Constant(new List<int>());
135135
//Expression expr = Or(

0 commit comments

Comments
 (0)