Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into Debugger

pull/219/head
Eusebiu Marcu 14 years ago
parent
commit
080bf7f8e3
  1. 442
      Debugger/ILSpy.Debugger/AvalonEdit/Editor/AvalonEditDocumentAdapter.cs
  2. 98
      Debugger/ILSpy.Debugger/AvalonEdit/Editor/AvalonEditTextSourceAdapter.cs
  3. 85
      Debugger/ILSpy.Debugger/AvalonEdit/Editor/IDocument.cs
  4. 98
      Debugger/ILSpy.Debugger/AvalonEdit/Editor/ITextAnchor.cs
  5. 146
      Debugger/ILSpy.Debugger/AvalonEdit/Editor/ITextBuffer.cs
  6. 50
      Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs
  7. 29
      Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs
  8. 59
      Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj
  9. 2
      Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
  10. 1
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  11. 2
      Debugger/ILSpy.Debugger/ToolTips/DebuggerTooltipControl.xaml.cs
  12. 71
      Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs
  13. 0
      Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml
  14. 0
      Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs
  15. 12
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  16. 15
      ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  17. 3
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  18. 19
      ICSharpCode.Decompiler/ILAst/GotoRemoval.cs
  19. 9
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  20. 4
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  21. 1
      ICSharpCode.Decompiler/ITextOutput.cs
  22. 13
      ICSharpCode.Decompiler/PlainTextOutput.cs
  23. 8
      ICSharpCode.Decompiler/Tests/Generics.cs
  24. 2
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  25. 2
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  26. 5
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs
  27. 3
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj
  28. 20
      ILSpy.sln
  29. 5
      ILSpy/AboutPage.cs
  30. 14
      ILSpy/AvalonEdit/ITextEditorListener.cs
  31. 123
      ILSpy/AvalonEdit/ITextMarker.cs
  32. 35
      ILSpy/AvalonEdit/IToolTip.cs
  33. 83
      ILSpy/AvalonEdit/IconBarManager.cs
  34. 318
      ILSpy/AvalonEdit/IconBarMargin.cs
  35. 190
      ILSpy/AvalonEdit/IconMarginActionsProvider.cs
  36. 75
      ILSpy/AvalonEdit/TextEditorWeakEventManager.cs
  37. 319
      ILSpy/AvalonEdit/TextMarkerService.cs
  38. 2
      ILSpy/Bookmarks/BookmarkBase.cs
  39. 2
      ILSpy/Bookmarks/BookmarkEventHandler.cs
  40. 2
      ILSpy/Bookmarks/BookmarkManager.cs
  41. 7
      ILSpy/Bookmarks/BreakpointBookmark.cs
  42. 0
      ILSpy/Bookmarks/BreakpointBookmarkEventArgs.cs
  43. 67
      ILSpy/Bookmarks/Commands.cs
  44. 6
      ILSpy/Bookmarks/CurrentLineBookmark.cs
  45. 4
      ILSpy/Bookmarks/IBookmark.cs
  46. 4
      ILSpy/Bookmarks/MarkerBookmark.cs
  47. 157
      ILSpy/Bookmarks/MemberBookmark.cs
  48. 111
      ILSpy/DebuggedData.cs
  49. 35
      ILSpy/ILSpy.csproj
  50. BIN
      ILSpy/Images/Breakpoint.png
  51. BIN
      ILSpy/Images/CurrentLine.png
  52. 3
      ILSpy/Images/Images.cs
  53. 10
      ILSpy/Languages/CSharpLanguage.cs
  54. 12
      ILSpy/Languages/ILLanguage.cs
  55. 45
      ILSpy/Languages/Language.cs
  56. 22
      ILSpy/MainWindow.xaml.cs
  57. 2
      ILSpy/Properties/AssemblyInfo.template.cs
  58. 2
      ILSpy/SessionSettings.cs
  59. 109
      ILSpy/TextView/DecompilerTextView.cs
  60. 43
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  61. 2
      ILSpy/XmlDoc/XmlDocKeyProvider.cs
  62. 3
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs

442
Debugger/ILSpy.Debugger/AvalonEdit/Editor/AvalonEditDocumentAdapter.cs

@ -1,442 +0,0 @@ @@ -1,442 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory;
namespace ILSpy.Debugger.AvalonEdit.Editor
{
/// <summary>
/// Wraps the AvalonEdit TextDocument to provide the IDocument interface.
/// </summary>
public class AvalonEditDocumentAdapter : IDocument
{
internal readonly TextDocument document;
/// <summary>
/// Creates a new AvalonEditDocumentAdapter instance.
/// </summary>
/// <param name="document">The document to wrap.</param>
public AvalonEditDocumentAdapter(TextDocument document)
{
if (document == null)
throw new ArgumentNullException("document");
this.document = document;
}
/// <summary>
/// Creates a new document.
/// </summary>
public AvalonEditDocumentAdapter()
{
this.document = new TextDocument();
}
sealed class LineAdapter : IDocumentLine
{
readonly TextDocument document;
readonly DocumentLine line;
public LineAdapter(TextDocument document, DocumentLine line)
{
Debug.Assert(document != null);
Debug.Assert(line != null);
this.document = document;
this.line = line;
}
public int Offset {
get { return line.Offset; }
}
public int Length {
get { return line.Length; }
}
public int EndOffset {
get { return line.EndOffset; }
}
public int TotalLength {
get { return line.TotalLength; }
}
public int DelimiterLength {
get { return line.DelimiterLength; }
}
public int LineNumber {
get { return line.LineNumber; }
}
public string Text {
get { return document.GetText(line); }
}
}
public int TextLength {
get { return document.TextLength; }
}
public int TotalNumberOfLines {
get { return document.LineCount; }
}
public string Text {
get { return document.Text; }
set { document.Text = value; }
}
public event EventHandler TextChanged {
add { document.TextChanged += value; }
remove { document.TextChanged -= value; }
}
public IDocumentLine GetLine(int lineNumber)
{
return new LineAdapter(document, document.GetLineByNumber(lineNumber));
}
public IDocumentLine GetLineForOffset(int offset)
{
return new LineAdapter(document, document.GetLineByOffset(offset));
}
public int PositionToOffset(int line, int column)
{
try {
return document.GetOffset(new TextLocation(line, column));
} catch (ArgumentOutOfRangeException e) {
// for UDC: re-throw exception so that stack trace identifies the caller (instead of the adapter)
throw new ArgumentOutOfRangeException(e.ParamName, e.ActualValue, e.Message);
}
}
public Location OffsetToPosition(int offset)
{
try {
return ToLocation(document.GetLocation(offset));
} catch (ArgumentOutOfRangeException e) {
// for UDC: re-throw exception so that stack trace identifies the caller (instead of the adapter)
throw new ArgumentOutOfRangeException(e.ParamName, e.ActualValue, e.Message);
}
}
public static Location ToLocation(TextLocation position)
{
return new Location(position.Column, position.Line);
}
public static TextLocation ToPosition(Location location)
{
return new TextLocation(location.Line, location.Column);
}
public void Insert(int offset, string text)
{
document.Insert(offset, text);
}
public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion) {
document.Replace(offset, 0, text, OffsetChangeMappingType.KeepAnchorBeforeInsertion);
} else {
document.Insert(offset, text);
}
}
public void Remove(int offset, int length)
{
document.Remove(offset, length);
}
public void Replace(int offset, int length, string newText)
{
document.Replace(offset, length, newText);
}
public void Replace(int offset, int length, string newText, AnchorMovementType defaultAnchorMovementType)
{
document.Replace(offset, length, newText);
}
public char GetCharAt(int offset)
{
return document.GetCharAt(offset);
}
public string GetText(int offset, int length)
{
return document.GetText(offset, length);
}
public System.IO.TextReader CreateReader()
{
return document.CreateSnapshot().CreateReader();
}
public System.IO.TextReader CreateReader(int offset, int length)
{
return document.CreateSnapshot(offset, length).CreateReader();
}
#region Snapshots and ITextBufferVersion
public ITextBuffer CreateSnapshot()
{
ChangeTrackingCheckpoint checkpoint;
ITextSource textSource = document.CreateSnapshot(out checkpoint);
return new Snapshot(textSource, checkpoint);
}
public ITextBuffer CreateSnapshot(int offset, int length)
{
return new AvalonEditTextSourceAdapter(document.CreateSnapshot(offset, length));
}
public ITextBufferVersion Version {
get {
return new SnapshotVersion(ChangeTrackingCheckpoint.Create(document));
}
}
sealed class Snapshot : AvalonEditTextSourceAdapter
{
readonly ITextBufferVersion version;
public Snapshot(ITextSource textSource, ChangeTrackingCheckpoint checkpoint)
: base(textSource)
{
this.version = new SnapshotVersion(checkpoint);
}
public override ITextBuffer CreateSnapshot()
{
// Snapshot is immutable
return this;
}
public override ITextBufferVersion Version {
get { return version; }
}
}
sealed class SnapshotVersion : ITextBufferVersion
{
readonly ChangeTrackingCheckpoint checkpoint;
public SnapshotVersion(ChangeTrackingCheckpoint checkpoint)
{
Debug.Assert(checkpoint != null);
this.checkpoint = checkpoint;
}
public bool BelongsToSameDocumentAs(ITextBufferVersion other)
{
SnapshotVersion otherVersion = other as SnapshotVersion;
return otherVersion != null && checkpoint.BelongsToSameDocumentAs(otherVersion.checkpoint);
}
public int CompareAge(ITextBufferVersion other)
{
SnapshotVersion otherVersion = other as SnapshotVersion;
if (otherVersion == null)
throw new ArgumentException("Does not belong to same document");
return checkpoint.CompareAge(otherVersion.checkpoint);
}
public IEnumerable<TextChangeEventArgs> GetChangesTo(ITextBufferVersion other)
{
SnapshotVersion otherVersion = other as SnapshotVersion;
if (otherVersion == null)
throw new ArgumentException("Does not belong to same document");
return checkpoint.GetChangesTo(otherVersion.checkpoint).Select(c => new TextChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText));
}
public int MoveOffsetTo(ITextBufferVersion other, int oldOffset, AnchorMovementType movement)
{
SnapshotVersion otherVersion = other as SnapshotVersion;
if (otherVersion == null)
throw new ArgumentException("Does not belong to same document");
switch (movement) {
case AnchorMovementType.AfterInsertion:
return checkpoint.MoveOffsetTo(otherVersion.checkpoint, oldOffset, ICSharpCode.AvalonEdit.Document.AnchorMovementType.AfterInsertion);
case AnchorMovementType.BeforeInsertion:
return checkpoint.MoveOffsetTo(otherVersion.checkpoint, oldOffset, ICSharpCode.AvalonEdit.Document.AnchorMovementType.BeforeInsertion);
default:
throw new NotSupportedException();
}
}
}
#endregion
public void StartUndoableAction()
{
document.BeginUpdate();
}
public void EndUndoableAction()
{
document.EndUpdate();
}
public IDisposable OpenUndoGroup()
{
return document.RunUpdate();
}
public ITextAnchor CreateAnchor(int offset)
{
return new AnchorAdapter(document.CreateAnchor(offset));
}
#region AnchorAdapter
sealed class AnchorAdapter : ITextAnchor
{
readonly TextAnchor anchor;
public AnchorAdapter(TextAnchor anchor)
{
this.anchor = anchor;
}
#region Forward Deleted Event
EventHandler deleted;
public event EventHandler Deleted {
add {
// we cannot simply forward the event handler because
// that would raise the event with an incorrect sender
if (deleted == null && value != null)
anchor.Deleted += OnDeleted;
deleted += value;
}
remove {
deleted -= value;
if (deleted == null)
anchor.Deleted -= OnDeleted;
}
}
void OnDeleted(object sender, EventArgs e)
{
// raise event with correct sender
if (deleted != null)
deleted(this, e);
}
#endregion
public Location Location {
get { return ToLocation(anchor.Location); }
}
public int Offset {
get { return anchor.Offset; }
}
public ILSpy.Debugger.AvalonEdit.Editor.AnchorMovementType MovementType {
get {
return (ILSpy.Debugger.AvalonEdit.Editor.AnchorMovementType)anchor.MovementType;
}
set {
anchor.MovementType = (ICSharpCode.AvalonEdit.Document.AnchorMovementType)value;
}
}
public bool SurviveDeletion {
get { return anchor.SurviveDeletion; }
set { anchor.SurviveDeletion = value; }
}
public bool IsDeleted {
get { return anchor.IsDeleted; }
}
public int Line {
get { return anchor.Line; }
}
public int Column {
get { return anchor.Column; }
}
}
#endregion
#region Changing/Changed events
EventHandler<TextChangeEventArgs> changing, changed;
bool eventsAreAttached;
void AttachEvents()
{
if (!eventsAreAttached && (changing != null || changed != null)) {
eventsAreAttached = true;
document.Changing += document_Changing;
document.Changed += document_Changed;
}
}
void DetachEvents()
{
if (eventsAreAttached && changing == null && changed == null) {
eventsAreAttached = false;
document.Changing -= document_Changing;
document.Changed -= document_Changed;
}
}
void document_Changing(object sender, DocumentChangeEventArgs e)
{
if (changing != null)
changing(this, new TextChangeEventArgs(e.Offset, e.RemovedText, e.InsertedText));
}
void document_Changed(object sender, DocumentChangeEventArgs e)
{
if (changed != null)
changed(this, new TextChangeEventArgs(e.Offset, e.RemovedText, e.InsertedText));
}
public event EventHandler<TextChangeEventArgs> Changing {
add {
changing += value;
AttachEvents();
}
remove {
changing -= value;
DetachEvents();
}
}
public event EventHandler<TextChangeEventArgs> Changed {
add {
changed += value;
AttachEvents();
}
remove {
changed -= value;
DetachEvents();
}
}
#endregion
}
}

