diff --git a/src/ExpressionTranslator/ExpressionTranslator.cs b/src/ExpressionTranslator/ExpressionTranslator.cs index 61a2ca03..6c219f86 100644 --- a/src/ExpressionTranslator/ExpressionTranslator.cs +++ b/src/ExpressionTranslator/ExpressionTranslator.cs @@ -16,7 +16,7 @@ namespace ExpressionDebugger { public class ExpressionTranslator : ExpressionVisitor { - private const int Tabsize = 4; + private const int TabSize = 4; private StringWriter _writer; private int _indentLevel; private List? _appendWriters; @@ -49,19 +49,18 @@ public ExpressionTranslator(TypeDefinitions? definitions = null) private void ResetIndentLevel() { _indentLevel = 0; - if (Definitions?.TypeName != null) - { + if (Definitions?.TypeName == null) return; + + _indentLevel++; + if (Definitions.Namespace != null) _indentLevel++; - if (Definitions.Namespace != null) - _indentLevel++; - } } public static ExpressionTranslator Create(Expression node, ExpressionDefinitions? definitions = null) { var translator = new ExpressionTranslator(definitions); if (node.NodeType == ExpressionType.Lambda) - translator.VisitLambda((LambdaExpression)node, + translator.VisitLambda((LambdaExpression)node, definitions?.IsExpression == true ? LambdaType.PublicLambda : LambdaType.PublicMethod, definitions?.MethodName, definitions?.IsInternal ?? false); @@ -239,7 +238,7 @@ private void WriteLine() { _writer.WriteLine(); - var spaceCount = _indentLevel * Tabsize; + var spaceCount = _indentLevel * TabSize; _writer.Write(new string(' ', spaceCount)); } @@ -385,6 +384,7 @@ protected override Expression VisitBinary(BinaryExpression node) VisitGroup(node.Left, node.NodeType); Write(" = "); } + Write(Translate(typeof(Math)), ".Pow("); left = Visit(node.Left)!; Write(", "); @@ -404,6 +404,7 @@ protected override Expression VisitBinary(BinaryExpression node) private byte? _nilCtx; private byte[]? _nil; private int _nilIndex; + private string TranslateNullable(Type type, byte? nullableContext, byte[]? nullable) { try @@ -419,6 +420,7 @@ private string TranslateNullable(Type type, byte? nullableContext, byte[]? nulla _nil = null; } } + public string Translate(Type type) { var refNullable = !type.GetTypeInfo().IsValueType && @@ -426,6 +428,7 @@ public string Translate(Type type) var typeName = TranslateInner(type); return refNullable ? $"{typeName}?" : typeName; } + private string TranslateInner(Type type) { if (type == typeof(bool)) @@ -487,13 +490,13 @@ private string TranslateInner(Type type) if (Definitions?.PrintFullTypeName != true && !string.IsNullOrEmpty(type.Namespace)) _usings.Add(type.Namespace); } - else if (!this.TypeNames.TryGetValue(type, out name)) + else if (!TypeNames.TryGetValue(type, out name)) { name = GetTypeName(type); if (Definitions?.PrintFullTypeName != true) { - var count = this.TypeNames.Count(kvp => GetTypeName(kvp.Key) == name); + var count = TypeNames.Count(kvp => GetTypeName(kvp.Key) == name); if (count > 0) { // NOTE: type alias cannot solve all name conflicted case, user should use PrintFullTypeName @@ -506,7 +509,8 @@ private string TranslateInner(Type type) else if (!string.IsNullOrEmpty(type.Namespace)) _usings.Add(type.Namespace); } - this.TypeNames.Add(type, name); + + TypeNames.Add(type, name); } return name; @@ -531,8 +535,8 @@ private string GetTypeName(Type type) private string GetSingleTypeName(Type type) { - var name = type.DeclaringType == null && Definitions?.PrintFullTypeName == true - ? type.FullName! + var name = type.DeclaringType == null && Definitions?.PrintFullTypeName == true + ? type.FullName! : type.Name; if (!type.GetTypeInfo().IsGenericType) { @@ -542,13 +546,12 @@ private string GetSingleTypeName(Type type) var index = name.IndexOf('`'); if (index >= 0) name = name.Substring(0, index); - if (type.GetTypeInfo().IsGenericTypeDefinition) - { - var typeArgs = type.GetGenericArguments(); - return name + "<" + new string(',', typeArgs.Length - 1) + ">"; - } - return name + "<" + string.Join(", ", type.GetGenericArguments().Select(Translate)) + ">"; + if (!type.GetTypeInfo().IsGenericTypeDefinition) + return $"{name}<{string.Join(", ", type.GetGenericArguments().Select(Translate))}>"; + + var typeArgs = type.GetGenericArguments(); + return name + "<" + new string(',', typeArgs.Length - 1) + ">"; } private static bool IsInline(Expression node) @@ -599,14 +602,18 @@ private Expression VisitMultiline(Expression node, bool shouldReturn) private Expression VisitBody(Expression node, bool shouldReturn = false) { - if (node.NodeType == ExpressionType.Block) - return VisitBlock((BlockExpression)node, shouldReturn); - - if (node.NodeType == ExpressionType.Default && node.Type == typeof(void)) - return node; - - var lines = VisitBlockBody(new List { node }, shouldReturn); - return Expression.Block(lines); + switch (node.NodeType) + { + case ExpressionType.Block: + return VisitBlock((BlockExpression)node, shouldReturn); + case ExpressionType.Default when node.Type == typeof(void): + return node; + default: + { + var lines = VisitBlockBody(new List { node }, shouldReturn); + return Expression.Block(lines); + } + } } private IEnumerable VisitBlockBody(IList exprs, bool shouldReturn) @@ -635,8 +642,10 @@ private IEnumerable VisitBlockBody(IList exprs, bool sho { next = VisitMultiline(expr, shouldReturn && i == last); } + lines.Add(next); } + return lines; } @@ -663,8 +672,10 @@ private Expression VisitBlock(BlockExpression node, bool shouldReturn) arg = VisitNextLine(Translate(variable.Type) + " ", variable, ";"); hasDeclaration = true; } + list.Add((ParameterExpression)arg); } + if (hasDeclaration) WriteLine(); @@ -684,6 +695,7 @@ private CatchBlock VisitCatchBlock(CatchBlock node, bool shouldReturn) { Visit(" ", node.Variable); } + Write(")"); var filter = node.Filter; @@ -691,6 +703,7 @@ private CatchBlock VisitCatchBlock(CatchBlock node, bool shouldReturn) { filter = Visit(" when (", filter, ")"); } + Indent(); var body = VisitBody(node.Body, shouldReturn); Outdent(); @@ -706,19 +719,14 @@ protected override CatchBlock VisitCatchBlock(CatchBlock node) private Expression VisitConditional(ConditionalExpression node, bool shouldReturn) { - if (IsInline(node)) - { - Expression test = VisitGroup(node.Test, node.NodeType); - Write(" ? "); - Expression ifTrue = VisitGroup(node.IfTrue, node.NodeType); - Write(" : "); - Expression ifFalse = VisitGroup(node.IfFalse, node.NodeType); - return node.Update(test, ifTrue, ifFalse); - } - else - { - return VisitConditionalBlock(node, shouldReturn); - } + if (!IsInline(node)) return VisitConditionalBlock(node, shouldReturn); + + var test = VisitGroup(node.Test, node.NodeType); + Write(" ? "); + var ifTrue = VisitGroup(node.IfTrue, node.NodeType); + Write(" : "); + var ifFalse = VisitGroup(node.IfFalse, node.NodeType); + return node.Update(test, ifTrue, ifFalse); } private Expression VisitConditionalBlock(ConditionalExpression node, bool shouldReturn, bool chain = false) @@ -727,8 +735,8 @@ private Expression VisitConditionalBlock(ConditionalExpression node, bool should var test = Visit(node.Test)!; Write(")"); Indent(); - Expression ifTrue = VisitBody(node.IfTrue, shouldReturn); - Expression ifFalse = node.IfFalse; + var ifTrue = VisitBody(node.IfTrue, shouldReturn); + var ifFalse = node.IfFalse; if (node.IfFalse.NodeType != ExpressionType.Default) { Outdent(); @@ -760,99 +768,106 @@ protected override Expression VisitConditional(ConditionalExpression node) private void WriteValue(object? value) { - if (value == null) + switch (value) { - Write("null"); - } - else if (value is string str) - { - if (str.IndexOf('\\') >= 0 || str.IndexOf('\n') >= 0 || str.IndexOf('"') >= 0) - { + case null: + Write("null"); + break; + case string str when str.IndexOf('\\') >= 0 || str.IndexOf('\n') >= 0 || str.IndexOf('"') >= 0: str = str.Replace(@"""", @""""""); Write($"@\"{str}\""); - } - else - { + break; + case string str: Write($"\"{str}\""); - } - } - else if (value is char c) - { - if (c == '\\') + break; + case char c when c == '\\': Write(@"'\\'"); - else if (c == '\'') + break; + case char c when c == '\'': Write(@"'\''"); - else + break; + case char c: Write($"'{c}'"); - } - else if (value is bool) - { - Write(value.ToString().ToLower()); - } - else if (value is Type t) - { - Write($"typeof({Translate(t)})"); - } - else if (value is int) - { - Write(value.ToString()); - } - else if (value is double d) - { - if (double.IsNaN(d)) + break; + case bool _: + Write(value.ToString().ToLower()); + break; + case Type t: + Write($"typeof({Translate(t)})"); + break; + case int _: + Write(value.ToString()); + break; + case double d when double.IsNaN(d): Write("double.NaN"); - else if (double.IsPositiveInfinity(d)) + break; + case double d when double.IsPositiveInfinity(d): Write("double.PositiveInfinity"); - else if (double.IsNegativeInfinity(d)) + break; + case double d when double.IsNegativeInfinity(d): Write("double.NegativeInfinity"); - else + break; + case double d: Write(d.ToString(CultureInfo.InvariantCulture), "d"); - } - else if (value is float f) - { - if (float.IsNaN(f)) + break; + case float f when float.IsNaN(f): Write("float.NaN"); - else if (float.IsPositiveInfinity(f)) + break; + case float f when float.IsPositiveInfinity(f): Write("float.PositiveInfinity"); - else if (float.IsNegativeInfinity(f)) + break; + case float f when float.IsNegativeInfinity(f): Write("float.NegativeInfinity"); - else + break; + case float f: Write(f.ToString(CultureInfo.InvariantCulture), "f"); - } - else if (value is decimal || value is long || value is uint || value is ulong) - { - Write(value.ToString(), GetLiteral(value.GetType())); - } - else if (value is byte || value is sbyte || value is short || value is ushort) - { - Write("((", Translate(value.GetType()), ")", value.ToString(), ")"); - } - else if (value.GetType().GetTypeInfo().IsEnum) - { - var name = Enum.GetName(value.GetType(), value); - if (name != null) - Write(Translate(value.GetType()), ".", name); - else - Write("(", Translate(value.GetType()), ")", value.ToString()); - } - else - { - var type = value.GetType(); - if (type.GetTypeInfo().IsValueType) + break; + case decimal _: + case long _: + case uint _: + case ulong _: + Write(value.ToString(), GetLiteral(value.GetType())); + break; + case byte _: + case sbyte _: + case short _: + case ushort _: + Write("((", Translate(value.GetType()), ")", value.ToString(), ")"); + break; + default: { - _defaults ??= new Dictionary(); - if (!_defaults.TryGetValue(type, out var def)) + if (value.GetType().GetTypeInfo().IsEnum) { - def = Activator.CreateInstance(type); - _defaults[type] = def; + var name = Enum.GetName(value.GetType(), value); + if (name != null) + Write(Translate(value.GetType()), ".", name); + else + Write("(", Translate(value.GetType()), ")", value.ToString()); } - if (value.Equals(def)) + else { - Write($"default({Translate(type)})"); - return; + var type = value.GetType(); + if (type.GetTypeInfo().IsValueType) + { + _defaults ??= new Dictionary(); + if (!_defaults.TryGetValue(type, out var def)) + { + def = Activator.CreateInstance(type); + _defaults[type] = def; + } + + if (value.Equals(def)) + { + Write($"default({Translate(type)})"); + return; + } + } + + Write(GetConstant(value)); } + + break; } - Write(GetConstant(value)); } } @@ -866,18 +881,17 @@ private static string GetLiteral(Type type) { if (type == typeof(decimal)) return "m"; - else if (type == typeof(long)) + if (type == typeof(long)) return "l"; - else if (type == typeof(uint)) + if (type == typeof(uint)) return "u"; - else if (type == typeof(ulong)) + if (type == typeof(ulong)) return "ul"; - else if (type == typeof(double)) + if (type == typeof(double)) return "d"; - else if (type == typeof(float)) + if (type == typeof(float)) return "f"; - else - return ""; + return ""; } protected override Expression VisitDefault(DefaultExpression node) @@ -896,91 +910,98 @@ private static Expression Update(DynamicExpression node, IEnumerable protected override Expression VisitDynamic(DynamicExpression node) { - if (node.Binder is ConvertBinder convert) - { - Write("(", Translate(convert.Type), ")"); - var expr = VisitGroup(node.Arguments[0], ExpressionType.Convert); - return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); - } - if (node.Binder is GetMemberBinder getMember) + switch (node.Binder) { - var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); - Write(".", getMember.Name); - return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); - } - if (node.Binder is SetMemberBinder setMember) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); - Write(".", setMember.Name, " = "); - var value = VisitGroup(node.Arguments[1], ExpressionType.Assign); - return Update(node, new[] { expr, value }.Concat(node.Arguments.Skip(2))); - } - if (node.Binder is DeleteMemberBinder deleteMember) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); - Write(".", deleteMember.Name, " = null"); - return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); - } - if (node.Binder is GetIndexBinder) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); - var args = VisitArguments("[", node.Arguments.Skip(1).ToList(), Visit, "]"); - return Update(node, new[] { expr }.Concat(args)); - } - if (node.Binder is SetIndexBinder) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); - var args = VisitArguments("[", node.Arguments.Skip(1).Take(node.Arguments.Count - 2).ToList(), Visit, "]"); - Write(" = "); - var value = VisitGroup(node.Arguments[node.Arguments.Count - 1], ExpressionType.Assign); - return Update(node, new[] { expr }.Concat(args).Concat(new[] { value })); - } - if (node.Binder is DeleteIndexBinder) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); - var args = VisitArguments("[", node.Arguments.Skip(1).ToList(), Visit, "]"); - Write(" = null"); - return Update(node, new[] { expr }.Concat(args)); - } - if (node.Binder is InvokeMemberBinder invokeMember) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); - Write(".", invokeMember.Name); - var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); - return Update(node, new[] { expr }.Concat(args)); - } - if (node.Binder is InvokeBinder) - { - var expr = VisitGroup(node.Arguments[0], ExpressionType.Invoke); - var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); - return Update(node, new[] { expr }.Concat(args)); - } - if (node.Binder is CreateInstanceBinder) - { - Write("new "); - var expr = VisitGroup(node.Arguments[0], ExpressionType.Invoke); - var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); - return Update(node, new[] { expr }.Concat(args)); - } - if (node.Binder is UnaryOperationBinder unary) - { - var expr = VisitUnary(node.Arguments[0], unary.Operation); - return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); - } - if (node.Binder is BinaryOperationBinder binary) - { - var left = VisitGroup(node.Arguments[0], node.NodeType); - Write(" ", Translate(binary.Operation), " "); - var right = VisitGroup(node.Arguments[1], node.NodeType, true); - return Update(node, new[] { left, right }.Concat(node.Arguments.Skip(2))); + case ConvertBinder convert: + { + Write("(", Translate(convert.Type), ")"); + var expr = VisitGroup(node.Arguments[0], ExpressionType.Convert); + return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); + } + case GetMemberBinder getMember: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); + Write(".", getMember.Name); + return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); + } + case SetMemberBinder setMember: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); + Write(".", setMember.Name, " = "); + var value = VisitGroup(node.Arguments[1], ExpressionType.Assign); + return Update(node, new[] { expr, value }.Concat(node.Arguments.Skip(2))); + } + case DeleteMemberBinder deleteMember: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); + Write(".", deleteMember.Name, " = null"); + return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); + } + case GetIndexBinder _: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); + var args = VisitArguments("[", node.Arguments.Skip(1).ToList(), Visit, "]"); + return Update(node, new[] { expr }.Concat(args)); + } + case SetIndexBinder _: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); + var args = VisitArguments("[", node.Arguments.Skip(1).Take(node.Arguments.Count - 2).ToList(), + Visit, + "]"); + Write(" = "); + var value = VisitGroup(node.Arguments[node.Arguments.Count - 1], ExpressionType.Assign); + return Update(node, new[] { expr }.Concat(args).Concat(new[] { value })); + } + case DeleteIndexBinder _: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.Index); + var args = VisitArguments("[", node.Arguments.Skip(1).ToList(), Visit, "]"); + Write(" = null"); + return Update(node, new[] { expr }.Concat(args)); + } + case InvokeMemberBinder invokeMember: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.MemberAccess); + Write(".", invokeMember.Name); + var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); + return Update(node, new[] { expr }.Concat(args)); + } + case InvokeBinder _: + { + var expr = VisitGroup(node.Arguments[0], ExpressionType.Invoke); + var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); + return Update(node, new[] { expr }.Concat(args)); + } + case CreateInstanceBinder _: + { + Write("new "); + var expr = VisitGroup(node.Arguments[0], ExpressionType.Invoke); + var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")"); + return Update(node, new[] { expr }.Concat(args)); + } + case UnaryOperationBinder unary: + { + var expr = VisitUnary(node.Arguments[0], unary.Operation); + return Update(node, new[] { expr }.Concat(node.Arguments.Skip(1))); + } + case BinaryOperationBinder binary: + { + var left = VisitGroup(node.Arguments[0], node.NodeType); + Write(" ", Translate(binary.Operation), " "); + var right = VisitGroup(node.Arguments[1], node.NodeType, true); + return Update(node, new[] { left, right }.Concat(node.Arguments.Skip(2))); + } } + Write("dynamic"); var dynArgs = VisitArguments("(" + Translate(node.Binder.GetType()) + ", ", node.Arguments, Visit, ")"); return node.Update(dynArgs); } #endif - private IList VisitArguments(string open, IList args, Func func, string end, bool wrap = false, IList? prefix = null) where T : class + private IList VisitArguments(string open, IList args, Func func, string end, bool wrap = false, + IList? prefix = null) where T : class { Write(open); if (wrap) @@ -1001,11 +1022,13 @@ private IList VisitArguments(string open, IList args, Func func, if (i != last) Write(wrap ? "," : ", "); } + if (wrap) { _indentLevel--; WriteLine(); } + Write(end); return changed ? list : args; } @@ -1018,11 +1041,9 @@ protected override ElementInit VisitElementInit(ElementInit node) var args = arg != node.Arguments[0] ? new[] { arg }.AsEnumerable() : node.Arguments; return node.Update(args); } - else - { - var list = VisitArguments("{", node.Arguments, Visit, "}"); - return node.Update(list); - } + + var list = VisitArguments("{", node.Arguments, Visit, "}"); + return node.Update(list); } private Dictionary? _counter; @@ -1030,7 +1051,7 @@ protected override ElementInit VisitElementInit(ElementInit node) private string GetConstant(object obj, string? typeName = null) { - if (this.Constants.TryGetValue(obj, out var name)) + if (Constants.TryGetValue(obj, out var name)) return name; _counter ??= new Dictionary(); @@ -1041,7 +1062,7 @@ private string GetConstant(object obj, string? typeName = null) id++; _counter[typeName] = id; name = typeName + id; - this.Constants[obj] = name; + Constants[obj] = name; return name; } @@ -1069,10 +1090,9 @@ private string GetName(ParameterExpression param) { if (string.IsNullOrEmpty(param.Name)) return GetName("p", param); - else if (ReservedWords.Contains(param.Name)) + if (_reservedWords.Contains(param.Name)) return "@" + param.Name; - else - return param.Name; + return param.Name; } private string GetName(LambdaExpression lambda, string defaultMethodName = "Main") @@ -1084,6 +1104,7 @@ private string GetName(LambdaExpression lambda, string defaultMethodName = "Main } private HashSet? _returnTargets; + protected override Expression VisitGoto(GotoExpression node) { switch (node.Kind) @@ -1105,6 +1126,7 @@ protected override Expression VisitGoto(GotoExpression node) default: throw new ArgumentOutOfRangeException(nameof(node)); } + return node; } @@ -1116,16 +1138,16 @@ protected override Expression VisitGoto(GotoExpression node) Write(".", member.Name); return result; } - else - { - Write(Translate(member.DeclaringType!), ".", member.Name); - return null; - } + + Write(Translate(member.DeclaringType!), ".", member.Name); + return null; } protected override Expression VisitIndex(IndexExpression node) { - var obj = node.Indexer != null && node.Indexer.DeclaringType!.GetCustomAttribute()?.MemberName != node.Indexer.Name + var obj = node.Indexer != null && + node.Indexer.DeclaringType!.GetCustomAttribute()?.MemberName != + node.Indexer.Name ? VisitMember(node.Object, node, node.Indexer) : VisitGroup(node.Object, node.NodeType); @@ -1161,6 +1183,7 @@ private void WriteModifier(string modifier) if (Definitions?.IsStatic == true) Write("static "); } + private void WriteModifierNextLine(string modifier) { WriteLine(); @@ -1168,7 +1191,9 @@ private void WriteModifierNextLine(string modifier) } private int _inlineCount; - public Expression VisitLambda(LambdaExpression node, LambdaType type, string? methodName = null, bool isInternal = false) + + public Expression VisitLambda(LambdaExpression node, LambdaType type, string? methodName = null, + bool isInternal = false) { if (type == LambdaType.PrivateLambda || type == LambdaType.PublicLambda) { @@ -1177,22 +1202,25 @@ public Expression VisitLambda(LambdaExpression node, LambdaType type, string? me { var name = methodName ?? "Main"; if (!isInternal) - isInternal = node.ReturnType.GetTypeInfo().IsNotPublic || node.Parameters.Any(it => it.Type.GetTypeInfo().IsNotPublic); + isInternal = node.ReturnType.GetTypeInfo().IsNotPublic || + node.Parameters.Any(it => it.Type.GetTypeInfo().IsNotPublic); WriteModifierNextLine(isInternal ? "internal" : "public"); var funcType = MakeDelegateType(node.ReturnType, node.Parameters.Select(it => it.Type).ToArray()); var exprType = typeof(Expression<>).MakeGenericType(funcType); Write(Translate(exprType), " ", name, " => "); } + IList args; if (node.Parameters.Count == 1) { args = new List(); var arg = VisitParameter(node.Parameters[0]); - args.Add((ParameterExpression) arg); + args.Add((ParameterExpression)arg); } else { - args = VisitArguments("(", node.Parameters.ToList(), p => (ParameterExpression) VisitParameter(p),")"); + args = VisitArguments("(", node.Parameters.ToList(), p => (ParameterExpression)VisitParameter(p), + ")"); } Write(" => "); @@ -1208,25 +1236,28 @@ public Expression VisitLambda(LambdaExpression node, LambdaType type, string? me if (type == LambdaType.PublicMethod || type == LambdaType.ExtensionMethod) { if (!isInternal) - isInternal = node.ReturnType.GetTypeInfo().IsNotPublic || node.Parameters.Any(it => it.Type.GetTypeInfo().IsNotPublic); + isInternal = node.ReturnType.GetTypeInfo().IsNotPublic || + node.Parameters.Any(it => it.Type.GetTypeInfo().IsNotPublic); WriteModifierNextLine(isInternal ? "internal" : "public"); - this.Methods[name] = node.Type; + Methods[name] = node.Type; } else { name = GetName(node, name); WriteModifierNextLine("private"); } + Write(Translate(node.ReturnType), " ", name); var open = "("; if (type == LambdaType.ExtensionMethod) { - if (this.Definitions?.IsStatic != true) + if (Definitions?.IsStatic != true) throw new InvalidOperationException("Extension method requires static class"); if (node.Parameters.Count == 0) throw new InvalidOperationException("Extension method requires at least 1 parameter"); open = "(this "; } + var args = VisitArguments(open, node.Parameters, VisitParameterDeclaration, ")"); Indent(); var body = VisitBody(node.Body, true); @@ -1239,6 +1270,7 @@ public Expression VisitLambda(LambdaExpression node, LambdaType type, string? me private HashSet? _visitedLambda; private int _writerLevel; + protected override Expression VisitLambda(Expression node) { if (_inlineCount > 0) @@ -1287,6 +1319,7 @@ private IList VisitElements(IList list, Func func) where T : clas { wrap = list[0] is MemberBinding && list.Count > 1; } + if (wrap) WriteLine(); else @@ -1371,67 +1404,68 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind private static Type MakeDelegateType(Type returnType, params Type[] parameters) { var del = GetDelegateType(returnType != typeof(void), parameters.Length); - if (del.GetTypeInfo().IsGenericTypeDefinition) - { - var types = parameters.AsEnumerable(); - if (returnType != typeof(void)) - types = types.Concat(new[] { returnType }); - del = del.MakeGenericType(types.ToArray()); - } + if (!del.GetTypeInfo().IsGenericTypeDefinition) return del; + var types = parameters.AsEnumerable(); + if (returnType != typeof(void)) + types = types.Concat(new[] { returnType }); + del = del.MakeGenericType(types.ToArray()); return del; } private static Type GetDelegateType(bool isFunc, int argCount) { - if (!isFunc) - { - switch (argCount) - { - case 0: return typeof(Action); - case 1: return typeof(Action<>); - case 2: return typeof(Action<,>); - case 3: return typeof(Action<,,>); - case 4: return typeof(Action<,,,>); - case 5: return typeof(Action<,,,,>); - case 6: return typeof(Action<,,,,,>); - case 7: return typeof(Action<,,,,,,>); - case 8: return typeof(Action<,,,,,,,>); - case 9: return typeof(Action<,,,,,,,,>); - case 10: return typeof(Action<,,,,,,,,,>); - case 11: return typeof(Action<,,,,,,,,,,>); - case 12: return typeof(Action<,,,,,,,,,,,>); - case 13: return typeof(Action<,,,,,,,,,,,,>); - case 14: return typeof(Action<,,,,,,,,,,,,,>); - case 15: return typeof(Action<,,,,,,,,,,,,,,>); - case 16: return typeof(Action<,,,,,,,,,,,,,,,>); - default: throw new InvalidOperationException("Cannot handle non-public method"); - } - } - else - { - switch (argCount) - { - case 0: return typeof(Func<>); - case 1: return typeof(Func<,>); - case 2: return typeof(Func<,,>); - case 3: return typeof(Func<,,,>); - case 4: return typeof(Func<,,,,>); - case 5: return typeof(Func<,,,,,>); - case 6: return typeof(Func<,,,,,,>); - case 7: return typeof(Func<,,,,,,,>); - case 8: return typeof(Func<,,,,,,,,>); - case 9: return typeof(Func<,,,,,,,,,>); - case 10: return typeof(Func<,,,,,,,,,,>); - case 11: return typeof(Func<,,,,,,,,,,,>); - case 12: return typeof(Func<,,,,,,,,,,,,>); - case 13: return typeof(Func<,,,,,,,,,,,,,>); - case 14: return typeof(Func<,,,,,,,,,,,,,,>); - case 15: return typeof(Func<,,,,,,,,,,,,,,,>); - case 16: return typeof(Func<,,,,,,,,,,,,,,,,>); - default: throw new InvalidOperationException("Cannot handle non-public method"); - } - } + return isFunc ? GetDelegateTypeWhenIsFunc(argCount) : GetDelegateTypeWhenIsNotFunc(argCount); + } + + private static Type GetDelegateTypeWhenIsFunc(int argCount) + { + return argCount switch + { + 0 => typeof(Func<>), + 1 => typeof(Func<,>), + 2 => typeof(Func<,,>), + 3 => typeof(Func<,,,>), + 4 => typeof(Func<,,,,>), + 5 => typeof(Func<,,,,,>), + 6 => typeof(Func<,,,,,,>), + 7 => typeof(Func<,,,,,,,>), + 8 => typeof(Func<,,,,,,,,>), + 9 => typeof(Func<,,,,,,,,,>), + 10 => typeof(Func<,,,,,,,,,,>), + 11 => typeof(Func<,,,,,,,,,,,>), + 12 => typeof(Func<,,,,,,,,,,,,>), + 13 => typeof(Func<,,,,,,,,,,,,,>), + 14 => typeof(Func<,,,,,,,,,,,,,,>), + 15 => typeof(Func<,,,,,,,,,,,,,,,>), + 16 => typeof(Func<,,,,,,,,,,,,,,,,>), + _ => throw new InvalidOperationException("Cannot handle non-public method") + }; + } + + private static Type GetDelegateTypeWhenIsNotFunc(int argCount) + { + return argCount switch + { + 0 => typeof(Action), + 1 => typeof(Action<>), + 2 => typeof(Action<,>), + 3 => typeof(Action<,,>), + 4 => typeof(Action<,,,>), + 5 => typeof(Action<,,,,>), + 6 => typeof(Action<,,,,,>), + 7 => typeof(Action<,,,,,,>), + 8 => typeof(Action<,,,,,,,>), + 9 => typeof(Action<,,,,,,,,>), + 10 => typeof(Action<,,,,,,,,,>), + 11 => typeof(Action<,,,,,,,,,,>), + 12 => typeof(Action<,,,,,,,,,,,>), + 13 => typeof(Action<,,,,,,,,,,,,>), + 14 => typeof(Action<,,,,,,,,,,,,,>), + 15 => typeof(Action<,,,,,,,,,,,,,,>), + 16 => typeof(Action<,,,,,,,,,,,,,,,>), + _ => throw new InvalidOperationException("Cannot handle non-public method") + }; } protected override Expression VisitMethodCall(MethodCallExpression node) @@ -1452,7 +1486,8 @@ protected override Expression VisitMethodCall(MethodCallExpression node) if (node.Method.GetParameters().Any(it => it.IsOut || it.ParameterType.IsByRef)) throw new InvalidOperationException("Cannot handle non-public method"); - var del = MakeDelegateType(node.Method.ReturnType, node.Method.GetParameters().Select(it => it.ParameterType).ToArray()); + var del = MakeDelegateType(node.Method.ReturnType, + node.Method.GetParameters().Select(it => it.ParameterType).ToArray()); var func = node.Method.CreateDelegate(del); Write(GetConstant(func, GetVarName(node.Method.Name)), ".Invoke"); } @@ -1493,12 +1528,14 @@ protected override Expression VisitMethodCall(MethodCallExpression node) Write("<", args, ">"); } } + var prefix = node.Method.GetParameters() .Select(p => p.IsOut ? "out " : p.ParameterType.IsByRef ? "ref " : ""); if (isExtension) { - var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")", prefix: prefix.Skip(1).ToList()); + var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")", + prefix: prefix.Skip(1).ToList()); var newArgs = new[] { arg0 }.Concat(args).ToList(); return newArgs.SequenceEqual(node.Arguments) ? node : node.Update(obj, newArgs); } @@ -1518,121 +1555,44 @@ protected override Expression VisitNew(NewExpression node) protected override Expression VisitNewArray(NewArrayExpression node) { - if (node.NodeType == ExpressionType.NewArrayBounds) - { - var elemType = node.Type.GetElementType(); - var arrayCount = 1; - // ReSharper disable once PossibleNullReferenceException - while (elemType.IsArray) - { - elemType = elemType.GetElementType(); - arrayCount++; - } - Write("new ", Translate(elemType)); - var args = VisitArguments("[", node.Expressions, Visit, "]"); - for (int i = 1; i < arrayCount; i++) - Write("[]"); - return node.Update(args); - } - else + if (node.NodeType != ExpressionType.NewArrayBounds) { Write("new ", Translate(node.Type)); var args = VisitElements(node.Expressions, Visit); return node.Update(args); } + + var elemType = node.Type.GetElementType(); + var arrayCount = 1; + // ReSharper disable once PossibleNullReferenceException + while (elemType.IsArray) + { + elemType = elemType.GetElementType(); + arrayCount++; + } + + Write("new ", Translate(elemType)); + var arrayArgs = VisitArguments("[", node.Expressions, Visit, "]"); + for (int i = 1; i < arrayCount; i++) + Write("[]"); + return node.Update(arrayArgs); } #region _reservedWords - private static readonly HashSet ReservedWords = new HashSet - { - "abstract", - "as", - "base", - "bool", - "break", - "by", - "byte", - "case", - "catch", - "char", - "checked", - "class", - "const", - "continue", - "decimal", - "default", - "delegate", - "descending", - "do", - "double", - "else", - "enum", - "event", - "explicit", - "extern", - "finally", - "fixed", - "float", - "for", - "foreach", - "from", - "goto", - "group", - "if", - "implicit", - "in", - "int", - "interface", - "internal", - "into", - "is", - "lock", - "long", - "namespace", - "new", - "null", - "object", - "operator", - "orderby", - "out", - "override", - "params", - "private", - "protected", - "public", - "readonly", - "ref", - "return", - "sbyte", - "sealed", - "select", - "short", - "sizeof", - "stackalloc", - "static", - "string", - "struct", - "switch", - "this", - "throw", - "try", - "typeof", - "ulong", - "unchecked", - "unit", - "unsafe", - "ushort", - "using", - "var", - "virtual", - "void", - "volatile", - "where", - "while", - "yield", - "false", - "true", + + private static readonly HashSet _reservedWords = new HashSet + { + "abstract", "as", "base", "bool", "break", "by", "byte", "case", "catch", "char", "checked", + "class", "const", "continue", "decimal", "default", "delegate", "descending", "do", "double", + "else", "enum", "event", "explicit", "extern", "finally", "fixed", "float", "for", "foreach", + "from", "goto", "group", "if", "implicit", "in", "int", "interface", "internal", "into", "is", + "lock", "long", "namespace", "new", "null", "object", "operator", "orderby", "out", "override", + "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", + "select", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", + "throw", "try", "typeof", "ulong", "unchecked", "unit", "unsafe", "ushort", "using", "var", + "virtual", "void", "volatile", "where", "while", "yield", "false", "true" }; + #endregion protected override Expression VisitParameter(ParameterExpression node) @@ -1642,6 +1602,7 @@ protected override Expression VisitParameter(ParameterExpression node) private HashSet? _pendingVariables; private Dictionary? _params; + private Expression VisitParameter(ParameterExpression node, bool write) { _pendingVariables ??= new HashSet(); @@ -1673,6 +1634,7 @@ private Expression VisitParameter(ParameterExpression node, bool write) result = Expression.Parameter(node.Type, name); _params[node] = result; } + return result; } @@ -1701,6 +1663,7 @@ private Expression VisitSwitch(SwitchExpression node, bool shouldReturn) WriteLine(); Write("break;"); } + _indentLevel--; Outdent(); @default = CreateBlock(@default); @@ -1735,6 +1698,7 @@ private SwitchCase VisitSwitchCase(SwitchCase node, bool shouldReturn) Write("break;"); body = CreateBlock(body); } + _indentLevel--; return node.Update(values, body); } @@ -1752,6 +1716,7 @@ private Expression VisitTry(TryExpression node, bool shouldReturn) faultParam = GetName("fault", node); WriteNextLine("bool ", faultParam, " = true;"); } + WriteNextLine("try"); Indent(); var body = VisitBody(node.Body, shouldReturn); @@ -1761,21 +1726,24 @@ private Expression VisitTry(TryExpression node, bool shouldReturn) var handlers = node.Handlers.Select(c => VisitCatchBlock(c, shouldReturn)).ToList(); var @finally = node.Finally; var fault = node.Fault; - if (node.Finally != null || node.Fault != null) + + if (node.Finally == null && node.Fault == null) + return node.Update(body, handlers, @finally, fault); + + WriteNextLine("finally"); + Indent(); + if (node.Finally != null) + @finally = VisitBody(node.Finally); + if (node.Fault != null) { - WriteNextLine("finally"); + WriteNextLine("if (", faultParam!, ")"); Indent(); - if (node.Finally != null) - @finally = VisitBody(node.Finally); - if (node.Fault != null) - { - WriteNextLine("if (", faultParam!, ")"); - Indent(); - fault = VisitBody(node.Fault); - Outdent(); - } + fault = VisitBody(node.Fault); Outdent(); } + + Outdent(); + return node.Update(body, handlers, @finally, fault); } @@ -1819,6 +1787,7 @@ private Expression VisitUnary(Expression operand, ExpressionType nodeType) Write(Translate(nodeType)); break; } + return result; } @@ -1841,6 +1810,7 @@ protected override Expression VisitUnary(UnaryExpression node) return node; } // ReSharper restore HeuristicUnreachableCode + Write("throw "); break; } @@ -1855,6 +1825,7 @@ protected override Expression VisitUnary(UnaryExpression node) Write(" as ", Translate(node.Type)); break; } + return node.Update(operand); } @@ -1878,7 +1849,8 @@ public override string ToString() .ToList(); var properties = _properties? .ToDictionary(it => it.Name, - it => $"{TranslateNullable(it.Type, it.NullableContext ?? Definitions?.NullableContext, it.Nullable)} {it.Name} {{ get; {(it.IsReadOnly ? "" : it.IsInitOnly ? "init; " : "set; ")}}}"); + it => + $"{TranslateNullable(it.Type, it.NullableContext ?? Definitions?.NullableContext, it.Nullable)} {it.Name} {{ get; {(it.IsReadOnly ? "" : it.IsInitOnly ? "init; " : "set; ")}}}"); var ctorParams = _properties?.Where(it => it.IsReadOnly).ToList(); if (Definitions?.TypeName != null) { @@ -1892,6 +1864,7 @@ public override string ToString() { WriteNextLine("using ", ns, ";"); } + WriteLine(); } @@ -1907,6 +1880,7 @@ public override string ToString() { WriteNextLine("using ", name.Value, " = ", name.Key.FullName!, ";"); } + if (names.Count > 0) WriteLine(); } @@ -1920,19 +1894,22 @@ public override string ToString() var isInternal = Definitions.IsInternal; if (!isInternal) isInternal = Definitions.Implements?.Any(it => - !it.GetTypeInfo().IsInterface && !it.GetTypeInfo().IsPublic) ?? false; + !it.GetTypeInfo().IsInterface && !it.GetTypeInfo().IsPublic) ?? false; WriteModifierNextLine(isInternal ? "internal" : "public"); Write("partial ", Definitions.IsRecordType ? "record " : "class ", Definitions.TypeName); if (Definitions.IsRecordType && ctorParams?.Count > 0) { WriteCtorParams(ctorParams); } + if (implements?.Any() == true) { Write(" : ", string.Join(", ", implements)); } + Indent(); } + if (constants != null) { foreach (var constant in constants) @@ -1940,8 +1917,10 @@ public override string ToString() WriteModifierNextLine("private"); Write(constant); } + WriteLine(); } + if (_properties != null && Definitions?.TypeName != null) { foreach (var property in _properties) @@ -1952,6 +1931,7 @@ public override string ToString() WriteModifierNextLine(isInternal ? "internal" : "public"); Write(properties![property.Name]); } + WriteLine(); if (ctorParams?.Count > 0 && !Definitions.IsRecordType) @@ -1963,8 +1943,10 @@ public override string ToString() Indent(); foreach (var parameter in ctorParams) { - WriteNextLine("this.", parameter.Name, " = ", char.ToLower(parameter.Name[0]).ToString(), parameter.Name.Substring(1), ";"); + WriteNextLine("this.", parameter.Name, " = ", char.ToLower(parameter.Name[0]).ToString(), + parameter.Name.Substring(1), ";"); } + Outdent(); WriteLine(); } @@ -2012,8 +1994,10 @@ private void WriteCtorParams(List ctorParams) var parameter = ctorParams[i]; if (i > 0) Write(", "); - Write($"{TranslateNullable(parameter.Type, parameter.NullableContext ?? Definitions?.NullableContext, parameter.Nullable)} {char.ToLower(parameter.Name[0]) + parameter.Name.Substring(1)}"); + Write( + $"{TranslateNullable(parameter.Type, parameter.NullableContext ?? Definitions?.NullableContext, parameter.Nullable)} {char.ToLower(parameter.Name[0]) + parameter.Name.Substring(1)}"); } + Write(")"); } @@ -2026,4 +2010,4 @@ public enum LambdaType ExtensionMethod, } } -} +} \ No newline at end of file diff --git a/src/Mapster/Adapters/BaseAdapter.cs b/src/Mapster/Adapters/BaseAdapter.cs index 86c090d2..0508808b 100644 --- a/src/Mapster/Adapters/BaseAdapter.cs +++ b/src/Mapster/Adapters/BaseAdapter.cs @@ -12,12 +12,12 @@ public abstract class BaseAdapter { protected virtual int Score => 0; protected virtual ObjectType ObjectType => ObjectType.Primitive; - protected virtual bool CheckExplicitMapping => this.ObjectType == ObjectType.Class; + protected virtual bool CheckExplicitMapping => ObjectType == ObjectType.Class; protected virtual bool UseTargetValue => false; public virtual int? Priority(PreCompileArgument arg) { - return CanMap(arg) ? this.Score : (int?)null; + return CanMap(arg) ? Score : (int?)null; } protected abstract bool CanMap(PreCompileArgument arg); @@ -45,11 +45,11 @@ public TypeAdapterRule CreateRule() { var rule = new TypeAdapterRule { - Priority = this.Priority, + Priority = Priority, Settings = new TypeAdapterSettings { - ConverterFactory = this.CreateAdaptFunc, - ConverterToTargetFactory = this.CreateAdaptToTargetFunc, + ConverterFactory = CreateAdaptFunc, + ConverterToTargetFactory = CreateAdaptToTargetFunc, } }; DecorateRule(rule); @@ -82,7 +82,7 @@ protected virtual bool CanInline(Expression source, Expression? destination, Com protected virtual Expression CreateExpressionBody(Expression source, Expression? destination, CompileArgument arg) { - if (this.CheckExplicitMapping && arg.Context.Config.RequireExplicitMapping && !arg.ExplicitMapping) + if (CheckExplicitMapping && arg.Context.Config.RequireExplicitMapping && !arg.ExplicitMapping) throw new InvalidOperationException("Implicit mapping is not allowed (check GlobalSettings.RequireExplicitMapping) and no configuration exists"); var oldMaxDepth = arg.Context.MaxDepth; @@ -96,9 +96,9 @@ protected virtual Expression CreateExpressionBody(Expression source, Expression? } if (arg.Context.MaxDepth.HasValue) { - if (this.ObjectType != ObjectType.Primitive && arg.Context.Depth >= arg.Context.MaxDepth.Value) + if (ObjectType != ObjectType.Primitive && arg.Context.Depth >= arg.Context.MaxDepth.Value) return arg.DestinationType.CreateDefault(); - if (this.ObjectType == ObjectType.Class) + if (ObjectType == ObjectType.Class) arg.Context.Depth++; } @@ -196,7 +196,7 @@ protected Expression CreateBlockExpressionBody(Expression source, Expression? de transformedSource = src; } var set = CreateInstantiationExpression(transformedSource, destination, arg); - if (destination != null && (this.UseTargetValue || arg.UseDestinationValue) && arg.GetConstructUsing()?.Parameters.Count != 2) + if (destination != null && (UseTargetValue || arg.UseDestinationValue) && arg.GetConstructUsing()?.Parameters.Count != 2) { if (destination.CanBeNull()) { diff --git a/src/Mapster/Adapters/BaseAfterMapper.cs b/src/Mapster/Adapters/BaseAfterMapper.cs index 8dfa470c..1b7d74e6 100644 --- a/src/Mapster/Adapters/BaseAfterMapper.cs +++ b/src/Mapster/Adapters/BaseAfterMapper.cs @@ -8,7 +8,7 @@ public abstract class BaseAfterMapper public virtual int? Priority(PreCompileArgument arg) { - return CanMap(arg) ? this.Score : (int?)null; + return CanMap(arg) ? Score : (int?)null; } protected abstract bool CanMap(PreCompileArgument arg); @@ -26,10 +26,10 @@ public LambdaExpression CreateAfterMapFunc(CompileArgument arg) public TypeAdapterRule CreateRule() { var settings = new TypeAdapterSettings(); - settings.AfterMappingFactories.Add(this.CreateAfterMapFunc); + settings.AfterMappingFactories.Add(CreateAfterMapFunc); var rule = new TypeAdapterRule { - Priority = this.Priority, + Priority = Priority, Settings = settings, }; DecorateRule(rule); diff --git a/src/Mapster/Compile/CompileArgument.cs b/src/Mapster/Compile/CompileArgument.cs index fe362fc4..2e15637a 100644 --- a/src/Mapster/Compile/CompileArgument.cs +++ b/src/Mapster/Compile/CompileArgument.cs @@ -36,11 +36,9 @@ internal HashSet GetDestinationNames() private LambdaExpression? _constructUsing; internal LambdaExpression? GetConstructUsing() { - if (!_fetchConstructUsing) - { - _constructUsing = Settings.ConstructUsingFactory?.Invoke(this); - _fetchConstructUsing = true; - } + if (_fetchConstructUsing) return _constructUsing; + _constructUsing = Settings.ConstructUsingFactory?.Invoke(this); + _fetchConstructUsing = true; return _constructUsing; } } diff --git a/src/Mapster/Compile/CompileContext.cs b/src/Mapster/Compile/CompileContext.cs index 371c512b..f0188fb4 100644 --- a/src/Mapster/Compile/CompileContext.cs +++ b/src/Mapster/Compile/CompileContext.cs @@ -6,16 +6,16 @@ namespace Mapster { public class CompileContext { - public HashSet Running { get; } = new HashSet(); - public Stack Configs { get; } = new Stack(); + public HashSet Running { get; } = new(); + public Stack Configs { get; } = new(); public TypeAdapterConfig Config => Configs.Peek(); public int? MaxDepth { get; set; } public int Depth { get; set; } - public HashSet ExtraParameters { get; } = new HashSet(); + public HashSet ExtraParameters { get; } = new(); internal bool IsSubFunction() { - return this.MaxDepth.HasValue || this.ExtraParameters.Count > 0; + return MaxDepth.HasValue || ExtraParameters.Count > 0; } public CompileContext(TypeAdapterConfig config) diff --git a/src/Mapster/Compile/CompileException.cs b/src/Mapster/Compile/CompileException.cs index 21196b03..baa1bbb4 100644 --- a/src/Mapster/Compile/CompileException.cs +++ b/src/Mapster/Compile/CompileException.cs @@ -7,14 +7,14 @@ public class CompileException : InvalidOperationException { public CompileException(CompileArgument argument, Exception innerException) : base(null, innerException) { - this.Argument = argument; + Argument = argument; } public override string Message => "Error while compiling\n" + - $"source={this.Argument.SourceType}\n" + - $"destination={this.Argument.DestinationType}\n" + - $"type={this.Argument.MapType}"; + $"source={Argument.SourceType}\n" + + $"destination={Argument.DestinationType}\n" + + $"type={Argument.MapType}"; public CompileArgument Argument { get; } public LambdaExpression? Expression { get; internal set; } diff --git a/src/Mapster/Models/InvokerModel.cs b/src/Mapster/Models/InvokerModel.cs index e7d046d4..b5a4546d 100644 --- a/src/Mapster/Models/InvokerModel.cs +++ b/src/Mapster/Models/InvokerModel.cs @@ -13,37 +13,37 @@ public class InvokerModel public InvokerModel? Next(ParameterExpression source, string destMemberName) { - if (!this.DestinationMemberName.StartsWith(destMemberName + ".")) + if (!DestinationMemberName.StartsWith(destMemberName + ".")) return null; return new InvokerModel { - DestinationMemberName = this.DestinationMemberName.Substring(destMemberName.Length + 1), - Condition = this.IsChildPath || this.Condition == null - ? this.Condition - : Expression.Lambda(this.Condition.Apply(source), source), - Invoker = this.IsChildPath - ? this.Invoker - : Expression.Lambda(this.GetInvokingExpression(source), source), - SourceMemberName = this.SourceMemberName, + DestinationMemberName = DestinationMemberName.Substring(destMemberName.Length + 1), + Condition = IsChildPath || Condition == null + ? Condition + : Expression.Lambda(Condition.Apply(source), source), + Invoker = IsChildPath + ? Invoker + : Expression.Lambda(GetInvokingExpression(source), source), + SourceMemberName = SourceMemberName, IsChildPath = true, }; } public Expression GetInvokingExpression(Expression exp, MapType mapType = MapType.Map) { - if (this.IsChildPath) - return this.Invoker!.Body; - return this.SourceMemberName != null - ? ExpressionEx.PropertyOrFieldPath(exp, this.SourceMemberName) - : this.Invoker!.Apply(mapType, exp); + if (IsChildPath) + return Invoker!.Body; + return SourceMemberName != null + ? ExpressionEx.PropertyOrFieldPath(exp, SourceMemberName) + : Invoker!.Apply(mapType, exp); } public Expression? GetConditionExpression(Expression exp, MapType mapType = MapType.Map) { - return this.IsChildPath - ? this.Condition?.Body - : this.Condition?.Apply(mapType, exp); + return IsChildPath + ? Condition?.Body + : Condition?.Apply(mapType, exp); } } } \ No newline at end of file diff --git a/src/Mapster/Models/KeyValuePairModel.cs b/src/Mapster/Models/KeyValuePairModel.cs index cbcc0396..81e25491 100644 --- a/src/Mapster/Models/KeyValuePairModel.cs +++ b/src/Mapster/Models/KeyValuePairModel.cs @@ -37,11 +37,11 @@ public IEnumerable GetCustomAttributesData() => public Expression GetExpression(Expression source) { - return _getFn(source, Expression.Constant(this.Name)); + return _getFn(source, Expression.Constant(Name)); } public Expression SetExpression(Expression source, Expression value) { - return _setFn(source, Expression.Constant(this.Name), value); + return _setFn(source, Expression.Constant(Name), value); } } } diff --git a/src/Mapster/Models/ParameterModel.cs b/src/Mapster/Models/ParameterModel.cs index 5e1ef469..ff919575 100644 --- a/src/Mapster/Models/ParameterModel.cs +++ b/src/Mapster/Models/ParameterModel.cs @@ -22,7 +22,7 @@ public ParameterModel(ParameterInfo parameterInfo) public Expression GetExpression(Expression source) { - return Expression.Variable(this.Type, _parameterInfo.Name); + return Expression.Variable(Type, _parameterInfo.Name); } public Expression SetExpression(Expression source, Expression value) { diff --git a/src/Mapster/Models/TypeTuple.cs b/src/Mapster/Models/TypeTuple.cs index 17318419..e25a71fd 100644 --- a/src/Mapster/Models/TypeTuple.cs +++ b/src/Mapster/Models/TypeTuple.cs @@ -36,8 +36,8 @@ public override int GetHashCode() public TypeTuple(Type source, Type destination) { - this.Source = source; - this.Destination = destination; + Source = source; + Destination = destination; } } } diff --git a/src/Mapster/Settings/DestinationTransform.cs b/src/Mapster/Settings/DestinationTransform.cs index 64eb0e01..32289a1c 100644 --- a/src/Mapster/Settings/DestinationTransform.cs +++ b/src/Mapster/Settings/DestinationTransform.cs @@ -79,7 +79,7 @@ public DestinationTransform WithCondition(Func condition) return new DestinationTransform { Condition = condition, - TransformFunc = this.TransformFunc + TransformFunc = TransformFunc }; } } diff --git a/src/Mapster/Settings/IgnoreDictionary.cs b/src/Mapster/Settings/IgnoreDictionary.cs index 832be161..aaa530f1 100644 --- a/src/Mapster/Settings/IgnoreDictionary.cs +++ b/src/Mapster/Settings/IgnoreDictionary.cs @@ -28,13 +28,13 @@ public void Apply(IgnoreDictionary other) { foreach (var member in other) { - this.Merge(member.Key, member.Value); + Merge(member.Key, member.Value); } } internal void Merge(string name, in IgnoreItem src) { - if (src.Condition != null && this.TryGetValue(name, out var item)) + if (src.Condition != null && TryGetValue(name, out var item)) { if (item.Condition == null) return; diff --git a/src/Mapster/Settings/NameMatchingStrategy.cs b/src/Mapster/Settings/NameMatchingStrategy.cs index 1b4a99f4..408c292d 100644 --- a/src/Mapster/Settings/NameMatchingStrategy.cs +++ b/src/Mapster/Settings/NameMatchingStrategy.cs @@ -18,8 +18,8 @@ public void Apply(object other) [SuppressMessage("ReSharper", "ConstantNullCoalescingCondition")] public void Apply(NameMatchingStrategy other) { - this.SourceMemberNameConverter ??= other.SourceMemberNameConverter; - this.DestinationMemberNameConverter ??= other.DestinationMemberNameConverter; + SourceMemberNameConverter ??= other.SourceMemberNameConverter; + DestinationMemberNameConverter ??= other.DestinationMemberNameConverter; } public static readonly NameMatchingStrategy Exact = new NameMatchingStrategy diff --git a/src/Mapster/TypeAdapterBuilder.cs b/src/Mapster/TypeAdapterBuilder.cs index 5a7bebac..13005760 100644 --- a/src/Mapster/TypeAdapterBuilder.cs +++ b/src/Mapster/TypeAdapterBuilder.cs @@ -10,19 +10,19 @@ namespace Mapster public class TypeAdapterBuilder : IAdapterBuilder { TSource Source { get; } - TSource IAdapterBuilder.Source => this.Source; + TSource IAdapterBuilder.Source => Source; TypeAdapterConfig Config { get; set; } - TypeAdapterConfig IAdapterBuilder.Config => this.Config; + TypeAdapterConfig IAdapterBuilder.Config => Config; private Dictionary? _parameters; Dictionary Parameters => _parameters ??= new Dictionary(); - Dictionary IAdapterBuilder.Parameters => this.Parameters; + Dictionary IAdapterBuilder.Parameters => Parameters; bool IAdapterBuilder.HasParameter => _parameters != null && _parameters.Count > 0; internal TypeAdapterBuilder(TSource source, TypeAdapterConfig config) { - this.Source = source; - this.Config = config; + Source = source; + Config = config; } [SuppressMessage("ReSharper", "ExplicitCallerInfoArgument")] @@ -36,13 +36,13 @@ public TypeAdapterBuilder ForkConfig(Action action, #endif int key2 = 0) { - this.Config = this.Config.Fork(action, key1, key2); + Config = Config.Fork(action, key1, key2); return this; } public TypeAdapterBuilder AddParameters(string name, object value) { - this.Parameters.Add(name, value); + Parameters.Add(name, value); return this; } @@ -50,7 +50,7 @@ private MapContextScope CreateMapContextScope() { var scope = new MapContextScope(); var parameters = scope.Context.Parameters; - foreach (var kvp in this.Parameters) + foreach (var kvp in Parameters) { parameters[kvp.Key] = kvp.Value; } @@ -65,7 +65,7 @@ public TDestination AdaptToType() if (_parameters == null) return Map(); - using (this.CreateMapContextScope()) + using (CreateMapContextScope()) { return Map(); } @@ -73,8 +73,8 @@ public TDestination AdaptToType() private TDestination Map() { - var fn = this.Config.GetMapFunction(); - return fn(this.Source); + var fn = Config.GetMapFunction(); + return fn(Source); } public TDestination AdaptTo(TDestination destination) @@ -82,7 +82,7 @@ public TDestination AdaptTo(TDestination destination) if (_parameters == null) return MapToTarget(destination); - using (this.CreateMapContextScope()) + using (CreateMapContextScope()) { return MapToTarget(destination); } @@ -90,26 +90,26 @@ public TDestination AdaptTo(TDestination destination) private TDestination MapToTarget(TDestination destination) { - var fn = this.Config.GetMapToTargetFunction(); - return fn(this.Source, destination); + var fn = Config.GetMapToTargetFunction(); + return fn(Source, destination); } public Expression> CreateMapExpression() { var tuple = new TypeTuple(typeof(TSource), typeof(TDestination)); - return (Expression>) this.Config.CreateMapExpression(tuple, MapType.Map); + return (Expression>) Config.CreateMapExpression(tuple, MapType.Map); } public Expression> CreateMapToTargetExpression() { var tuple = new TypeTuple(typeof(TSource), typeof(TDestination)); - return (Expression>) this.Config.CreateMapExpression(tuple, MapType.MapToTarget); + return (Expression>) Config.CreateMapExpression(tuple, MapType.MapToTarget); } public Expression> CreateProjectionExpression() { var tuple = new TypeTuple(typeof(TSource), typeof(TDestination)); - return (Expression>) this.Config.CreateMapExpression(tuple, MapType.Projection); + return (Expression>) Config.CreateMapExpression(tuple, MapType.Projection); } } } \ No newline at end of file diff --git a/src/Mapster/TypeAdapterConfig.cs b/src/Mapster/TypeAdapterConfig.cs index 265e4164..73efdcd3 100644 --- a/src/Mapster/TypeAdapterConfig.cs +++ b/src/Mapster/TypeAdapterConfig.cs @@ -93,10 +93,10 @@ private static List CreateRuleTemplate() public TypeAdapterConfig() { - this.Rules = RulesTemplate.ToList(); + Rules = RulesTemplate.ToList(); var settings = new TypeAdapterSettings(); - this.Default = new TypeAdapterSetter(settings, this); - this.Rules.Add(new TypeAdapterRule + Default = new TypeAdapterSetter(settings, this); + Rules.Add(new TypeAdapterRule { Priority = arg => -100, Settings = settings, @@ -110,7 +110,7 @@ public TypeAdapterSetter When(Func canMap) Priority = arg => canMap(arg.SourceType, arg.DestinationType, arg.MapType) ? (int?)25 : null, Settings = new TypeAdapterSettings(), }; - this.Rules.LockAdd(rule); + Rules.LockAdd(rule); return new TypeAdapterSetter(rule.Settings, this); } @@ -121,7 +121,7 @@ public TypeAdapterSetter When(Func canMap) Priority = arg => canMap(arg) ? (int?)25 : null, Settings = new TypeAdapterSettings(), }; - this.Rules.LockAdd(rule); + Rules.LockAdd(rule); return new TypeAdapterSetter(rule.Settings, this); } @@ -167,12 +167,12 @@ public TypeAdapterSetter ForDestinationType(Type destinationType) private TypeAdapterSettings GetSettings(TypeTuple key) { - var rule = this.RuleMap.GetOrAdd(key, types => + var rule = RuleMap.GetOrAdd(key, types => { var r = types.Source == typeof(void) ? CreateDestinationTypeRule(types) : CreateTypeTupleRule(types); - this.Rules.LockAdd(r); + Rules.LockAdd(r); return r; }); return rule.Settings; @@ -184,10 +184,10 @@ private TypeAdapterRule CreateTypeTupleRule(TypeTuple key) { Priority = arg => { - var score1 = GetSubclassDistance(arg.DestinationType, key.Destination, this.AllowImplicitDestinationInheritance); + var score1 = GetSubclassDistance(arg.DestinationType, key.Destination, AllowImplicitDestinationInheritance); if (score1 == null) return null; - var score2 = GetSubclassDistance(arg.SourceType, key.Source, this.AllowImplicitSourceInheritance); + var score2 = GetSubclassDistance(arg.SourceType, key.Source, AllowImplicitSourceInheritance); if (score2 == null) return null; return score1.Value + score2.Value; @@ -250,7 +250,7 @@ private T AddToHash(ConcurrentDictionary hash, TypeTuple key, F var del = func(types); hash[types] = del; - if (this.RuleMap.TryGetValue(types, out var rule)) + if (RuleMap.TryGetValue(types, out var rule)) rule.Settings.Compiled = true; return del; @@ -336,7 +336,7 @@ public LambdaExpression CreateMapExpression(TypeTuple tuple, MapType mapType) fork = arg.Settings.Fork; if (fork != null) { - var cloned = this.Clone(); + var cloned = Clone(); fork(cloned); context.Configs.Push(cloned); arg.Settings = cloned.GetMergedSettings(tuple, mapType); @@ -442,7 +442,7 @@ private LambdaExpression CreateMapInvokeExpression(Type sourceType, Type destina internal Expression CreateMapInvokeExpressionBody(Type sourceType, Type destinationType, Expression p) { - if (this.RequireExplicitMapping) + if (RequireExplicitMapping) { var key = new TypeTuple(sourceType, destinationType); _mapDict[key] = Compiler(CreateMapExpression(key, MapType.Map)); @@ -465,7 +465,7 @@ internal Expression CreateMapInvokeExpressionBody(Type sourceType, Type destinat internal Expression CreateMapToTargetInvokeExpressionBody(Type sourceType, Type destinationType, Expression p1, Expression p2) { - if (this.RequireExplicitMapping) + if (RequireExplicitMapping) { var key = new TypeTuple(sourceType, destinationType); _mapToTargetDict[key] = Compiler(CreateMapExpression(key, MapType.MapToTarget)); @@ -534,7 +534,7 @@ internal TypeAdapterSettings GetMergedSettings(TypeTuple tuple, MapType mapType) SourceType = tuple.Source, DestinationType = tuple.Destination, MapType = mapType, - ExplicitMapping = this.RuleMap.ContainsKey(tuple), + ExplicitMapping = RuleMap.ContainsKey(tuple), }; //auto add setting if there is attr setting @@ -546,9 +546,9 @@ internal TypeAdapterSettings GetMergedSettings(TypeTuple tuple, MapType mapType) } var result = new TypeAdapterSettings(); - lock (this.Rules) + lock (Rules) { - var rules = this.Rules.Reverse().Concat(attrSettings); + var rules = Rules.Reverse().Concat(attrSettings); var settings = from rule in rules let priority = rule.Priority(arg) where priority != null @@ -575,7 +575,7 @@ private CompileArgument GetCompileArgument(TypeTuple tuple, MapType mapType, Com { SourceType = tuple.Source, DestinationType = tuple.Destination, - ExplicitMapping = this.RuleMap.ContainsKey(tuple), + ExplicitMapping = RuleMap.ContainsKey(tuple), MapType = mapType, Context = context, Settings = setting, @@ -648,13 +648,13 @@ public IList Scan(params Assembly[] assemblies) .SelectMany(registerTypes => registerTypes.Select(registerType => (IRegister)Activator.CreateInstance(registerType))).ToList(); - this.Apply(registers); + Apply(registers); return registers; } public void Apply(IEnumerable> registers) { - this.Apply(registers.Select(register => register.Value)); + Apply(registers.Select(register => register.Value)); } public void Apply(IEnumerable registers) @@ -690,8 +690,8 @@ internal void Remove(Type sourceType, Type destinationType) private void Remove(TypeTuple key) { - if (this.RuleMap.TryRemove(key, out var rule)) - this.Rules.LockRemove(rule); + if (RuleMap.TryRemove(key, out var rule)) + Rules.LockRemove(rule); _mapDict.TryRemove(key, out _); _mapToTargetDict.TryRemove(key, out _); _projectionDict.TryRemove(key, out _); @@ -728,7 +728,7 @@ public TypeAdapterConfig Fork(Action action, var key = $"{key1}|{key2}"; return InlineConfigs.GetOrAdd(key, _ => { - var cloned = this.Clone(); + var cloned = Clone(); action(cloned); return cloned; }); diff --git a/src/Mapster/TypeAdapterSetter.cs b/src/Mapster/TypeAdapterSetter.cs index cd24fe68..9215f375 100644 --- a/src/Mapster/TypeAdapterSetter.cs +++ b/src/Mapster/TypeAdapterSetter.cs @@ -18,8 +18,8 @@ public class TypeAdapterSetter public readonly TypeAdapterConfig Config; public TypeAdapterSetter(TypeAdapterSettings settings, TypeAdapterConfig config) { - this.Settings = settings; - this.Config = config; + Settings = settings; + Config = config; } } public static class TypeAdapterSetterExtensions @@ -434,7 +434,7 @@ public TypeAdapterSetter MapToConstructor(ConstructorInfo ctor) throw new ArgumentException("Constructor of abstract type cannot be created", nameof(ctor)); } - this.Settings.MapToConstructor = ctor; + Settings.MapToConstructor = ctor; return this; } @@ -835,17 +835,17 @@ public TypeAdapterSetter GenerateMapper(MapType mapType) public TwoWaysTypeAdapterSetter TwoWays() { - return new TwoWaysTypeAdapterSetter(this.Config); + return new TwoWaysTypeAdapterSetter(Config); } public void Compile() { - this.Config.Compile(typeof(TSource), typeof(TDestination)); + Config.Compile(typeof(TSource), typeof(TDestination)); } public void CompileProjection() { - this.Config.CompileProjection(typeof(TSource), typeof(TDestination)); + Config.CompileProjection(typeof(TSource), typeof(TDestination)); } } @@ -1019,7 +1019,7 @@ public TwoWaysTypeAdapterSetter Ignore(params Expression< foreach (var member in members) { var path = member.GetMemberPath()!; - this.Ignore(path); + Ignore(path); } return this; } diff --git a/src/Mapster/Utils/BlockExpressionDetector.cs b/src/Mapster/Utils/BlockExpressionDetector.cs index d27a3c91..9c788882 100644 --- a/src/Mapster/Utils/BlockExpressionDetector.cs +++ b/src/Mapster/Utils/BlockExpressionDetector.cs @@ -8,7 +8,7 @@ sealed class BlockExpressionDetector : ExpressionVisitor public override Expression? Visit(Expression? node) { - if (this.IsBlockExpression || node == null) + if (IsBlockExpression || node == null) return node; switch (node.NodeType) @@ -40,7 +40,7 @@ sealed class BlockExpressionDetector : ExpressionVisitor case ExpressionType.PreDecrementAssign: case ExpressionType.PostIncrementAssign: case ExpressionType.PostDecrementAssign: - this.IsBlockExpression = true; + IsBlockExpression = true; return node; }