/Test/Mono.Cecil.Tests/Formatter.cs
C# | 193 lines | 158 code | 35 blank | 0 comment | 24 complexity | a32935c52c72a8d5b4f7d4991e2d5ab8 MD5 | raw file
1using System; 2using System.IO; 3using Mono.Cecil; 4using Mono.Cecil.Cil; 5 6namespace Mono.Cecil.Tests { 7 8 public static class Formatter { 9 10 public static string FormatInstruction (Instruction instruction) 11 { 12 var writer = new StringWriter (); 13 WriteInstruction (writer, instruction); 14 return writer.ToString (); 15 } 16 17 public static string FormatMethodBody (MethodDefinition method) 18 { 19 var writer = new StringWriter (); 20 WriteMethodBody (writer, method); 21 return writer.ToString (); 22 } 23 24 public static void WriteMethodBody (TextWriter writer, MethodDefinition method) 25 { 26 var body = method.Body; 27 28 WriteVariables (writer, body); 29 30 foreach (Instruction instruction in body.Instructions) { 31 var sequence_point = body.Method.DebugInformation.GetSequencePoint (instruction); 32 if (sequence_point != null) { 33 writer.Write ('\t'); 34 WriteSequencePoint (writer, sequence_point); 35 writer.WriteLine (); 36 } 37 38 writer.Write ('\t'); 39 WriteInstruction (writer, instruction); 40 writer.WriteLine (); 41 } 42 43 WriteExceptionHandlers (writer, body); 44 } 45 46 static void WriteVariables (TextWriter writer, MethodBody body) 47 { 48 var variables = body.Variables; 49 50 writer.Write ('\t'); 51 writer.Write (".locals {0}(", body.InitLocals ? "init " : string.Empty); 52 53 for (int i = 0; i < variables.Count; i++) { 54 if (i > 0) 55 writer.Write (", "); 56 57 var variable = variables [i]; 58 59 writer.Write ("{0} {1}", variable.VariableType, GetVariableName (variable, body)); 60 } 61 writer.WriteLine (")"); 62 } 63 64 static string GetVariableName (VariableDefinition variable, MethodBody body) 65 { 66 string name; 67 if (body.Method.DebugInformation.TryGetName (variable, out name)) 68 return name; 69 70 return variable.ToString (); 71 } 72 73 static void WriteInstruction (TextWriter writer, Instruction instruction) 74 { 75 writer.Write (FormatLabel (instruction.Offset)); 76 writer.Write (": "); 77 writer.Write (instruction.OpCode.Name); 78 if (null != instruction.Operand) { 79 writer.Write (' '); 80 WriteOperand (writer, instruction.Operand); 81 } 82 } 83 84 static void WriteSequencePoint (TextWriter writer, SequencePoint sequence_point) 85 { 86 if (sequence_point.IsHidden) { 87 writer.Write (".line hidden '{0}'", sequence_point.Document.Url); 88 return; 89 } 90 91 writer.Write (".line {0},{1}:{2},{3} '{4}'", 92 sequence_point.StartLine, 93 sequence_point.EndLine, 94 sequence_point.StartColumn, 95 sequence_point.EndColumn, 96 sequence_point.Document.Url); 97 } 98 99 static string FormatLabel (int offset) 100 { 101 string label = "000" + offset.ToString ("x"); 102 return "IL_" + label.Substring (label.Length - 4); 103 } 104 105 static string FormatLabel (Instruction instruction) 106 { 107 return FormatLabel (instruction.Offset); 108 } 109 110 static void WriteOperand (TextWriter writer, object operand) 111 { 112 if (null == operand) throw new ArgumentNullException ("operand"); 113 114 var target = operand as Instruction; 115 if (null != target) { 116 writer.Write (FormatLabel (target.Offset)); 117 return; 118 } 119 120 var targets = operand as Instruction []; 121 if (null != targets) { 122 WriteLabelList (writer, targets); 123 return; 124 } 125 126 string s = operand as string; 127 if (null != s) { 128 writer.Write ("\"" + s + "\""); 129 return; 130 } 131 132 var parameter = operand as ParameterDefinition; 133 if (parameter != null) { 134 writer.Write (ToInvariantCultureString (parameter.Sequence)); 135 return; 136 } 137 138 s = ToInvariantCultureString (operand); 139 writer.Write (s); 140 } 141 142 static void WriteLabelList (TextWriter writer, Instruction [] instructions) 143 { 144 writer.Write ("("); 145 146 for (int i = 0; i < instructions.Length; i++) { 147 if (i != 0) writer.Write (", "); 148 writer.Write (FormatLabel (instructions [i].Offset)); 149 } 150 151 writer.Write (")"); 152 } 153 154 static void WriteExceptionHandlers (TextWriter writer, MethodBody body) 155 { 156 if (!body.HasExceptionHandlers) 157 return; 158 159 foreach (var handler in body.ExceptionHandlers) { 160 writer.Write ("\t"); 161 writer.WriteLine (".try {0} to {1} {2} handler {3} to {4}", 162 FormatLabel (handler.TryStart), 163 FormatLabel (handler.TryEnd), 164 FormatHandlerType (handler), 165 FormatLabel (handler.HandlerStart), 166 FormatLabel (handler.HandlerEnd)); 167 } 168 } 169 170 static string FormatHandlerType (ExceptionHandler handler) 171 { 172 var handler_type = handler.HandlerType; 173 var type = handler_type.ToString ().ToLowerInvariant (); 174 175 switch (handler_type) { 176 case ExceptionHandlerType.Catch: 177 return string.Format ("{0} {1}", type, handler.CatchType.FullName); 178 case ExceptionHandlerType.Filter: 179 throw new NotImplementedException (); 180 default: 181 return type; 182 } 183 } 184 185 public static string ToInvariantCultureString (object value) 186 { 187 var convertible = value as IConvertible; 188 return (null != convertible) 189 ? convertible.ToString (System.Globalization.CultureInfo.InvariantCulture) 190 : value.ToString (); 191 } 192 } 193}