98
Debugger/ILSpy.Debugger/AvalonEdit/Editor/AvalonEditTextSourceAdapter.cs

@ -1,98 +0,0 @@ @@ -1,98 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.AvalonEdit.Document;
using System;
namespace ILSpy.Debugger.AvalonEdit.Editor
{
public class AvalonEditTextSourceAdapter : ITextBuffer
{
internal readonly ITextSource textSource;
public AvalonEditTextSourceAdapter(ITextSource textSource)
{
if (textSource == null)
throw new ArgumentNullException("textSource");
this.textSource = textSource;
}
public virtual ITextBufferVersion Version {
get { return null; }
}
/// <summary>
/// Creates an immutable snapshot of this text buffer.
/// </summary>
public virtual ITextBuffer CreateSnapshot()
{
return new AvalonEditTextSourceAdapter(textSource.CreateSnapshot());
}
/// <summary>
/// Creates an immutable snapshot of a part of this text buffer.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
public ITextBuffer CreateSnapshot(int offset, int length)
{
return new AvalonEditTextSourceAdapter(textSource.CreateSnapshot(offset, length));
}
/// <summary>
/// Creates a new TextReader to read from this text buffer.
/// </summary>
public System.IO.TextReader CreateReader()
{
return textSource.CreateReader();
}
/// <summary>
/// Creates a new TextReader to read from this text buffer.
/// </summary>
public System.IO.TextReader CreateReader(int offset, int length)
{
return textSource.CreateSnapshot(offset, length).CreateReader();
}
public int TextLength {
get { return textSource.TextLength; }
}
public string Text {
get { return textSource.Text; }
}
/// <summary>
/// Is raised when the Text property changes.
/// </summary>
public event EventHandler TextChanged {
add { textSource.TextChanged += value; }
remove { textSource.TextChanged -= value; }
}
public char GetCharAt(int offset)
{
return textSource.GetCharAt(offset);
}
public string GetText(int offset, int length)
{
return textSource.GetText(offset, length);
}
}
}

85
Debugger/ILSpy.Debugger/AvalonEdit/Editor/IDocument.cs

@ -1,85 +0,0 @@ @@ -1,85 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp;
namespace ILSpy.Debugger.AvalonEdit.Editor
{
/// <summary>
/// A document representing a source code file for refactoring.
/// Line and column counting starts at 1.
/// Offset counting starts at 0.
/// </summary>
public interface IDocument : ITextBuffer
{
/// <summary>
/// Gets/Sets the whole text as string.
/// </summary>
new string Text { get; set; } // hides TextBuffer.Text to add the setter
/// <summary>
/// Gets the total number of lines in the document.
/// </summary>
int TotalNumberOfLines { get; }
/// <summary>
/// Gets the document line with the specified number.
/// </summary>
/// <param name="lineNumber">The number of the line to retrieve. The first line has number 1.</param>
IDocumentLine GetLine(int lineNumber);
/// <summary>
/// Gets the document line that contains the specified offset.
/// </summary>
IDocumentLine GetLineForOffset(int offset);
int PositionToOffset(int line, int column);
AstLocation OffsetToPosition(int offset);
void Insert(int offset, string text);
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType);
void Remove(int offset, int length);
void Replace(int offset, int length, string newText);
/// <summary>
/// Make the document combine the following actions into a single
/// action for undo purposes.
/// </summary>
void StartUndoableAction();
/// <summary>
/// Ends the undoable action started with <see cref="StartUndoableAction"/>.
/// </summary>
void EndUndoableAction();
/// <summary>
/// Creates an undo group. Dispose the returned value to close the undo group.
/// </summary>
/// <returns>An object that closes the undo group when Dispose() is called.</returns>
IDisposable OpenUndoGroup();
/// <summary>
/// Creates a new text anchor at the specified position.
/// </summary>
ITextAnchor CreateAnchor(int offset);
event EventHandler<TextChangeEventArgs> Changing;
event EventHandler<TextChangeEventArgs> Changed;
}
}

98
Debugger/ILSpy.Debugger/AvalonEdit/Editor/ITextAnchor.cs

@ -1,98 +0,0 @@ @@ -1,98 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp;
namespace ILSpy.Debugger.AvalonEdit.Editor
{
/// <summary>
/// Represents an anchored location inside an <see cref="IDocument"/>.
/// </summary>
public interface ITextAnchor
{
/// <summary>
/// Gets the text location of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
AstLocation Location { get; }
/// <summary>
/// Gets the offset of the text anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Offset { get; }
/// <summary>
/// Controls how the anchor moves.
/// </summary>
AnchorMovementType MovementType { get; set; }
/// <summary>
/// Specifies whether the anchor survives deletion of the text containing it.
/// <c>false</c>: The anchor is deleted when the a selection that includes the anchor is deleted.
/// <c>true</c>: The anchor is not deleted.
/// </summary>
bool SurviveDeletion { get; set; }
/// <summary>
/// Gets whether the anchor was deleted.
/// </summary>
bool IsDeleted { get; }
/// <summary>
/// Occurs after the anchor was deleted.
/// </summary>
event EventHandler Deleted;
/// <summary>
/// Gets the line number of the anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Line { get; }
/// <summary>
/// Gets the column number of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Column { get; }
}
/// <summary>
/// Defines how a text anchor moves.
/// </summary>
public enum AnchorMovementType
{
/// <summary>
/// When text is inserted at the anchor position, the type of the insertion
/// determines where the caret moves to. For normal insertions, the anchor will stay
/// behind the inserted text.
/// </summary>
Default = ICSharpCode.AvalonEdit.Document.AnchorMovementType.Default,
/// <summary>
/// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay
/// before the inserted text.
/// </summary>
BeforeInsertion = ICSharpCode.AvalonEdit.Document.AnchorMovementType.BeforeInsertion,
/// <summary>
/// Behave like an end marker - when text is insered at the anchor position, the anchor will move
/// after the inserted text.
/// </summary>
AfterInsertion = ICSharpCode.AvalonEdit.Document.AnchorMovementType.AfterInsertion
}
}

146
Debugger/ILSpy.Debugger/AvalonEdit/Editor/ITextBuffer.cs

@ -1,146 +0,0 @@ @@ -1,146 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.AvalonEdit.Document;
namespace ILSpy.Debugger.AvalonEdit.Editor
{
/// <summary>
/// A read-only view on a (potentially mutable) text buffer.
/// The IDocument interfaces derives from this interface.
/// </summary>
public interface ITextBuffer
{
/// <summary>
/// Gets a version identifier for this text buffer.
/// Returns null for unversioned text buffers.
/// </summary>
ITextBufferVersion Version { get; }
/// <summary>
/// Creates an immutable snapshot of this text buffer.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextBuffer CreateSnapshot();
/// <summary>
/// Creates an immutable snapshot of a part of this text buffer.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextBuffer CreateSnapshot(int offset, int length);
/// <summary>
/// Creates a new TextReader to read from this text buffer.
/// </summary>
TextReader CreateReader();
/// <summary>
/// Creates a new TextReader to read from this text buffer.
/// </summary>
TextReader CreateReader(int offset, int length);
/// <summary>
/// Gets the total text length.
/// </summary>
/// <returns>The length of the text, in characters.</returns>
/// <remarks>This is the same as Text.Length, but is more efficient because
/// it doesn't require creating a String object.</remarks>
int TextLength { get; }
/// <summary>
/// Gets the whole text as string.
/// </summary>
string Text { get; }
/// <summary>
/// Is raised when the Text property changes.
/// </summary>
event EventHandler TextChanged;
/// <summary>
/// Gets a character at the specified position in the document.
/// </summary>
/// <paramref name="offset">The index of the character to get.</paramref>
/// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception>
/// <returns>The character at the specified position.</returns>
/// <remarks>This is the same as Text[offset], but is more efficient because
/// it doesn't require creating a String object.</remarks>
char GetCharAt(int offset);
/// <summary>
/// Retrieves the text for a portion of the document.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
/// <remarks>This is the same as Text.Substring, but is more efficient because
/// it doesn't require creating a String object for the whole document.</remarks>
string GetText(int offset, int length);
}
/// <summary>
/// Represents a version identifier for a text buffer.
/// </summary>
/// <remarks>
/// This is SharpDevelop's equivalent to AvalonEdit ChangeTrackingCheckpoint.
/// It is used by the ParserService to efficiently detect whether a document has changed and needs reparsing.
/// It is a separate class from ITextBuffer to allow the GC to collect the text buffer while the version checkpoint
/// is still in use.
/// </remarks>
public interface ITextBufferVersion
{
/// <summary>
/// Gets whether this checkpoint belongs to the same document as the other checkpoint.
/// </summary>
bool BelongsToSameDocumentAs(ITextBufferVersion other);
/// <summary>
/// Compares the age of this checkpoint to the other checkpoint.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this version.</exception>
/// <returns>-1 if this version is older than <paramref name="other"/>.
/// 0 if <c>this</c> version instance represents the same version as <paramref name="other"/>.
/// 1 if this version is newer than <paramref name="other"/>.</returns>
int CompareAge(ITextBufferVersion other);
/// <summary>
/// Gets the changes from this checkpoint to the other checkpoint.
/// If 'other' is older than this checkpoint, reverse changes are calculated.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
IEnumerable<TextChangeEventArgs> GetChangesTo(ITextBufferVersion other);
/// <summary>
/// Calculates where the offset has moved in the other buffer version.
/// </summary>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
int MoveOffsetTo(ITextBufferVersion other, int oldOffset, AnchorMovementType movement);
}
public sealed class StringTextBuffer : AvalonEditTextSourceAdapter
{
public StringTextBuffer(string text)
: base(new StringTextSource(text))
{
}
}
}

50
Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// 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.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Services;
namespace ICSharpCode.ILSpy.Debugger.Commands
{
[ExportBookmarkActionEntry(Icon = "images/Breakpoint.png", Category="Debugger")]
public class BreakpointCommand : IBookmarkActionEntry
{
public bool IsEnabled()
{
return true;
}
public void Execute(int line)
{
if (DebugData.CodeMappings != null && DebugData.CodeMappings.Count > 0) {
// check if the codemappings exists for this line
var storage = DebugData.CodeMappings;
int token = 0;
foreach (var key in storage.Keys) {
var instruction = storage[key].GetInstructionByLineNumber(line, out token);
if (instruction == null) {
continue;
}
// no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt(
DebugData.DecompiledMemberReferences[key],
line,
instruction.ILInstructionOffset,
DebugData.Language);
break;
}
if (token == 0) {
MessageBox.Show(string.Format("Missing code mappings at line {0}.", line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
}
}
}
}

29
ILSpy/Commands/DebuggerCommands.cs → Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs

@ -12,6 +12,7 @@ using System.Windows.Media; @@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services;
@ -20,9 +21,9 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -20,9 +21,9 @@ using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
using Microsoft.Win32;
namespace ICSharpCode.ILSpy.Commands
namespace ICSharpCode.ILSpy.Debugger.Commands
{
internal abstract class DebuggerCommand : SimpleCommand
public abstract class DebuggerCommand : SimpleCommand
{
public DebuggerCommand()
{
@ -82,7 +83,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -82,7 +83,7 @@ namespace ICSharpCode.ILSpy.Commands
public override void Execute(object parameter)
{
DebugData.LoadedAssemblies = MainWindow.Instance.CurrentAssemblyList.assemblies.Select(a => a.AssemblyDefinition);
DebugData.LoadedAssemblies = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().Select(a => a.AssemblyDefinition);
}
protected static IDebugger CurrentDebugger {
@ -127,8 +128,8 @@ namespace ICSharpCode.ILSpy.Commands @@ -127,8 +128,8 @@ namespace ICSharpCode.ILSpy.Commands
protected void EnableDebuggerUI(bool enable)
{
var menuItems = MainWindow.Instance.mainMenu.Items;
var toolbarItems = MainWindow.Instance.toolBar.Items;
var menuItems = MainWindow.Instance.GetMainMenuItems();
var toolbarItems = MainWindow.Instance.GetToolBarItems();
// menu
var items = menuItems.OfType<MenuItem>().Where(m => (m.Header as string) == "_Debugger");
@ -150,7 +151,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -150,7 +151,7 @@ namespace ICSharpCode.ILSpy.Commands
}
// internal types
MainWindow.Instance.sessionSettings.FilterSettings.ShowInternalApi = true;
MainWindow.Instance.SessionSettings.FilterSettings.ShowInternalApi = true;
}
void CurrentDebugger_IsProcessRunningChanged(object sender, EventArgs e)
@ -174,7 +175,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -174,7 +175,7 @@ namespace ICSharpCode.ILSpy.Commands
}
}
[ExportContextMenuEntry(Header = "_Debug Assembly", Icon = "ILSpy.Debugger;component/Images/application-x-executable.png")]
[ExportContextMenuEntry(Header = "_Debug Assembly", Icon = "Images/application-x-executable.png")]
internal sealed class DebugExecutableNodeCommand : DebuggerCommand, IContextMenuEntry
{
public bool IsVisible(SharpTreeNode[] selectedNodes)
@ -212,12 +213,12 @@ namespace ICSharpCode.ILSpy.Commands @@ -212,12 +213,12 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportToolbarCommand(ToolTip = "Debug an executable",
ToolbarIcon = "ILSpy.Debugger;component/Images/application-x-executable.png",
ToolbarIcon = "Images/application-x-executable.png",
ToolbarCategory = "Debugger",
Tag = "Debugger",
ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/application-x-executable.png",
MenuIcon = "Images/application-x-executable.png",
MenuCategory = "Start",
Header = "Debug an _executable",
MenuOrder = 0)]
@ -286,7 +287,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -286,7 +287,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/ContinueDebugging.png",
MenuIcon = "Images/ContinueDebugging.png",
MenuCategory = "SteppingArea",
Header = "Continue debugging",
InputGestureText = "F5",
@ -304,7 +305,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -304,7 +305,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepInto.png",
MenuIcon = "Images/StepInto.png",
MenuCategory = "SteppingArea",
Header = "Step into",
InputGestureText = "F11",
@ -322,7 +323,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -322,7 +323,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepOver.png",
MenuIcon = "Images/StepOver.png",
MenuCategory = "SteppingArea",
Header = "Step over",
InputGestureText = "F10",
@ -340,7 +341,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -340,7 +341,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepOut.png",
MenuIcon = "Images/StepOut.png",
MenuCategory = "SteppingArea",
Header = "Step out",
IsEnabled = false,
@ -375,7 +376,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -375,7 +376,7 @@ namespace ICSharpCode.ILSpy.Commands
}
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/DeleteAllBreakpoints.png",
MenuIcon = "Images/DeleteAllBreakpoints.png",
MenuCategory = "Others",
Header = "Remove all _breakpoints",
MenuOrder = 7)]

