PageRenderTime 15ms CodeModel.GetById 2ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/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
  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}