5 using System.Collections.Generic;
8 using Mono.Collections.Generic;
12 class AssemblyLocationProvider
14 AssemblyDefinition assembly;
16 public AssemblyLocationProvider (string assemblyPath)
18 assemblyPath = Path.GetFullPath (assemblyPath);
20 if (!File.Exists (assemblyPath))
21 throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
23 var readerParameters = new ReaderParameters { ReadSymbols = true };
24 assembly = AssemblyDefinition.ReadAssembly (assemblyPath, readerParameters);
27 public bool TryResolveLocation (StackFrameData sfData, SeqPointInfo seqPointInfo)
29 if (!assembly.MainModule.HasSymbols)
32 TypeDefinition type = null;
33 var nested = sfData.TypeFullName.Split ('+');
34 var types = assembly.MainModule.Types;
35 foreach (var ntype in nested) {
36 type = types.FirstOrDefault (t => t.Name == ntype);
40 types = type.NestedTypes;
43 var parensStart = sfData.MethodSignature.IndexOf ('(');
44 var methodName = sfData.MethodSignature.Substring (0, parensStart).TrimEnd ();
45 var methodParameters = sfData.MethodSignature.Substring (parensStart);
46 var method = type.Methods.FirstOrDefault (m => CompareName (m, methodName) && CompareParameters (m.Parameters, methodParameters));
51 if (sfData.IsILOffset) {
52 ilOffset = sfData.Offset;
54 if (seqPointInfo == null)
57 ilOffset = seqPointInfo.GetILOffset (method.MetadataToken.ToInt32 (), sfData.MethodIndex, sfData.Offset);
63 SequencePoint sp = null;
64 foreach (var instr in method.Body.Instructions) {
65 if (instr.SequencePoint != null)
66 sp = instr.SequencePoint;
68 if (instr.Offset >= ilOffset) {
69 sfData.SetLocation (sp.Document.Url, sp.StartLine);
77 static bool CompareName (MethodDefinition candidate, string expected)
79 if (candidate.Name == expected)
82 if (!candidate.HasGenericParameters)
85 var genStart = expected.IndexOf ('[');
89 if (candidate.Name != expected.Substring (0, genStart))
93 for (int pos = genStart; pos < expected.Length; ++pos) {
94 if (expected [pos] == ',')
98 return candidate.GenericParameters.Count == arity;
101 static bool CompareParameters (Collection<ParameterDefinition> candidate, string expected)
103 var builder = new StringBuilder ();
104 builder.Append ("(");
106 for (int i = 0; i < candidate.Count; i++) {
107 var parameter = candidate [i];
109 builder.Append (", ");
111 if (parameter.ParameterType.IsSentinel)
112 builder.Append ("...,");
114 var pt = parameter.ParameterType;
115 if (!string.IsNullOrEmpty (pt.Namespace)) {
116 builder.Append (pt.Namespace);
117 builder.Append (".");
120 FormatElementType (pt, builder);
122 builder.Append (" ");
123 builder.Append (parameter.Name);
126 builder.Append (")");
128 return builder.ToString () == expected;
131 static void FormatElementType (TypeReference tr, StringBuilder builder)
133 var ts = tr as TypeSpecification;
135 if (ts.IsByReference) {
136 FormatElementType (ts.ElementType, builder);
137 builder.Append ("&");
141 var array = ts as ArrayType;
143 FormatElementType (ts.ElementType, builder);
144 builder.Append ("[");
146 for (int ii = 0; ii < array.Rank - 1; ++ii) {
147 builder.Append (",");
150 builder.Append ("]");
155 builder.Append (tr.Name);