59
Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj

@ -11,26 +11,38 @@ @@ -11,26 +11,38 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<OutputPath>..\..\ILSpy\bin\Debug\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<StartAction>Project</StartAction>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<OutputPath>..\..\ILSpy\bin\Release\</OutputPath>
<DebugSymbols>false</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
@ -41,6 +53,9 @@ @@ -41,6 +53,9 @@
<Reference Include="System.ComponentModel.Composition">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.ComponentModel.Composition">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
@ -56,20 +71,8 @@ @@ -56,20 +71,8 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="AvalonEdit\TextEditorWeakEventManager.cs" />
<Compile Include="AvalonEdit\IconBarMargin.cs" />
<Compile Include="AvalonEdit\IToolTip.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="Bookmarks\BookmarkBase.cs" />
<Compile Include="Bookmarks\BookmarkEventHandler.cs" />
<Compile Include="Bookmarks\BookmarkManager.cs" />
<Compile Include="Bookmarks\BreakpointBookmark.cs" />
<Compile Include="Bookmarks\BreakpointBookmarkEventArgs.cs" />
<Compile Include="Bookmarks\CurrentLineBookmark.cs" />
<Compile Include="Bookmarks\IBookmark.cs" />
<Compile Include="Bookmarks\MarkerBookmark.cs" />
<Compile Include="DebuggedData.cs" />
<Compile Include="Commands\BreakpointCommand.cs" />
<Compile Include="Commands\DebuggerCommands.cs" />
<Compile Include="DebuggerSettings.cs" />
<Compile Include="Models\TreeModel\ArrayRangeNode.cs" />
<Compile Include="Models\TreeModel\ChildNodesOfObject.cs" />
@ -107,6 +110,10 @@ @@ -107,6 +110,10 @@
<DependentUpon>AttachToProcessWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\DebuggerSettingsPanel.xaml.cs">
<DependentUpon>DebuggerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\ExecuteProcessWindow.xaml.cs">
<DependentUpon>ExecuteProcessWindow.xaml</DependentUpon>
<SubType>Code</SubType>
@ -115,6 +122,7 @@ @@ -115,6 +122,7 @@
<ItemGroup>
<Folder Include="Images" />
<Folder Include="Models\TreeModel" />
<Folder Include="Commands" />
<Folder Include="ToolTips" />
<Folder Include="ToolTips\Models" />
</ItemGroup>
@ -123,6 +131,7 @@ @@ -123,6 +131,7 @@
<Page Include="ToolTips\PinControlsDictionary.xaml" />
<Page Include="ToolTips\VisualizerPicker.xaml" />
<Page Include="UI\AttachToProcessWindow.xaml" />
<Page Include="UI\DebuggerSettingsPanel.xaml" />
<Page Include="UI\ExecuteProcessWindow.xaml" />
</ItemGroup>
<ItemGroup>
@ -134,6 +143,10 @@ @@ -134,6 +143,10 @@
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
@ -142,6 +155,10 @@ @@ -142,6 +155,10 @@
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
<ProjectReference Include="..\Debugger.Core\Debugger.Core.csproj">
<Project>{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}</Project>
<Name>Debugger.Core</Name>

2
Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Tooltips;
using ICSharpCode.NRefactory.CSharp.Resolver;
@ -25,6 +26,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -25,6 +26,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
static IDebugger GetCompatibleDebugger()
{
DebugData.IsDebuggerLoaded = true;
return currentDebugger = new WindowsDebugger();
}

1
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -12,6 +12,7 @@ using Debugger; @@ -12,6 +12,7 @@ using Debugger;
using Debugger.Interop.CorPublish;
using Debugger.MetaData;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Models.TreeModel;
using ICSharpCode.ILSpy.Debugger.Services.Debugger;

2
Debugger/ILSpy.Debugger/ToolTips/DebuggerTooltipControl.xaml.cs

@ -14,7 +14,7 @@ using System.Windows.Media.Animation; @@ -14,7 +14,7 @@ using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Models.TreeModel;
using ICSharpCode.ILSpy.Debugger.Services;

71
Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
@ -10,74 +12,66 @@ using System.Windows.Input; @@ -10,74 +12,66 @@ using System.Windows.Input;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Services;
namespace ICSharpCode.ILSpy.Debugger.Tooltips
{
public sealed class TextEditorListener : IWeakEventListener
[Export(typeof(ITextEditorListener))]
public class TextEditorListener : IWeakEventListener, ITextEditorListener
{
private static readonly TextEditorListener instance;
static TextEditorListener()
public TextEditorListener()
{
instance = new TextEditorListener();
}
private TextEditorListener() { }
Popup popup;
TextEditor editor;
public static TextEditorListener Instance {
get { return instance; }
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager.MouseHover)) {
if (managerType == typeof(ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseHover)) {
editor = (TextEditor)sender;
OnMouseHover((MouseEventArgs)e);
}
if (managerType == typeof(ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager.MouseHoverStopped)) {
if (managerType == typeof(ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseHoverStopped)) {
OnMouseHoverStopped((MouseEventArgs)e);
}
if (managerType == typeof(ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager.MouseDown)) {
if (managerType == typeof(ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseDown)) {
OnMouseDown((MouseEventArgs)e);
}
return true;
}
void OnMouseDown(MouseEventArgs e)
{
ClosePopup();
}
void OnMouseHoverStopped(MouseEventArgs e)
{
}
void OnMouseHover(MouseEventArgs e)
{
ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor);
var pos = editor.GetPositionFromPoint(e.GetPosition(editor));
args.InDocument = pos.HasValue;
if (pos.HasValue) {
args.LogicalPosition = new AstLocation(pos.Value.Line, pos.Value.Column);
} else {
} else {
return;
}
DebuggerService.HandleToolTipRequest(args);
if (args.ContentToShow != null) {
var contentToShowITooltip = args.ContentToShow as ITooltip;
if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) {
if (!(args.ContentToShow is UIElement)) {
throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
@ -103,7 +97,7 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips @@ -103,7 +97,7 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips
TryCloseExistingPopup(false);
}
}
bool TryCloseExistingPopup(bool mouseClick)
{
bool canClose = true;
@ -118,14 +112,14 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips @@ -118,14 +112,14 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips
}
return canClose;
}
void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs)
{
var popupPosition = GetPopupPosition(mouseArgs);
popup.HorizontalOffset = popupPosition.X;
popup.VerticalOffset = popupPosition.Y;
}
/// <summary> Returns Popup position based on mouse position, in device independent units </summary>
Point GetPopupPosition(MouseEventArgs mouseArgs)
{
@ -135,9 +129,7 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips @@ -135,9 +129,7 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips
TextViewPosition? logicalPos = editor.GetPositionFromPoint(mousePos);
if (logicalPos.HasValue) {
var textView = editor.TextArea.TextView;
positionInPixels =
textView.PointToScreen(
textView.GetVisualPosition(logicalPos.Value, VisualYPosition.LineBottom) - textView.ScrollOffset);
positionInPixels = textView.PointToScreen(textView.GetVisualPosition(logicalPos.Value, VisualYPosition.LineBottom) - textView.ScrollOffset);
positionInPixels.X -= 4;
} else {
positionInPixels = editor.PointToScreen(mousePos + new Vector(-4, 6));
@ -145,27 +137,28 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips @@ -145,27 +137,28 @@ namespace ICSharpCode.ILSpy.Debugger.Tooltips
// use device independent units, because Popup Left/Top are in independent units
return positionInPixels.TransformFromDevice(editor);
}
Popup CreatePopup()
{
popup = new Popup();
popup.Closed += delegate { popup = null; };
popup.AllowsTransparency = true;
popup.PlacementTarget = editor; // required for property inheritance
popup.PlacementTarget = editor;
// required for property inheritance
popup.Placement = PlacementMode.Absolute;
popup.StaysOpen = true;
return popup;
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
return ReceiveWeakEvent(managerType, sender, e);
}
public void ClosePopup()
{
TryCloseExistingPopup(true);
if (popup != null)
popup.IsOpen = false;
}

0
ILSpy/Options/DebuggerSettingsPanel.xaml → Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml

0
ILSpy/Options/DebuggerSettingsPanel.xaml.cs → Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs

12
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1509,13 +1509,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -1509,13 +1509,13 @@ namespace ICSharpCode.Decompiler.Ast
{ // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve();
if (enumDefinition != null && enumDefinition.IsEnum) {
TypeCode enumBaseTypeCode = TypeCode.Int32;
foreach (FieldDefinition field in enumDefinition.Fields) {
if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
return ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
return ConvertType(type).Member(field.Name).WithAnnotation(field);
else if (!field.IsStatic && field.IsRuntimeSpecialName)
type = field.FieldType; // use primitive type of the enum
enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum
}
TypeCode enumBaseTypeCode = TypeAnalysis.GetTypeCode(type);
if (IsFlagsEnum(enumDefinition)) {
long enumValue = val;
Expression expr = null;
@ -1542,7 +1542,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1542,7 +1542,7 @@ namespace ICSharpCode.Decompiler.Ast
continue; // skip None enum value
if ((fieldValue & enumValue) == fieldValue) {
var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
if (expr == null)
expr = fieldExpression;
else
@ -1551,7 +1551,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1551,7 +1551,7 @@ namespace ICSharpCode.Decompiler.Ast
enumValue &= ~fieldValue;
}
if ((fieldValue & negatedEnumValue) == fieldValue) {
var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
if (negatedExpr == null)
negatedExpr = fieldExpression;
else
@ -1569,7 +1569,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1569,7 +1569,7 @@ namespace ICSharpCode.Decompiler.Ast
return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr);
}
}
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(enumDefinition));
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type));
}
}
TypeCode code = TypeAnalysis.GetTypeCode(type);

15
ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -148,9 +148,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -148,9 +148,9 @@ namespace ICSharpCode.Decompiler.Ast
public void StartNode(AstNode node)
{
// code mappings
var ranges = node.Annotation<List<ILRange>>();
if (ranges != null && ranges.Count > 0)
{
if (ranges != null && ranges.Count > 0) {
// find the ancestor that has method mapping as annotation
if (node.Parent != null)
{
@ -170,6 +170,17 @@ namespace ICSharpCode.Decompiler.Ast @@ -170,6 +170,17 @@ namespace ICSharpCode.Decompiler.Ast
}
}
// definitions of types and their members
Predicate<AstNode> predicate = n => n is AttributedNode;
if (predicate(node)) {
var n = node as AttributedNode;
int c = 0;
if (n != null)
c = n.Attributes.Count;
node.AddAnnotation(Tuple.Create(output.CurrentLine + c, output.CurrentColumn));
}
nodeStack.Push(node);
}

3
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -220,7 +220,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -220,7 +220,8 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[method.MetadataToken.ToInt32()]);
CreateCodeMappings(method.MetadataToken.ToInt32(), currentMember);
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[method.MetadataToken.ToInt32()], currentMember);
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
}

19
ICSharpCode.Decompiler/ILAst/GotoRemoval.cs

