CodeDomDecompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Activities / Rules / CodeDomDecompiler.cs / 1305376 / CodeDomDecompiler.cs

                            using System; 
using System.CodeDom;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; 
using System.Reflection;
using System.Text; 
using System.Workflow.ComponentModel; 

namespace System.Workflow.Activities.Rules 
{
    internal static class RuleDecompiler
    {
        #region Decompile literals 

        internal static void DecompileObjectLiteral(StringBuilder decompilation, object primitiveValue) 
        { 
            if (primitiveValue == null)
            { 
                decompilation.Append("null");
            }
            else
            { 
                Type primitiveType = primitiveValue.GetType();
 
                if (primitiveType == typeof(string)) 
                    DecompileStringLiteral(decompilation, (string)primitiveValue);
                else if (primitiveType == typeof(char)) 
                    DecompileCharacterLiteral(decompilation, (char)primitiveValue);
                else if (primitiveType == typeof(long))
                    DecompileSuffixedIntegerLiteral(decompilation, primitiveValue, "L");
                else if (primitiveType == typeof(uint)) 
                    DecompileSuffixedIntegerLiteral(decompilation, primitiveValue, "U");
                else if (primitiveType == typeof(ulong)) 
                    DecompileSuffixedIntegerLiteral(decompilation, primitiveValue, "UL"); 
                else if (primitiveType == typeof(float))
                    DecompileFloatingPointLiteral(decompilation, primitiveValue, 'f'); 
                else if (primitiveType == typeof(double))
                    DecompileFloatingPointLiteral(decompilation, primitiveValue, 'd');
                else if (primitiveType == typeof(decimal))
                    DecompileFloatingPointLiteral(decompilation, primitiveValue, 'm'); 
                else
                    decompilation.Append(primitiveValue.ToString()); 
            } 
        }
 
        private static void DecompileFloatingPointLiteral(StringBuilder decompilation, object value, char suffix)
        {
            // Make sure decimal point isn't converted to a comma in European locales.
            string svalue = Convert.ToString(value, CultureInfo.InvariantCulture); 
            decompilation.Append(svalue);
 
            if (suffix == 'd') 
            {
                // Don't append 'd' suffixes, they're ugly.  Only if the string-ified value contains 
                // no decimal and no exponent do we need to append a ".0" to make it a double (as
                // opposed to an integer).

                bool hasDecimal = svalue.IndexOf('.') >= 0; 
                bool hasExponent = svalue.IndexOfAny(new char[] { 'e', 'E' }) >= 0;
 
                if (!hasDecimal && !hasExponent) 
                    decompilation.Append(".0");
            } 
            else
            {
                decompilation.Append(suffix);
            } 
        }
 
        private static void DecompileSuffixedIntegerLiteral(StringBuilder decompilation, object value, string suffix) 
        {
            decompilation.Append(value.ToString()); 
            decompilation.Append(suffix);
        }

        private static void DecompileStringLiteral(StringBuilder decompilation, string strValue) 
        {
            decompilation.Append("\""); 
 			for (int i = 0; i < strValue.Length; ++i) 
			{
				char c = strValue[i]; 

				// is this character a surrogate pair?
 				if ((char.IsHighSurrogate(c)) && (i+1 < strValue.Length) && (char.IsLowSurrogate(strValue[i+1])))
				{ 
 					// yes, so leave the two characters unchanged
 					decompilation.Append(c); 
					++i; 
 					decompilation.Append(strValue[i]);
				} 
				else
					AppendCharacter(decompilation, c, '"');
 			}
            decompilation.Append("\""); 
        }
 
        private static void DecompileCharacterLiteral(StringBuilder decompilation, char charValue) 
        {
            decompilation.Append("'"); 
            AppendCharacter(decompilation, charValue, '\'');
            decompilation.Append("'");
        }
 
