/Test/Mono.Cecil.Tests/Formatter.cs

http://github.com/jbevain/cecil · C# · 193 lines · 158 code · 35 blank · 0 comment · 24 complexity · a32935c52c72a8d5b4f7d4991e2d5ab8 MD5 · raw file

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