@ -98,10 +98,27 @@ namespace ICSharpCode.Decompiler.ILAst @@ -98,10 +98,27 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
// Remove redundant return
// Remove redundant return at the end of method
if (method.Body.Count > 0 && method.Body.Last().Match(ILCode.Ret) && ((ILExpression)method.Body.Last()).Arguments.Count == 0) {
method.Body.RemoveAt(method.Body.Count - 1);
}
// Remove unreachable return statements
bool modified = false;
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count - 1;) {
if (block.Body[i].IsUnconditionalControlFlow() && block.Body[i+1].Match(ILCode.Ret)) {
modified = true;
block.Body.RemoveAt(i+1);
} else {
i++;
}
}
}
if (modified) {
// More removals might be possible
new GotoRemoval().RemoveGotos(method);
}
}
IEnumerable<ILNode> GetParents(ILNode node)

9
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -281,6 +281,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -281,6 +281,8 @@ namespace ICSharpCode.Decompiler.ILAst
int varCount = methodDef.Body.Variables.Count;
var exceptionHandlerStarts = new HashSet<ByteCode>(methodDef.Body.ExceptionHandlers.Select(eh => instrToByteCode[eh.HandlerStart]));
// Add known states
if(methodDef.Body.HasExceptionHandlers) {
foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
@ -347,7 +349,12 @@ namespace ICSharpCode.Decompiler.ILAst @@ -347,7 +349,12 @@ namespace ICSharpCode.Decompiler.ILAst
// Find all successors
List<ByteCode> branchTargets = new List<ByteCode>();
if (!byteCode.Code.IsUnconditionalControlFlow()) {
branchTargets.Add(byteCode.Next);
if (exceptionHandlerStarts.Contains(byteCode.Next)) {
// Do not fall though down to exception handler
// It is invalid IL as per ECMA-335 §12.4.2.8.1, but some obfuscators produce it
} else {
branchTargets.Add(byteCode.Next);
}
}
if (byteCode.Operand is Instruction[]) {
foreach(Instruction inst in (Instruction[])byteCode.Operand) {

4
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -56,6 +56,7 @@ namespace ICSharpCode.Decompiler.ILAst
RemoveRedundantCode2,
GotoRemoval,
DuplicateReturns,
GotoRemoval2,
ReduceIfNesting,
InlineVariables3,
CachedDelegateInitialization,
@ -182,6 +183,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -182,6 +183,9 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
DuplicateReturnStatements(method);
if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval2) return;
new GotoRemoval().RemoveGotos(method);
if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting) return;
ReduceIfNesting(method);

1
ICSharpCode.Decompiler/ITextOutput.cs

@ -24,6 +24,7 @@ namespace ICSharpCode.Decompiler @@ -24,6 +24,7 @@ namespace ICSharpCode.Decompiler
public interface ITextOutput
{
int CurrentLine { get; }
int CurrentColumn { get; }
void Indent();
void Unindent();

13
ICSharpCode.Decompiler/PlainTextOutput.cs

@ -23,10 +23,13 @@ namespace ICSharpCode.Decompiler @@ -23,10 +23,13 @@ namespace ICSharpCode.Decompiler
{
public sealed class PlainTextOutput : ITextOutput
{
const int TAB_SIZE = 4;
readonly TextWriter writer;
int indent;
bool needsIndent;
int lineNumber = 1;
int columnNumber = 1;
public PlainTextOutput(TextWriter writer)
{
@ -40,10 +43,14 @@ namespace ICSharpCode.Decompiler @@ -40,10 +43,14 @@ namespace ICSharpCode.Decompiler
this.writer = new StringWriter();
}
public int CurrentLine {
public int CurrentLine {
get { return lineNumber; }
}
public int CurrentColumn {
get { return columnNumber; }
}
public override string ToString()
{
return writer.ToString();
@ -65,6 +72,7 @@ namespace ICSharpCode.Decompiler @@ -65,6 +72,7 @@ namespace ICSharpCode.Decompiler
needsIndent = false;
for (int i = 0; i < indent; i++) {
writer.Write('\t');
columnNumber += TAB_SIZE - 1;
}
}
}
@ -73,12 +81,14 @@ namespace ICSharpCode.Decompiler @@ -73,12 +81,14 @@ namespace ICSharpCode.Decompiler
{
WriteIndent();
writer.Write(ch);
columnNumber++;
}
public void Write(string text)
{
WriteIndent();
writer.Write(text);
columnNumber += text.Length;
}
public void WriteLine()
@ -86,6 +96,7 @@ namespace ICSharpCode.Decompiler @@ -86,6 +96,7 @@ namespace ICSharpCode.Decompiler
lineNumber++;
writer.WriteLine();
needsIndent = true;
columnNumber = TAB_SIZE * indent;
}
public void WriteDefinition(string text, object definition)

8
ICSharpCode.Decompiler/Tests/Generics.cs

@ -29,6 +29,12 @@ public static class Generics @@ -29,6 +29,12 @@ public static class Generics
public Y Item2;
}
public enum NestedEnum
{
A,
B
}
private T[] arr;
public MyArray(int capacity)
@ -75,11 +81,13 @@ public static class Generics @@ -75,11 +81,13 @@ public static class Generics
}
}
private const Generics.MyArray<string>.NestedEnum enumVal = Generics.MyArray<string>.NestedEnum.A;
private static Type type1 = typeof(List<>);
private static Type type2 = typeof(Generics.MyArray<>);
private static Type type3 = typeof(List<>.Enumerator);
private static Type type4 = typeof(Generics.MyArray<>.NestedClass<>);
private static Type type5 = typeof(List<int>[]);
private static Type type6 = typeof(Generics.MyArray<>.NestedEnum);
public static void MethodWithConstraint<T, S>() where T : class, S where S : ICloneable, new()
{

2
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<NoWarn>67,169</NoWarn>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<NoWarn>67,169,1058,728</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>

2
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -158,7 +158,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -158,7 +158,7 @@ namespace ICSharpCode.Decompiler.Tests
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
options.CompilerOptions = "/unsafe";
options.CompilerOptions = "/unsafe /o-";
options.ReferencedAssemblies.Add("System.Core.dll");
CompilerResults results = provider.CompileAssemblyFromSource(options, code);
try {

5
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs

@ -132,6 +132,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -132,6 +132,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else
return false;
}
public override int GetHashCode()
{
return this.AssemblyId ^ this.Name.GetHashCode() ^ this.Namespace.GetHashCode();
}
}
}

3
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -44,11 +44,9 @@ @@ -44,11 +44,9 @@
<Reference Include="nunit.framework">
<HintPath>..\..\ICSharpCode.Decompiler\Tests\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework" />
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
@ -63,7 +61,6 @@ @@ -63,7 +61,6 @@
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>

20
ILSpy.sln

@ -1,12 +1,20 @@ @@ -1,12 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
# SharpDevelop 4.1.0.7469-alpha
# SharpDevelop 4.1.0.7590-alpha
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"
ProjectSection(SolutionItems) = postProject
doc\Command Line.txt = doc\Command Line.txt
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{89C4A682-2706-44A3-ADDC-BC273164C37E}"
ProjectSection(SolutionItems) = postProject
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.Debugger", "Debugger\ILSpy.Debugger\ILSpy.Debugger.csproj", "{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "Debugger\Debugger.Core\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}"
@ -29,14 +37,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler", "ILS @@ -29,14 +37,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler", "ILS
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler\Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{89C4A682-2706-44A3-ADDC-BC273164C37E}"
ProjectSection(SolutionItems) = postProject
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "Debugger\Debugger.Core\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.Debugger", "Debugger\ILSpy.Debugger\ILSpy.Debugger.csproj", "{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -146,7 +146,7 @@ Global @@ -146,7 +146,7 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A} = {89C4A682-2706-44A3-ADDC-BC273164C37E}
{1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {89C4A682-2706-44A3-ADDC-BC273164C37E}
{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A} = {89C4A682-2706-44A3-ADDC-BC273164C37E}
EndGlobalSection
EndGlobal

5
ILSpy/AboutPage.cs

@ -31,8 +31,10 @@ using System.Windows.Data; @@ -31,8 +31,10 @@ using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy
@ -95,6 +97,9 @@ namespace ICSharpCode.ILSpy @@ -95,6 +97,9 @@ namespace ICSharpCode.ILSpy
output.AddVisualLineElementGenerator(new MyLinkElementGenerator("MIT License", "resource:license.txt"));
output.AddVisualLineElementGenerator(new MyLinkElementGenerator("LGPL", "resource:LGPL.txt"));
textView.ShowText(output);
//reset icon bar
textView.manager.Bookmarks.Clear();
}
sealed class MyLinkElementGenerator : LinkElementGenerator

14
ILSpy/AvalonEdit/ITextEditorListener.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
// 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.Windows;
namespace ICSharpCode.ILSpy.AvalonEdit
{
public interface ITextEditorListener : IWeakEventListener
{
new bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e);
void ClosePopup();
}
}

123
ILSpy/AvalonEdit/ITextMarker.cs

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
// 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 System.Windows.Media;
using ICSharpCode.ILSpy.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Represents a text marker.
/// </summary>
public interface ITextMarker
{
/// <summary>
/// Gets the start offset of the marked text region.
/// </summary>
int StartOffset { get; }
/// <summary>
/// Gets the end offset of the marked text region.
/// </summary>
int EndOffset { get; }
/// <summary>
/// Gets the length of the marked region.
/// </summary>
int Length { get; }
/// <summary>
/// Deletes the text marker.
/// </summary>
void Delete();
/// <summary>
/// Gets whether the text marker was deleted.
/// </summary>
bool IsDeleted { get; }
/// <summary>
/// Event that occurs when the text marker is deleted.
/// </summary>
event EventHandler Deleted;
/// <summary>
/// Gets/Sets the background color.
/// </summary>
Color? BackgroundColor { get; set; }
/// <summary>
/// Gets/Sets the foreground color.
/// </summary>
Color? ForegroundColor { get; set; }
/// <summary>
/// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers.
/// </summary>
TextMarkerType MarkerType { get; set; }
/// <summary>
/// Gets/Sets the color of the marker.
/// </summary>
Color MarkerColor { get; set; }
/// <summary>
/// Gets/Sets an object with additional data for this text marker.
/// </summary>
object Tag { get; set; }
/// <summary>
/// Gets/Sets an object that will be displayed as tooltip in the text editor.
/// </summary>
object ToolTip { get; set; }
/// <summary>
/// Gets or sets if the marker is visible or not.
/// </summary>
Predicate<object> IsVisible { get; set; }
/// <summary>
/// Gets or sets the bookmark.
/// </summary>
IBookmark Bookmark { get; set; }
}
public enum TextMarkerType
{
/// <summary>
/// Use no marker
/// </summary>
None,
/// <summary>
/// Use squiggly underline marker
/// </summary>
SquigglyUnderline
}
public interface ITextMarkerService
{
/// <summary>
/// Creates a new text marker. The text marker will be invisible at first,
/// you need to set one of the Color properties to make it visible.
/// </summary>
ITextMarker Create(int startOffset, int length);
/// <summary>
/// Gets the list of text markers.
/// </summary>
IEnumerable<ITextMarker> TextMarkers { get; }
/// <summary>
/// Removes the specified text marker.
/// </summary>
void Remove(ITextMarker marker);
/// <summary>
/// Removes all text markers that match the condition.
/// </summary>
void RemoveAll(Predicate<ITextMarker> predicate);
}
}

35
ILSpy/AvalonEdit/IToolTip.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// 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.Windows;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Content of text editor tooltip (used as <see cref="ToolTipRequestEventArgs.ContentToShow"/>),
/// specifying whether it should be displayed in a WPF Popup.
/// </summary>
public interface ITooltip
{
/// <summary>
/// If true, this ITooltip will be displayed in a WPF Popup.
/// Otherwise it will be displayed in a WPF Tooltip.
/// WPF Popups are (unlike WPF Tooltips) focusable.
/// </summary>
bool ShowAsPopup { get; }
/// <summary>
/// Closes this tooltip.
/// </summary>
/// <param name="mouseClick">True if close request is raised
/// because of mouse click on some SharpDevelop GUI element.</param>
/// <returns>True if Close succeeded (that is, can close). False otherwise.</returns>
bool Close(bool mouseClick);
/// <summary>
/// Occurs when this tooltip decides to close.
/// </summary>
event RoutedEventHandler Closed;
}
}

83
ILSpy/AvalonEdit/IconBarManager.cs

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Stores the entries in the icon bar margin. Multiple icon bar margins
/// can use the same manager if split view is used.
/// </summary>
public class IconBarManager : IBookmarkMargin
{
ObservableCollection<IBookmark> bookmarks = new ObservableCollection<IBookmark>();
public IconBarManager()
{
bookmarks.CollectionChanged += bookmarks_CollectionChanged;
}
public IList<IBookmark> Bookmarks {
get { return bookmarks; }
}
void bookmarks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Redraw();
}
public void Redraw()
{
if (RedrawRequested != null)
RedrawRequested(this, EventArgs.Empty);
}
public event EventHandler RedrawRequested;
internal void UpdateClassMemberBookmarks(IEnumerable<AstNode> nodes)
{
this.bookmarks.Clear();
if (nodes == null || nodes.Count() == 0)
return;
foreach (var n in nodes) {
switch (n.NodeType) {
case NodeType.TypeDeclaration:
case NodeType.TypeReference:
this.bookmarks.Add(new TypeBookmark(n));
break;
case NodeType.Member:
this.bookmarks.Add(new MemberBookmark(n));
break;
default:
// do nothing
break;
}
}
}
}
}

