4 using System.Diagnostics;
5 using System.Collections.Generic;
7 using Mono.CompilerServices.SymbolWriter;
12 public string FileName;
16 class LocationProvider {
17 class AssemblyLocationProvider {
18 AssemblyDefinition assembly;
19 MonoSymbolFile symbolFile;
21 public AssemblyLocationProvider (AssemblyDefinition assembly, MonoSymbolFile symbolFile)
23 this.assembly = assembly;
24 this.symbolFile = symbolFile;
27 public bool TryGetLocation (string methodFullName, string[] methodParamsTypes, int ilOffset, out Location location)
29 location = default (Location);
30 if (symbolFile == null)
33 var typeNameEnd = methodFullName.LastIndexOf (".");
34 var typeName = methodFullName.Substring (0, typeNameEnd);
35 var methodName = methodFullName.Substring (typeNameEnd + 1, methodFullName.Length - typeNameEnd - 1);
37 var type = assembly.MainModule.Types.FirstOrDefault (t => t.FullName == typeName);
41 var method = type.Methods.FirstOrDefault (m => {
42 if (m.Name != methodName)
45 if (m.Parameters.Count != methodParamsTypes.Length)
48 for (var i = 0; i < methodParamsTypes.Length; i++) {
49 var paramType = m.Parameters[i].ParameterType;
50 if (paramType.Name != methodParamsTypes[i])
60 var methodSymbol = symbolFile.Methods [method.MetadataToken.RID-1];
62 foreach (var lineNumber in methodSymbol.GetLineNumberTable ().LineNumbers) {
63 if (lineNumber.Offset < ilOffset)
66 location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
67 location.Line = lineNumber.Row;
75 Dictionary<string, AssemblyLocationProvider> assemblies;
76 HashSet<string> directories;
78 public LocationProvider () {
79 assemblies = new Dictionary<string, AssemblyLocationProvider> ();
80 directories = new HashSet<string> ();
83 public void AddAssembly (string assemblyPath)
85 assemblyPath = Path.GetFullPath (assemblyPath);
86 if (assemblies.ContainsKey (assemblyPath))
89 if (!File.Exists (assemblyPath))
90 throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
92 var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
93 MonoSymbolFile symbolFile = null;
95 var symbolPath = assemblyPath + ".mdb";
96 if (!File.Exists (symbolPath))
97 Debug.WriteLine (".mdb file was not found for " + assemblyPath);
99 symbolFile = MonoSymbolFile.ReadSymbolFile (assemblyPath + ".mdb");
101 assemblies.Add (assemblyPath, new AssemblyLocationProvider (assembly, symbolFile));
103 directories.Add (Path.GetDirectoryName (assemblyPath));
105 foreach (var assemblyRef in assembly.MainModule.AssemblyReferences) {
106 string refPath = null;
107 foreach (var dir in directories) {
108 refPath = Path.Combine (dir, assemblyRef.Name);
109 if (File.Exists (refPath))
111 refPath = Path.Combine (dir, assemblyRef.Name + ".dll");
112 if (File.Exists (refPath))
114 refPath = Path.Combine (dir, assemblyRef.Name + ".exe");
115 if (File.Exists (refPath))
120 AddAssembly (refPath);
124 public void AddDirectory (string directory)
126 if (Directory.Exists (directory))
127 throw new ArgumentException ("Directory " + directory + " does not exist.");
129 directories.Add (directory);
132 public bool TryGetLocation (string methodName, string[] methodParams, int ilOffset, out Location location)
134 location = default (Location);
135 foreach (var assembly in assemblies.Values) {
136 if (assembly.TryGetLocation (methodName, methodParams, ilOffset, out location))