From f6ecd0645ad244cd4728596132180f1aa3f210c1 Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Sun, 1 May 2011 23:23:18 +0300 Subject: [PATCH] Store code mappings using token as key. Sync bookmarks. --- Debugger/Debugger.Core/Breakpoint.cs | 4 +- .../AvalonEdit/IconBarMargin.cs | 75 +++++------- .../Bookmarks/BookmarkManager.cs | 55 +-------- .../Bookmarks/BreakpointBookmark.cs | 2 +- .../Bookmarks/CurrentLineBookmark.cs | 5 +- Debugger/ILSpy.Debugger/DebuggedData.cs | 6 +- .../Services/Debugger/WindowsDebugger.cs | 107 +++++++++--------- .../Services/ExtensionMethods.cs | 43 ------- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 77 ++++++------- ICSharpCode.Decompiler/CodeMappings.cs | 40 +++---- .../Disassembler/ReflectionDisassembler.cs | 83 ++++++-------- ILSpy/Commands/DebuggerCommands.cs | 19 ++-- ILSpy/Language.cs | 7 +- ILSpy/TextView/DecompilerTextView.cs | 24 ++-- 14 files changed, 207 insertions(+), 340 deletions(-) diff --git a/Debugger/Debugger.Core/Breakpoint.cs b/Debugger/Debugger.Core/Breakpoint.cs index 551bf6390..0b5555538 100644 --- a/Debugger/Debugger.Core/Breakpoint.cs +++ b/Debugger/Debugger.Core/Breakpoint.cs @@ -176,7 +176,7 @@ namespace Debugger public class ILBreakpoint : Breakpoint { - public ILBreakpoint(NDebugger debugger, string typeName, string memberReferenceName, int line, uint metadataToken, int offset, bool enabled) + public ILBreakpoint(NDebugger debugger, string typeName, string memberReferenceName, int line, int metadataToken, int offset, bool enabled) { this.Debugger = debugger; this.Line = line; @@ -187,7 +187,7 @@ namespace Debugger this.Enabled = enabled; } - public uint MetadataToken { get; private set; } + public int MetadataToken { get; private set; } public int ILOffset { get; private set; } diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs index 19220c1b2..80570ab2f 100644 --- a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs +++ b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Input; @@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit Dictionary bookmarkDict = new Dictionary(); foreach (var bm in BookmarkManager.Bookmarks) { if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 || - !DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) + !DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) continue; int line = bm.LineNumber; @@ -121,7 +122,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit BookmarkBase result = null; foreach (BookmarkBase bm in BookmarkManager.Bookmarks) { if (bm.LineNumber == line && - DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) { + DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) { if (result == null || bm.ZOrder > result.ZOrder) result = bm; } @@ -191,7 +192,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit } BreakpointBookmark bm = BookmarkManager.Bookmarks.Find( - b => DebugData.CodeMappings.ContainsKey(b.MemberReference.FullName) && + b => DebugData.CodeMappings != null && DebugData.CodeMappings.ContainsKey(b.MemberReference.MetadataToken.ToInt32()) && b.LineNumber == GetLineFromMousePosition(e) && b is BreakpointBookmark) as BreakpointBookmark; @@ -224,14 +225,13 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit return; } if (e.ChangedButton == MouseButton.Left) { - if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) { + if (DebugData.CodeMappings != null && DebugData.CodeMappings.Count > 0) { // check if the codemappings exists for this line var storage = DebugData.CodeMappings; - uint token = 0; - foreach (var member in DebugData.DecompiledMemberReferences.Values) { - string memberName = member.FullName; - var instruction = storage[memberName].GetInstructionByLineNumber(line, out token); + int token = 0; + foreach (var key in storage.Keys) { + var instruction = storage[key].GetInstructionByLineNumber(line, out token); if (instruction == null) { continue; @@ -239,7 +239,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit // no bookmark on the line: create a new breakpoint DebuggerService.ToggleBreakpointAt( - member, + DebugData.DecompiledMemberReferences[key], line, instruction.ILInstructionOffset, DebugData.Language); @@ -259,7 +259,8 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit public void SyncBookmarks() { - if (DebugData.CodeMappings == null || DebugData.CodeMappings.Count == 0) + var storage = DebugData.CodeMappings; + if (storage == null || storage.Count == 0) return; //remove existing bookmarks and create new ones @@ -269,46 +270,22 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit if (breakpoint == null) continue; - foreach (var key in DebugData.CodeMappings.Keys) { - var member = DebugData.DecompiledMemberReferences[key]; - - uint token; - if (member is TypeDefinition) { - var m = member as TypeDefinition; - if (breakpoint.MemberReference is TypeDefinition) { - if (member != breakpoint.MemberReference) - continue; - token = (uint)member.MetadataToken.ToInt32(); - } else { - if (!m.ContainsMember(breakpoint.MemberReference)) - continue; - token = (uint)breakpoint.MemberReference.MetadataToken.ToInt32(); - } - } else { - if (breakpoint.MemberReference is TypeDefinition) { - if (!(breakpoint.MemberReference as TypeDefinition).ContainsMember(member)) - continue; - token = (uint)member.MetadataToken.ToInt32(); - } else { - if (breakpoint.MemberReference != member) - continue; - token = (uint)breakpoint.MemberReference.MetadataToken.ToInt32(); - } - } - - bool isMatch; - SourceCodeMapping map = DebugData.CodeMappings[key] - .GetInstructionByTokenAndOffset(token, breakpoint.ILRange.From, out isMatch); + var key = breakpoint.MemberReference.MetadataToken.ToInt32(); + if (!storage.ContainsKey(key)) + continue; + + var member = DebugData.DecompiledMemberReferences[key]; + + bool isMatch; + SourceCodeMapping map = storage[key].GetInstructionByTokenAndOffset( + member.MetadataToken.ToInt32(), breakpoint.ILRange.From, out isMatch); + + if (map != null) { + newBookmarks.Add(new BreakpointBookmark( + member, new AstLocation(map.SourceCodeLine, 0), + map.ILInstructionOffset, BreakpointAction.Break, DebugData.Language)); - if (map != null) { - newBookmarks.Add(new BreakpointBookmark( - DebugData.DecompiledMemberReferences[key], - new AstLocation(map.SourceCodeLine, 0), - map.ILInstructionOffset, BreakpointAction.Break, DebugData.Language)); - - BookmarkManager.RemoveMark(breakpoint); - break; - } + BookmarkManager.RemoveMark(breakpoint); } } diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs index fea2a704c..a068e010c 100644 --- a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs +++ b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs @@ -152,71 +152,24 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks int line = CurrentLineBookmark.Instance.LineNumber; var markerType = CurrentLineBookmark.Instance.MemberReference; - if (!oldMappings.ContainsKey(markerType.FullName) || !newMappings.ContainsKey(markerType.FullName)) + if (!oldMappings.ContainsKey(markerType.MetadataToken.ToInt32()) || !newMappings.ContainsKey(markerType.MetadataToken.ToInt32())) return; // 2. Remove it CurrentLineBookmark.Remove(); // 3. map the marker line - uint token; - var instruction = oldMappings[markerType.FullName].GetInstructionByLineNumber(line, out token); + int token; + var instruction = oldMappings[markerType.MetadataToken.ToInt32()].GetInstructionByLineNumber(line, out token); if (instruction == null) return; MemberReference memberReference; int newline; - if (newMappings[markerType.FullName].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) { + if (newMappings[markerType.MetadataToken.ToInt32()].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) { // 4. create breakpoint for new languages CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0); } } - - /// - /// Synchronize the IL<->C# breakpoints bookmarks. - /// - /// Old language. - /// New language. - static void SyncBreakpointBookmarks(DecompiledLanguages oldLanguage, DecompiledLanguages newLanguage) - { - // checks - var oldMappings = DebugData.OldCodeMappings; - var newMappings = DebugData.CodeMappings; - - if (oldMappings == null || newMappings == null) - return; - - // 1. map the breakpoint lines - var oldbps = bookmarks.FindAll(b => b is BreakpointBookmark && - ((BreakpointBookmark)b).Language == oldLanguage); - if (oldbps == null || oldbps.Count == 0) - return; - - foreach (var bp in oldbps) { - uint token; - string name = bp.MemberReference.FullName; - if (!oldMappings.ContainsKey(name) || !newMappings.ContainsKey(name)) - continue; - - var instruction = oldMappings[name].GetInstructionByLineNumber(bp.LineNumber, out token); - if (instruction == null) - continue; - - MemberReference memberReference; - int line; - if (newMappings[name].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out line)) { - // 2. create breakpoint for new languages - var bookmark = new BreakpointBookmark(memberReference, new AstLocation(line, 0), instruction.ILInstructionOffset, BreakpointAction.Break, newLanguage); - AddMark(bookmark); - } - } - - // 3. remove all breakpoints for the old language - for (int i = bookmarks.Count - 1; i >= 0; --i) { - var bm = bookmarks[i]; - if (bm is BreakpointBookmark && ((BreakpointBookmark)bm).Language == oldLanguage) - RemoveMark(bm); - } - } } } diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs b/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs index 1254f910f..06020b99a 100644 --- a/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs +++ b/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs @@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks marker.BackgroundColor = Color.FromRgb(180, 38, 38); marker.ForegroundColor = Colors.White; marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences != null && - DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName); + DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.MetadataToken.ToInt32()); marker.Bookmark = this; this.Marker = marker; diff --git a/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs b/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs index 3472d1bd5..683395de1 100644 --- a/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs +++ b/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs @@ -3,9 +3,10 @@ using System; using System.Windows.Media; -using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.Debugger.AvalonEdit; using ICSharpCode.ILSpy.Debugger.Services; +using ICSharpCode.NRefactory.CSharp; using Mono.Cecil; using Mono.CSharp; @@ -82,7 +83,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks marker.BackgroundColor = Colors.Yellow; marker.ForegroundColor = Colors.Blue; marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences != null && - DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName); + DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.MetadataToken.ToInt32()); marker.Bookmark = this; this.Marker = marker; return marker; diff --git a/Debugger/ILSpy.Debugger/DebuggedData.cs b/Debugger/ILSpy.Debugger/DebuggedData.cs index 6fdc436bc..cc2ece74e 100644 --- a/Debugger/ILSpy.Debugger/DebuggedData.cs +++ b/Debugger/ILSpy.Debugger/DebuggedData.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.Debugger /// /// Gets or sets the current code mappings. /// - public static Dictionary> CodeMappings { get; set; } + public static Dictionary> CodeMappings { get; set; } /// /// Gets or sets the local variables of the current decompiled type, method, etc. @@ -50,12 +50,12 @@ namespace ICSharpCode.ILSpy.Debugger /// /// Gets or sets the old code mappings. /// - public static Dictionary> OldCodeMappings { get; set; } + public static Dictionary> OldCodeMappings { get; set; } /// /// Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc) /// - public static Dictionary DecompiledMemberReferences { get; set; } + public static Dictionary DecompiledMemberReferences { get; set; } /// /// Occures when the language is changed. diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs index 10a1a4eb3..3830ac8a7 100644 --- a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs +++ b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs @@ -288,13 +288,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services { isMatch = false; frame = debuggedProcess.SelectedThread.MostRecentStackFrame; - var debugType = (DebugType)frame.MethodInfo.DeclaringType; - string nameKey = debugType.FullNameWithoutGenericArguments; + int key = frame.MethodInfo.MetadataToken; // get the mapped instruction from the current line marker or the next one - return DebugData.CodeMappings[nameKey].GetInstructionByTokenAndOffset( - (uint)frame.MethodInfo.MetadataToken, - frame.IP, out isMatch); + return DebugData.CodeMappings[key].GetInstructionByTokenAndOffset(key, frame.IP, out isMatch); } StackFrame GetStackFrame() @@ -560,25 +557,14 @@ namespace ICSharpCode.ILSpy.Debugger.Services { Breakpoint breakpoint = null; - uint token; - SourceCodeMapping map = DebugData.CodeMappings[bookmark.MemberReference.FullName] - .GetInstructionByLineNumber(bookmark.LineNumber, out token); - - if (map != null) { - var declaringType = bookmark.MemberReference.DeclaringType; - - breakpoint = new ILBreakpoint( - debugger, - (declaringType ?? bookmark.MemberReference).FullName, - bookmark.MemberReference.FullName, - bookmark.LineNumber, - token, - map.ILInstructionOffset.From, - bookmark.IsEnabled); - } - - if (breakpoint == null) - return; + breakpoint = new ILBreakpoint( + debugger, + bookmark.MemberReference.DeclaringType.FullName, + bookmark.MemberReference.FullName, + bookmark.LineNumber, + bookmark.MemberReference.MetadataToken.ToInt32(), + bookmark.ILRange.From, + bookmark.IsEnabled); debugger.Breakpoints.Add(breakpoint); // Action setBookmarkColor = delegate { @@ -749,7 +735,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services foreach (var bookmark in DebuggerService.Breakpoints) { var breakpoint = debugger.Breakpoints.FirstOrDefault( - b => b.Line == bookmark.LineNumber && (b as ILBreakpoint).MemberReferenceName.CreateKey() == bookmark.MemberReference.FullName.CreateKey()); + b => b.Line == bookmark.LineNumber && (b as ILBreakpoint).MetadataToken == bookmark.MemberReference.MetadataToken.ToInt32()); if (breakpoint == null) continue; // set the breakpoint only if the module contains the type @@ -817,32 +803,33 @@ namespace ICSharpCode.ILSpy.Debugger.Services if (frame == null) return; - uint token = (uint)frame.MethodInfo.MetadataToken; - var debugType = (DebugType)frame.MethodInfo.DeclaringType; + int token = frame.MethodInfo.MetadataToken; int ilOffset = frame.IP; int line; MemberReference memberReference; - string nameKey = debugType.FullNameWithoutGenericArguments; - foreach (var key in DebugData.CodeMappings.Keys) { - if (key.CreateKey() == nameKey.CreateKey()) { - if (DebugData.CodeMappings[key].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) { - DebuggerService.RemoveCurrentLineMarker(); - DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0); - } else { - // is possible that the type is not decompiled yet, so we must do a decompilation on demand - DecompileOnDemand(frame); - } + if (DebugData.CodeMappings.ContainsKey(token)) { + if (DebugData.CodeMappings[token].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) { + DebuggerService.RemoveCurrentLineMarker(); + DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0); + } else { + // is possible that the type is not decompiled yet, so we must do a decompilation on demand + DecompileOnDemand(frame); } } + else { + // is possible that the type is not decompiled yet, so we must do a decompilation on demand + DecompileOnDemand(frame); + } } + } void DecompileOnDemand(StackFrame frame) { string debuggeeVersion = frame.MethodInfo.DebugModule.Process.DebuggeeVersion.Substring(1, 3); // should retrieve 2.0, 3.0, 4.0 var debugType = (DebugType)frame.MethodInfo.DeclaringType; - uint token = (uint)frame.MethodInfo.MetadataToken; + int token = frame.MethodInfo.MetadataToken; int ilOffset = frame.IP; string fullName = debugType.FullNameWithoutGenericArguments; @@ -852,7 +839,6 @@ namespace ICSharpCode.ILSpy.Debugger.Services // search for type in the current assembly list TypeDefinition typeDef = null; TypeDefinition nestedTypeDef = null; - MemberReference member = null; foreach (var assembly in DebugData.LoadedAssemblies) { if ((assembly.FullName.StartsWith("System") || assembly.FullName.StartsWith("Microsoft") || assembly.FullName.StartsWith("mscorlib")) && @@ -876,40 +862,55 @@ namespace ICSharpCode.ILSpy.Debugger.Services } if (typeDef != null) { - member = nestedTypeDef ?? typeDef; + TypeDefinition type = nestedTypeDef ?? typeDef; + MemberReference memberReference = null; - // decompile on demand if the type was not decompiled - Dictionary> codeMappings = null; - if (!DebugData.CodeMappings.ContainsKey(member.FullName)) { + // decompile on demand if the type was no decompiled + Dictionary> codeMappings = null; + Dictionary members = null; + if (!DebugData.CodeMappings.ContainsKey(token)) { if (DebugData.Language == DecompiledLanguages.IL) { var dis = new ReflectionDisassembler(new PlainTextOutput(), true, CancellationToken.None); - dis.DisassembleType(nestedTypeDef ?? typeDef); + dis.DisassembleType(type); codeMappings = dis.CodeMappings; } else { + // decompile type AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module)); - builder.AddType(nestedTypeDef ?? typeDef); + builder.AddType(type); builder.GenerateCode(new PlainTextOutput()); - codeMappings = builder.CodeMappings; + memberReference = builder.DecompiledMemberReferences[token]; + + // decompile member + var context = new DecompilerContext(typeDef.Module); + context.CurrentType = type; + builder = new AstBuilder(context); + if (memberReference is PropertyDefinition) + builder.AddProperty(memberReference as PropertyDefinition); + else if (memberReference is MethodDefinition) + builder.AddMethod(memberReference as MethodDefinition); + else if (memberReference is EventDefinition) + builder.AddEvent(memberReference as EventDefinition); + + builder.GenerateCode(new PlainTextOutput()); + DebugData.CodeMappings = codeMappings = builder.CodeMappings; + DebugData.DecompiledMemberReferences = members = builder.DecompiledMemberReferences; } } + // try jump int line; - MemberReference memberReference; codeMappings = codeMappings ?? DebugData.CodeMappings; - string name = (nestedTypeDef ?? typeDef).FullName; - if (codeMappings[name].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) { + if (codeMappings[token].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) { DebuggerService.RemoveCurrentLineMarker(); - DebuggerService.JumpToCurrentLine(nestedTypeDef ?? typeDef, line, 0, line, 0); + DebuggerService.JumpToCurrentLine(members[token], line, 0, line, 0); } else { StepOut(); } - } else { - // continue since we cannot find the debugged type - Debug.Assert(typeDef != null, string.Format("The type {0} was not found!", fullName)); } } } + public void ShowAttachDialog() { throw new NotImplementedException(); diff --git a/Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs b/Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs index e7b531db8..034029acf 100644 --- a/Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs +++ b/Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs @@ -400,48 +400,5 @@ namespace ICSharpCode.ILSpy.Debugger.Services { scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset); } - - /// - /// Verifies if the type contains the member. - /// - /// - /// - /// - public static bool ContainsMember(this TypeDefinition type, MemberReference member) - { - // check fields - if (member is FieldDefinition) { - foreach (var field in type.Fields) { - if (field == member) - return true; - } - } - - // check properties - if (member is PropertyDefinition) { - foreach (var field in type.Properties) { - if (field.Resolve() == member) - return true; - } - } - - // check methods - if (member is MethodDefinition) { - foreach (var field in type.Methods) { - if (field == member) - return true; - } - } - - // check events - if (member is EventDefinition) { - foreach (var field in type.Events) { - if (field == member) - return true; - } - } - - return false; - } } } diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index aa5dc14f0..41141179e 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -46,8 +46,8 @@ namespace ICSharpCode.Decompiler.Ast this.DecompileMethodBodies = true; this.LocalVariables = new ConcurrentDictionary>(); - this.CodeMappings = new Dictionary>(); - this.DecompiledMemberReferences = new Dictionary(); + this.CodeMappings = new Dictionary>(); + this.DecompiledMemberReferences = new Dictionary(); } public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings) @@ -161,10 +161,6 @@ namespace ICSharpCode.Decompiler.Ast public void AddType(TypeDefinition typeDef) { - // add to mappings information - this.DecompiledMemberReferences.Add(typeDef.FullName, typeDef); - this.CodeMappings.Add(typeDef.FullName, new List()); - var astType = CreateType(typeDef); NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace); if (astNS != null) { @@ -176,36 +172,22 @@ namespace ICSharpCode.Decompiler.Ast public void AddMethod(MethodDefinition method) { - // add to mappings information - this.CodeMappings.Add(method.FullName, new List()); - this.DecompiledMemberReferences.Add(method.FullName, method); - AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method); astCompileUnit.AddChild(node, CompilationUnit.MemberRole); } public void AddProperty(PropertyDefinition property) { - // add to mappings information - this.CodeMappings.Add(property.FullName, new List()); - this.DecompiledMemberReferences.Add(property.FullName, property); - astCompileUnit.AddChild(CreateProperty(property), CompilationUnit.MemberRole); } public void AddField(FieldDefinition field) { - this.DecompiledMemberReferences.Add(field.FullName, field); - astCompileUnit.AddChild(CreateField(field), CompilationUnit.MemberRole); } public void AddEvent(EventDefinition ev) { - // add to mappings information - this.DecompiledMemberReferences.Add(ev.FullName, ev); - this.CodeMappings.Add(ev.FullName, new List()); - astCompileUnit.AddChild(CreateEvent(ev), CompilationUnit.MemberRole); } @@ -215,7 +197,7 @@ namespace ICSharpCode.Decompiler.Ast /// /// TypeDeclaration or DelegateDeclaration. public AttributedNode CreateType(TypeDefinition typeDef) - { + { // create type TypeDefinition oldCurrentType = context.CurrentType; context.CurrentType = typeDef; @@ -619,12 +601,12 @@ namespace ICSharpCode.Decompiler.Ast // Add events foreach(EventDefinition eventDef in typeDef.Events) { - astType.AddChild(CreateEvent(eventDef, true), TypeDeclaration.MemberRole); + astType.AddChild(CreateEvent(eventDef), TypeDeclaration.MemberRole); } // Add properties foreach(PropertyDefinition propDef in typeDef.Properties) { - astType.Members.Add(CreateProperty(propDef, true)); + astType.Members.Add(CreateProperty(propDef)); } // Add methods @@ -632,17 +614,17 @@ namespace ICSharpCode.Decompiler.Ast if (MemberIsHidden(methodDef, context.Settings)) continue; if (methodDef.IsConstructor) - astType.Members.Add(CreateConstructor(methodDef, true)); + astType.Members.Add(CreateConstructor(methodDef)); else - astType.Members.Add(CreateMethod(methodDef, true)); + astType.Members.Add(CreateMethod(methodDef)); } } - AttributedNode CreateMethod(MethodDefinition methodDef, bool isTypeDecompiled = false) + AttributedNode CreateMethod(MethodDefinition methodDef) { // Create mapping - used in debugger - string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName; - MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef); + MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]); MethodDeclaration astMethod = new MethodDeclaration(); astMethod.AddAnnotation(methodDef); @@ -734,11 +716,11 @@ namespace ICSharpCode.Decompiler.Ast } } - ConstructorDeclaration CreateConstructor(MethodDefinition methodDef, bool isTypeDecompiled = false) + ConstructorDeclaration CreateConstructor(MethodDefinition methodDef) { // Create mapping - used in debugger - string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName; - MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef); + MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]); ConstructorDeclaration astMethod = new ConstructorDeclaration(); astMethod.AddAnnotation(methodDef); @@ -768,7 +750,7 @@ namespace ICSharpCode.Decompiler.Ast return m & ~Modifiers.Private; } - MemberDeclaration CreateProperty(PropertyDefinition propDef, bool isTypeDecompiled = false) + MemberDeclaration CreateProperty(PropertyDefinition propDef) { PropertyDeclaration astProp = new PropertyDeclaration(); astProp.AddAnnotation(propDef); @@ -804,11 +786,10 @@ namespace ICSharpCode.Decompiler.Ast astProp.Name = CleanName(propDef.Name); astProp.ReturnType = ConvertType(propDef.PropertyType, propDef); - string name = isTypeDecompiled ? propDef.DeclaringType.FullName : propDef.FullName; - if (propDef.GetMethod != null) { // Create mapping - used in debugger - MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef); + MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]); astProp.Getter = new Accessor(); astProp.Getter.Body = CreateMethodBody(propDef.GetMethod); @@ -822,7 +803,8 @@ namespace ICSharpCode.Decompiler.Ast } if (propDef.SetMethod != null) { // Create mapping - used in debugger - MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef); + MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]); astProp.Setter = new Accessor(); astProp.Setter.Body = CreateMethodBody(propDef.SetMethod); @@ -858,7 +840,7 @@ namespace ICSharpCode.Decompiler.Ast return astIndexer; } - AttributedNode CreateEvent(EventDefinition eventDef, bool isTypeDecompiled = false) + AttributedNode CreateEvent(EventDefinition eventDef) { if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) { // An abstract event cannot be custom @@ -881,11 +863,10 @@ namespace ICSharpCode.Decompiler.Ast else astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType); - string name = isTypeDecompiled ? eventDef.DeclaringType.FullName : eventDef.FullName; - if (eventDef.AddMethod != null) { // Create mapping - used in debugger - MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef); + MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]); astEvent.AddAccessor = new Accessor { Body = CreateMethodBody(eventDef.AddMethod) @@ -896,7 +877,8 @@ namespace ICSharpCode.Decompiler.Ast } if (eventDef.RemoveMethod != null) { // Create mapping - used in debugger - MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + int currentMemberToken = CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef); + MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]); astEvent.RemoveAccessor = new Accessor { Body = CreateMethodBody(eventDef.RemoveMethod) @@ -926,6 +908,8 @@ namespace ICSharpCode.Decompiler.Ast FieldDeclaration CreateField(FieldDefinition fieldDef) { + this.DecompiledMemberReferences.Add(fieldDef.MetadataToken.ToInt32(), fieldDef); + FieldDeclaration astField = new FieldDeclaration(); astField.AddAnnotation(fieldDef); VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name)); @@ -1395,7 +1379,7 @@ namespace ICSharpCode.Decompiler.Ast /// /// /// - public Dictionary> CodeMappings { get; private set; } + public Dictionary> CodeMappings { get; private set; } /// /// Gets the local variables for the current decompiled type, method, etc. @@ -1406,6 +1390,13 @@ namespace ICSharpCode.Decompiler.Ast /// /// /// - public Dictionary DecompiledMemberReferences { get; private set; } + public Dictionary DecompiledMemberReferences { get; private set; } + + private int CreateCodeMappings(int token, MemberReference member) + { + this.CodeMappings.Add(token, new List()); + this.DecompiledMemberReferences.Add(token, member); + return token; + } } } diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs index 700b03d49..30cc452a7 100644 --- a/ICSharpCode.Decompiler/CodeMappings.cs +++ b/ICSharpCode.Decompiler/CodeMappings.cs @@ -41,13 +41,15 @@ namespace ICSharpCode.Decompiler { /// /// Gets the code mappings. + /// Key is the metadata token. /// - Dictionary> CodeMappings { get; } + Dictionary> CodeMappings { get; } /// /// Gets the MembeReference that is decompiled (a TypeDefinition, MethodDefinition, etc) + /// Key is the metadata token. /// - Dictionary DecompiledMemberReferences { get; } + Dictionary DecompiledMemberReferences { get; } } /// @@ -117,9 +119,9 @@ namespace ICSharpCode.Decompiler public MemberReference MemberReference { get; internal set; } /// - /// Metadata token of the method. + /// Metadata token of the member. /// - public uint MetadataToken { get; internal set; } + public int MetadataToken { get; internal set; } /// /// Gets or sets the code size for the member mapping. @@ -162,8 +164,7 @@ namespace ICSharpCode.Decompiler /// True, if a full type was decompiled; false otherwise. internal static MemberMapping CreateCodeMapping( this MethodDefinition member, - List codeMappings, - bool isTypeDecompiled) + List codeMappings) { if (member == null || !member.HasBody) return null; @@ -173,20 +174,15 @@ namespace ICSharpCode.Decompiler // create IL/CSharp code mappings - used in debugger MemberMapping currentMemberMapping = null; - string key = isTypeDecompiled ? member.DeclaringType.FullName : member.FullName; - if (codeMappings.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) { + if (codeMappings.Find(map => map.MetadataToken == member.MetadataToken.ToInt32()) == null) { currentMemberMapping = new MemberMapping() { - MetadataToken = (uint)member.MetadataToken.ToInt32(), + MetadataToken = member.MetadataToken.ToInt32(), MemberCodeMappings = new List(), + MemberReference = member, CodeSize = member.Body.CodeSize }; - if (isTypeDecompiled) - currentMemberMapping.MemberReference = member.DeclaringType.Resolve(); - else - currentMemberMapping.MemberReference = member.Resolve(); - codeMappings.Add(currentMemberMapping); } @@ -204,7 +200,7 @@ namespace ICSharpCode.Decompiler public static SourceCodeMapping GetInstructionByLineNumber( this List codeMappings, int lineNumber, - out uint metadataToken) + out int metadataToken) { if (codeMappings == null) throw new ArgumentException("CodeMappings storage must be valid!"); @@ -231,7 +227,7 @@ namespace ICSharpCode.Decompiler /// A code mapping. public static SourceCodeMapping GetInstructionByTokenAndOffset( this List codeMappings, - uint token, + int token, int ilOffset, out bool isMatch) { @@ -273,7 +269,7 @@ namespace ICSharpCode.Decompiler /// It is possible to exist to different types from different assemblies with the same metadata token. public static bool GetSourceCodeFromMetadataTokenAndOffset( this List codeMappings, - uint token, + int token, int ilOffset, out MemberReference member, out int line) @@ -303,15 +299,5 @@ namespace ICSharpCode.Decompiler line = codeMapping.SourceCodeLine; return true; } - - /// - /// Create a key by replacing "::" with ".", "+" with "/", " " with ""; - /// - /// Item to convert. - /// - public static string CreateKey(this string item) - { - return item.Replace("+", "/").Replace("::", ".").Replace(" ", string.Empty); - } } } diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index c9b6ea23a..b201618dd 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.Disassembler bool detectControlStructure; bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings) MethodBodyDisassembler methodBodyDisassembler; + int currentMemberToken; public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken) { @@ -45,8 +46,8 @@ namespace ICSharpCode.Decompiler.Disassembler this.detectControlStructure = detectControlStructure; this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken); - this.CodeMappings = new Dictionary>(); - this.DecompiledMemberReferences = new Dictionary(); + this.CodeMappings = new Dictionary>(); + this.DecompiledMemberReferences = new Dictionary(); } #region Disassemble Method @@ -95,21 +96,17 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodImplAttributes.NoOptimization, "nooptimization" }, }; - public void DisassembleMethod(MethodDefinition method, bool isTypeDecompiled = false) + public void DisassembleMethod(MethodDefinition method) { // create mappings for decompiled methods only - string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName; - if (!isTypeDecompiled) { - this.CodeMappings.Add(name, new List()); - this.DecompiledMemberReferences.Add(method.FullName, method); - } + currentMemberToken = CreateCodeMappings(method.MetadataToken.ToInt32(), method); // write method header output.WriteDefinition(".method ", method); - DisassembleMethodInternal(method, isTypeDecompiled); + DisassembleMethodInternal(method); } - void DisassembleMethodInternal(MethodDefinition method, bool isTypeDecompiled) + void DisassembleMethodInternal(MethodDefinition method) { // .method public hidebysig specialname // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed @@ -158,8 +155,7 @@ namespace ICSharpCode.Decompiler.Disassembler if (method.HasBody) { // create IL code mappings - used in debugger - string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName; - MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled); + MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[currentMemberToken]); methodBodyDisassembler.Disassemble(method.Body, methodMapping); } @@ -203,12 +199,10 @@ namespace ICSharpCode.Decompiler.Disassembler { FieldAttributes.NotSerialized, "notserialized" }, }; - public void DisassembleField(FieldDefinition field, bool isTypeDecompiled = false) + public void DisassembleField(FieldDefinition field) { // create mappings for decompiled fields only - if (!isTypeDecompiled) { - this.DecompiledMemberReferences.Add(field.FullName, field); - } + this.DecompiledMemberReferences.Add(field.MetadataToken.ToInt32(), field); output.WriteDefinition(".field ", field); WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); @@ -237,14 +231,10 @@ namespace ICSharpCode.Decompiler.Disassembler { PropertyAttributes.HasDefault, "hasdefault" }, }; - public void DisassembleProperty(PropertyDefinition property, bool isTypeDecompiled = false) + public void DisassembleProperty(PropertyDefinition property) { // create mappings for decompiled properties only - string name = isTypeDecompiled ? property.DeclaringType.FullName : property.FullName; - if (!isTypeDecompiled) { - this.CodeMappings.Add(name, new List()); - this.DecompiledMemberReferences.Add(property.FullName, property); - } + currentMemberToken = CreateCodeMappings(property.MetadataToken.ToInt32(), property); output.WriteDefinition(".property ", property); WriteFlags(property.Attributes, propertyAttributes); @@ -253,22 +243,22 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(DisassemblerHelpers.Escape(property.Name)); OpenBlock(false); WriteAttributes(property.CustomAttributes); - WriteNestedMethod(".get", property.GetMethod, isTypeDecompiled); - WriteNestedMethod(".set", property.SetMethod, isTypeDecompiled); + WriteNestedMethod(".get", property.GetMethod); + WriteNestedMethod(".set", property.SetMethod); foreach (var method in property.OtherMethods) { - WriteNestedMethod(".method", method, isTypeDecompiled); + WriteNestedMethod(".method", method); } CloseBlock(); } - void WriteNestedMethod(string keyword, MethodDefinition method, bool isTypeDecompiled) + void WriteNestedMethod(string keyword, MethodDefinition method) { if (method == null) return; if (detectControlStructure) { output.WriteDefinition(keyword, method); output.Write(' '); - DisassembleMethodInternal(method, isTypeDecompiled); + DisassembleMethodInternal(method); } else { output.Write(keyword); output.Write(' '); @@ -284,14 +274,10 @@ namespace ICSharpCode.Decompiler.Disassembler { EventAttributes.RTSpecialName, "rtspecialname" }, }; - public void DisassembleEvent(EventDefinition ev, bool isTypeDecompiled = false) + public void DisassembleEvent(EventDefinition ev) { // create mappings for decompiled events only - string name = isTypeDecompiled ? ev.DeclaringType.FullName : ev.FullName; - if (!isTypeDecompiled) { - this.CodeMappings.Add(name, new List()); - this.DecompiledMemberReferences.Add(ev.FullName, ev); - } + currentMemberToken = CreateCodeMappings(ev.MetadataToken.ToInt32(), ev); output.WriteDefinition(".event ", ev); WriteFlags(ev.Attributes, eventAttributes); @@ -300,11 +286,11 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(DisassemblerHelpers.Escape(ev.Name)); OpenBlock(false); WriteAttributes(ev.CustomAttributes); - WriteNestedMethod(".add", ev.AddMethod, isTypeDecompiled); - WriteNestedMethod(".remove", ev.RemoveMethod, isTypeDecompiled); - WriteNestedMethod(".invoke", ev.InvokeMethod, isTypeDecompiled); + WriteNestedMethod(".add", ev.AddMethod); + WriteNestedMethod(".remove", ev.RemoveMethod); + WriteNestedMethod(".invoke", ev.InvokeMethod); foreach (var method in ev.OtherMethods) { - WriteNestedMethod(".method", method, isTypeDecompiled); + WriteNestedMethod(".method", method); } CloseBlock(); } @@ -346,10 +332,6 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleType(TypeDefinition type) { - // create IL code mappings - used for debugger - this.CodeMappings.Add(type.FullName, new List()); - this.DecompiledMemberReferences.Add(type.FullName, type); - // start writing IL output.WriteDefinition(".class ", type); @@ -413,7 +395,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("// Fields"); foreach (var field in type.Fields) { cancellationToken.ThrowIfCancellationRequested(); - DisassembleField(field, true); + DisassembleField(field); } output.WriteLine(); } @@ -421,7 +403,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("// Properties"); foreach (var prop in type.Properties) { cancellationToken.ThrowIfCancellationRequested(); - DisassembleProperty(prop, true); + DisassembleProperty(prop); } output.WriteLine(); } @@ -429,7 +411,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("// Events"); foreach (var ev in type.Events) { cancellationToken.ThrowIfCancellationRequested(); - DisassembleEvent(ev, true); + DisassembleEvent(ev); output.WriteLine(); } output.WriteLine(); @@ -440,7 +422,7 @@ namespace ICSharpCode.Decompiler.Disassembler foreach (var m in type.Methods) { cancellationToken.ThrowIfCancellationRequested(); if (!(detectControlStructure && accessorMethods.Contains(m))) { - DisassembleMethod(m, true); + DisassembleMethod(m); output.WriteLine(); } } @@ -638,11 +620,18 @@ namespace ICSharpCode.Decompiler.Disassembler /// /// /// - public Dictionary> CodeMappings { get; private set; } + public Dictionary> CodeMappings { get; private set; } /// /// /// - public Dictionary DecompiledMemberReferences { get; private set; } + public Dictionary DecompiledMemberReferences { get; private set; } + + private int CreateCodeMappings(int token, MemberReference member) + { + this.CodeMappings.Add(token, new List()); + this.DecompiledMemberReferences.Add(token, member); + return token; + } } } diff --git a/ILSpy/Commands/DebuggerCommands.cs b/ILSpy/Commands/DebuggerCommands.cs index 461a2d538..27a255104 100644 --- a/ILSpy/Commands/DebuggerCommands.cs +++ b/ILSpy/Commands/DebuggerCommands.cs @@ -11,6 +11,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Xml.Linq; +using ICSharpCode.AvalonEdit.Document; using ICSharpCode.ILSpy.Debugger; using ICSharpCode.ILSpy.Debugger.Bookmarks; using ICSharpCode.ILSpy.Debugger.Services; @@ -157,19 +158,21 @@ namespace ICSharpCode.ILSpy.Commands return; } + var inst = MainWindow.Instance; + // breakpoint was hit => bring to front the main window - SendWpfWindowPos(MainWindow.Instance, HWND_TOP); - MainWindow.Instance.Activate(); + SendWpfWindowPos(inst, HWND_TOP); inst.Activate(); // jump to type & expand folding - if (CurrentLineBookmark.Instance != null) { - if (!DebugData.DecompiledMemberReferences.ContainsKey(CurrentLineBookmark.Instance.MemberReference.FullName)) - MainWindow.Instance.JumpToReference(CurrentLineBookmark.Instance.MemberReference); - - MainWindow.Instance.TextView.UnfoldAndScroll(CurrentLineBookmark.Instance.LineNumber); + var bm = CurrentLineBookmark.Instance; + if (bm != null) { + if (!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) + inst.JumpToReference(bm.MemberReference); + + inst.TextView.UnfoldAndScroll(bm.LineNumber); } - MainWindow.Instance.SetStatus("Debugging...", Brushes.Red); + inst.SetStatus("Debugging...", Brushes.Red); } } diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs index 0ee9a74f6..7df9c2bb9 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Language.cs @@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy /// /// Decompilation event arguments. /// - public sealed class DecompileEventArgs : EventArgs + public sealed class DecompileEventArgs : EventArgs, ICodeMappings { /// /// Gets ot sets the code mappings /// - public Dictionary> CodeMappings { get; set; } + public Dictionary> CodeMappings { get; set; } /// /// Gets or sets the local variables. @@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy /// /// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc) /// - public Dictionary DecompiledMemberReferences { get; set; } + public Dictionary DecompiledMemberReferences { get; set; } } /// @@ -111,6 +111,7 @@ namespace ICSharpCode.ILSpy public virtual void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, nameSpace); + OnDecompilationFinished(null); } public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 5c29c9e03..a1ce8d8ce 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -394,7 +394,7 @@ namespace ICSharpCode.ILSpy.TextView // show the currentline marker var bm = CurrentLineBookmark.Instance; if (bm != null) { - if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) { + if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) { DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber); bm.Marker = bm.CreateMarker(textMarkerService, line.Offset, line.Length); } @@ -456,6 +456,11 @@ namespace ICSharpCode.ILSpy.TextView static void DecompileNodes(DecompilationContext context, ITextOutput textOutput) { + // reset data + DebugData.CodeMappings = null; + DebugData.LocalVariables = null; + DebugData.DecompiledMemberReferences = null; + var nodes = context.TreeNodes; context.Language.DecompileFinished += Language_DecompileFinished; for (int i = 0; i < nodes.Length; i++) { @@ -471,13 +476,16 @@ namespace ICSharpCode.ILSpy.TextView static void Language_DecompileFinished(object sender, DecompileEventArgs e) { if (e != null) { - DebugData.CodeMappings = e.CodeMappings; - DebugData.LocalVariables = e.LocalVariables; - DebugData.DecompiledMemberReferences = e.DecompiledMemberReferences; - } else { - DebugData.CodeMappings = null; - DebugData.LocalVariables = null; - DebugData.DecompiledMemberReferences = null; + if (DebugData.CodeMappings == null) { + DebugData.CodeMappings = e.CodeMappings; + DebugData.LocalVariables = e.LocalVariables; + DebugData.DecompiledMemberReferences = e.DecompiledMemberReferences; + } else { + DebugData.CodeMappings.AddRange(e.CodeMappings); + DebugData.DecompiledMemberReferences.AddRange(e.DecompiledMemberReferences); + if (e.LocalVariables != null) + DebugData.LocalVariables.AddRange(e.LocalVariables); + } } } #endregion