318
ILSpy/AvalonEdit/IconBarMargin.cs

@ -0,0 +1,318 @@ @@ -0,0 +1,318 @@
// 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 System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.AvalonEdit
{
public class IconBarMargin : AbstractMargin, IDisposable
{
readonly IconBarManager manager;
public IconBarMargin(IconBarManager manager)
{
BookmarkManager.Added += delegate { InvalidateVisual(); };
BookmarkManager.Removed += delegate { InvalidateVisual(); };
this.manager = manager;
}
public IconBarManager Manager {
get { return manager; }
}
public IList<MemberReference> DecompiledMembers { get; set; }
public virtual void Dispose()
{
this.TextView = null; // detach from TextView (will also detach from manager)
}
/// <inheritdoc/>
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
// accept clicks even when clicking on the background
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
/// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize)
{
return new Size(18, 0);
}
protected override void OnRender(DrawingContext drawingContext)
{
Size renderSize = this.RenderSize;
drawingContext.DrawRectangle(SystemColors.ControlBrush, null,
new Rect(0, 0, renderSize.Width, renderSize.Height));
drawingContext.DrawLine(new Pen(SystemColors.ControlDarkBrush, 1),
new Point(renderSize.Width - 0.5, 0),
new Point(renderSize.Width - 0.5, renderSize.Height));
ICSharpCode.AvalonEdit.Rendering.TextView textView = this.TextView;
if (textView != null && textView.VisualLinesValid) {
// create a dictionary line number => first bookmark
Dictionary<int, IBookmark> bookmarkDict = new Dictionary<int, IBookmark>();
foreach (var bm in BookmarkManager.Bookmarks) {
if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 ||
!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32()))
continue;
int line = bm.LineNumber;
IBookmark existingBookmark;
if (!bookmarkDict.TryGetValue(line, out existingBookmark) || bm.ZOrder > existingBookmark.ZOrder)
bookmarkDict[line] = bm;
}
foreach (var bm in manager.Bookmarks) {
int line = bm.LineNumber;
IBookmark existingBookmark;
if (!bookmarkDict.TryGetValue(line, out existingBookmark) || bm.ZOrder > existingBookmark.ZOrder)
bookmarkDict[line] = bm;
}
Size pixelSize = PixelSnapHelpers.GetPixelSize(this);
foreach (VisualLine line in textView.VisualLines) {
int lineNumber = line.FirstDocumentLine.LineNumber;
IBookmark bm;
if (bookmarkDict.TryGetValue(lineNumber, out bm)) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(line.VisualTop - textView.VerticalOffset, pixelSize.Height), 16, 16);
if (dragDropBookmark == bm && dragStarted)
drawingContext.PushOpacity(0.5);
drawingContext.DrawImage(bm.Image, rect);
if (dragDropBookmark == bm && dragStarted)
drawingContext.Pop();
}
}
if (dragDropBookmark != null && dragStarted) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(dragDropCurrentPoint - 8, pixelSize.Height), 16, 16);
drawingContext.DrawImage(dragDropBookmark.Image, rect);
}
}
}
IBookmark dragDropBookmark; // bookmark being dragged (!=null if drag'n'drop is active)
double dragDropStartPoint;
double dragDropCurrentPoint;
bool dragStarted; // whether drag'n'drop operation has started (mouse was moved minimum distance)
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && line > 0) {
IBookmark bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseDown(e);
if (!e.Handled) {
if (e.ChangedButton == MouseButton.Left && bm.CanDragDrop && CaptureMouse()) {
StartDragDrop(bm, e);
e.Handled = true;
}
}
}
}
// don't allow selecting text through the IconBarMargin
if (e.ChangedButton == MouseButton.Left)
e.Handled = true;
}
IBookmark GetBookmarkFromLine(int line)
{
BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line &&
this.DecompiledMembers != null && this.DecompiledMembers.Contains(bm.MemberReference)) {
if (result == null || bm.ZOrder > result.ZOrder)
return result;
}
}
return manager.Bookmarks.FirstOrDefault(b => b.LineNumber == line);
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
CancelDragDrop();
base.OnLostMouseCapture(e);
}
void StartDragDrop(IBookmark bm, MouseEventArgs e)
{
dragDropBookmark = bm;
dragDropStartPoint = dragDropCurrentPoint = e.GetPosition(this).Y;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown += TextArea_PreviewKeyDown;
}
}
void CancelDragDrop()
{
if (dragDropBookmark != null) {
dragDropBookmark = null;
dragStarted = false;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown -= TextArea_PreviewKeyDown;
}
ReleaseMouseCapture();
InvalidateVisual();
}
}
void TextArea_PreviewKeyDown(object sender, KeyEventArgs e)
{
// any key press cancels drag'n'drop
CancelDragDrop();
if (e.Key == Key.Escape)
e.Handled = true;
}
internal int GetLineFromMousePosition(MouseEventArgs e)
{
ICSharpCode.AvalonEdit.Rendering.TextView textView = this.TextView;
if (textView == null)
return 0;
VisualLine vl = textView.GetVisualLineFromVisualTop(e.GetPosition(textView).Y + textView.ScrollOffset.Y);
if (vl == null)
return 0;
return vl.FirstDocumentLine.LineNumber;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (dragDropBookmark != null) {
dragDropCurrentPoint = e.GetPosition(this).Y;
if (Math.Abs(dragDropCurrentPoint - dragDropStartPoint) > SystemParameters.MinimumVerticalDragDistance)
dragStarted = true;
InvalidateVisual();
}
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && dragDropBookmark != null) {
if (dragStarted) {
if (line != 0)
dragDropBookmark.Drop(line);
e.Handled = true;
}
CancelDragDrop();
}
if (!e.Handled && line != 0) {
var bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseUp(e);
if (bm is BookmarkBase) {
if ((bm as BookmarkBase).CanToggle) {
BookmarkManager.RemoveMark(bm as BookmarkBase);
InvalidateVisual();
}
}
if (e.Handled)
return;
}
if (e.ChangedButton == MouseButton.Left) {
// see IBookmarkActionEntry interface
}
InvalidateVisual();
}
}
public void SyncBookmarks()
{
var storage = DebugData.CodeMappings;
if (storage == null || storage.Count == 0)
return;
//remove existing bookmarks and create new ones
List<BreakpointBookmark> newBookmarks = new List<BreakpointBookmark>();
for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) {
var breakpoint = BookmarkManager.Bookmarks[i] as BreakpointBookmark;
if (breakpoint == null)
continue;
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));
BookmarkManager.RemoveMark(breakpoint);
}
}
newBookmarks.ForEach(m => BookmarkManager.AddMark(m));
SyncCurrentLineBookmark();
}
void SyncCurrentLineBookmark()
{
// checks
if (CurrentLineBookmark.Instance == null)
return;
var oldMappings = DebugData.OldCodeMappings;
var newMappings = DebugData.CodeMappings;
if (oldMappings == null || newMappings == null)
return;
// 1. Save it's data
int line = CurrentLineBookmark.Instance.LineNumber;
var markerType = CurrentLineBookmark.Instance.MemberReference;
if (!oldMappings.ContainsKey(markerType.MetadataToken.ToInt32()) || !newMappings.ContainsKey(markerType.MetadataToken.ToInt32()))
return;
// 2. Remove it
CurrentLineBookmark.Remove();
// 3. map the marker line
int token;
var instruction = oldMappings[markerType.MetadataToken.ToInt32()].GetInstructionByLineNumber(line, out token);
if (instruction == null)
return;
MemberReference memberReference;
int newline;
if (newMappings[markerType.MetadataToken.ToInt32()].GetInstructionByTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
// 4. create breakpoint for new languages
CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0);
}
}
}
}

190
ILSpy/AvalonEdit/IconMarginActionsProvider.cs

@ -0,0 +1,190 @@ @@ -0,0 +1,190 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
#region Context menu extensibility
public interface IBookmarkContextMenuEntry
{
bool IsVisible(IBookmark[] bookmarks);
bool IsEnabled(IBookmark[] bookmarks);
void Execute(IBookmark[] bookmarks);
}
public interface IBookmarkContextMenuEntryMetadata
{
string Icon { get; }
string Header { get; }
string Category { get; }
double Order { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ExportBookmarkContextMenuEntryAttribute : ExportAttribute, IBookmarkContextMenuEntryMetadata
{
public ExportBookmarkContextMenuEntryAttribute()
: base(typeof(IBookmarkContextMenuEntry))
{
}
public string Icon { get; set; }
public string Header { get; set; }
public string Category { get; set; }
public double Order { get; set; }
}
#endregion
#region Actions (simple clicks) - this will be used for creating bookmarks (e.g. Breakpoint bookmarks)
public interface IBookmarkActionEntry
{
bool IsEnabled();
void Execute(int line);
}
public interface IBookmarkActionMetadata
{
string Category { get; }
double Order { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ExportBookmarkActionEntryAttribute : ExportAttribute, IBookmarkActionMetadata
{
public ExportBookmarkActionEntryAttribute()
: base(typeof(IBookmarkActionEntry))
{
}
public string Icon { get; set; }
public string Header { get; set; }
public string Category { get; set; }
public double Order { get; set; }
}
#endregion
internal class IconMarginActionsProvider
{
/// <summary>
/// Enables extensible context menu support for the specified icon margin.
/// </summary>
public static void Add(IconBarMargin margin)
{
var provider = new IconMarginActionsProvider(margin);
margin.MouseUp += provider.HandleMouseEvent;
margin.ContextMenu = new ContextMenu();
}
readonly IconBarMargin margin;
[ImportMany(typeof(IBookmarkContextMenuEntry))]
Lazy<IBookmarkContextMenuEntry, IBookmarkContextMenuEntryMetadata>[] contextEntries = null;
[ImportMany(typeof(IBookmarkActionEntry))]
Lazy<IBookmarkActionEntry, IBookmarkActionMetadata>[] actionEntries = null;
private IconMarginActionsProvider(IconBarMargin margin)
{
this.margin = margin;
App.CompositionContainer.ComposeParts(this);
}
void HandleMouseEvent(object sender, MouseButtonEventArgs e)
{
int line = margin.GetLineFromMousePosition(e);
if (e.ChangedButton == MouseButton.Left) {
foreach (var category in actionEntries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
foreach (var entryPair in category) {
IBookmarkActionEntry entry = entryPair.Value;
if (entryPair.Value.IsEnabled()) {
entry.Execute(line);
}
}
}
}
// context menu entries
var bookmarks = margin.Manager.Bookmarks.ToArray();
if (bookmarks.Length == 0) {
// don't show the menu
e.Handled = true;
this.margin.ContextMenu = null;
return;
}
if (e.ChangedButton == MouseButton.Right) {
// check if we are on a Member
var bookmark = bookmarks.FirstOrDefault(b => b.LineNumber == line);
if (bookmark == null) {
// don't show the menu
e.Handled = true;
this.margin.ContextMenu = null;
return;
}
var marks = new[] { bookmark };
ContextMenu menu = new ContextMenu();
foreach (var category in contextEntries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
if (menu.Items.Count > 0) {
menu.Items.Add(new Separator());
}
foreach (var entryPair in category) {
IBookmarkContextMenuEntry entry = entryPair.Value;
if (entry.IsVisible(marks)) {
MenuItem menuItem = new MenuItem();
menuItem.Header = entryPair.Metadata.Header;
if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) {
menuItem.Icon = new Image {
Width = 16,
Height = 16,
Source = Images.LoadImage(entry, entryPair.Metadata.Icon)
};
}
if (entryPair.Value.IsEnabled(marks)) {
menuItem.Click += delegate { entry.Execute(marks); };
} else
menuItem.IsEnabled = false;
menu.Items.Add(menuItem);
}
}
}
if (menu.Items.Count > 0)
margin.ContextMenu = menu;
else
// hide the context menu.
e.Handled = true;
}
}
}
}

75
Debugger/ILSpy.Debugger/AvalonEdit/Editor/TextChangeEventArgs.cs → ILSpy/AvalonEdit/TextEditorWeakEventManager.cs

@ -17,52 +17,51 @@ @@ -17,52 +17,51 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Utils;
namespace ILSpy.Debugger.AvalonEdit.Editor
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Describes a change of the document text.
/// This class is thread-safe.
/// </summary>
public class TextChangeEventArgs : EventArgs
public static class TextEditorWeakEventManager
{
/// <summary>
/// The offset at which the change occurs.
/// </summary>
public int Offset { get; private set; }
/// <summary>
/// The text that was inserted.
/// </summary>
public string RemovedText { get; private set; }
/// <summary>
/// The number of characters removed.
/// </summary>
public int RemovalLength {
get { return RemovedText.Length; }
public sealed class MouseHover : WeakEventManagerBase<MouseHover, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHover -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHover += DeliverEvent;
}
}
/// <summary>
/// The text that was inserted.
/// </summary>
public string InsertedText { get; private set; }
/// <summary>
/// The number of characters inserted.
/// </summary>
public int InsertionLength {
get { return InsertedText.Length; }
public sealed class MouseHoverStopped : WeakEventManagerBase<MouseHoverStopped, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHoverStopped -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHoverStopped += DeliverEvent;
}
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, string removedText, string insertedText)
public sealed class MouseDown : WeakEventManagerBase<MouseDown, TextEditor>
{
this.Offset = offset;
this.RemovedText = removedText ?? string.Empty;
this.InsertedText = insertedText ?? string.Empty;
protected override void StopListening(TextEditor source)
{
source.MouseDown -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseDown += DeliverEvent;
}
}
}
}

