mirror of https://github.com/icsharpcode/ILSpy.git
13 changed files with 318 additions and 201 deletions
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Decompiler; |
||||
|
||||
namespace Decompiler |
||||
{ |
||||
/// <summary>
|
||||
/// Stores the C# code mappings.
|
||||
/// </summary>
|
||||
public static class CSharpCodeMapping |
||||
{ |
||||
static Dictionary<string, List<MethodMapping>> codeMappings = new Dictionary<string, List<MethodMapping>>(); |
||||
|
||||
/// <summary>
|
||||
/// Stores the source codes mappings: CSharp <-> editor lines
|
||||
/// </summary>
|
||||
public static Dictionary<string, List<MethodMapping>> SourceCodeMappings { |
||||
get { return codeMappings; } |
||||
set { codeMappings = value; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,157 @@
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Decompiler; |
||||
using ICSharpCode.Decompiler.Disassembler; |
||||
using Mono.Cecil; |
||||
|
||||
namespace ICSharpCode.Decompiler |
||||
{ |
||||
public enum DecompiledLanguages |
||||
{ |
||||
IL, |
||||
CSharp |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Maps the source code to IL.
|
||||
/// </summary>
|
||||
public class SourceCodeMapping |
||||
{ |
||||
public int SourceCodeLine { get; set; } |
||||
|
||||
public ILRange ILInstructionOffset { get; set; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stores the method information and its source code mappings.
|
||||
/// </summary>
|
||||
public sealed class MethodMapping |
||||
{ |
||||
public string TypeName { get; set; } |
||||
|
||||
public uint MetadataToken { get; set; } |
||||
|
||||
public List<SourceCodeMapping> MethodCodeMappings { get; set; } |
||||
} |
||||
|
||||
public static class CodeMappings |
||||
{ |
||||
public static Dictionary<string, List<MethodMapping>> GetStorage(DecompiledLanguages language) |
||||
{ |
||||
Dictionary<string, List<MethodMapping>> storage = null; |
||||
|
||||
switch (language) { |
||||
case DecompiledLanguages.IL: |
||||
storage = ILCodeMapping.SourceCodeMappings; |
||||
break; |
||||
case DecompiledLanguages.CSharp: |
||||
storage = CSharpCodeMapping.SourceCodeMappings; |
||||
break; |
||||
default: |
||||
throw new System.Exception("Invalid value for DecompiledLanguages"); |
||||
} |
||||
|
||||
return storage; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Create code mapping for a method.
|
||||
/// </summary>
|
||||
/// <param name="method">Method to create the mapping for.</param>
|
||||
/// <param name="sourceCodeMappings">Source code mapping storage.</param>
|
||||
public static MethodMapping CreateCodeMapping( |
||||
this MethodDefinition method, |
||||
Dictionary<string, List<MethodMapping>> sourceCodeMappings) |
||||
{ |
||||
// create IL code mappings - used in debugger
|
||||
MethodMapping currentMethodMapping = null; |
||||
if (sourceCodeMappings.ContainsKey(method.DeclaringType.FullName)) { |
||||
var mapping = sourceCodeMappings[method.DeclaringType.FullName]; |
||||
if (mapping.Find(map => (int)map.MetadataToken == method.MetadataToken.ToInt32()) == null) { |
||||
currentMethodMapping = new MethodMapping() { |
||||
MetadataToken = (uint)method.MetadataToken.ToInt32(), |
||||
TypeName = method.DeclaringType.FullName, |
||||
MethodCodeMappings = new List<SourceCodeMapping>() |
||||
}; |
||||
mapping.Add(currentMethodMapping); |
||||
} |
||||
} |
||||
|
||||
return currentMethodMapping; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets source code mapping and metadata token based on type name and line number.
|
||||
/// </summary>
|
||||
/// <param name="codeMappings">Code mappings storage.</param>
|
||||
/// <param name="typeName">Type name.</param>
|
||||
/// <param name="lineNumber">Line number.</param>
|
||||
/// <param name="metadataToken">Metadata token.</param>
|
||||
/// <returns></returns>
|
||||
public static SourceCodeMapping GetInstructionByTypeAndLine( |
||||
this Dictionary<string, List<MethodMapping>> codeMappings, |
||||
string typeName, |
||||
int lineNumber, |
||||
out uint metadataToken) |
||||
{ |
||||
if (!codeMappings.ContainsKey(typeName)) { |
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
if (lineNumber <= 0) { |
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
var methodMappings = codeMappings[typeName]; |
||||
foreach (var maping in methodMappings) { |
||||
var map = maping.MethodCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
||||
if (map != null) { |
||||
metadataToken = maping.MetadataToken; |
||||
return map; |
||||
} |
||||
} |
||||
|
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the source code and type name from metadata token and offset.
|
||||
/// </summary>
|
||||
/// <param name="codeMappings">Code mappings storage.</param>
|
||||
/// <param name="token">Metadata token.</param>
|
||||
/// <param name="ilOffset">IL offset.</param>
|
||||
/// <param name="typeName">Type name.</param>
|
||||
/// <param name="line">Line number.</param>
|
||||
public static void GetSourceCodeFromMetadataTokenAndOffset( |
||||
this Dictionary<string, List<MethodMapping>> codeMappings, |
||||
uint token, |
||||
int ilOffset, |
||||
out string typeName, |
||||
out int line) |
||||
{ |
||||
typeName = null; |
||||
line = 0; |
||||
|
||||
foreach (var typename in codeMappings.Keys) { |
||||
var mapping = codeMappings[typename].Find(m => m.MetadataToken == token); |
||||
if (mapping == null) |
||||
continue; |
||||
|
||||
var codeMapping = mapping.MethodCodeMappings.Find( |
||||
cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To); |
||||
if (codeMapping == null) |
||||
continue; |
||||
|
||||
typeName = typename; |
||||
line = codeMapping.SourceCodeLine; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,124 +0,0 @@
@@ -1,124 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Mono.Cecil.Cil; |
||||
|
||||
namespace ICSharpCode.Decompiler.Disassembler |
||||
{ |
||||
public class ILCodeMapping |
||||
{ |
||||
public int SourceCodeLine { get; set; } |
||||
|
||||
public Instruction ILInstruction { get; set; } |
||||
} |
||||
|
||||
public class MethodMapping |
||||
{ |
||||
public string TypeName { get; set; } |
||||
|
||||
public uint MetadataToken { get; set; } |
||||
|
||||
public List<ILCodeMapping> MethodCodeMappings { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Finds the IL instruction given a source code line number.
|
||||
/// </summary>
|
||||
/// <param name="sourceCodeLine">Source code line number.</param>
|
||||
/// <returns>IL Instruction or null, if the instruction was not found.</returns>
|
||||
public Instruction FindByLine(int sourceCodeLine) |
||||
{ |
||||
if (sourceCodeLine <= 0) |
||||
throw new ArgumentException("The source line must be greater thatn 0."); |
||||
|
||||
if (MethodCodeMappings == null || MethodCodeMappings.Count == 0) |
||||
return null; |
||||
|
||||
foreach (var codeMapping in MethodCodeMappings) { |
||||
if (codeMapping.SourceCodeLine == sourceCodeLine) |
||||
return codeMapping.ILInstruction; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds the source code line given an IL instruction offset.
|
||||
/// </summary>
|
||||
/// <param name="instruction">IL Instruction offset.</param>
|
||||
/// <returns>Source code line, if it is found, -1 otherwise.</returns>
|
||||
public int FindByInstruction(int instructionOffset) |
||||
{ |
||||
if (instructionOffset <= 0) |
||||
throw new ArgumentNullException("The instruction offset cannot be lower than 0."); |
||||
|
||||
if (MethodCodeMappings == null || MethodCodeMappings.Count == 0) |
||||
return -1; |
||||
|
||||
foreach (var codeMapping in MethodCodeMappings) { |
||||
if (codeMapping.ILInstruction.Offset == instructionOffset) |
||||
return codeMapping.SourceCodeLine; |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
public static class ILCodeMappings |
||||
{ |
||||
static Dictionary<string, List<MethodMapping>> ilCodeMappings = new Dictionary<string, List<MethodMapping>>(); |
||||
|
||||
/// <summary>
|
||||
/// Stores the source codes mappings: IL <-> editor lines
|
||||
/// </summary>
|
||||
public static Dictionary<string, List<MethodMapping>> ILSourceCodeMappings { |
||||
get { return ilCodeMappings; } |
||||
set { ilCodeMappings = value; } |
||||
} |
||||
|
||||
public static ILCodeMapping GetInstructionByTypeAndLine(string typeName, int lineNumber, out uint metadataToken) |
||||
{ |
||||
if (!ilCodeMappings.ContainsKey(typeName)) { |
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
if (lineNumber <= 0) { |
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
var methodMappings = ilCodeMappings[typeName]; |
||||
foreach (var maping in methodMappings) { |
||||
var ilMap = maping.MethodCodeMappings.Find(m => m.SourceCodeLine == lineNumber); |
||||
if (ilMap != null) { |
||||
metadataToken = maping.MetadataToken; |
||||
return ilMap; |
||||
} |
||||
} |
||||
|
||||
metadataToken = 0; |
||||
return null; |
||||
} |
||||
|
||||
public static void GetSourceCodeFromMetadataTokenAndOffset(uint token, int ilOffset, out string typeName, out int line) |
||||
{ |
||||
typeName = null; |
||||
line = 0; |
||||
|
||||
foreach (var typename in ilCodeMappings.Keys) { |
||||
var mapping = ilCodeMappings[typename].Find(m => m.MetadataToken == token); |
||||
if (mapping == null) |
||||
continue; |
||||
|
||||
var ilCodeMapping = mapping.MethodCodeMappings.Find(cm => cm.ILInstruction.Offset == ilOffset); |
||||
if (ilCodeMapping == null) |
||||
continue; |
||||
|
||||
typeName = typename; |
||||
line = ilCodeMapping.SourceCodeLine; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.Decompiler.Disassembler |
||||
{ |
||||
/// <summary>
|
||||
/// Stores the IL code mappings.
|
||||
/// </summary>
|
||||
public static class ILCodeMapping |
||||
{ |
||||
static Dictionary<string, List<MethodMapping>> codeMappings = new Dictionary<string, List<MethodMapping>>(); |
||||
|
||||
/// <summary>
|
||||
/// Stores the source codes mappings: IL <-> editor lines
|
||||
/// </summary>
|
||||
public static Dictionary<string, List<MethodMapping>> SourceCodeMappings { |
||||
get { return codeMappings; } |
||||
set { codeMappings = value; } |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue