Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
DebugViewWriter.cs1220 linesDownload Raw Back to parser
1/* ****************************************************************************2 *3 * Copyright (c) Microsoft Corporation.4 *5 * This source code is subject to terms and conditions of the Microsoft Public License. A6 * copy of the license can be found in the License.html file at the root of this distribution. If7 * you cannot locate the Microsoft Public License, please send an email to8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound9 * by the terms of the Microsoft Public License.10 *11 * You must not remove this notice, or any other, from this software.12 *13 *14 * ***************************************************************************/15 16#if ENABLE_BINDER_DEBUG_LOGGING17 18using System.Linq.Expressions;19using System.Collections.Generic;20using System.IO;21using System.Runtime.CompilerServices;22using System.Reflection;23using System.Globalization;24using System.Diagnostics;25using System.Dynamic;26 27namespace System.Management.Automation.Language {28    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]29    internal sealed class DebugViewWriter : DynamicExpressionVisitor {30        [Flags]31        private enum Flow {32            None,33            Space,34            NewLine,35 36            Break = 0x8000      // newline if column > MaxColumn37        };38 39        private const int Tab = 4;40        private const int MaxColumn = 120;41 42        private TextWriter _out;43        private int _column;44 45        private Stack<int> _stack = new Stack<int>();46        private int _delta;47        private Flow _flow;48 49        // All the unique lambda expressions in the ET, will be used for displaying all50        // the lambda definitions.51        private Queue<LambdaExpression> _lambdas;52 53        // Associate every unique anonymous LambdaExpression in the tree with an integer.54        // The id is used to create a name for the anonymous lambda.55        //56        private Dictionary<LambdaExpression, int> _lambdaIds;57 58        // Associate every unique anonymous parameter or variable in the tree with an integer.59        // The id is used to create a name for the anonymous parameter or variable.60        //61        private Dictionary<ParameterExpression, int> _paramIds;62 63        // Associate every unique anonymous LabelTarget in the tree with an integer.64        // The id is used to create a name for the anonymous LabelTarget.65        //66        private Dictionary<LabelTarget, int> _labelIds;67 68        private DebugViewWriter(TextWriter file) {69            _out = file;70        }71 72        private int Base {73            get {74                return _stack.Count > 0 ? _stack.Peek() : 0;75            }76        }77 78        private int Delta {79            get { return _delta; }80        }81 82        private int Depth {83            get { return Base + Delta; }84        }85 86        private void Indent() {87            _delta += Tab;88        }89 90        private void Dedent() {91            _delta -= Tab;92        }93 94        private void NewLine() {95            _flow = Flow.NewLine;96        }97 98        private static int GetId<T>(T e, ref Dictionary<T, int> ids) {99            if (ids == null) {100                ids = new Dictionary<T, int>();101                ids.Add(e, 1);102                return 1;103            } else {104                int id;105                if (!ids.TryGetValue(e, out id)) {106                    // e is met the first time107                    id = ids.Count + 1;108                    ids.Add(e, id);109                }110 111                return id;112            }113        }114 115        private int GetLambdaId(LambdaExpression le) {116            Debug.Assert(string.IsNullOrEmpty(le.Name));117            return GetId(le, ref _lambdaIds);118        }119 120        private int GetParamId(ParameterExpression p) {121            Debug.Assert(string.IsNullOrEmpty(p.Name));122            return GetId(p, ref _paramIds);123        }124 125        private int GetLabelTargetId(LabelTarget target) {126            Debug.Assert(string.IsNullOrEmpty(target.Name));127            return GetId(target, ref _labelIds);128        }129 130        /// <summary>131        /// Write out the given AST.132        /// </summary>133        internal static void WriteTo(Expression node, TextWriter writer) {134            Debug.Assert(node != null);135            Debug.Assert(writer != null);136 137            new DebugViewWriter(writer).WriteTo(node);138        }139 140        private void WriteTo(Expression node) {141            var lambda = node as LambdaExpression;142            if (lambda != null) {143                WriteLambda(lambda);144            } else {145                Visit(node);146                Debug.Assert(_stack.Count == 0);147            }148 149            //150            // Output all lambda expression definitions.151            // in the order of their appearances in the tree.152            //153            while (_lambdas != null && _lambdas.Count > 0) {154                WriteLine();155                WriteLine();156                WriteLambda(_lambdas.Dequeue());157            }158        }159 160#region The printing code161 162        private void Out(string s) {163            Out(Flow.None, s, Flow.None);164        }165 166        private void Out(Flow before, string s) {167            Out(before, s, Flow.None);168        }169 170        private void Out(string s, Flow after) {171            Out(Flow.None, s, after);172        }173 174        private void Out(Flow before, string s, Flow after) {175            switch (GetFlow(before)) {176                case Flow.None:177                    break;178                case Flow.Space:179                    Write(" ");180                    break;181                case Flow.NewLine:182                    WriteLine();183                    Write(new string(' ', Depth));184                    break;185            }186 187            Write(s);188            _flow = after;189        }190 191        private void WriteLine() {192            _out.WriteLine();193            _column = 0;194        }195 196        private void Write(string s) {197            _out.Write(s);198            _column += s.Length;199        }200 201        private Flow GetFlow(Flow flow) {202            Flow last;203 204            last = CheckBreak(_flow);205            flow = CheckBreak(flow);206 207            // Get the biggest flow that is requested None < Space < NewLine208            return (Flow)System.Math.Max((int)last, (int)flow);209        }210 211        private Flow CheckBreak(Flow flow) {212            if ((flow & Flow.Break) != 0) {213                if (_column > (MaxColumn + Depth)) {214                    flow = Flow.NewLine;215                } else {216                    flow &= ~Flow.Break;217                }218            }219 220            return flow;221        }222 223#endregion224 225#region The AST Output226 227        // More proper would be to make this a virtual method on Action228        private static string FormatBinder(CallSiteBinder binder) {229            ConvertBinder convert;230            GetMemberBinder getMember;231            SetMemberBinder setMember;232            DeleteMemberBinder deleteMember;233            GetIndexBinder getIndex;234            SetIndexBinder setIndex;235            DeleteIndexBinder deleteIndex;236            InvokeMemberBinder call;237            InvokeBinder invoke;238            CreateInstanceBinder create;239            UnaryOperationBinder unary;240            BinaryOperationBinder binary;241 242            if ((convert = binder as ConvertBinder) != null) {243                return "Convert " + convert.Type.ToString();244            } else if ((getMember = binder as GetMemberBinder) != null) {245                return "GetMember " + getMember.Name;246            } else if ((setMember = binder as SetMemberBinder) != null) {247                return "SetMember " + setMember.Name;248            } else if ((deleteMember = binder as DeleteMemberBinder) != null) {249                return "DeleteMember " + deleteMember.Name;250            } else if ((getIndex = binder as GetIndexBinder) != null) {251                return "GetIndex";252            } else if ((setIndex = binder as SetIndexBinder) != null) {253                return "SetIndex";254            } else if ((deleteIndex = binder as DeleteIndexBinder) != null) {255                return "DeleteIndex";256            } else if ((call = binder as InvokeMemberBinder) != null) {257                return "Call " + call.Name;258            } else if ((invoke = binder as InvokeBinder) != null) {259                return "Invoke";260            } else if ((create = binder as CreateInstanceBinder) != null) {261                return "Create";262            } else if ((unary = binder as UnaryOperationBinder) != null) {263                return "UnaryOperation " + unary.Operation;264            } else if ((binary = binder as BinaryOperationBinder) != null) {265                return "BinaryOperation " + binary.Operation;266            } else {267                return binder.ToString();268            }269        }270 271        private void VisitExpressions<T>(char open, IList<T> expressions) where T : Expression {272            VisitExpressions<T>(open, ',', expressions);273        }274 275        private void VisitExpressions<T>(char open, char separator, IList<T> expressions) where T : Expression {276            VisitExpressions(open, separator, expressions, e => Visit(e));277        }278 279        private void VisitDeclarations(IList<ParameterExpression> expressions) {280            VisitExpressions('(', ',', expressions, variable =>281            {282                Out(variable.Type.ToString());283                if (variable.IsByRef) {284                    Out("&");285                }286 287                Out(" ");288                VisitParameter(variable);289            });290        }291 292        private void VisitExpressions<T>(char open, char separator, IList<T> expressions, Action<T> visit) {293            Out(open.ToString());294 295            if (expressions != null) {296                Indent();297                bool isFirst = true;298                foreach (T e in expressions) {299                    if (isFirst) {300                        if (open == '{' || expressions.Count > 1) {301                            NewLine();302                        }303 304                        isFirst = false;305                    } else {306                        Out(separator.ToString(), Flow.NewLine);307                    }308 309                    visit(e);310                }311 312                Dedent();313            }314 315            char close;316            switch (open) {317                case '(': close = ')'; break;318                case '{': close = '}'; break;319                case '[': close = ']'; break;320                case '<': close = '>'; break;321                default:322                close = ' ';323                Diagnostics.Assert(false, "Unexpected open brace.");324                break;325            }326 327            if (open == '{') {328                NewLine();329            }330 331            Out(close.ToString(), Flow.Break);332        }333 334        protected override Expression VisitDynamic(DynamicExpression node) {335            Out(".Dynamic", Flow.Space);336            Out(FormatBinder(node.Binder));337            VisitExpressions('(', node.Arguments);338            return node;339        }340 341        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]342        protected override Expression VisitBinary(BinaryExpression node) {343            if (node.NodeType == ExpressionType.ArrayIndex) {344                ParenthesizedVisit(node, node.Left);345                Out("[");346                Visit(node.Right);347                Out("]");348            } else {349                bool parenthesizeLeft = NeedsParentheses(node, node.Left);350                bool parenthesizeRight = NeedsParentheses(node, node.Right);351 352                string op;353                bool isChecked = false;354                Flow beforeOp = Flow.Space;355                switch (node.NodeType) {356                    case ExpressionType.Assign: op = "="; break;357                    case ExpressionType.Equal: op = "=="; break;358                    case ExpressionType.NotEqual: op = "!="; break;359                    case ExpressionType.AndAlso: op = "&&"; beforeOp = Flow.Break | Flow.Space; break;360                    case ExpressionType.OrElse: op = "||"; beforeOp = Flow.Break | Flow.Space; break;361                    case ExpressionType.GreaterThan: op = ">"; break;362                    case ExpressionType.LessThan: op = "<"; break;363                    case ExpressionType.GreaterThanOrEqual: op = ">="; break;364                    case ExpressionType.LessThanOrEqual: op = "<="; break;365                    case ExpressionType.Add: op = "+"; break;366                    case ExpressionType.AddAssign: op = "+="; break;367                    case ExpressionType.AddAssignChecked: op = "+="; isChecked = true; break;368                    case ExpressionType.AddChecked: op = "+"; isChecked = true; break;369                    case ExpressionType.Subtract: op = "-"; break;370                    case ExpressionType.SubtractAssign: op = "-="; break;371                    case ExpressionType.SubtractAssignChecked: op = "-="; isChecked = true; break;372                    case ExpressionType.SubtractChecked: op = "-"; isChecked = true; break;373                    case ExpressionType.Divide: op = "/"; break;374                    case ExpressionType.DivideAssign: op = "/="; break;375                    case ExpressionType.Modulo: op = "%"; break;376                    case ExpressionType.ModuloAssign: op = "%="; break;377                    case ExpressionType.Multiply: op = "*"; break;378                    case ExpressionType.MultiplyAssign: op = "*="; break;379                    case ExpressionType.MultiplyAssignChecked: op = "*="; isChecked = true; break;380                    case ExpressionType.MultiplyChecked: op = "*"; isChecked = true; break;381                    case ExpressionType.LeftShift: op = "<<"; break;382                    case ExpressionType.LeftShiftAssign: op = "<<="; break;383                    case ExpressionType.RightShift: op = ">>"; break;384                    case ExpressionType.RightShiftAssign: op = ">>="; break;385                    case ExpressionType.And: op = "&"; break;386                    case ExpressionType.AndAssign: op = "&="; break;387                    case ExpressionType.Or: op = "|"; break;388                    case ExpressionType.OrAssign: op = "|="; break;389                    case ExpressionType.ExclusiveOr: op = "^"; break;390                    case ExpressionType.ExclusiveOrAssign: op = "^="; break;391                    case ExpressionType.Power: op = "**"; break;392                    case ExpressionType.PowerAssign: op = "**="; break;393                    case ExpressionType.Coalesce: op = "??"; break;394 395                    default:396                        throw new InvalidOperationException();397                }398 399                if (parenthesizeLeft) {400                    Out("(", Flow.None);401                }402 403                Visit(node.Left);404                if (parenthesizeLeft) {405                    Out(Flow.None, ")", Flow.Break);406                }407 408                // prepend # to the operator to represent checked op409                if (isChecked) {410                    op = string.Format(411                            CultureInfo.CurrentCulture,412                            "#{0}",413                            op414                    );415                }416 417                Out(beforeOp, op, Flow.Space | Flow.Break);418 419                if (parenthesizeRight) {420                    Out("(", Flow.None);421                }422 423                Visit(node.Right);424                if (parenthesizeRight) {425                    Out(Flow.None, ")", Flow.Break);426                }427            }428 429            return node;430        }431 432        protected override Expression VisitParameter(ParameterExpression node) {433            // Have '$' for the DebugView of ParameterExpressions434            Out("$");435            if (string.IsNullOrEmpty(node.Name)) {436                // If no name if provided, generate a name as $var1, $var2.437                // No guarantee for not having name conflicts with user provided variable names.438                //439                int id = GetParamId(node);440                Out("var" + id);441            } else {442                Out(GetDisplayName(node.Name));443            }444 445            return node;446        }447 448        protected override Expression VisitLambda<T>(Expression<T> node) {449            Out(450                string.Format(CultureInfo.CurrentCulture,451                    "{0} {1}<{2}>",452                    ".Lambda",453                    GetLambdaName(node),454                    node.Type.ToString()455                )456            );457 458            if (_lambdas == null) {459                _lambdas = new Queue<LambdaExpression>();460            }461 462            // N^2 performance, for keeping the order of the lambdas.463            if (!_lambdas.Contains(node)) {464                _lambdas.Enqueue(node);465            }466 467            return node;468        }469 470        private static bool IsSimpleExpression(Expression node) {471            var binary = node as BinaryExpression;472            if (binary != null) {473                return binary.Left is not BinaryExpression && binary.Right is not BinaryExpression;474            }475 476            return false;477        }478 479        protected override Expression VisitConditional(ConditionalExpression node) {480            if (IsSimpleExpression(node.Test)) {481                Out(".If (");482                Visit(node.Test);483                Out(") {", Flow.NewLine);484            } else {485                Out(".If (", Flow.NewLine);486                Indent();487                Visit(node.Test);488                Dedent();489                Out(Flow.NewLine, ") {", Flow.NewLine);490            }491 492            Indent();493            Visit(node.IfTrue);494            Dedent();495            Out(Flow.NewLine, "} .Else {", Flow.NewLine);496            Indent();497            Visit(node.IfFalse);498            Dedent();499            Out(Flow.NewLine, "}");500            return node;501        }502 503        protected override Expression VisitConstant(ConstantExpression node) {504            object value = node.Value;505 506            if (value == null) {507                Out("null");508            } else if ((value is string) && node.Type == typeof(string)) {509                Out(string.Format(510                    CultureInfo.CurrentCulture,511                    "\"{0}\"",512                    value));513            } else if ((value is char) && node.Type == typeof(char)) {514                    Out(string.Format(515                        CultureInfo.CurrentCulture,516                        "'{0}'",517                        value));518            } else if ((value is int) && node.Type == typeof(int)519                || (value is bool) && node.Type == typeof(bool)) {520                Out(value.ToString());521            } else {522                string suffix = GetConstantValueSuffix(node.Type);523                if (suffix != null) {524                    Out(value.ToString());525                    Out(suffix);526                } else {527                    Out(string.Format(528                        CultureInfo.CurrentCulture,529                        ".Constant<{0}>({1})",530                        node.Type.ToString(),531                        value));532                }533            }534 535            return node;536        }537 538        private static string GetConstantValueSuffix(Type type) {539            if (type == typeof(UInt32)) {540                return "U";541            }542 543            if (type == typeof(Int64)) {544                return "L";545            }546 547            if (type == typeof(UInt64)) {548                return "UL";549            }550 551            if (type == typeof(double)) {552                return "D";553            }554 555            if (type == typeof(Single)) {556                return "F";557            }558 559            if (type == typeof(decimal)) {560                return "M";561            }562 563            return null;564        }565 566        protected override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {567            Out(".RuntimeVariables");568            VisitExpressions('(', node.Variables);569            return node;570        }571 572        // Prints ".instanceField" or "declaringType.staticField"573        private void OutMember(Expression node, Expression instance, MemberInfo member) {574            if (instance != null) {575                ParenthesizedVisit(node, instance);576                Out("." + member.Name);577            } else {578                // For static members, include the type name579                Out(member.DeclaringType.ToString() + "." + member.Name);580            }581        }582 583        protected override Expression VisitMember(MemberExpression node) {584            OutMember(node, node.Expression, node.Member);585            return node;586        }587 588        protected override Expression VisitInvocation(InvocationExpression node) {589            Out(".Invoke ");590            ParenthesizedVisit(node, node.Expression);591            VisitExpressions('(', node.Arguments);592            return node;593        }594 595        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]596        private static bool NeedsParentheses(Expression parent, Expression child) {597            Debug.Assert(parent != null);598            if (child == null) {599                return false;600            }601 602            // Some nodes always have parentheses because of how they are603            // displayed, for example: ".Unbox(obj.Foo)"604            switch (parent.NodeType) {605                case ExpressionType.Increment:606                case ExpressionType.Decrement:607                case ExpressionType.IsTrue:608                case ExpressionType.IsFalse:609                case ExpressionType.Unbox:610                    return true;611            }612 613            int childOpPrec = GetOperatorPrecedence(child);614            int parentOpPrec = GetOperatorPrecedence(parent);615 616            if (childOpPrec == parentOpPrec) {617                // When parent op and child op has the same precedence,618                // we want to be a little conservative to have more clarity.619                // Parentheses are not needed if620                // 1) Both ops are &&, ||, &, |, or ^, all of them are the only621                // op that has the precedence.622                // 2) Parent op is + or *, e.g. x + (y - z) can be simplified to623                // x + y - z.624                // 3) Parent op is -, / or %, and the child is the left operand.625                // In this case, if left and right operand are the same, we don't626                // remove parenthesis, e.g. (x + y) - (x + y)627                //628                switch (parent.NodeType) {629                    case ExpressionType.AndAlso:630                    case ExpressionType.OrElse:631                    case ExpressionType.And:632                    case ExpressionType.Or:633                    case ExpressionType.ExclusiveOr:634                        // Since these ops are the only ones on their precedence,635                        // the child op must be the same.636                        Debug.Assert(child.NodeType == parent.NodeType);637                        // We remove the parenthesis, e.g. x && y && z638                        return false;639                    case ExpressionType.Add:640                    case ExpressionType.AddChecked:641                    case ExpressionType.Multiply:642                    case ExpressionType.MultiplyChecked:643                        return false;644                    case ExpressionType.Subtract:645                    case ExpressionType.SubtractChecked:646                    case ExpressionType.Divide:647                    case ExpressionType.Modulo:648                        BinaryExpression binary = parent as BinaryExpression;649                        Debug.Assert(binary != null);650                        // Need to have parenthesis for the right operand.651                        return child == binary.Right;652                }653 654                return true;655            }656 657            // Special case: negate of a constant needs parentheses, to658            // disambiguate it from a negative constant.659            if (child != null && child.NodeType == ExpressionType.Constant &&660                (parent.NodeType == ExpressionType.Negate || parent.NodeType == ExpressionType.NegateChecked)) {661                return true;662            }663 664            // If the parent op has higher precedence, need parentheses for the child.665            return childOpPrec < parentOpPrec;666        }667 668        // the greater the higher669        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]670        private static int GetOperatorPrecedence(Expression node) {671 672            // Roughly matches C# operator precedence, with some additional673            // operators. Also things which are not binary/unary expressions,674            // such as conditional and type testing, don't use this mechanism.675            switch (node.NodeType) {676                // Assignment677                case ExpressionType.Assign:678                case ExpressionType.ExclusiveOrAssign:679                case ExpressionType.AddAssign:680                case ExpressionType.AddAssignChecked:681                case ExpressionType.SubtractAssign:682                case ExpressionType.SubtractAssignChecked:683                case ExpressionType.DivideAssign:684                case ExpressionType.ModuloAssign:685                case ExpressionType.MultiplyAssign:686                case ExpressionType.MultiplyAssignChecked:687                case ExpressionType.LeftShiftAssign:688                case ExpressionType.RightShiftAssign:689                case ExpressionType.AndAssign:690                case ExpressionType.OrAssign:691                case ExpressionType.PowerAssign:692                case ExpressionType.Coalesce:693                    return 1;694 695                // Conditional (?:) would go here696 697                // Conditional OR698                case ExpressionType.OrElse:699                    return 2;700 701                // Conditional AND702                case ExpressionType.AndAlso:703                    return 3;704 705                // Logical OR706                case ExpressionType.Or:707                    return 4;708 709                // Logical XOR710                case ExpressionType.ExclusiveOr:711                    return 5;712 713                // Logical AND714                case ExpressionType.And:715                    return 6;716 717                // Equality718                case ExpressionType.Equal:719                case ExpressionType.NotEqual:720                    return 7;721 722                // Relational, type testing723                case ExpressionType.GreaterThan:724                case ExpressionType.LessThan:725                case ExpressionType.GreaterThanOrEqual:726                case ExpressionType.LessThanOrEqual:727                case ExpressionType.TypeAs:728                case ExpressionType.TypeIs:729                case ExpressionType.TypeEqual:730                    return 8;731 732                // Shift733                case ExpressionType.LeftShift:734                case ExpressionType.RightShift:735                    return 9;736 737                // Additive738                case ExpressionType.Add:739                case ExpressionType.AddChecked:740                case ExpressionType.Subtract:741                case ExpressionType.SubtractChecked:742                    return 10;743 744                // Multiplicative745                case ExpressionType.Divide:746                case ExpressionType.Modulo:747                case ExpressionType.Multiply:748                case ExpressionType.MultiplyChecked:749                    return 11;750 751                // Unary752                case ExpressionType.Negate:753                case ExpressionType.NegateChecked:754                case ExpressionType.UnaryPlus:755                case ExpressionType.Not:756                case ExpressionType.Convert:757                case ExpressionType.ConvertChecked:758                case ExpressionType.PreIncrementAssign:759                case ExpressionType.PreDecrementAssign:760                case ExpressionType.OnesComplement:761                case ExpressionType.Increment:762                case ExpressionType.Decrement:763                case ExpressionType.IsTrue:764                case ExpressionType.IsFalse:765                case ExpressionType.Unbox:766                case ExpressionType.Throw:767                    return 12;768 769                // Power, which is not in C#770                // But VB/Python/Ruby put it here, above unary.771                case ExpressionType.Power:772                    return 13;773 774                // Primary, which includes all other node types:775                //   member access, calls, indexing, new.776                case ExpressionType.PostIncrementAssign:777                case ExpressionType.PostDecrementAssign:778                default:779                    return 14;780 781                // These aren't expressions, so never need parentheses:782                //   constants, variables783                case ExpressionType.Constant:784                case ExpressionType.Parameter:785                    return 15;786            }787        }788 789        private void ParenthesizedVisit(Expression parent, Expression nodeToVisit) {790            if (NeedsParentheses(parent, nodeToVisit)) {791                Out("(");792                Visit(nodeToVisit);793                Out(")");794            } else {795                Visit(nodeToVisit);796            }797        }798 799        protected override Expression VisitMethodCall(MethodCallExpression node) {800            Out(".Call ");801            if (node.Object != null) {802                ParenthesizedVisit(node, node.Object);803            } else if (node.Method.DeclaringType != null) {804                Out(node.Method.DeclaringType.ToString());805            } else {806                Out("<UnknownType>");807            }808 809            Out(".");810            Out(node.Method.Name);811            VisitExpressions('(', node.Arguments);812            return node;813        }814 815        protected override Expression VisitNewArray(NewArrayExpression node) {816            if (node.NodeType == ExpressionType.NewArrayBounds) {817                // .NewArray MyType[expr1, expr2]818                Out(".NewArray " + node.Type.GetElementType().ToString());819                VisitExpressions('[', node.Expressions);820            } else {821                // .NewArray MyType {expr1, expr2}822 823                Out(".NewArray " + node.Type.ToString(), Flow.Space);824                VisitExpressions('{', node.Expressions);825            }826 827            return node;828        }829 830        protected override Expression VisitNew(NewExpression node) {831            Out(".New " + node.Type.ToString());832            VisitExpressions('(', node.Arguments);833            return node;834        }835 836        protected override ElementInit VisitElementInit(ElementInit node) {837            if (node.Arguments.Count == 1) {838                Visit(node.Arguments[0]);839            } else {840                VisitExpressions('{', node.Arguments);841            }842 843            return node;844        }845 846        protected override Expression VisitListInit(ListInitExpression node) {847            Visit(node.NewExpression);848            VisitExpressions('{', ',', node.Initializers, e => VisitElementInit(e));849            return node;850        }851 852        protected override MemberAssignment VisitMemberAssignment(MemberAssignment assignment) {853            Out(assignment.Member.Name);854            Out(Flow.Space, "=", Flow.Space);855            Visit(assignment.Expression);856            return assignment;857        }858 859        protected override MemberListBinding VisitMemberListBinding(MemberListBinding binding) {860            Out(binding.Member.Name);861            Out(Flow.Space, "=", Flow.Space);862            VisitExpressions('{', ',', binding.Initializers, e => VisitElementInit(e));863            return binding;864        }865 866        protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) {867            Out(binding.Member.Name);868            Out(Flow.Space, "=", Flow.Space);869            VisitExpressions('{', ',', binding.Bindings, e => VisitMemberBinding(e));870            return binding;871        }872 873        protected override Expression VisitMemberInit(MemberInitExpression node) {874            Visit(node.NewExpression);875            VisitExpressions('{', ',', node.Bindings, e => VisitMemberBinding(e));876            return node;877        }878 879        protected override Expression VisitTypeBinary(TypeBinaryExpression node) {880            ParenthesizedVisit(node, node.Expression);881            switch (node.NodeType) {882                case ExpressionType.TypeIs:883                    Out(Flow.Space, ".Is", Flow.Space);884                    break;885                case ExpressionType.TypeEqual:886                    Out(Flow.Space, ".TypeEqual", Flow.Space);887                    break;888            }889 890            Out(node.TypeOperand.ToString());891            return node;892        }893 894        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]895        protected override Expression VisitUnary(UnaryExpression node) {896            bool parenthesize = NeedsParentheses(node, node.Operand);897 898            switch (node.NodeType) {899                case ExpressionType.Convert:900                    Out("(" + node.Type.ToString() + ")");901                    break;902                case ExpressionType.ConvertChecked:903                    Out("#(" + node.Type.ToString() + ")");904                    break;905                case ExpressionType.TypeAs:906                    break;907                case ExpressionType.Not:908                    Out(node.Type == typeof(bool) ? "!" : "~");909                    break;910                case ExpressionType.OnesComplement:911                    Out("~");912                    break;913                case ExpressionType.Negate:914                    Out("-");915                    break;916                case ExpressionType.NegateChecked:917                    Out("#-");918                    break;919                case ExpressionType.UnaryPlus:920                    Out("+");921                    break;922                case ExpressionType.ArrayLength:923                    break;924                case ExpressionType.Quote:925                    Out("'");926                    break;927                case ExpressionType.Throw:928                    if (node.Operand == null) {929                        Out(".Rethrow");930                    } else {931                        Out(".Throw", Flow.Space);932                    }933 934                    break;935                case ExpressionType.IsFalse:936                    Out(".IsFalse");937                    break;938                case ExpressionType.IsTrue:939                    Out(".IsTrue");940                    break;941                case ExpressionType.Decrement:942                    Out(".Decrement");943                    break;944                case ExpressionType.Increment:945                    Out(".Increment");946                    break;947                case ExpressionType.PreDecrementAssign:948                    Out("--");949                    break;950                case ExpressionType.PreIncrementAssign:951                    Out("++");952                    break;953                case ExpressionType.Unbox:954                    Out(".Unbox");955                    break;956            }957 958            ParenthesizedVisit(node, node.Operand);959 960            switch (node.NodeType) {961                case ExpressionType.TypeAs:962                    Out(Flow.Space, ".As", Flow.Space | Flow.Break);963                    Out(node.Type.ToString());964                    break;965 966                case ExpressionType.ArrayLength:967                    Out(".Length");968                    break;969 970                case ExpressionType.PostDecrementAssign:971                    Out("--");972                    break;973 974                case ExpressionType.PostIncrementAssign:975                    Out("++");976                    break;977            }978 979            return node;980        }981 982        protected override Expression VisitBlock(BlockExpression node) {983            Out(".Block");984 985            // Display <type> if the type of the BlockExpression is different from the986            // last expression's type in the block.987            if (node.Type != node.Expressions[node.Expressions.Count - 1].Type) {988                Out(string.Create(CultureInfo.CurrentCulture, $"<{node.Type}>"));989            }990 991            VisitDeclarations(node.Variables);992            Out(" ");993            // Use ; to separate expressions in the block994            VisitExpressions('{', ';', node.Expressions);995 996            return node;997        }998 999        protected override Expression VisitDefault(DefaultExpression node) {1000            Out(".Default(" + node.Type.ToString() + ")");1001            return node;1002        }1003 1004        protected override Expression VisitLabel(LabelExpression node) {1005            Out(".Label", Flow.NewLine);1006            Indent();1007            Visit(node.DefaultValue);1008            Dedent();1009            NewLine();1010            DumpLabel(node.Target);1011            return node;1012        }1013 1014        protected override Expression VisitGoto(GotoExpression node) {1015            Out("." + node.Kind.ToString(), Flow.Space);1016            Out(GetLabelTargetName(node.Target), Flow.Space);1017            Out("{", Flow.Space);1018            Visit(node.Value);1019            Out(Flow.Space, "}");1020            return node;1021        }1022 1023        protected override Expression VisitLoop(LoopExpression node) {1024            Out(".Loop", Flow.Space);1025            if (node.ContinueLabel != null) {1026                DumpLabel(node.ContinueLabel);1027            }1028 1029            Out(" {", Flow.NewLine);1030            Indent();1031            Visit(node.Body);1032            Dedent();1033            Out(Flow.NewLine, "}");1034            if (node.BreakLabel != null) {1035                Out(string.Empty, Flow.NewLine);1036                DumpLabel(node.BreakLabel);1037            }1038 1039            return node;1040        }1041 1042        protected override SwitchCase VisitSwitchCase(SwitchCase node) {1043            foreach (var test in node.TestValues) {1044                Out(".Case (");1045                Visit(test);1046                Out("):", Flow.NewLine);1047            }1048 1049            Indent(); Indent();1050            Visit(node.Body);1051            Dedent(); Dedent();1052            NewLine();1053            return node;1054        }1055 1056        protected override Expression VisitSwitch(SwitchExpression node) {1057            Out(".Switch ");1058            Out("(");1059            Visit(node.SwitchValue);1060            Out(") {", Flow.NewLine);1061            Visit(node.Cases, VisitSwitchCase);1062            if (node.DefaultBody != null) {1063                Out(".Default:", Flow.NewLine);1064                Indent(); Indent();1065                Visit(node.DefaultBody);1066                Dedent(); Dedent();1067                NewLine();1068            }1069 1070            Out("}");1071            return node;1072        }1073 1074        protected override CatchBlock VisitCatchBlock(CatchBlock node) {1075            Out(Flow.NewLine, "} .Catch (" + node.Test.ToString());1076            if (node.Variable != null) {1077                Out(Flow.Space, string.Empty);1078                VisitParameter(node.Variable);1079            }1080 1081            if (node.Filter != null) {1082                Out(") .If (", Flow.Break);1083                Visit(node.Filter);1084            }1085 1086            Out(") {", Flow.NewLine);1087            Indent();1088            Visit(node.Body);1089            Dedent();1090            return node;1091        }1092 1093        protected override Expression VisitTry(TryExpression node) {1094            Out(".Try {", Flow.NewLine);1095            Indent();1096            Visit(node.Body);1097            Dedent();1098            Visit(node.Handlers, VisitCatchBlock);1099            if (node.Finally != null) {1100                Out(Flow.NewLine, "} .Finally {", Flow.NewLine);1101                Indent();1102                Visit(node.Finally);1103                Dedent();1104            } else if (node.Fault != null) {1105                Out(Flow.NewLine, "} .Fault {", Flow.NewLine);1106                Indent();1107                Visit(node.Fault);1108                Dedent();1109            }1110 1111            Out(Flow.NewLine, "}");1112            return node;1113        }1114 1115        protected override Expression VisitIndex(IndexExpression node) {1116            if (node.Indexer != null) {1117                OutMember(node, node.Object, node.Indexer);1118            } else {1119                ParenthesizedVisit(node, node.Object);1120            }1121 1122            VisitExpressions('[', node.Arguments);1123            return node;1124        }1125 1126        protected override Expression VisitExtension(Expression node) {1127            Out(string.Create(CultureInfo.CurrentCulture, $".Extension<{node.GetType()}>"));1128 1129            if (node.CanReduce) {1130                Out(Flow.Space, "{", Flow.NewLine);1131                Indent();1132                Visit(node.Reduce());1133                Dedent();1134                Out(Flow.NewLine, "}");1135            }1136 1137            return node;1138        }1139 1140        protected override Expression VisitDebugInfo(DebugInfoExpression node) {1141            Out(string.Format(1142                CultureInfo.CurrentCulture,1143                ".DebugInfo({0}: {1}, {2} - {3}, {4})",1144                node.Document.FileName,1145                node.StartLine,1146                node.StartColumn,1147                node.EndLine,1148                node.EndColumn)1149            );1150            return node;1151        }1152 1153        private void DumpLabel(LabelTarget target) {1154            Out(string.Create(CultureInfo.CurrentCulture, $".LabelTarget {GetLabelTargetName(target)}:"));1155        }1156 1157        private string GetLabelTargetName(LabelTarget target) {1158            if (string.IsNullOrEmpty(target.Name)) {1159                // Create the label target name as #Label1, #Label2, etc.1160                return string.Create(CultureInfo.CurrentCulture, $"#Label{GetLabelTargetId(target)}");1161            } else {1162                return GetDisplayName(target.Name);1163            }1164        }1165 1166        private void WriteLambda(LambdaExpression lambda) {1167            Out(1168                string.Create(CultureInfo.CurrentCulture, $".Lambda {GetLambdaName(lambda)}<{lambda.Type}>")1169            );1170 1171            VisitDeclarations(lambda.Parameters);1172 1173            Out(Flow.Space, "{", Flow.NewLine);1174            Indent();1175            Visit(lambda.Body);1176            Dedent();1177            Out(Flow.NewLine, "}");1178            Debug.Assert(_stack.Count == 0);1179        }1180 1181        private string GetLambdaName(LambdaExpression lambda) {1182            if (string.IsNullOrEmpty(lambda.Name)) {1183                return "#Lambda" + GetLambdaId(lambda);1184            }1185 1186            return GetDisplayName(lambda.Name);1187        }1188 1189        /// <summary>1190        /// Return true if the input string contains any whitespace character.1191        /// Otherwise false.1192        /// </summary>1193        private static bool ContainsWhiteSpace(string name) {1194            foreach (char c in name) {1195                if (char.IsWhiteSpace(c)) {1196                    return true;1197                }1198            }1199 1200            return false;

Showing the first 1,200 of 1220 lines. Download the file for the rest.