319
ILSpy/AvalonEdit/TextMarkerService.cs

@ -0,0 +1,319 @@ @@ -0,0 +1,319 @@
// 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 System.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Handles the text markers for a code editor.
/// </summary>
public sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService
{
TextEditor codeEditor;
TextSegmentCollection<TextMarker> markers = new TextSegmentCollection<TextMarker>();
public TextMarkerService()
{
BookmarkManager.Added += new BookmarkEventHandler(BookmarkManager_Added);
BookmarkManager.Removed += new BookmarkEventHandler(BookmarkManager_Removed);
}
public TextEditor CodeEditor {
get { return codeEditor; }
set { codeEditor = value; }
}
void BookmarkManager_Removed(object sender, BookmarkEventArgs e)
{
if (e.Bookmark is BreakpointBookmark) {
var bm = (MarkerBookmark)e.Bookmark;
Remove(bm.Marker);
}
if (e.Bookmark is CurrentLineBookmark) {
RemoveAll(m => m.Bookmark is CurrentLineBookmark);
}
}
void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{
if (e.Bookmark is MarkerBookmark) {
var bm = (MarkerBookmark)e.Bookmark;
// add bookmark for the current type
if (bm.LineNumber < codeEditor.Document.LineCount) {
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
bm.CreateMarker(this, line.Offset, line.Length);
}
}
}
#region ITextMarkerService
public ITextMarker Create(int startOffset, int length)
{
int textLength = codeEditor.TextArea.TextView.Document.TextLength;
if (startOffset < 0 || startOffset > textLength)
throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between 0 and " + textLength);
if (length < 0 || startOffset + length > textLength)
throw new ArgumentOutOfRangeException("length", length, "length must not be negative and startOffset+length must not be after the end of the document");
TextMarker m = new TextMarker(this, startOffset, length);
markers.Add(m);
// no need to mark segment for redraw: the text marker is invisible until a property is set
return m;
}
public IEnumerable<ITextMarker> GetMarkersAtOffset(int offset)
{
return markers.FindSegmentsContaining(offset);
}
public IEnumerable<ITextMarker> TextMarkers {
get { return markers; }
}
public void RemoveAll(Predicate<ITextMarker> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
foreach (TextMarker m in markers.ToArray()) {
if (predicate(m))
Remove(m);
}
}
public void Remove(ITextMarker marker)
{
if (marker == null)
return;
TextMarker m = marker as TextMarker;
if (markers.Remove(m)) {
Redraw(m);
m.OnDeleted();
}
}
/// <summary>
/// Redraws the specified text segment.
/// </summary>
public void Redraw(ISegment segment)
{
codeEditor.TextArea.TextView.Redraw(segment, DispatcherPriority.Normal);
}
#endregion
#region DocumentColorizingTransformer
protected override void ColorizeLine(DocumentLine line)
{
if (markers == null)
return;
int lineStart = line.Offset;
int lineEnd = lineStart + line.Length;
foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length).Reverse()) {
if (!marker.IsVisible(marker.Bookmark))
continue;
Brush foregroundBrush = null;
if (marker.ForegroundColor != null) {
foregroundBrush = new SolidColorBrush(marker.ForegroundColor.Value);
foregroundBrush.Freeze();
}
ChangeLinePart(
Math.Max(marker.StartOffset, lineStart),
Math.Min(marker.EndOffset, lineEnd),
element => {
if (foregroundBrush != null) {
element.TextRunProperties.SetForegroundBrush(foregroundBrush);
}
}
);
}
}
#endregion
#region IBackgroundRenderer
public KnownLayer Layer {
get {
// draw behind selection
return KnownLayer.Selection;
}
}
public void Draw(ICSharpCode.AvalonEdit.Rendering.TextView textView, DrawingContext drawingContext)
{
if (textView == null)
throw new ArgumentNullException("textView");
if (drawingContext == null)
throw new ArgumentNullException("drawingContext");
if (markers == null || !textView.VisualLinesValid)
return;
var visualLines = textView.VisualLines;
if (visualLines.Count == 0)
return;
int viewStart = visualLines.First().FirstDocumentLine.Offset;
int viewEnd = visualLines.Last().LastDocumentLine.Offset + visualLines.Last().LastDocumentLine.Length;
foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart).Reverse()) {
if (!marker.IsVisible(marker.Bookmark))
continue;
if (marker.BackgroundColor != null) {
BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder();
geoBuilder.AlignToWholePixels = true;
geoBuilder.CornerRadius = 3;
geoBuilder.AddSegment(textView, marker);
Geometry geometry = geoBuilder.CreateGeometry();
if (geometry != null) {
Color color = marker.BackgroundColor.Value;
SolidColorBrush brush = new SolidColorBrush(color);
brush.Freeze();
drawingContext.DrawGeometry(brush, null, geometry);
}
}
if (marker.MarkerType != TextMarkerType.None) {
foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) {
Point startPoint = r.BottomLeft;
Point endPoint = r.BottomRight;
Pen usedPen = new Pen(new SolidColorBrush(marker.MarkerColor), 1);
usedPen.Freeze();
switch (marker.MarkerType) {
case TextMarkerType.SquigglyUnderline:
double offset = 2.5;
int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open()) {
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
}
geometry.Freeze();
drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
break;
}
}
}
}
}
IEnumerable<Point> CreatePoints(Point start, Point end, double offset, int count)
{
for (int i = 0; i < count; i++)
yield return new Point(start.X + i * offset, start.Y - ((i + 1) % 2 == 0 ? offset : 0));
}
#endregion
}
sealed class TextMarker : TextSegment, ITextMarker
{
readonly TextMarkerService service;
public TextMarker(TextMarkerService service, int startOffset, int length)
{
if (service == null)
throw new ArgumentNullException("service");
this.service = service;
this.StartOffset = startOffset;
this.Length = length;
this.markerType = TextMarkerType.None;
}
public event EventHandler Deleted;
public bool IsDeleted {
get { return !this.IsConnectedToCollection; }
}
public void Delete()
{
service.Remove(this);
}
internal void OnDeleted()
{
if (Deleted != null)
Deleted(this, EventArgs.Empty);
}
void Redraw()
{
service.Redraw(this);
}
Color? backgroundColor;
public Color? BackgroundColor {
get { return backgroundColor; }
set {
if (backgroundColor != value) {
backgroundColor = value;
Redraw();
}
}
}
Color? foregroundColor;
public Color? ForegroundColor {
get { return foregroundColor; }
set {
if (foregroundColor != value) {
foregroundColor = value;
Redraw();
}
}
}
public object Tag { get; set; }
TextMarkerType markerType;
public TextMarkerType MarkerType {
get { return markerType; }
set {
if (markerType != value) {
markerType = value;
Redraw();
}
}
}
Color markerColor;
public Color MarkerColor {
get { return markerColor; }
set {
if (markerColor != value) {
markerColor = value;
Redraw();
}
}
}
/// <inheritdoc/>
public object ToolTip { get; set; }
/// <inheritdoc/>
public Predicate<object> IsVisible { get; set; }
/// <inheritdoc/>
public IBookmark Bookmark { get; set; }
}
}

2
Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs → ILSpy/Bookmarks/BookmarkBase.cs

@ -8,7 +8,7 @@ using System.Windows.Media; @@ -8,7 +8,7 @@ using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.Bookmarks
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// A bookmark that can be attached to an AvalonEdit TextDocument.

2
Debugger/ILSpy.Debugger/Bookmarks/BookmarkEventHandler.cs → ILSpy/Bookmarks/BookmarkEventHandler.cs

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
using System;
namespace ICSharpCode.ILSpy.Debugger.Bookmarks
namespace ICSharpCode.ILSpy.Bookmarks
{
public delegate void BookmarkEventHandler(object sender, BookmarkEventArgs e);

2
Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs → ILSpy/Bookmarks/BookmarkManager.cs

@ -8,7 +8,7 @@ using ICSharpCode.NRefactory.CSharp; @@ -8,7 +8,7 @@ using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using Mono.CSharp;
namespace ICSharpCode.ILSpy.Debugger.Bookmarks
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// Static class that maintains the list of bookmarks and breakpoints.

7
Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs → ILSpy/Bookmarks/BreakpointBookmark.cs

@ -3,11 +3,10 @@ @@ -3,11 +3,10 @@
using System;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
@ -82,7 +81,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -82,7 +81,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
public override ImageSource Image {
get {
return ImageService.Breakpoint;
return Images.Breakpoint;
}
}

0
Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmarkEventArgs.cs → ILSpy/Bookmarks/BreakpointBookmarkEventArgs.cs

67
Debugger/ILSpy.Debugger/AvalonEdit/Editor/IDocumentLine.cs → ILSpy/Bookmarks/Commands.cs

@ -17,49 +17,34 @@ @@ -17,49 +17,34 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using Mono.Cecil;
namespace ILSpy.Debugger.AvalonEdit.Editor
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// A line inside a <see cref="IDocument"/>.
/// </summary>
public interface IDocumentLine
[ExportBookmarkContextMenuEntry(Header = "Analyze", Icon = "images/Search.png", Category="Default")]
internal sealed class AnalyzeBookmarkEntry : IBookmarkContextMenuEntry
{
/// <summary>
/// Gets the starting offset of the line in the document's text.
/// </summary>
int Offset { get; }
/// <summary>
/// Gets the length of this line (=the number of characters on the line).
/// </summary>
int Length { get; }
/// <summary>
/// Gets the ending offset of the line in the document's text (= Offset + Length).
/// </summary>
int EndOffset { get; }
/// <summary>
/// Gets the length of this line, including the line delimiter.
/// </summary>
int TotalLength { get; }
/// <summary>
/// Gets the length of the line terminator.
/// Returns 1 or 2; or 0 at the end of the document.
/// </summary>
int DelimiterLength { get; }
/// <summary>
/// Gets the number of this line.
/// The first line has the number 1.
/// </summary>
int LineNumber { get; }
/// <summary>
/// Gets the text on this line.
/// </summary>
string Text { get; }
public bool IsVisible(IBookmark[] marks)
{
return true;
}
public bool IsEnabled(IBookmark[] marks)
{
return true;
}
public void Execute(IBookmark[] marks)
{
foreach (var mark in marks) {
if (!(mark is MemberBookmark))
continue;
var member = (mark as MemberBookmark).Node.Annotation<MemberReference>();
AnalyzeContextMenuEntry.Analyze(member);
}
}
}
}

6
Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs → ILSpy/Bookmarks/CurrentLineBookmark.cs