        private static void AppendCharacter(StringBuilder decompilation, char charValue, char quoteCharacter)
        { 
            if (charValue == quoteCharacter) 
            {
                decompilation.Append("\\"); 
                decompilation.Append(quoteCharacter);
            }
            else if (charValue == '\\')
            { 
                decompilation.Append("\\\\");
            } 
            else if ((charValue >= ' ' && charValue < '\u007f') || char.IsLetterOrDigit(charValue) || char.IsPunctuation(charValue)) 
            {
                decompilation.Append(charValue); 
            }
            else
            {
                string escapeSequence = null; 
                switch (charValue)
                { 
                    case '\0': 
                        escapeSequence = "\\0";
                        break; 
                    case '\n':
                        escapeSequence = "\\n";
                        break;
                    case '\r': 
                        escapeSequence = "\\r";
                        break; 
                    case '\b': 
                        escapeSequence = "\\b";
                        break; 
                    case '\a':
                        escapeSequence = "\\a";
                        break;
                    case '\t': 
                        escapeSequence = "\\t";
                        break; 
                    case '\f': 
                        escapeSequence = "\\f";
                        break; 
                    case '\v':
                        escapeSequence = "\\v";
                        break;
                } 

                if (escapeSequence != null) 
                { 
                    decompilation.Append(escapeSequence);
                } 
                else
                {
                    decompilation.Append("\\u");
 
                    UInt16 cv = (UInt16)charValue;
                    for (int i = 12; i >= 0; i -= 4) 
                    { 
                        int mask = 0xF << i;
                        byte c = (byte)((cv & mask) >> i); 
                        decompilation.Append("0123456789ABCDEF"[c]);
                    }
                }
            } 
        }
 
        #endregion 

        #region Type decompilation 

        internal static string DecompileType(Type type)
        {
            if (type == null) 
                return string.Empty;
 
            StringBuilder sb = new StringBuilder(); 
            DecompileType_Helper(sb, type);
            return sb.ToString(); 
        }

        private static void DecompileType_Helper(StringBuilder decompilation, Type type)
        { 
            int i;
 
            if (type.HasElementType) 
            {
                DecompileType_Helper(decompilation, type.GetElementType()); 

                if (type.IsArray)
                {
                    decompilation.Append("["); 
                    decompilation.Append(',', type.GetArrayRank() - 1);
                    decompilation.Append("]"); 
                } 
                else if (type.IsByRef)
                { 
                    decompilation.Append('&');
                }
                else if (type.IsPointer)
                { 
                    decompilation.Append('*');
                } 
            } 
            else
            { 
                string typeName = type.FullName;
                if (typeName == null) // Full name may be null for an unbound generic.
                    typeName = type.Name;
 
                typeName = UnmangleTypeName(typeName);
                decompilation.Append(typeName); 
 
                if (type.IsGenericType)
                { 
                    decompilation.Append("<");

                    Type[] typeArgs = type.GetGenericArguments();
 
                    DecompileType_Helper(decompilation, typeArgs[0]); // decompile the first type arg
                    for (i = 1; i < typeArgs.Length; ++i) 
                    { 
                        decompilation.Append(", ");
                        DecompileType_Helper(decompilation, typeArgs[i]); 
                    }

                    decompilation.Append(">");
                } 
            }
        } 
 
        internal static void DecompileType(StringBuilder decompilation, CodeTypeReference typeRef)
        { 
            // Remove any back-tick decorations on generic types, if present.
            string baseType = UnmangleTypeName(typeRef.BaseType);
            decompilation.Append(baseType);
 
            if (typeRef.TypeArguments != null && typeRef.TypeArguments.Count > 0)
            { 
                decompilation.Append("<"); 

                bool first = true; 
                foreach (CodeTypeReference argTypeRef in typeRef.TypeArguments)
                {
                    if (!first)
                        decompilation.Append(", "); 
                    first = false;
 
                    DecompileType(decompilation, argTypeRef); 
                }
 
                decompilation.Append(">");
            }

            if (typeRef.ArrayRank > 0) 
            {
                do 
                { 
                    decompilation.Append("[");
                    for (int i = 1; i < typeRef.ArrayRank; ++i) 
                        decompilation.Append(",");
                    decompilation.Append("]");

                    typeRef = typeRef.ArrayElementType; 
                } while (typeRef.ArrayRank > 0);
            } 
        } 

        private static Dictionary knownTypeMap = InitializeKnownTypeMap(); 

        private static Dictionary InitializeKnownTypeMap()
        {
            Dictionary map = new Dictionary(); 
            map.Add("System.Char", "char");
            map.Add("System.Byte", "byte"); 
            map.Add("System.SByte", "sbyte"); 
            map.Add("System.Int16", "short");
            map.Add("System.UInt16", "ushort"); 
            map.Add("System.Int32", "int");
            map.Add("System.UInt32", "uint");
            map.Add("System.Int64", "long");
            map.Add("System.UInt64", "ulong"); 
            map.Add("System.Single", "float");
            map.Add("System.Double", "double"); 
            map.Add("System.Decimal", "decimal"); 
            map.Add("System.Boolean", "bool");
            map.Add("System.String", "string"); 
            map.Add("System.Object", "object");
            map.Add("System.Void", "void");
            return map;
        } 