@ -4,8 +4,8 @@ @@ -4,8 +4,8 @@
using System;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using Mono.CSharp;
@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
}
public override ImageSource Image {
get { return ImageService.CurrentLine; }
get { return Images.CurrentLine; }
}
public override bool CanDragDrop {

4
Debugger/ILSpy.Debugger/Bookmarks/IBookmark.cs → ILSpy/Bookmarks/IBookmark.cs

@ -8,7 +8,7 @@ using System.Collections.Specialized; @@ -8,7 +8,7 @@ using System.Collections.Specialized;
using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.Debugger.Bookmarks
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// The bookmark margin.
@ -18,7 +18,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -18,7 +18,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
/// <summary>
/// Gets the list of bookmarks.
/// </summary>
IList<BookmarkBase> Bookmarks { get; }
IList<IBookmark> Bookmarks { get; }
/// <summary>
/// Redraws the bookmark margin. Bookmarks need to call this method when the Image changes.

4
Debugger/ILSpy.Debugger/Bookmarks/MarkerBookmark.cs → ILSpy/Bookmarks/MarkerBookmark.cs

@ -3,10 +3,10 @@ @@ -3,10 +3,10 @@
using System;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.AvalonEdit;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.Bookmarks
namespace ICSharpCode.ILSpy.Bookmarks
{
public abstract class MarkerBookmark : BookmarkBase
{

157
ILSpy/Bookmarks/MemberBookmark.cs

@ -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 the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// Bookmark used to give additional operations for class members.
/// Does not derive from SDBookmark because it is not stored in the central BookmarkManager,
/// but only in the document's BookmarkManager.
/// </summary>
public class MemberBookmark : IBookmark
{
AstNode node;
public AstNode Node {
get {
return node;
}
}
public MemberBookmark(AstNode node)
{
this.node = node;
}
public virtual ImageSource Image {
get {
var attrNode = (AttributedNode)node;
if (node is EnumMemberDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.EnumValue);
if (node is FieldDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Field);
if (node is PropertyDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Property);
if (node is EventDeclaration || node is CustomEventDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Event);
if (node is IndexerDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Indexer);
if (node is OperatorDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Operator);
if (node is ConstructorDeclaration || node is DestructorDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Constructor);
return GetMemberOverlayedImage(attrNode, MemberIcon.Method);
}
}
ImageSource GetMemberOverlayedImage(AttributedNode attrNode, MemberIcon icon)
{
switch (attrNode.Modifiers & Modifiers.VisibilityMask) {
case Modifiers.Protected:
return Images.GetIcon(icon, AccessOverlayIcon.Protected, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
case Modifiers.Private:
return Images.GetIcon(icon, AccessOverlayIcon.Private, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
case Modifiers.Internal:
return Images.GetIcon(icon, AccessOverlayIcon.Internal, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
}
return Images.GetIcon(icon, AccessOverlayIcon.Public, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
}
public int LineNumber {
get {
var t = node.Annotation<Tuple<int, int>>();
if (t != null)
return t.Item1;
return 0;
}
}
public virtual void MouseDown(MouseButtonEventArgs e)
{
}
public virtual void MouseUp(MouseButtonEventArgs e)
{
}
int IBookmark.ZOrder {
get { return -10; }
}
bool IBookmark.CanDragDrop {
get { return false; }
}
void IBookmark.Drop(int lineNumber)
{
throw new NotSupportedException();
}
}
public class TypeBookmark : MemberBookmark
{
public TypeBookmark(AstNode node) : base (node)
{
}
public override ImageSource Image {
get {
var attrNode = (AttributedNode)Node;
if (Node is DelegateDeclaration)
return GetTypeOverlayedImage(attrNode, TypeIcon.Delegate);
if (Node is TypeDeclaration) {
var n = Node as TypeDeclaration;
switch (n.ClassType)
{
case ClassType.Delegate:
return GetTypeOverlayedImage(attrNode, TypeIcon.Delegate);
case ClassType.Enum:
return GetTypeOverlayedImage(attrNode, TypeIcon.Enum);
case ClassType.Struct:
return GetTypeOverlayedImage(attrNode, TypeIcon.Struct);
case ClassType.Interface:
return GetTypeOverlayedImage(attrNode, TypeIcon.Interface);
}
}
if ((attrNode.Modifiers & Modifiers.Static) == Modifiers.Static)
return GetTypeOverlayedImage(attrNode, TypeIcon.StaticClass);
return GetTypeOverlayedImage(attrNode, TypeIcon.Class);
}
}
ImageSource GetTypeOverlayedImage(AttributedNode attrNode, TypeIcon icon)
{
switch (attrNode.Modifiers & Modifiers.VisibilityMask) {
case Modifiers.Protected:
return Images.GetIcon(icon, AccessOverlayIcon.Protected);
case Modifiers.Private:
return Images.GetIcon(icon, AccessOverlayIcon.Private);
case Modifiers.Internal:
return Images.GetIcon(icon, AccessOverlayIcon.Internal);
}
return Images.GetIcon(icon, AccessOverlayIcon.Public);
}
}
}

111
ILSpy/DebuggedData.cs

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.ILAst;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger
{
/// <summary>
/// Contains the data important for debugger from the main application.
/// </summary>
public static class DebugData
{
static DecompiledLanguages language;
/// <summary>
/// Gets or sets the decompiled language.
/// </summary>
public static DecompiledLanguages Language {
get { return language; }
set {
var oldLanguage = language;
if (value != language) {
language = value;
OnLanguageChanged(new LanguageEventArgs(oldLanguage, language));
}
}
}
/// <summary>
/// List of loaded assemblies.
/// </summary>
public static IEnumerable<AssemblyDefinition> LoadedAssemblies { get; set; }
/// <summary>
/// Gets or sets the current code mappings.
/// </summary>
public static Dictionary<int, List<MemberMapping>> CodeMappings { get; set; }
/// <summary>
/// Gets or sets the local variables of the current decompiled type, method, etc.
/// </summary>
public static ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; set; }
/// <summary>
/// Gets or sets the old code mappings.
/// </summary>
public static Dictionary<int, List<MemberMapping>> OldCodeMappings { get; set; }
/// <summary>
/// Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc)
/// </summary>
public static Dictionary<int, MemberReference> DecompiledMemberReferences { get; set; }
/// <summary>
/// Gets or sets the current token, IL offset and member reference. Used for step in/out.
/// </summary>
public static Tuple<int, int, MemberReference> DebugStepInformation { get; set; }
/// <summary>
/// Gets or sets whether the debugger is loaded.
/// </summary>
public static bool IsDebuggerLoaded { get; set; }
/// <summary>
/// Occures when the language is changed.
/// </summary>
public static event EventHandler<LanguageEventArgs> LanguageChanged;
private static void OnLanguageChanged(LanguageEventArgs e)
{
var handler = LanguageChanged;
if (handler != null) {
handler(null, e);
}
}
}
public class LanguageEventArgs : EventArgs
{
public DecompiledLanguages OldLanguage { get; private set; }
public DecompiledLanguages NewLanguage { get; private set; }
public LanguageEventArgs(DecompiledLanguages oldLanguage, DecompiledLanguages newLanguage)
{
this.OldLanguage = oldLanguage;
this.NewLanguage = newLanguage;
}
}
}

35
ILSpy/ILSpy.csproj

@ -94,8 +94,26 @@ @@ -94,8 +94,26 @@
</Compile>
<Compile Include="AssemblyList.cs" />
<Compile Include="AssemblyListManager.cs" />
<Compile Include="AvalonEdit\ITextEditorListener.cs" />
<Compile Include="AvalonEdit\IToolTip.cs" />
<Compile Include="Bookmarks\BreakpointBookmark.cs" />
<Compile Include="Bookmarks\BreakpointBookmarkEventArgs.cs" />
<Compile Include="Bookmarks\CurrentLineBookmark.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" />
<Compile Include="AvalonEdit\IconBarManager.cs" />
<Compile Include="AvalonEdit\IconBarMargin.cs" />
<Compile Include="AvalonEdit\IconMarginActionsProvider.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="AvalonEdit\TextEditorWeakEventManager.cs" />
<Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="Bookmarks\BookmarkBase.cs" />
<Compile Include="Bookmarks\BookmarkEventHandler.cs" />
<Compile Include="Bookmarks\BookmarkManager.cs" />
<Compile Include="Bookmarks\Commands.cs" />
<Compile Include="Bookmarks\MemberBookmark.cs" />
<Compile Include="Bookmarks\IBookmark.cs" />
<Compile Include="Bookmarks\MarkerBookmark.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands\ExitCommand.cs" />
<Compile Include="Commands\CommandWrapper.cs" />
@ -103,9 +121,9 @@ @@ -103,9 +121,9 @@
<Compile Include="Controls\DockedPane.cs" />
<Compile Include="Commands\DecompileAllCommand.cs" />
<Compile Include="Commands\ExportCommandAttribute.cs" />
<Compile Include="Commands\DebuggerCommands.cs" />
<Compile Include="Controls\SearchBox.cs" />
<Compile Include="Controls\SortableGridViewColumn.cs" />
<Compile Include="DebuggedData.cs" />
<Compile Include="Languages\CSharpLanguage.cs" />
<Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" />
@ -135,10 +153,6 @@ @@ -135,10 +153,6 @@
<DependentUpon>OpenFromGacDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Options\DebuggerSettingsPanel.xaml.cs">
<DependentUpon>DebuggerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Options\DecompilerSettingsPanel.xaml.cs">
<DependentUpon>DecompilerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
@ -212,6 +226,8 @@ @@ -212,6 +226,8 @@
<Resource Include="Images\ILSpy.ico" />
<Resource Include="Images\FindAssembly.png" />
<None Include="app.config" />
<Resource Include="Images\Breakpoint.png" />
<Resource Include="Images\CurrentLine.png" />
<None Include="Properties\AssemblyInfo.template.cs" />
<Compile Include="Properties\WPFAssemblyInfo.cs" />
<Compile Include="MainWindow.xaml.cs">
@ -258,7 +274,6 @@ @@ -258,7 +274,6 @@
</Page>
<Page Include="MainWindow.xaml" />
<Page Include="OpenFromGacDialog.xaml" />
<Page Include="Options\DebuggerSettingsPanel.xaml" />
<Page Include="Options\DecompilerSettingsPanel.xaml" />
<Page Include="Options\DisplaySettingsPanel.xaml" />
<Page Include="Options\OptionsDialog.xaml" />
@ -315,10 +330,6 @@ @@ -315,10 +330,6 @@
<Resource Include="Images\PInvokeMethod.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Debugger\ILSpy.Debugger\ILSpy.Debugger.csproj">
<Project>{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A}</Project>
<Name>ILSpy.Debugger</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Name>ICSharpCode.Decompiler</Name>
@ -350,6 +361,10 @@ @@ -350,6 +361,10 @@
<Resource Include="Images\ResourceXslt.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="AvalonEdit" />
<Folder Include="Bookmarks" />
</ItemGroup>
<ItemGroup>
<Folder Include="Options" />
</ItemGroup>

BIN
ILSpy/Images/Breakpoint.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 B

BIN
ILSpy/Images/CurrentLine.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

3
ILSpy/Images/Images.cs

@ -32,6 +32,9 @@ namespace ICSharpCode.ILSpy @@ -32,6 +32,9 @@ namespace ICSharpCode.ILSpy
image.Freeze();
return image;
}
public static readonly BitmapImage Breakpoint = LoadBitmap("Breakpoint");
public static readonly BitmapImage CurrentLine = LoadBitmap("CurrentLine");
public static readonly BitmapImage ViewCode = LoadBitmap("ViewCode");
public static readonly BitmapImage Save = LoadBitmap("SaveFile");

10
ILSpy/Languages/CSharpLanguage.cs

@ -101,7 +101,7 @@ namespace ICSharpCode.ILSpy @@ -101,7 +101,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddMethod(method);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
}
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
NotifyDecompilationFinished(codeDomBuilder);
}
class SelectCtorTransform : IAstTransform
@ -146,7 +146,7 @@ namespace ICSharpCode.ILSpy @@ -146,7 +146,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true);
codeDomBuilder.AddProperty(property);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
NotifyDecompilationFinished(codeDomBuilder);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy @@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy
AddFieldsAndCtors(codeDomBuilder, field.DeclaringType, field.IsStatic);
}
RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectFieldTransform(field));
OnDecompilationFinished(new DecompileEventArgs { DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
NotifyDecompilationFinished(codeDomBuilder);
}
/// <summary>
@ -204,7 +204,7 @@ namespace ICSharpCode.ILSpy @@ -204,7 +204,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType, isSingleMember: true);
codeDomBuilder.AddEvent(ev);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
NotifyDecompilationFinished(codeDomBuilder);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
@ -212,7 +212,7 @@ namespace ICSharpCode.ILSpy @@ -212,7 +212,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
NotifyDecompilationFinished(codeDomBuilder);
}
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, IAstTransform additionalTransform = null)

12
ILSpy/Languages/ILLanguage.cs

@ -52,14 +52,14 @@ namespace ICSharpCode.ILSpy @@ -52,14 +52,14 @@ namespace ICSharpCode.ILSpy
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleMethod(method);
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings, DecompiledMemberReferences = dis.DecompiledMemberReferences });
NotifyDecompilationFinished(dis);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleField(field);
OnDecompilationFinished(new DecompileEventArgs { DecompiledMemberReferences = dis.DecompiledMemberReferences });
NotifyDecompilationFinished(dis);
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
@ -78,8 +78,7 @@ namespace ICSharpCode.ILSpy @@ -78,8 +78,7 @@ namespace ICSharpCode.ILSpy
output.WriteLine();
rd.DisassembleMethod(m);
}
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = rd.CodeMappings, DecompiledMemberReferences = rd.DecompiledMemberReferences });
NotifyDecompilationFinished(rd);
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
@ -98,15 +97,14 @@ namespace ICSharpCode.ILSpy @@ -98,15 +97,14 @@ namespace ICSharpCode.ILSpy
output.WriteLine();
rd.DisassembleMethod(m);
}
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = rd.CodeMappings, DecompiledMemberReferences = rd.DecompiledMemberReferences });
NotifyDecompilationFinished(rd);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleType(type);
OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings , DecompiledMemberReferences = dis.DecompiledMemberReferences});
NotifyDecompilationFinished(dis);
}
public override void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)

45
ILSpy/Languages/Language.cs

@ -19,9 +19,14 @@ @@ -19,9 +19,14 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
@ -34,17 +39,22 @@ namespace ICSharpCode.ILSpy @@ -34,17 +39,22 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Gets ot sets the code mappings
/// </summary>
public Dictionary<int, List<MemberMapping>> CodeMappings { get; set; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; internal set; }
/// <summary>
/// Gets or sets the local variables.
/// </summary>
public ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; set; }
public ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; internal set; }
/// <summary>
/// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc)
/// </summary>
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; set; }
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; internal set; }
/// <summary>
/// Gets (or internal sets) the AST nodes.
/// </summary>
public IEnumerable<AstNode> AstNodes { get; internal set; }
}
/// <summary>
@ -189,5 +199,32 @@ namespace ICSharpCode.ILSpy @@ -189,5 +199,32 @@ namespace ICSharpCode.ILSpy
DecompileFinished(this, e);
}
}
protected void NotifyDecompilationFinished(BaseCodeMappings b)
{
if (b is AstBuilder) {
var builder = b as AstBuilder;
var nodes = TreeTraversal
.PreOrder((AstNode)builder.CompilationUnit, n => n.Children)
.Where(n => n is AttributedNode && n.Annotation<Tuple<int, int>>() != null);
OnDecompilationFinished(new DecompileEventArgs {
CodeMappings = builder.CodeMappings,
LocalVariables = builder.LocalVariables,
DecompiledMemberReferences = builder.DecompiledMemberReferences,
AstNodes = nodes
});
}
if (b is ReflectionDisassembler) {
var dis = b as ReflectionDisassembler;
OnDecompilationFinished(new DecompileEventArgs {
CodeMappings = dis.CodeMappings,
DecompiledMemberReferences = dis.DecompiledMemberReferences,
AstNodes = null // TODO: how can I find the nodes with line numbers from dis?
});
}
}
}
}
}

22
ILSpy/MainWindow.xaml.cs

@ -32,7 +32,7 @@ using System.Windows.Interop; @@ -32,7 +32,7 @@ using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.XmlDoc;
@ -50,6 +50,7 @@ namespace ICSharpCode.ILSpy @@ -50,6 +50,7 @@ namespace ICSharpCode.ILSpy
NavigationHistory<NavigationState> history = new NavigationHistory<NavigationState>();
ILSpySettings spySettings;
internal SessionSettings sessionSettings;
AssemblyListManager assemblyListManager;
AssemblyList assemblyList;
AssemblyListTreeNode assemblyListTreeNode;
@ -63,6 +64,10 @@ namespace ICSharpCode.ILSpy @@ -63,6 +64,10 @@ namespace ICSharpCode.ILSpy
get { return instance; }
}
public SessionSettings SessionSettings {
get { return sessionSettings; }
}
public MainWindow()
{
instance = this;
@ -494,11 +499,12 @@ namespace ICSharpCode.ILSpy @@ -494,11 +499,12 @@ namespace ICSharpCode.ILSpy
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (!DebuggerService.CurrentDebugger.IsDebugging) {
e.Handled = true;
if (!DebugData.IsDebuggerLoaded) {
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
} else {
e.Handled = false;
}
}
@ -703,5 +709,15 @@ namespace ICSharpCode.ILSpy @@ -703,5 +709,15 @@ namespace ICSharpCode.ILSpy
this.StatusLabel.Foreground = foreground;
this.StatusLabel.Text = status;
}
public ItemCollection GetMainMenuItems()
{
return mainMenu.Items;
}
public ItemCollection GetToolBarItems()
{
return toolBar.Items;
}
}
}

2
ILSpy/Properties/AssemblyInfo.template.cs

@ -31,7 +31,7 @@ using System.Runtime.InteropServices; @@ -31,7 +31,7 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
public const string Major = "1";
public const string Major = "2";
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";

2
ILSpy/SessionSettings.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy
/// Per-session setting:
/// Loaded at startup; saved at exit.
/// </summary>
sealed class SessionSettings : INotifyPropertyChanged
public sealed class SessionSettings : INotifyPropertyChanged
{
public SessionSettings(ILSpySettings spySettings)
{

109
ILSpy/TextView/DecompilerTextView.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
@ -34,23 +35,22 @@ using System.Xml; @@ -34,23 +35,22 @@ using System.Xml;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.Debugger.Tooltips;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.Documentation;
using Microsoft.Win32;
using Mono.Cecil;
using TextEditorWeakEventManager = ICSharpCode.ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager;
namespace ICSharpCode.ILSpy.TextView
{
@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpy.TextView
/// Contains all the threading logic that makes the decompiler work in the background.
/// </summary>
[Export, PartCreationPolicy(CreationPolicy.Shared)]
public sealed partial class DecompilerTextView : UserControl
public sealed partial class DecompilerTextView : UserControl, IDisposable
{
readonly ReferenceElementGenerator referenceElementGenerator;
readonly UIElementGenerator uiElementGenerator;
@ -70,11 +70,12 @@ namespace ICSharpCode.ILSpy.TextView @@ -70,11 +70,12 @@ namespace ICSharpCode.ILSpy.TextView
DefinitionLookup definitionLookup;
CancellationTokenSource currentCancellationTokenSource;
[Import("IconMargin")]
IconBarMargin iconMargin = null;
internal readonly IconBarManager manager;
readonly IconBarMargin iconMargin;
readonly TextMarkerService textMarkerService;
[Import("TextMarkerService")]
TextMarkerService textMarkerService = null;
[ImportMany(typeof(ITextEditorListener))]
IEnumerable<ITextEditorListener> textEditorListeners;
#region Constructor
public DecompilerTextView()
@ -89,6 +90,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -89,6 +90,7 @@ namespace ICSharpCode.ILSpy.TextView
}
});
this.Loaded+= new RoutedEventHandler(DecompilerTextView_Loaded);
InitializeComponent();
this.referenceElementGenerator = new ReferenceElementGenerator(this.JumpToReference, this.IsLink);
@ -100,25 +102,63 @@ namespace ICSharpCode.ILSpy.TextView @@ -100,25 +102,63 @@ namespace ICSharpCode.ILSpy.TextView
textEditor.TextArea.TextView.MouseHoverStopped += TextViewMouseHoverStopped;
textEditor.SetBinding(TextEditor.FontFamilyProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFont") });
textEditor.SetBinding(TextEditor.FontSizeProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFontSize") });
textEditor.SetBinding(TextEditor.ShowLineNumbersProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("ShowLineNumbers") });
// wire the events
TextEditorWeakEventManager.MouseHover.AddListener(textEditor, TextEditorListener.Instance);
TextEditorWeakEventManager.MouseHoverStopped.AddListener(textEditor, TextEditorListener.Instance);
TextEditorWeakEventManager.MouseDown.AddListener(textEditor, TextEditorListener.Instance);
textEditor.TextArea.TextView.VisualLinesChanged += (s, e) => iconMargin.InvalidateVisual();
// add marker service & margin
iconMargin = new IconBarMargin((manager = new IconBarManager()));
textMarkerService = new TextMarkerService();
textMarkerService.CodeEditor = textEditor;
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
textEditor.ShowLineNumbers = true;
DisplaySettingsPanel.CurrentDisplaySettings.PropertyChanged += CurrentDisplaySettings_PropertyChanged;
textEditor.TextArea.LeftMargins.Insert(0, iconMargin);
textEditor.TextArea.TextView.VisualLinesChanged += delegate { iconMargin.InvalidateVisual(); };
// Bookmarks context menu
IconMarginActionsProvider.Add(iconMargin);
this.Loaded += new RoutedEventHandler(DecompilerTextView_Loaded);
}
void DecompilerTextView_Loaded(object sender, RoutedEventArgs e)
{
ShowLineMargin();
// wire the events
if (textEditorListeners != null) {
foreach (var listener in textEditorListeners) {
ICSharpCode.ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseHover.AddListener(textEditor, listener);
ICSharpCode.ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseHoverStopped.AddListener(textEditor, listener);
ICSharpCode.ILSpy.AvalonEdit.TextEditorWeakEventManager.MouseDown.AddListener(textEditor, listener);
}
}
textEditor.TextArea.TextView.VisualLinesChanged += (s, _) => iconMargin.InvalidateVisual();
// add marker service & margin
textMarkerService.CodeEditor = textEditor;
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
textEditor.TextArea.LeftMargins.Add(iconMargin);
}
#endregion
#region Line margin
void CurrentDisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "ShowLineNumbers") {
ShowLineMargin();
}
}
void ShowLineMargin()
{
foreach (var margin in this.textEditor.TextArea.LeftMargins) {
if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line) {
margin.Visibility = DisplaySettingsPanel.CurrentDisplaySettings.ShowLineNumbers ? Visibility.Visible : Visibility.Collapsed;
}
}
}
#endregion
@ -362,7 +402,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -362,7 +402,11 @@ namespace ICSharpCode.ILSpy.TextView
void DoDecompile(DecompilationContext context, int outputLengthLimit)
{
// close popup
TextEditorListener.Instance.ClosePopup();
if (textEditorListeners != null) {
foreach (var listener in textEditorListeners) {
listener.ClosePopup();
}
}
bool isDecompilationOk = true;
RunWithCancellation(
@ -417,10 +461,10 @@ namespace ICSharpCode.ILSpy.TextView @@ -417,10 +461,10 @@ namespace ICSharpCode.ILSpy.TextView
DebugData.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out member, out line);
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(member, line, 0, line, 0);
// update marker
CurrentLineBookmark.Remove();
CurrentLineBookmark.SetPosition(member, line, 0, line, 0);
// create marker
var bm = CurrentLineBookmark.Instance;
DocumentLine docline = textEditor.Document.GetLineByNumber(line);
bm.Marker = bm.CreateMarker(textMarkerService, docline.Offset + 1, docline.Length);
@ -433,7 +477,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -433,7 +477,7 @@ namespace ICSharpCode.ILSpy.TextView
}
}
static Task<AvalonEditTextOutput> DecompileAsync(DecompilationContext context, int outputLengthLimit)
Task<AvalonEditTextOutput> DecompileAsync(DecompilationContext context, int outputLengthLimit)
{
Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length);
@ -478,7 +522,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -478,7 +522,7 @@ namespace ICSharpCode.ILSpy.TextView
return tcs.Task;
}
static void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{
// reset data
DebugData.OldCodeMappings = DebugData.CodeMappings;
@ -499,10 +543,17 @@ namespace ICSharpCode.ILSpy.TextView @@ -499,10 +543,17 @@ namespace ICSharpCode.ILSpy.TextView
}
context.Language.DecompileFinished -= Language_DecompileFinished;
}
static void Language_DecompileFinished(object sender, DecompileEventArgs e)
void Language_DecompileFinished(object sender, DecompileEventArgs e)
{
if (e != null) {
manager.UpdateClassMemberBookmarks(e.AstNodes);
if (iconMargin.DecompiledMembers == null) {
iconMargin.DecompiledMembers = new List<MemberReference>();
}
iconMargin.DecompiledMembers.AddRange(e.DecompiledMemberReferences.Values.AsEnumerable());
// debugger info
if (DebugData.CodeMappings == null) {
DebugData.CodeMappings = e.CodeMappings;
DebugData.LocalVariables = e.LocalVariables;
@ -513,8 +564,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -513,8 +564,11 @@ namespace ICSharpCode.ILSpy.TextView
if (e.LocalVariables != null)
DebugData.LocalVariables.AddRange(e.LocalVariables);
}
} else {
manager.UpdateClassMemberBookmarks(null);
}
}
#endregion
#region WriteOutputLengthExceededMessage
@ -704,6 +758,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -704,6 +758,11 @@ namespace ICSharpCode.ILSpy.TextView
return state;
}
public void Dispose()
{
DisplaySettingsPanel.CurrentDisplaySettings.PropertyChanged -= CurrentDisplaySettings_PropertyChanged;
}
#region Unfold
public void UnfoldAndScroll(int lineNumber)
{

43
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -35,10 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -35,10 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
foreach (IMemberTreeNode node in selectedNodes) {
if (!(node.Member is TypeDefinition
|| node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)
|| Analyzer.AnalyzedEventTreeNode.CanShow(node.Member)))
|| node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)
|| Analyzer.AnalyzedEventTreeNode.CanShow(node.Member)))
return false;
}
@ -50,22 +50,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -50,22 +50,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
// TODO: figure out when equivalent nodes are already present
// and focus those instead.
foreach (IMemberTreeNode node in selectedNodes) {
TypeDefinition type = node.Member as TypeDefinition;
if (type != null)
AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type));
FieldDefinition field = node.Member as FieldDefinition;
if (field != null)
AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field));
MethodDefinition method = node.Member as MethodDefinition;
if (method != null)
AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member);
if (propertyAnalyzer != null)
AnalyzerTreeView.Instance.Show(propertyAnalyzer);
var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(node.Member);
if (eventAnalyzer != null)
AnalyzerTreeView.Instance.Show(eventAnalyzer);
Analyze(node.Member);
}
}
public static void Analyze(MemberReference member)
{
TypeDefinition type = member as TypeDefinition;
if (type != null)
AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type));
FieldDefinition field = member as FieldDefinition;
if (field != null)
AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field));
MethodDefinition method = member as MethodDefinition;
if (method != null)
AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(member);
if (propertyAnalyzer != null)
AnalyzerTreeView.Instance.Show(propertyAnalyzer);
var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(member);
if (eventAnalyzer != null)
AnalyzerTreeView.Instance.Show(eventAnalyzer);
}
}
}

2
ILSpy/XmlDoc/XmlDocKeyProvider.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.XmlDoc @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.XmlDoc
StringBuilder b = new StringBuilder();
if (member is TypeReference) {
b.Append("T:");
AppendTypeName(b, (TypeDefinition)member);
AppendTypeName(b, (TypeReference)member);
} else {
if (member is FieldReference)
b.Append("F:");

3
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs

@ -25,6 +25,9 @@ @@ -25,6 +25,9 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp
{

Loading…
Cancel
Save