        private static string TryReplaceKnownTypes(string typeName) 
        { 
            string newTypeName = null;
            if (!knownTypeMap.TryGetValue(typeName, out newTypeName)) 
                newTypeName = typeName;
            return newTypeName;
        }
 
        private static string UnmangleTypeName(string typeName)
        { 
            int tickIndex = typeName.IndexOf('`'); 
            if (tickIndex > 0)
                typeName = typeName.Substring(0, tickIndex); 

            // Replace the '+' for a nested type with a '.'
            typeName = typeName.Replace('+', '.');
 
            typeName = TryReplaceKnownTypes(typeName);
 
            return typeName; 
        }
 
        #endregion

		#region Method decompilation
 
 		internal static string DecompileMethod(MethodInfo method)
 		{ 
			if (method == null) 
 				return string.Empty;
 
			StringBuilder sb = new StringBuilder();
			string operatorName;
			DecompileType_Helper(sb, method.DeclaringType);
 			sb.Append('.'); 
			if (knownOperatorMap.TryGetValue(method.Name, out operatorName))
 				sb.Append(operatorName); 
 			else 
				sb.Append(method.Name);
 			sb.Append('('); 
			ParameterInfo[] parms = method.GetParameters();
			for (int i = 0; i < parms.Length; ++i)
			{
 				DecompileType_Helper(sb, parms[i].ParameterType); 
				if (i != parms.Length - 1)
 					sb.Append(", "); 
 			} 
			sb.Append(')');
 			return sb.ToString(); 
		}

		private static Dictionary knownOperatorMap = InitializeKnownOperatorMap();
 
		private static Dictionary InitializeKnownOperatorMap()
 		{ 
			Dictionary map = new Dictionary(27); 
 			
 			// unary operators 
			map.Add("op_UnaryPlus", "operator +");
 			map.Add("op_UnaryNegation", "operator -");
			map.Add("op_OnesComplement", "operator ~");
			map.Add("op_LogicalNot", "operator !"); 
			map.Add("op_Increment", "operator ++");
 			map.Add("op_Decrement", "operator --"); 
			map.Add("op_True", "operator true"); 
 			map.Add("op_False", "operator false");
 			map.Add("op_Implicit", "implicit operator"); 
			map.Add("op_Explicit", "explicit operator");

 			// binary operators
			map.Add("op_Equality", "operator =="); 
			map.Add("op_Inequality", "operator !=");
			map.Add("op_GreaterThan", "operator >"); 
 			map.Add("op_GreaterThanOrEqual", "operator >="); 
			map.Add("op_LessThan", "operator <");
 			map.Add("op_LessThanOrEqual", "operator <="); 
 			map.Add("op_Addition", "operator +");
			map.Add("op_Subtraction", "operator -");
 			map.Add("op_Multiply", "operator *");
			map.Add("op_Division", "operator /"); 
			map.Add("op_IntegerDivision", "operator \\");
			map.Add("op_Modulus", "operator %"); 
 			map.Add("op_LeftShift", "operator <<"); 
			map.Add("op_RightShift", "operator >>");
 			map.Add("op_BitwiseAnd", "operator &"); 
 			map.Add("op_BitwiseOr", "operator |");
			map.Add("op_ExclusiveOr", "operator ^");
 			return map;
		} 
		#endregion
 
		#region Operator Precedence 

 		// These operations are sorted in order of precedence, lowest-to-highest 
        private enum Operation
        {
            RootExpression,
            LogicalOr,          // || 
            LogicalAnd,         // &&
            BitwiseOr,          // | 
            BitwiseAnd,         // & 
            Equality,           // ==  !=
            Comparitive,        // <  <=  >  >= 
            Additive,           // +  -
            Multiplicative,     // *  /  %
            Unary,              // -  !  (cast)
            Postfix,            // field/property ref and method call 
            NoParentheses       // Highest
        } 
 
        private delegate Operation ComputePrecedence(CodeExpression expresssion);
 
        private static Dictionary precedenceMap = InitializePrecedenceMap();


        private static Dictionary InitializePrecedenceMap() 
        {
            Dictionary map = new Dictionary(7); 
            map.Add(typeof(CodeBinaryOperatorExpression), GetBinaryPrecedence); 
            map.Add(typeof(CodeCastExpression), GetCastPrecedence);
            map.Add(typeof(CodeFieldReferenceExpression), GetPostfixPrecedence); 
            map.Add(typeof(CodePropertyReferenceExpression), GetPostfixPrecedence);
            map.Add(typeof(CodeMethodInvokeExpression), GetPostfixPrecedence);
            map.Add(typeof(CodeObjectCreateExpression), GetPostfixPrecedence);
            map.Add(typeof(CodeArrayCreateExpression), GetPostfixPrecedence); 
            return map;
        } 
 
        private static Operation GetPostfixPrecedence(CodeExpression expression)
        { 
            return Operation.Postfix;
        }

        private static Operation GetCastPrecedence(CodeExpression expression) 
        {
            return Operation.Unary; 
        } 

        private static Operation GetBinaryPrecedence(CodeExpression expression) 
        {
            CodeBinaryOperatorExpression binaryExpr = (CodeBinaryOperatorExpression)expression;

            Operation operation = Operation.NoParentheses; 
            switch (binaryExpr.Operator)
            { 
                case CodeBinaryOperatorType.Multiply: 
                case CodeBinaryOperatorType.Divide:
                case CodeBinaryOperatorType.Modulus: 
                    operation = Operation.Multiplicative;
                    break;

                case CodeBinaryOperatorType.Subtract: 
                case CodeBinaryOperatorType.Add:
                    operation = Operation.Additive; 
                    break; 

                case CodeBinaryOperatorType.LessThan: 
                case CodeBinaryOperatorType.LessThanOrEqual:
                case CodeBinaryOperatorType.GreaterThan:
                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    operation = Operation.Comparitive; 
                    break;
 
                case CodeBinaryOperatorType.IdentityEquality: 
                case CodeBinaryOperatorType.ValueEquality:
                case CodeBinaryOperatorType.IdentityInequality: 
                    operation = Operation.Equality;
                    break;

                case CodeBinaryOperatorType.BitwiseAnd: 
                    operation = Operation.BitwiseAnd;
                    break; 
 
                case CodeBinaryOperatorType.BitwiseOr:
                    operation = Operation.BitwiseOr; 
                    break;

                case CodeBinaryOperatorType.BooleanAnd:
                    operation = Operation.LogicalAnd; 
                    break;
 
                case CodeBinaryOperatorType.BooleanOr: 
                    operation = Operation.LogicalOr;
                    break; 

                default:
                    string message = string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, binaryExpr.Operator.ToString());
                    NotSupportedException exception = new NotSupportedException(message); 
                    exception.Data[RuleUserDataKeys.ErrorObject] = binaryExpr;
                    throw exception; 
            } 

            return operation; 
        }

        private static Operation GetPrecedence(CodeExpression expression)
        { 
            // Assume the operation needs no parentheses.
            Operation operation = Operation.NoParentheses; 
 
            ComputePrecedence computePrecedence;
            if (precedenceMap.TryGetValue(expression.GetType(), out computePrecedence)) 
                operation = computePrecedence(expression);

            return operation;
        } 

        internal static bool MustParenthesize(CodeExpression childExpr, CodeExpression parentExpr) 
        { 
            // No parent... we're at the root, so no need to parenthesize the root.
            if (parentExpr == null) 
                return false;

            Operation childOperation = GetPrecedence(childExpr);
            Operation parentOperation = GetPrecedence(parentExpr); 

            if (parentOperation == childOperation) 
            { 
                CodeBinaryOperatorExpression parentBinary = parentExpr as CodeBinaryOperatorExpression;
                if (parentBinary != null) 
                {
                    if (childExpr == parentBinary.Right)
                    {
                        // Something like 2 - (3 - 4) needs parentheses. 
                        return true;
                    } 
                    else 
                    {
                        // Something like (2 - 3) - 4 doesn't need parentheses. 
                        return false;
                    }
                }
                else 
                {
                    return false; 
                } 
            }
            else if (parentOperation > childOperation) 
            {
                return true;
            }
            else 
            {
                return false; 
            } 
        }
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK