Browse Source

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

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
bde3783a92
  1. 7
      .gitignore
  2. 3
      AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs
  3. 25
      AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  4. 2
      AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocumentWeakEventManager.cs
  5. 5
      AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
  6. 7
      AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs
  7. 70
      AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs
  8. 6
      AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs
  9. 24
      AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs
  10. 5
      AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs
  11. 2
      AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/ASPX.xshd
  12. 2
      AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  13. 6
      AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs
  14. 3
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/IBackgroundRenderer.cs
  15. 12
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ITextRunConstructionContext.cs
  16. 28
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LinkElementGenerator.cs
  17. 21
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
  18. 6
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/SingleCharacterElementGenerator.cs
  19. 15
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  20. 12
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
  21. 8
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs
  22. 15
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs
  23. 4
      AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs
  24. 58
      AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs
  25. 107
      AvalonEdit/ICSharpCode.AvalonEdit/Utils/StringSegment.cs
  26. 52
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  27. 13
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  28. 13
      ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
  29. 54
      ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
  30. 10
      ICSharpCode.Decompiler/CecilExtensions.cs
  31. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  32. 2
      ICSharpCode.Decompiler/ITextOutput.cs
  33. 50
      ICSharpCode.Decompiler/ReferenceResolvingException.cs
  34. 12
      ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs
  35. 10
      ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
  36. 3
      ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
  37. 108
      ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
  38. 8
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  39. 12
      ICSharpCode.Decompiler/Tests/IncrementDecrement.cs
  40. 80
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  41. 26
      ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
  42. 4
      ICSharpCode.Decompiler/Tests/packages.config
  43. 12
      ILSpy/ContextMenuEntry.cs
  44. 5
      ILSpy/ILSpy.csproj
  45. 20
      ILSpy/TextView/AvalonEditTextOutput.cs
  46. 3
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs
  47. 3
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  48. 25
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  49. 26
      ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs
  50. 36
      ILSpy/TreeNodes/Analyzer/Helpers.cs
  51. BIN
      packages/DiffLib.1.0.0.55/DiffLib.1.0.0.55.nupkg
  52. 641
      packages/DiffLib.1.0.0.55/lib/net35-Client/DiffLib.XML
  53. BIN
      packages/DiffLib.1.0.0.55/lib/net35-Client/DiffLib.dll
  54. 4
      packages/repositories.config

7
.gitignore vendored

@ -3,4 +3,9 @@ obj/ @@ -3,4 +3,9 @@ obj/
/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
/ILSpy/Properties/AssemblyInfo.cs
*.suo
*.suo
*.user
/Resharper-ILSpy-Style.xml
_ReSharper*/
*.ReSharper
*.patch

3
AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs

@ -314,6 +314,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -314,6 +314,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
int GetMatchQuality(string itemText, string query)
{
if (itemText == null)
throw new ArgumentNullException("itemText", "ICompletionData.Text returned null");
// Qualities:
// 8 = full match case sensitive
// 7 = full match

25
AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Globalization;
@ -21,7 +22,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -21,7 +22,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <inheritdoc cref="VerifyAccess"/>
/// <para>However, there is a single method that is thread-safe: <see cref="CreateSnapshot()"/> (and its overloads).</para>
/// </remarks>
public sealed class TextDocument : ITextSource
public sealed class TextDocument : ITextSource, INotifyPropertyChanged
{
#region Thread ownership
readonly object lockObject = new object();
@ -207,8 +208,16 @@ namespace ICSharpCode.AvalonEdit.Document @@ -207,8 +208,16 @@ namespace ICSharpCode.AvalonEdit.Document
/// Is raised when the TextLength property changes.
/// </summary>
/// <remarks><inheritdoc cref="Changing"/></remarks>
[Obsolete("This event will be removed in a future version; use the PropertyChanged event instead")]
public event EventHandler TextLengthChanged;
/// <summary>
/// Is raised when one of the properties <see cref="Text"/>, <see cref="TextLength"/>, <see cref="LineCount"/>,
/// <see cref="UndoStack"/> changes.
/// </summary>
/// <remarks><inheritdoc cref="Changing"/></remarks>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Is raised before the document changes.
/// </summary>
@ -231,8 +240,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -231,8 +240,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <item><description><b><see cref="EndUpdate">EndUpdate()</see></b></description>
/// <list type="bullet">
/// <item><description><see cref="TextChanged"/> event is raised</description></item>
/// <item><description><see cref="TextLengthChanged"/> event is raised</description></item>
/// <item><description><see cref="LineCountChanged"/> event is raised</description></item>
/// <item><description><see cref="PropertyChanged"/> event is raised (for the Text, TextLength, LineCount properties, in that order)</description></item>
/// <item><description>End of change group (on undo stack)</description></item>
/// <item><description><see cref="UpdateFinished"/> event is raised</description></item>
/// </list></item>
@ -418,21 +426,30 @@ namespace ICSharpCode.AvalonEdit.Document @@ -418,21 +426,30 @@ namespace ICSharpCode.AvalonEdit.Document
fireTextChanged = false;
if (TextChanged != null)
TextChanged(this, EventArgs.Empty);
OnPropertyChanged("Text");
int textLength = rope.Length;
if (textLength != oldTextLength) {
oldTextLength = textLength;
if (TextLengthChanged != null)
TextLengthChanged(this, EventArgs.Empty);
OnPropertyChanged("TextLength");
}
int lineCount = lineTree.LineCount;
if (lineCount != oldLineCount) {
oldLineCount = lineCount;
if (LineCountChanged != null)
LineCountChanged(this, EventArgs.Empty);
OnPropertyChanged("LineCount");
}
}
}
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Insert / Remove / Replace
@ -743,6 +760,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -743,6 +760,7 @@ namespace ICSharpCode.AvalonEdit.Document
undoStack.ClearAll(); // first clear old undo stack, so that it can't be used to perform unexpected changes on this document
// ClearAll() will also throw an exception when it's not safe to replace the undo stack (e.g. update is currently in progress)
undoStack = value;
OnPropertyChanged("UndoStack");
}
}
}
@ -775,6 +793,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -775,6 +793,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary>
/// Is raised when the LineCount property changes.
/// </summary>
[Obsolete("This event will be removed in a future version; use the PropertyChanged event instead")]
public event EventHandler LineCountChanged;
#endregion

2
AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocumentWeakEventManager.cs

@ -91,6 +91,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -91,6 +91,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// Weak event manager for the <see cref="TextDocument.LineCountChanged"/> event.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
[Obsolete("The TextDocument.LineCountChanged event will be removed in a future version. Use PropertyChangedEventManager instead.")]
public sealed class LineCountChanged : WeakEventManagerBase<LineCountChanged, TextDocument>
{
/// <inheritdoc/>
@ -110,6 +111,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -110,6 +111,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// Weak event manager for the <see cref="TextDocument.TextLengthChanged"/> event.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
[Obsolete("The TextDocument.TextLengthChanged event will be removed in a future version. Use PropertyChangedEventManager instead.")]
public sealed class TextLengthChanged : WeakEventManagerBase<TextLengthChanged, TextDocument>
{
/// <inheritdoc/>

5
AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs

@ -300,7 +300,10 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -300,7 +300,10 @@ namespace ICSharpCode.AvalonEdit.Editing
if (textArea.Selection.IsEmpty && textArea.Options.CutCopyWholeLine) {
DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line);
CopyWholeLine(textArea, currentLine);
textArea.Document.Remove(currentLine.Offset, currentLine.TotalLength);
ISegment[] segmentsToDelete = textArea.GetDeletableSegments(new SimpleSegment(currentLine.Offset, currentLine.TotalLength));
for (int i = segmentsToDelete.Length - 1; i >= 0; i--) {
textArea.Document.Remove(segmentsToDelete[i]);
}
} else {
CopySelectedText(textArea);
textArea.RemoveSelectedText();

7
AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
@ -89,11 +90,11 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -89,11 +90,11 @@ namespace ICSharpCode.AvalonEdit.Editing
protected override void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument)
{
if (oldDocument != null) {
TextDocumentWeakEventManager.LineCountChanged.RemoveListener(oldDocument, this);
PropertyChangedEventManager.RemoveListener(oldDocument, this, "LineCount");
}
base.OnDocumentChanged(oldDocument, newDocument);
if (newDocument != null) {
TextDocumentWeakEventManager.LineCountChanged.AddListener(newDocument, this);
PropertyChangedEventManager.AddListener(newDocument, this, "LineCount");
}
OnDocumentLineCountChanged();
}
@ -101,7 +102,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -101,7 +102,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/>
protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(TextDocumentWeakEventManager.LineCountChanged)) {
if (managerType == typeof(PropertyChangedEventManager)) {
OnDocumentLineCountChanged();
return true;
}

70
AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
@ -56,9 +57,6 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -56,9 +57,6 @@ namespace ICSharpCode.AvalonEdit.Editing
}
#endregion
// TODO: allow disabling text drag'n'drop
const bool AllowTextDragDrop = true;
readonly TextArea textArea;
SelectionMode mode;
@ -83,14 +81,11 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -83,14 +81,11 @@ namespace ICSharpCode.AvalonEdit.Editing
textArea.MouseMove += textArea_MouseMove;
textArea.MouseLeftButtonUp += textArea_MouseLeftButtonUp;
textArea.QueryCursor += textArea_QueryCursor;
if (AllowTextDragDrop) {
textArea.AllowDrop = true;
textArea.GiveFeedback += textArea_GiveFeedback;
textArea.QueryContinueDrag += textArea_QueryContinueDrag;
textArea.DragEnter += textArea_DragEnter;
textArea.DragOver += textArea_DragOver;
textArea.DragLeave += textArea_DragLeave;
textArea.Drop += textArea_Drop;
textArea.OptionChanged += textArea_OptionChanged;
enableTextDragDrop = textArea.Options.EnableTextDragDrop;
if (enableTextDragDrop) {
AttachDragDrop();
}
}
@ -101,14 +96,45 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -101,14 +96,45 @@ namespace ICSharpCode.AvalonEdit.Editing
textArea.MouseMove -= textArea_MouseMove;
textArea.MouseLeftButtonUp -= textArea_MouseLeftButtonUp;
textArea.QueryCursor -= textArea_QueryCursor;
if (AllowTextDragDrop) {
textArea.AllowDrop = false;
textArea.GiveFeedback -= textArea_GiveFeedback;
textArea.QueryContinueDrag -= textArea_QueryContinueDrag;
textArea.DragEnter -= textArea_DragEnter;
textArea.DragOver -= textArea_DragOver;
textArea.DragLeave -= textArea_DragLeave;
textArea.Drop -= textArea_Drop;
textArea.OptionChanged -= textArea_OptionChanged;
if (enableTextDragDrop) {
DetachDragDrop();
}
}
void AttachDragDrop()
{
textArea.AllowDrop = true;
textArea.GiveFeedback += textArea_GiveFeedback;
textArea.QueryContinueDrag += textArea_QueryContinueDrag;
textArea.DragEnter += textArea_DragEnter;
textArea.DragOver += textArea_DragOver;
textArea.DragLeave += textArea_DragLeave;
textArea.Drop += textArea_Drop;
}
void DetachDragDrop()
{
textArea.AllowDrop = false;
textArea.GiveFeedback -= textArea_GiveFeedback;
textArea.QueryContinueDrag -= textArea_QueryContinueDrag;
textArea.DragEnter -= textArea_DragEnter;
textArea.DragOver -= textArea_DragOver;
textArea.DragLeave -= textArea_DragLeave;
textArea.Drop -= textArea_Drop;
}
bool enableTextDragDrop;
void textArea_OptionChanged(object sender, PropertyChangedEventArgs e)
{
bool newEnableTextDragDrop = textArea.Options.EnableTextDragDrop;
if (newEnableTextDragDrop != enableTextDragDrop) {
enableTextDragDrop = newEnableTextDragDrop;
if (newEnableTextDragDrop)
AttachDragDrop();
else
DetachDragDrop();
}
}
#endregion
@ -323,7 +349,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -323,7 +349,7 @@ namespace ICSharpCode.AvalonEdit.Editing
void textArea_QueryCursor(object sender, QueryCursorEventArgs e)
{
if (!e.Handled) {
if (mode != SelectionMode.None || !AllowTextDragDrop) {
if (mode != SelectionMode.None || !enableTextDragDrop) {
e.Cursor = Cursors.IBeam;
e.Handled = true;
} else if (textArea.TextView.VisualLinesValid) {
@ -352,7 +378,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -352,7 +378,7 @@ namespace ICSharpCode.AvalonEdit.Editing
if (!e.Handled && e.ChangedButton == MouseButton.Left) {
ModifierKeys modifiers = Keyboard.Modifiers;
bool shift = (modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
if (AllowTextDragDrop && e.ClickCount == 1 && !shift) {
if (enableTextDragDrop && e.ClickCount == 1 && !shift) {
int visualColumn;
int offset = GetOffsetFromMousePosition(e, out visualColumn);
if (textArea.Selection.Contains(offset)) {
@ -373,7 +399,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -373,7 +399,7 @@ namespace ICSharpCode.AvalonEdit.Editing
textArea.Selection = Selection.Empty;
}
if (textArea.CaptureMouse()) {
if ((modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) {
if ((modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && textArea.Options.EnableRectangularSelection) {
mode = SelectionMode.Rectangular;
if (shift && textArea.Selection is RectangleSelection) {
textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldOffset, textArea.Caret.Offset);

6
AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs

@ -167,10 +167,16 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -167,10 +167,16 @@ namespace ICSharpCode.AvalonEdit.Folding
}
}
/// <summary>
/// Default brush for folding element text. Value: Brushes.Gray
/// </summary>
public static readonly Brush DefaultTextBrush = Brushes.Gray;
static Brush textBrush = DefaultTextBrush;
/// <summary>
/// Gets/sets the brush used for folding element text.
/// </summary>
public static Brush TextBrush {
get { return textBrush; }
set { textBrush = value; }

24
AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs

@ -28,39 +28,63 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -28,39 +28,63 @@ namespace ICSharpCode.AvalonEdit.Folding
internal const double SizeFactor = Constants.PixelPerPoint;
#region Brushes
/// <summary>
/// FoldingMarkerBrush dependency property.
/// </summary>
public static readonly DependencyProperty FoldingMarkerBrushProperty =
DependencyProperty.RegisterAttached("FoldingMarkerBrush", typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.Gray, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
/// <summary>
/// Gets/sets the Brush used for displaying the lines of folding markers.
/// </summary>
public Brush FoldingMarkerBrush {
get { return (Brush)GetValue(FoldingMarkerBrushProperty); }
set { SetValue(FoldingMarkerBrushProperty, value); }
}
/// <summary>
/// FoldingMarkerBackgroundBrush dependency property.
/// </summary>
public static readonly DependencyProperty FoldingMarkerBackgroundBrushProperty =
DependencyProperty.RegisterAttached("FoldingMarkerBackgroundBrush", typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.White, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
/// <summary>
/// Gets/sets the Brush used for displaying the background of folding markers.
/// </summary>
public Brush FoldingMarkerBackgroundBrush {
get { return (Brush)GetValue(FoldingMarkerBackgroundBrushProperty); }
set { SetValue(FoldingMarkerBackgroundBrushProperty, value); }
}
/// <summary>
/// SelectedFoldingMarkerBrush dependency property.
/// </summary>
public static readonly DependencyProperty SelectedFoldingMarkerBrushProperty =
DependencyProperty.RegisterAttached("SelectedFoldingMarkerBrush",
typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
/// <summary>
/// Gets/sets the Brush used for displaying the lines of selected folding markers.
/// </summary>
public Brush SelectedFoldingMarkerBrush {
get { return (Brush)GetValue(SelectedFoldingMarkerBrushProperty); }
set { SetValue(SelectedFoldingMarkerBrushProperty, value); }
}
/// <summary>
/// SelectedFoldingMarkerBackgroundBrush dependency property.
/// </summary>
public static readonly DependencyProperty SelectedFoldingMarkerBackgroundBrushProperty =
DependencyProperty.RegisterAttached("SelectedFoldingMarkerBackgroundBrush",
typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.White, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
/// <summary>
/// Gets/sets the Brush used for displaying the background of selected folding markers.
/// </summary>
public Brush SelectedFoldingMarkerBackgroundBrush {
get { return (Brush)GetValue(SelectedFoldingMarkerBackgroundBrushProperty); }
set { SetValue(SelectedFoldingMarkerBackgroundBrushProperty, value); }

5
AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs

@ -154,6 +154,11 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -154,6 +154,11 @@ namespace ICSharpCode.AvalonEdit.Highlighting
if (b != null)
element.TextRunProperties.SetForegroundBrush(b);
}
if (color.Background != null) {
Brush b = color.Background.GetBrush(CurrentContext);
if (b != null)
element.TextRunProperties.SetBackgroundBrush(b);
}
if (color.FontStyle != null || color.FontWeight != null) {
Typeface tf = element.TextRunProperties.Typeface;
element.TextRunProperties.SetTypeface(new Typeface(

2
AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/ASPX.xshd

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<Color name="ASPSectionStartEndTags" foreground="Black" background="Yellow" exampleText="&lt;% System.Console.WriteLine(&quot;Hello World!&quot;); %&gt;" />
<Color name="ASPSection" foreground="Black" background="#FFF7F2E3" exampleText="&lt;% System.Console.WriteLine(&quot;Hello World!&quot;); %&gt;" />
<RuleSet ignoreCase="true">
<Span color="ASPSection" ruleSet="ASP" multiline="true">
<Span ruleSet="ASP" multiline="true">
<Begin color="ASPSectionStartEndTags">&lt;%</Begin>
<End color="ASPSectionStartEndTags">%&gt;</End>
</Span>

2
AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -215,7 +215,6 @@ @@ -215,7 +215,6 @@
<Compile Include="Indentation\CSharp\DocumentAccessor.cs" />
<Compile Include="Indentation\DefaultIndentationStrategy.cs" />
<Compile Include="Indentation\IIndentationStrategy.cs" />
<Compile Include="Properties\GlobalAssemblyInfo.cs" />
<Compile Include="Rendering\BackgroundGeometryBuilder.cs">
<DependentUpon>IBackgroundRenderer.cs</DependentUpon>
</Compile>
@ -341,6 +340,7 @@ @@ -341,6 +340,7 @@
<Compile Include="Utils\Rope.cs" />
<Compile Include="Utils\RopeNode.cs" />
<Compile Include="Utils\RopeTextReader.cs" />
<Compile Include="Utils\StringSegment.cs" />
<Compile Include="Utils\TextFormatterFactory.cs" />
<Compile Include="Utils\WeakEventManagerBase.cs" />
<Compile Include="Utils\PixelSnapHelpers.cs" />

6
AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs

@ -18,7 +18,7 @@ using System.Reflection; @@ -18,7 +18,7 @@ using System.Reflection;
[assembly: AssemblyProduct("SharpDevelop")]
[assembly: AssemblyCopyright("2000-2011 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyVersion(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision)]
[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-d9a90d79")]
[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-3301c6c4")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
@ -29,8 +29,8 @@ internal static class RevisionClass @@ -29,8 +29,8 @@ internal static class RevisionClass
public const string Major = "4";
public const string Minor = "1";
public const string Build = "0";
public const string Revision = "7275";
public const string Revision = "7411";
public const string VersionName = "alpha";
public const string FullVersion = Major + "." + Minor + "." + Build + ".7275-alpha";
public const string FullVersion = Major + "." + Minor + "." + Build + ".7411-alpha";
}

3
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/IBackgroundRenderer.cs

@ -11,9 +11,6 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -11,9 +11,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// You can use background renderers to draw non-interactive elements on the TextView
/// without introducing new UIElements.
/// </summary>
/// <remarks>Background renderer will draw only if their associated known
/// layer chooses to draw them. For example, background renderers in the caret
/// layer will be invisible when the caret is hidden.</remarks>
public interface IBackgroundRenderer
{
/// <summary>

12
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ITextRunConstructionContext.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Windows.Media.TextFormatting;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Rendering
{
@ -31,5 +32,16 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -31,5 +32,16 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// Gets the global text run properties.
/// </summary>
TextRunProperties GlobalTextRunProperties { get; }
/// <summary>
/// Gets a piece of text from the document.
/// </summary>
/// <remarks>
/// This method is allowed to return a larger string than requested.
/// It does this by returning a <see cref="StringSegment"/> that describes the requested segment within the returned string.
/// This method should be the preferred text access method in the text transformation pipeline, as it can avoid repeatedly allocating string instances
/// for text within the same line.
/// </remarks>
StringSegment GetText(int offset, int length);
}
}

28
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LinkElementGenerator.cs

@ -2,16 +2,8 @@ @@ -2,16 +2,8 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using ICSharpCode.AvalonEdit.Document;
using System.Windows.Navigation;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Rendering
{
@ -65,25 +57,29 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -65,25 +57,29 @@ namespace ICSharpCode.AvalonEdit.Rendering
this.RequireControlModifierForClick = options.RequireControlModifierForHyperlinkClick;
}
Match GetMatch(int startOffset)
Match GetMatch(int startOffset, out int matchOffset)
{
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
string relevantText = CurrentContext.Document.GetText(startOffset, endOffset - startOffset);
return linkRegex.Match(relevantText);
StringSegment relevantText = CurrentContext.GetText(startOffset, endOffset - startOffset);
Match m = linkRegex.Match(relevantText.Text, relevantText.Offset, relevantText.Count);
matchOffset = m.Success ? m.Index - relevantText.Offset + startOffset : -1;
return m;
}
/// <inheritdoc/>
public override int GetFirstInterestedOffset(int startOffset)
{
Match m = GetMatch(startOffset);
return m.Success ? startOffset + m.Index : -1;
int matchOffset;
GetMatch(startOffset, out matchOffset);
return matchOffset;
}
/// <inheritdoc/>
public override VisualLineElement ConstructElement(int offset)
{
Match m = GetMatch(offset);
if (m.Success && m.Index == 0) {
int matchOffset;
Match m = GetMatch(offset, out matchOffset);
if (m.Success && matchOffset == offset) {
Uri uri = GetUriFromMatch(m);
if (uri == null)
return null;

21
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs

@ -8,6 +8,9 @@ using System.Windows.Threading; @@ -8,6 +8,9 @@ using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.Rendering
{
/// <summary>
/// Encapsulates and adds MouseHover support to UIElements.
/// </summary>
public class MouseHoverLogic : IDisposable
{
UIElement target;
@ -17,6 +20,9 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -17,6 +20,9 @@ namespace ICSharpCode.AvalonEdit.Rendering
MouseEventArgs mouseHoverLastEventArgs;
bool mouseHovering;
/// <summary>
/// Creates a new instance and attaches itself to the <paramref name="target" /> UIElement.
/// </summary>
public MouseHoverLogic(UIElement target)
{
if (target == null)
@ -70,8 +76,14 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -70,8 +76,14 @@ namespace ICSharpCode.AvalonEdit.Rendering
OnMouseHover(mouseHoverLastEventArgs);
}
/// <summary>
/// Occurs when the mouse starts hovering over a certain location.
/// </summary>
public event EventHandler<MouseEventArgs> MouseHover;
/// <summary>
/// Raises the <see cref="MouseHover"/> event.
/// </summary>
protected virtual void OnMouseHover(MouseEventArgs e)
{
if (MouseHover != null) {
@ -79,8 +91,14 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -79,8 +91,14 @@ namespace ICSharpCode.AvalonEdit.Rendering
}
}
/// <summary>
/// Occurs when the mouse stops hovering over a certain location.
/// </summary>
public event EventHandler<MouseEventArgs> MouseHoverStopped;
/// <summary>
/// Raises the <see cref="MouseHoverStopped"/> event.
/// </summary>
protected virtual void OnMouseHoverStopped(MouseEventArgs e)
{
if (MouseHoverStopped != null) {
@ -90,6 +108,9 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -90,6 +108,9 @@ namespace ICSharpCode.AvalonEdit.Rendering
bool disposed;
/// <summary>
/// Removes the MouseHover support from the target UIElement.
/// </summary>
public void Dispose()
{
if (!disposed) {

6
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/SingleCharacterElementGenerator.cs

@ -60,10 +60,10 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -60,10 +60,10 @@ namespace ICSharpCode.AvalonEdit.Rendering
public override int GetFirstInterestedOffset(int startOffset)
{
DocumentLine endLine = CurrentContext.VisualLine.LastDocumentLine;
string relevantText = CurrentContext.Document.GetText(startOffset, endLine.EndOffset - startOffset);
StringSegment relevantText = CurrentContext.GetText(startOffset, endLine.EndOffset - startOffset);
for (int i = 0; i < relevantText.Length; i++) {
char c = relevantText[i];
for (int i = 0; i < relevantText.Count; i++) {
char c = relevantText.Text[relevantText.Offset + i];
switch (c) {
case ' ':
if (ShowSpaces)

15
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -1739,12 +1739,21 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -1739,12 +1739,21 @@ namespace ICSharpCode.AvalonEdit.Rendering
#endregion
/// <summary>
/// Collapses lines for the purpose of scrolling. This method is meant for
/// <see cref="VisualLineElementGenerator"/>s that cause <see cref="VisualLine"/>s to span
/// Collapses lines for the purpose of scrolling. <see cref="DocumentLine"/>s marked as collapsed will be hidden
/// and not used to start the generation of a <see cref="VisualLine"/>.
/// </summary>
/// <remarks>
/// This method is meant for <see cref="VisualLineElementGenerator"/>s that cause <see cref="VisualLine"/>s to span
/// multiple <see cref="DocumentLine"/>s. Do not call it without providing a corresponding
/// <see cref="VisualLineElementGenerator"/>.
/// If you want to create collapsible text sections, see <see cref="Folding.FoldingManager"/>.
/// </summary>
///
/// Note that if you want a VisualLineElement to span from line N to line M, then you need to collapse only the lines
/// N+1 to M. Do not collapse line N itself.
///
/// When you no longer need the section to be collapsed, call <see cref="CollapsedLineSection.Uncollapse()"/> on the
/// <see cref="CollapsedLineSection"/> returned from this method.
/// </remarks>
public CollapsedLineSection CollapseLines(DocumentLine start, DocumentLine end)
{
VerifyAccess();

12
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs

@ -53,7 +53,7 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -53,7 +53,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// Gets the start offset of the VisualLine inside the document.
/// This is equivalent to <c>FirstDocumentLine.Offset</c>.
/// </summary>
public int StartOffset {
public int StartOffset {
get {
return FirstDocumentLine.Offset;
}
@ -137,8 +137,14 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -137,8 +137,14 @@ namespace ICSharpCode.AvalonEdit.Rendering
askInterestOffset = 0;
offset += element.DocumentLength;
if (offset > currentLineEnd) {
LastDocumentLine = document.GetLineByOffset(offset);
currentLineEnd = LastDocumentLine.Offset + LastDocumentLine.Length;
DocumentLine newEndLine = document.GetLineByOffset(offset);
if (newEndLine == this.LastDocumentLine) {
throw new InvalidOperationException(
"The VisualLineElementGenerator " + g.GetType().Name +
" produced an element which ends within the line delimiter");
}
currentLineEnd = newEndLine.Offset + newEndLine.Length;
this.LastDocumentLine = newEndLine;
}
break;
}

8
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineText.cs

@ -53,8 +53,8 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -53,8 +53,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
throw new ArgumentNullException("context");
int relativeOffset = startVisualColumn - VisualColumn;
string text = context.Document.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset + relativeOffset, DocumentLength - relativeOffset);
return new TextCharacters(text, 0, text.Length, this.TextRunProperties);
StringSegment text = context.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset + relativeOffset, DocumentLength - relativeOffset);
return new TextCharacters(text.Text, text.Offset, text.Count, this.TextRunProperties);
}
/// <inheritdoc/>
@ -71,8 +71,8 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -71,8 +71,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
throw new ArgumentNullException("context");
int relativeOffset = visualColumnLimit - VisualColumn;
string text = context.Document.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset, relativeOffset);
CharacterBufferRange range = new CharacterBufferRange(text, 0, text.Length);
StringSegment text = context.GetText(context.VisualLine.FirstDocumentLine.Offset + RelativeTextOffset, relativeOffset);
CharacterBufferRange range = new CharacterBufferRange(text.Text, text.Offset, text.Count);
return new TextSpan<CultureSpecificCharacterBufferRange>(range.Length, new CultureSpecificCharacterBufferRange(this.TextRunProperties.CultureInfo, range));
}

15
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs

@ -6,6 +6,7 @@ using System.Diagnostics; @@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Windows.Media.TextFormatting;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Rendering
{
@ -83,5 +84,19 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -83,5 +84,19 @@ namespace ICSharpCode.AvalonEdit.Rendering
{
throw new NotSupportedException();
}
string cachedString;
int cachedStringOffset;
public StringSegment GetText(int offset, int length)
{
if (cachedString != null) {
if (offset >= cachedStringOffset && offset + length <= cachedStringOffset + cachedString.Length) {
return new StringSegment(cachedString, offset - cachedStringOffset, length);
}
}
cachedStringOffset = offset;
return new StringSegment(cachedString = this.Document.GetText(offset, length));
}
}
}

4
AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs

@ -669,6 +669,7 @@ namespace ICSharpCode.AvalonEdit @@ -669,6 +669,7 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public void ScrollToEnd()
{
ApplyTemplate(); // ensure scrollViewer is created
if (scrollViewer != null)
scrollViewer.ScrollToEnd();
}
@ -678,6 +679,7 @@ namespace ICSharpCode.AvalonEdit @@ -678,6 +679,7 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public void ScrollToHome()
{
ApplyTemplate(); // ensure scrollViewer is created
if (scrollViewer != null)
scrollViewer.ScrollToHome();
}
@ -687,6 +689,7 @@ namespace ICSharpCode.AvalonEdit @@ -687,6 +689,7 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public void ScrollToHorizontalOffset(double offset)
{
ApplyTemplate(); // ensure scrollViewer is created
if (scrollViewer != null)
scrollViewer.ScrollToHorizontalOffset(offset);
}
@ -696,6 +699,7 @@ namespace ICSharpCode.AvalonEdit @@ -696,6 +699,7 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public void ScrollToVerticalOffset(double offset)
{
ApplyTemplate(); // ensure scrollViewer is created
if (scrollViewer != null)
scrollViewer.ScrollToVerticalOffset(offset);
}

58
AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.ComponentModel;
using System.Reflection;
using System.Text;
namespace ICSharpCode.AvalonEdit
@ -13,6 +14,31 @@ namespace ICSharpCode.AvalonEdit @@ -13,6 +14,31 @@ namespace ICSharpCode.AvalonEdit
[Serializable]
public class TextEditorOptions : INotifyPropertyChanged
{
#region ctor
/// <summary>
/// Initializes an empty instance of TextEditorOptions.
/// </summary>
public TextEditorOptions()
{
}
/// <summary>
/// Initializes a new instance of TextEditorOptions by copying all values
/// from <paramref name="options"/> to the new instance.
/// </summary>
public TextEditorOptions(TextEditorOptions options)
{
// get all the fields in the class
FieldInfo[] fields = typeof(TextEditorOptions).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
// copy each value over to 'this'
foreach(FieldInfo fi in fields) {
if (!fi.IsNotSerialized)
fi.SetValue(this, fi.GetValue(options));
}
}
#endregion
#region PropertyChanged handling
/// <inheritdoc/>
[field: NonSerialized]
@ -304,5 +330,37 @@ namespace ICSharpCode.AvalonEdit @@ -304,5 +330,37 @@ namespace ICSharpCode.AvalonEdit
}
}
}
bool enableRectangularSelection = true;
/// <summary>
/// Enables rectangular selection (press ALT and select a rectangle)
/// </summary>
[DefaultValue(true)]
public bool EnableRectangularSelection {
get { return enableRectangularSelection; }
set {
if (enableRectangularSelection != value) {
enableRectangularSelection = value;
OnPropertyChanged("AllowRectangularSelection");
}
}
}
bool enableTextDragDrop = true;
/// <summary>
/// Enable dragging text within the text area.
/// </summary>
[DefaultValue(true)]
public bool EnableTextDragDrop {
get { return enableTextDragDrop; }
set {
if (enableTextDragDrop != value) {
enableTextDragDrop = value;
OnPropertyChanged("EnableTextDrag");
}
}
}
}
}

107
AvalonEdit/ICSharpCode.AvalonEdit/Utils/StringSegment.cs

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
// 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;
namespace ICSharpCode.AvalonEdit.Utils
{
/// <summary>
/// Represents a string with a segment.
/// Similar to System.ArraySegment&lt;T&gt;, but for strings instead of arrays.
/// </summary>
public struct StringSegment : IEquatable<StringSegment>
{
readonly string text;
readonly int offset;
readonly int count;
/// <summary>
/// Creates a new StringSegment.
/// </summary>
public StringSegment(string text, int offset, int count)
{
if (text == null)
throw new ArgumentNullException("text");
if (offset < 0 || offset > text.Length)
throw new ArgumentOutOfRangeException("offset");
if (offset + count > text.Length)
throw new ArgumentOutOfRangeException("count");
this.text = text;
this.offset = offset;
this.count = count;
}
/// <summary>
/// Creates a new StringSegment.
/// </summary>
public StringSegment(string text)
{
if (text == null)
throw new ArgumentNullException("text");
this.text = text;
this.offset = 0;
this.count = text.Length;
}
/// <summary>
/// Gets the string used for this segment.
/// </summary>
public string Text {
get { return text; }
}
/// <summary>
/// Gets the start offset of the segment with the text.
/// </summary>
public int Offset {
get { return offset; }
}
/// <summary>
/// Gets the length of the segment.
/// </summary>
public int Count {
get { return count; }
}
#region Equals and GetHashCode implementation
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is StringSegment)
return Equals((StringSegment)obj); // use Equals method below
else
return false;
}
/// <inheritdoc/>
public bool Equals(StringSegment other)
{
// add comparisions for all members here
return object.ReferenceEquals(this.text, other.text) && offset == other.offset && count == other.count;
}
/// <inheritdoc/>
public override int GetHashCode()
{
return text.GetHashCode() ^ offset ^ count;
}
/// <summary>
/// Equality operator.
/// </summary>
public static bool operator ==(StringSegment left, StringSegment right)
{
return left.Equals(right);
}
/// <summary>
/// Inequality operator.
/// </summary>
public static bool operator !=(StringSegment left, StringSegment right)
{
return !left.Equals(right);
}
#endregion
}
}

52
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -268,6 +268,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -268,6 +268,7 @@ namespace ICSharpCode.Decompiler.Ast
if (m.Name == "Invoke") {
dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType);
dd.Parameters.AddRange(MakeParameters(m));
ConvertAttributes(dd, m.MethodReturnType, m.Module);
}
}
result = dd;
@ -637,11 +638,16 @@ namespace ICSharpCode.Decompiler.Ast @@ -637,11 +638,16 @@ namespace ICSharpCode.Decompiler.Ast
if (!methodDef.HasOverrides) {
astMethod.Modifiers = ConvertModifiers(methodDef);
if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) {
if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any())
astMethod.Modifiers |= Modifiers.New;
try {
if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any())
astMethod.Modifiers |= Modifiers.New;
} catch (ReferenceResolvingException) {
// TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
}
}
} else
} else {
astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
}
astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
}
ConvertAttributes(astMethod, methodDef);
@ -756,17 +762,24 @@ namespace ICSharpCode.Decompiler.Ast @@ -756,17 +762,24 @@ namespace ICSharpCode.Decompiler.Ast
getterModifiers = ConvertModifiers(propDef.GetMethod);
setterModifiers = ConvertModifiers(propDef.SetMethod);
astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null))
foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef))
if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
break;
} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot)
break;
if (accessor.IsVirtual ^ !accessor.IsNewSlot) {
if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any())
astProp.Modifiers |= Modifiers.New;
try {
if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) {
foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) {
if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
break;
} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) {
break;
}
}
}
if (accessor.IsVirtual ^ !accessor.IsNewSlot) {
if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any())
astProp.Modifiers |= Modifiers.New;
}
} catch (ReferenceResolvingException) {
// TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
}
}
astProp.Name = CleanName(propDef.Name);
@ -1099,9 +1112,14 @@ namespace ICSharpCode.Decompiler.Ast @@ -1099,9 +1112,14 @@ namespace ICSharpCode.Decompiler.Ast
}
#endregion
ConvertCustomAttributes(attributedNode, methodDefinition.MethodReturnType, "return");
if (methodDefinition.MethodReturnType.HasMarshalInfo) {
var marshalInfo = ConvertMarshalInfo(methodDefinition.MethodReturnType, methodDefinition.Module);
ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module);
}
void ConvertAttributes(AttributedNode attributedNode, MethodReturnType methodReturnType, ModuleDefinition module)
{
ConvertCustomAttributes(attributedNode, methodReturnType, "return");
if (methodReturnType.HasMarshalInfo) {
var marshalInfo = ConvertMarshalInfo(methodReturnType, module);
attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" });
}
}

13
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -633,6 +633,17 @@ namespace ICSharpCode.Decompiler.Ast @@ -633,6 +633,17 @@ namespace ICSharpCode.Decompiler.Ast
return InlineAssembly(byteCode, args);
}
}
case ILCode.Refanytype:
return new UndocumentedExpression {
UndocumentedExpressionType = UndocumentedExpressionType.RefType,
Arguments = { arg1 }
}.Member("TypeHandle");
case ILCode.Refanyval:
return MakeRef(
new UndocumentedExpression {
UndocumentedExpressionType = UndocumentedExpressionType.RefValue,
Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) }
});
case ILCode.Newobj: {
Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
if (declaringType is ArrayType) {
@ -669,8 +680,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -669,8 +680,6 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Nop: return null;
case ILCode.Pop: return arg1;
case ILCode.Readonly: return InlineAssembly(byteCode, args);
case ILCode.Refanytype: return InlineAssembly(byteCode, args);
case ILCode.Refanyval: return InlineAssembly(byteCode, args);
case ILCode.Ret:
if (methodDef.ReturnType.FullName != "System.Void") {
return new Ast.ReturnStatement { Expression = arg1 };

13
ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs

@ -14,6 +14,14 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -14,6 +14,14 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
/// </summary>
public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>, IAstTransform
{
static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression {
Target = new Choice {
new TypeOfExpression(new AnyNode()),
new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefType, Arguments = { new AnyNode() } }
},
MemberName = "TypeHandle"
};
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
base.VisitInvocationExpression(invocationExpression, data);
@ -38,9 +46,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -38,9 +46,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
switch (methodRef.FullName) {
case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)":
if (arguments.Length == 1) {
MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
if (mre != null && mre.Target is TypeOfExpression && mre.MemberName == "TypeHandle") {
invocationExpression.ReplaceWith(mre.Target);
if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) {
invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target);
return null;
}
}

54
ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs

@ -14,9 +14,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -14,9 +14,9 @@ namespace ICSharpCode.Decompiler.Ast
if (resolveTypeArguments)
return BaseTypes(derivedType).Any(t => t.Item == baseType);
else {
var comparableBaseType = baseType.Resolve();
var comparableBaseType = baseType.ResolveOrThrow();
while (derivedType.BaseType != null) {
var resolvedBaseType = derivedType.BaseType.Resolve();
var resolvedBaseType = derivedType.BaseType.ResolveOrThrow();
if (resolvedBaseType == null)
return false;
if (comparableBaseType == resolvedBaseType)
@ -29,11 +29,16 @@ namespace ICSharpCode.Decompiler.Ast @@ -29,11 +29,16 @@ namespace ICSharpCode.Decompiler.Ast
public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod)
{
if (parentMethod == null)
throw new ArgumentNullException("parentMethod");
if (childMethod == null)
throw new ArgumentNullException("childMethod");
if (parentMethod.Name != childMethod.Name)
return false;
if (parentMethod.HasParameters || childMethod.HasParameters)
if(!parentMethod.HasParameters || ! childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count)
if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count)
return false;
return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.);
@ -41,6 +46,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -41,6 +46,11 @@ namespace ICSharpCode.Decompiler.Ast
public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty)
{
if (parentProperty == null)
throw new ArgumentNullException("parentProperty");
if (childProperty == null)
throw new ArgumentNullException("childProperty");
if (parentProperty.Name != childProperty.Name)
return false;
@ -53,6 +63,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -53,6 +63,9 @@ namespace ICSharpCode.Decompiler.Ast
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
var typeContext = CreateGenericContext(method.DeclaringType);
var gMethod = typeContext.ApplyTo(method);
@ -65,8 +78,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -65,8 +78,11 @@ namespace ICSharpCode.Decompiler.Ast
}
}
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property, bool ignoreResolveExceptions = false)
{
if (property == null)
throw new ArgumentNullException("property");
var typeContext = CreateGenericContext(property.DeclaringType);
var gProperty = typeContext.ApplyTo(property);
@ -109,7 +125,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -109,7 +125,7 @@ namespace ICSharpCode.Decompiler.Ast
if (mCandidate.HasOverrides)
return false;
if (!IsSameType(candidate.Resolve(mCandidate.ReturnType), method.Resolve(mMethod.ReturnType)))
if (!IsSameType(candidate.ResolveWithContext(mCandidate.ReturnType), method.ResolveWithContext(mMethod.ReturnType)))
return false;
if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
@ -140,7 +156,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -140,7 +156,7 @@ namespace ICSharpCode.Decompiler.Ast
if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
return false;
if (!IsSameType(candidate.Resolve(mCandidate.PropertyType), property.Resolve(mProperty.PropertyType)))
if (!IsSameType(candidate.ResolveWithContext(mCandidate.PropertyType), property.ResolveWithContext(mProperty.PropertyType)))
return false;
if (mCandidate.HasParameters || mProperty.HasParameters) {
@ -158,8 +174,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -158,8 +174,8 @@ namespace ICSharpCode.Decompiler.Ast
private static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
{
var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType);
var param = parameterType.Resolve(parameterType.Item.ParameterType);
var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType);
var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType);
return IsSameType(baseParam, param);
}
@ -186,10 +202,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -186,10 +202,10 @@ namespace ICSharpCode.Decompiler.Ast
var baseType = type.Item.BaseType;
var genericBaseType = baseType as GenericInstanceType;
if (genericBaseType != null) {
type = new GenericContext<TypeDefinition>(genericBaseType.Resolve(),
genericBaseType.GenericArguments.Select(t => type.Resolve(t)));
type = new GenericContext<TypeDefinition>(genericBaseType.ResolveOrThrow(),
genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t)));
} else
type = new GenericContext<TypeDefinition>(baseType.Resolve());
type = new GenericContext<TypeDefinition>(baseType.ResolveOrThrow());
yield return type;
}
}
@ -201,7 +217,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -201,7 +217,7 @@ namespace ICSharpCode.Decompiler.Ast
: new GenericContext<TypeDefinition>(type);
}
struct GenericContext<T>
struct GenericContext<T> where T : class
{
private static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
@ -210,12 +226,18 @@ namespace ICSharpCode.Decompiler.Ast @@ -210,12 +226,18 @@ namespace ICSharpCode.Decompiler.Ast
public GenericContext(T item)
{
if (item == null)
throw new ArgumentNullException("item");
Item = item;
TypeArguments = Empty;
}
public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
{
if (item == null)
throw new ArgumentNullException("item");
Item = item;
var list = new List<TypeReference>();
foreach (var arg in typeArguments) {
@ -231,7 +253,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -231,7 +253,7 @@ namespace ICSharpCode.Decompiler.Ast
TypeArguments = typeArguments;
}
public TypeReference Resolve(TypeReference type)
public TypeReference ResolveWithContext(TypeReference type)
{
var genericParameter = type as GenericParameter;
if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) {
@ -239,7 +261,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -239,7 +261,7 @@ namespace ICSharpCode.Decompiler.Ast
}
var arrayType = type as ArrayType;
if (arrayType != null) {
var resolvedElementType = Resolve(arrayType.ElementType);
var resolvedElementType = ResolveWithContext(arrayType.ElementType);
if (resolvedElementType == null)
return null;
if (resolvedElementType == arrayType.ElementType)
@ -249,10 +271,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -249,10 +271,10 @@ namespace ICSharpCode.Decompiler.Ast
newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension];
return newArrayType;
}
return type.Resolve();
return type.ResolveOrThrow();
}
public GenericContext<T2> ApplyTo<T2>(T2 item)
public GenericContext<T2> ApplyTo<T2>(T2 item) where T2 : class
{
return new GenericContext<T2>(item, this.TypeArguments);
}

10
ICSharpCode.Decompiler/CecilExtensions.cs

@ -185,7 +185,15 @@ namespace ICSharpCode.Decompiler @@ -185,7 +185,15 @@ namespace ICSharpCode.Decompiler
else
return null;
}
public static TypeDefinition ResolveOrThrow(this TypeReference typeReference)
{
var resolved = typeReference.Resolve();
if (resolved == null)
throw new ReferenceResolvingException();
return resolved;
}
public static bool IsCompilerGenerated(this ICustomAttributeProvider provider)
{
if (provider != null && provider.HasCustomAttributes) {

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -111,6 +111,7 @@ @@ -111,6 +111,7 @@
<Compile Include="ITextOutput.cs" />
<Compile Include="PlainTextOutput.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReferenceResolvingException.cs" />
<Compile Include="TextOutputWriter.cs" />
<None Include="Properties\AssemblyInfo.template.cs" />
</ItemGroup>

2
ICSharpCode.Decompiler/ITextOutput.cs

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

50
ICSharpCode.Decompiler/ReferenceResolvingException.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.Decompiler
{
/// <summary>
/// Represents an error while resolving a reference to a type or a member.
/// </summary>
[Serializable]
public class ReferenceResolvingException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// </summary>
public ReferenceResolvingException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// </summary>
/// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
public ReferenceResolvingException(string message)
: base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// </summary>
/// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
/// <param name="inner">The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param>
public ReferenceResolvingException(string message, Exception inner)
: base(message, inner)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// </summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param>
protected ReferenceResolvingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
}
}

12
ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs

@ -28,8 +28,10 @@ public class CheckedUnchecked @@ -28,8 +28,10 @@ public class CheckedUnchecked
public void ForWithCheckedIteratorAndUncheckedBody(int n)
{
checked {
for (int i = n + 1; i < n + 1; i++) {
checked
{
for (int i = n + 1; i < n + 1; i++)
{
n = unchecked(i * i);
}
}
@ -37,9 +39,11 @@ public class CheckedUnchecked @@ -37,9 +39,11 @@ public class CheckedUnchecked
public void ForWithCheckedInitializerAndUncheckedIterator(int n)
{
checked {
checked
{
int i = n;
for (i -= 10; i < n; i = unchecked(i + 1)) {
for (i -= 10; i < n; i = unchecked(i + 1))
{
n--;
}
}

10
ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs

@ -468,3 +468,13 @@ namespace ClassAttributeOnTypeParameter @@ -468,3 +468,13 @@ namespace ClassAttributeOnTypeParameter
{
}
}
//$$ AttributeOnReturnTypeOfDelegate
namespace AttributeOnReturnTypeOfDelegate
{
[AttributeUsage(AttributeTargets.All)]
public class MyAttributeAttribute : Attribute
{
}
[return: MyAttribute]
public delegate void Test();
}

3
ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs

@ -6,6 +6,7 @@ using System.Linq; @@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Tests.Helpers;
using Microsoft.CSharp;
using Mono.Cecil;
using NUnit.Framework;
@ -19,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -19,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests
var lines = File.ReadAllLines(Path.Combine(@"..\..\Tests", samplesFileName));
var testCode = RemoveIgnorableLines(lines);
var decompiledTestCode = RoundtripCode(testCode);
Assert.AreEqual(testCode, decompiledTestCode);
CodeAssert.AreEqual(testCode, decompiledTestCode);
}
static string RemoveIgnorableLines(IEnumerable<string> lines)

108
ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using DiffLib;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
public class CodeAssert
{
public static void AreEqual(string input1, string input2)
{
var diff = new StringWriter();
if (!Compare(input1, input2, diff)) {
Assert.Fail(diff.ToString());
}
}
static bool Compare(string input1, string input2, StringWriter diff)
{
var differ = new AlignedDiff<string>(
NormalizeAndSplitCode(input1),
NormalizeAndSplitCode(input2),
new CodeLineEqualityComparer(),
new StringSimilarityComparer(),
new StringAlignmentFilter());
bool result = true, ignoreChange;
int line1 = 0, line2 = 0;
foreach (var change in differ.Generate()) {
switch (change.Change) {
case ChangeType.Same:
diff.Write("{0,4} {1,4} ", ++line1, ++line2);
diff.Write(" ");
diff.WriteLine(change.Element1);
break;
case ChangeType.Added:
diff.Write(" {1,4} ", line1, ++line2);
result &= ignoreChange = ShouldIgnoreChange(change.Element2);
diff.Write(ignoreChange ? " " : " + ");
diff.WriteLine(change.Element2);
break;
case ChangeType.Deleted:
diff.Write("{0,4} ", ++line1, line2);
result &= ignoreChange = ShouldIgnoreChange(change.Element1);
diff.Write(ignoreChange ? " " : " - ");
diff.WriteLine(change.Element1);
break;
case ChangeType.Changed:
diff.Write("{0,4} ", ++line1, line2);
result = false;
diff.Write("(-) ");
diff.WriteLine(change.Element1);
diff.Write(" {1,4} ", line1, ++line2);
diff.Write("(+) ");
diff.WriteLine(change.Element2);
break;
}
}
return result;
}
class CodeLineEqualityComparer : IEqualityComparer<string>
{
private IEqualityComparer<string> baseComparer = EqualityComparer<string>.Default;
public bool Equals(string x, string y)
{
return baseComparer.Equals(
NormalizeLine(x),
NormalizeLine(y)
);
}
public int GetHashCode(string obj)
{
return baseComparer.GetHashCode(NormalizeLine(obj));
}
}
private static string NormalizeLine(string line)
{
line = line.Trim();
var index = line.IndexOf("//");
if (index >= 0) {
return line.Substring(0, index);
} else {
return line;
}
}
private static bool ShouldIgnoreChange(string line)
{
// for the result, we should ignore blank lines and added comments
return NormalizeLine(line) == string.Empty;
}
private static IEnumerable<string> NormalizeAndSplitCode(string input)
{
return input.Split(new[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.None);
}
}
}

8
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -38,6 +38,9 @@ @@ -38,6 +38,9 @@
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="DiffLib">
<HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\nunit.framework.dll</HintPath>
@ -54,12 +57,15 @@ @@ -54,12 +57,15 @@
<ItemGroup>
<Compile Include="CallOverloadedMethod.cs" />
<Compile Include="CheckedUnchecked.cs" />
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="IncrementDecrement.cs" />
<Compile Include="QueryExpressions.cs" />
<Compile Include="Switch.cs" />
<Compile Include="UndocumentedExpressions.cs" />
<Compile Include="UnsafeCode.cs" />
<Compile Include="Types\S_TypeDeclarations.cs" />
<Compile Include="YieldReturn.cs" />
<None Include="packages.config" />
<None Include="Types\S_EnumSamples.cs" />
<None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" />
<Compile Include="Helpers\RemoveCompilerAttribute.cs" />
@ -101,4 +107,4 @@ @@ -101,4 +107,4 @@
<None Include="StackTests\StackTests.il" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>
</Project>

12
ICSharpCode.Decompiler/Tests/IncrementDecrement.cs

@ -200,7 +200,12 @@ public class IncrementDecrement @@ -200,7 +200,12 @@ public class IncrementDecrement
// {
// return this.M()[name]++;
// }
// public unsafe int PostIncrementOfPointer(int* ptr)
// {
// return *(ptr++);
// }
public int PostIncrementInstanceField()
{
return this.M().Field--;
@ -225,9 +230,4 @@ public class IncrementDecrement @@ -225,9 +230,4 @@ public class IncrementDecrement
{
return (*this.GetPointer())++;
}
// public unsafe int PostIncrementOfPointer(int* ptr)
// {
// return *(ptr++);
// }
}

80
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -5,8 +5,11 @@ using System; @@ -5,8 +5,11 @@ using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using DiffLib;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Tests.Helpers;
using Microsoft.CSharp;
using Mono.Cecil;
using NUnit.Framework;
@ -16,6 +19,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -16,6 +19,12 @@ namespace ICSharpCode.Decompiler.Tests
[TestFixture]
public class TestRunner
{
[Test, Ignore("disambiguating overloads is not yet implemented")]
public void CallOverloadedMethod()
{
TestFile(@"..\..\Tests\CallOverloadedMethod.cs");
}
[Test, Ignore("unncessary primitive casts")]
public void CheckedUnchecked()
{
@ -28,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -28,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\DelegateConstruction.cs");
}
[Test, Ignore("bug with variable-less catch")]
[Test, Ignore("arg-Variables in catch clauses")]
public void ExceptionHandling()
{
TestFile(@"..\..\Tests\ExceptionHandling.cs");
@ -70,19 +79,31 @@ namespace ICSharpCode.Decompiler.Tests @@ -70,19 +79,31 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\PropertiesAndEvents.cs");
}
[Test, Ignore]
[Test, Ignore("Formatting differences in anonymous method create expressions")]
public void QueryExpressions()
{
TestFile(@"..\..\Tests\QueryExpressions.cs");
}
[Test, Ignore("switch transform is currently broken")]
public void Switch()
{
TestFile(@"..\..\Tests\Switch.cs");
}
[Test]
public void UndocumentedExpressions()
{
TestFile(@"..\..\Tests\UndocumentedExpressions.cs");
}
[Test, Ignore("has incorrect casts to IntPtr")]
public void UnsafeCode()
{
TestFile(@"..\..\Tests\UnsafeCode.cs");
}
[Test, Ignore("IncrementArrayLocation not yet supported")]
[Test]
public void ValueTypes()
{
TestFile(@"..\..\Tests\ValueTypes.cs");
@ -94,12 +115,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -94,12 +115,6 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\YieldReturn.cs");
}
[Test, Ignore("Formatting differences")]
public void QueryExpressions()
{
TestFile(@"..\..\Tests\QueryExpressions.cs");
}
static void TestFile(string fileName)
{
string code = File.ReadAllText(fileName);
@ -109,52 +124,9 @@ namespace ICSharpCode.Decompiler.Tests @@ -109,52 +124,9 @@ namespace ICSharpCode.Decompiler.Tests
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
StringWriter output = new StringWriter();
decompiler.GenerateCode(new PlainTextOutput(output));
StringWriter diff = new StringWriter();
if (!Compare(code, output.ToString(), diff)) {
throw new Exception("Test failure." + Environment.NewLine + diff.ToString());
}
}
static bool Compare(string input1, string input2, StringWriter diff)
{
bool ok = true;
int numberOfContinuousMistakes = 0;
StringReader r1 = new StringReader(input1);
StringReader r2 = new StringReader(input2);
string line1, line2;
while ((line1 = r1.ReadLine()) != null) {
string trimmed = line1.Trim();
if (trimmed.Length == 0 || trimmed.StartsWith("//", StringComparison.Ordinal) | trimmed.StartsWith("#", StringComparison.Ordinal)) {
diff.WriteLine(" " + line1);
continue;
}
line2 = r2.ReadLine();
while (line2 != null && string.IsNullOrWhiteSpace(line2))
line2 = r2.ReadLine();
if (line2 == null) {
ok = false;
diff.WriteLine("-" + line1);
continue;
}
if (line1.Trim() != line2.Trim()) {
ok = false;
if (numberOfContinuousMistakes++ > 5)
return false;
diff.WriteLine("-" + line1);
diff.WriteLine("+" + line2);
} else {
if (numberOfContinuousMistakes > 0)
numberOfContinuousMistakes--;
diff.WriteLine(" " + line1);
}
}
while ((line2 = r2.ReadLine()) != null) {
ok = false;
diff.WriteLine("+" + line2);
}
return ok;
CodeAssert.AreEqual(code, output.ToString());
}
static AssemblyDefinition Compile(string code)
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });

26
ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
public class UndocumentedExpressions
{
public static int GetArgCount(__arglist)
{
ArgIterator argIterator = new ArgIterator(__arglist);
return argIterator.GetRemainingCount();
}
public static void MakeTypedRef(object o)
{
TypedReference tr = __makeref(o);
UndocumentedExpressions.AcceptTypedRef(tr);
}
private static void AcceptTypedRef(TypedReference tr)
{
Console.WriteLine("Value is: " + __refvalue(tr, object).ToString());
Console.WriteLine("Type is: " + __reftype(tr).Name);
__refvalue(tr, object) = 1;
}
}

4
ICSharpCode.Decompiler/Tests/packages.config

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DiffLib" version="1.0.0.55" />
</packages>

12
ILSpy/ContextMenuEntry.cs

@ -65,7 +65,9 @@ namespace ICSharpCode.ILSpy @@ -65,7 +65,9 @@ namespace ICSharpCode.ILSpy
{
var provider = new ContextMenuProvider(treeView);
treeView.ContextMenuOpening += provider.treeView_ContextMenuOpening;
treeView.ContextMenuClosing -= provider.treeView_ContextMenuClosing;
// Context menu is shown only when the ContextMenu property is not null before the
// ContextMenuOpening event handler is called.
treeView.ContextMenu = new ContextMenu();
}
readonly SharpTreeView treeView;
@ -114,11 +116,9 @@ namespace ICSharpCode.ILSpy @@ -114,11 +116,9 @@ namespace ICSharpCode.ILSpy
}
if (menu.Items.Count > 0)
treeView.ContextMenu = menu;
}
void treeView_ContextMenuClosing(object sender, ContextMenuEventArgs e)
{
treeView.ContextMenu = null;
else
// hide the context menu.
e.Handled = true;
}
}
}

5
ILSpy/ILSpy.csproj

@ -136,6 +136,7 @@ @@ -136,6 +136,7 @@
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\IMemberTreeNode.cs" />
<Compile Include="TreeNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyAccessorsTreeNode.cs" />
@ -280,9 +281,7 @@ @@ -280,9 +281,7 @@
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="XmlDoc" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="Options" />
</ItemGroup>

20
ILSpy/TextView/AvalonEditTextOutput.cs

@ -64,6 +64,8 @@ namespace ICSharpCode.ILSpy.TextView @@ -64,6 +64,8 @@ namespace ICSharpCode.ILSpy.TextView
/// </summary>
public sealed class AvalonEditTextOutput : ISmartTextOutput
{
int lineNumber = 1;
int lastLineStart = 0;
readonly StringBuilder b = new StringBuilder();
/// <summary>Current indentation level</summary>
@ -87,7 +89,6 @@ namespace ICSharpCode.ILSpy.TextView @@ -87,7 +89,6 @@ namespace ICSharpCode.ILSpy.TextView
public AvalonEditTextOutput()
{
CurrentLine = 1;
}
/// <summary>
@ -108,8 +109,6 @@ namespace ICSharpCode.ILSpy.TextView @@ -108,8 +109,6 @@ namespace ICSharpCode.ILSpy.TextView
get { return b.Length; }
}
public int CurrentLine { get; set; }
#region Text Document
TextDocument textDocument;
@ -179,8 +178,9 @@ namespace ICSharpCode.ILSpy.TextView @@ -179,8 +178,9 @@ namespace ICSharpCode.ILSpy.TextView
{
Debug.Assert(textDocument == null);
b.AppendLine();
++CurrentLine;
needsIndent = true;
lastLineStart = b.Length;
lineNumber++;
if (this.TextLength > LengthLimit) {
throw new OutputLengthExceededException();
}
@ -228,5 +228,17 @@ namespace ICSharpCode.ILSpy.TextView @@ -228,5 +228,17 @@ namespace ICSharpCode.ILSpy.TextView
this.UIElements.Add(new KeyValuePair<int, Lazy<UIElement>>(this.TextLength, new Lazy<UIElement>(element)));
}
}
public int CurrentLine {
get {
return lineNumber;
}
}
public int CurrentColumn {
get {
return b.Length - lastLineStart + 1;
}
}
}
}

3
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs

@ -67,7 +67,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -67,7 +67,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string name = analyzedField.Name;
string declTypeName = analyzedField.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
foreach (MethodDefinition method in type.Methods) {
@ -78,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -78,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (Instruction instr in method.Body.Instructions) {
if (CanBeReference(instr.OpCode.Code)) {
FieldReference fr = instr.Operand as FieldReference;
if (fr != null && fr.Name == name && fr.DeclaringType.FullName == declTypeName && fr.Resolve() == analyzedField) {
if (fr != null && fr.Name == name && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) {
found = true;
break;
}

3
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -80,7 +80,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -80,7 +80,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string name = analyzedMethod.Name;
string declTypeName = analyzedMethod.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
foreach (MethodDefinition method in type.Methods) {
@ -90,7 +89,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -90,7 +89,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
continue;
foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name && mr.DeclaringType.FullName == declTypeName && mr.Resolve() == analyzedMethod) {
if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) {
found = true;
break;
}

25
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
@ -69,18 +70,26 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -69,18 +70,26 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false))
continue;
SharpTreeNode newNode = null;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false))
continue;
foreach (PropertyDefinition property in type.Properties) {
ct.ThrowIfCancellationRequested();
foreach (PropertyDefinition property in type.Properties) {
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
newNode = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
}
}
}
catch (ReferenceResolvingException) {
// ignore this type definition.
}
if (newNode != null)
yield return newNode;
}
}

26
ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
@ -73,20 +74,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -73,20 +74,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes))
{
ct.ThrowIfCancellationRequested();
SharpTreeNode newNode = null;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
continue;
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
continue;
foreach (MethodDefinition method in type.Methods) {
ct.ThrowIfCancellationRequested();
foreach (MethodDefinition method in type.Methods)
{
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method))
{
bool hidesParent = !method.IsVirtual ^ method.IsNewSlot;
yield return new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : "");
if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) {
bool hidesParent = !method.IsVirtual ^ method.IsNewSlot;
newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : "");
}
}
}
catch (ReferenceResolvingException) {
// ignore this type definition. maybe add a notification about such cases.
}
if (newNode != null)
yield return newNode;
}
}

36
ILSpy/TreeNodes/Analyzer/Helpers.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
static class Helpers
{
public static bool IsReferencedBy(TypeDefinition type, TypeReference typeRef)
{
// TODO: move it to a better place after adding support for more cases.
if (type == null)
throw new ArgumentNullException("type");
if (typeRef == null)
throw new ArgumentNullException("typeRef");
if (type == typeRef)
return true;
if (type.Name != typeRef.Name)
return false;
if (type.Namespace != typeRef.Namespace)
return false;
if (type.DeclaringType != null || typeRef.DeclaringType != null) {
if (type.DeclaringType == null || typeRef.DeclaringType == null)
return false;
if (!IsReferencedBy(type.DeclaringType, typeRef.DeclaringType))
return false;
}
return true;
}
}
}

BIN
packages/DiffLib.1.0.0.55/DiffLib.1.0.0.55.nupkg vendored

Binary file not shown.

641
packages/DiffLib.1.0.0.55/lib/net35-Client/DiffLib.XML vendored

@ -0,0 +1,641 @@ @@ -0,0 +1,641 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>DiffLib</name>
</assembly>
<members>
<member name="T:DiffLib.AlignedDiffChange`1">
<summary>
This class holds a single collection from either the first or the second, or both,
collections given to the <see cref="T:DiffLib.AlignedDiff`1"/> class, along
with the type of change that the elements produce.
</summary>
</member>
<member name="M:DiffLib.AlignedDiffChange`1.#ctor(DiffLib.ChangeType,`0,`0)">
<summary>
Initializes a new instance of <see cref="T:DiffLib.AlignedDiffChange`1"/>.
</summary>
<param name="change">
The <see cref="P:DiffLib.AlignedDiffChange`1.Change">type</see> of change this <see cref="T:DiffLib.AlignedDiffChange`1"/> details.
</param>
<param name="element1">
The element from the first collection. If <paramref name="change"/> is <see cref="F:DiffLib.ChangeType.Added"/>, then
this parameter has no meaning.
</param>
<param name="element2">
The element from the second collection. If <paramref name="change"/> is <see cref="F:DiffLib.ChangeType.Deleted"/>, then
this parameter has no meaning.
</param>
</member>
<member name="M:DiffLib.AlignedDiffChange`1.Equals(DiffLib.AlignedDiffChange{`0})">
<summary>
Indicates whether the current object is equal to another object of the same type.
</summary>
<returns>
true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
</returns>
<param name="other">An object to compare with this object.</param>
</member>
<member name="M:DiffLib.AlignedDiffChange`1.Equals(System.Object)">
<summary>
Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
</summary>
<returns>
true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
</returns>
<param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.AlignedDiffChange`1.GetHashCode">
<summary>
Serves as a hash function for a particular type.
</summary>
<returns>
A hash code for the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.AlignedDiffChange`1.ToString">
<summary>
Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</summary>
<returns>
A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="P:DiffLib.AlignedDiffChange`1.Change">
<summary>
The <see cref="P:DiffLib.AlignedDiffChange`1.Change">type</see> of change this <see cref="T:DiffLib.AlignedDiffChange`1"/> details.
</summary>
</member>
<member name="P:DiffLib.AlignedDiffChange`1.Element1">
<summary>
The element from the first collection. If <see cref="T:System.Type"/> is <see cref="F:DiffLib.ChangeType.Added"/>, then
the value of this property has no meaning.
</summary>
</member>
<member name="P:DiffLib.AlignedDiffChange`1.Element2">
<summary>
The element from the second collection. If <see cref="T:System.Type"/> is <see cref="F:DiffLib.ChangeType.Deleted"/>, then
the value of this property has no meaning.
</summary>
</member>
<member name="T:DiffLib.ChangeType">
<summary>
This enum is used by <see cref="T:DiffLib.AlignedDiffChange`1"/> to specify how
the two elements from the two collections relate.
</summary>
</member>
<member name="F:DiffLib.ChangeType.Same">
<summary>
The two elements are the same.
</summary>
</member>
<member name="F:DiffLib.ChangeType.Added">
<summary>
The second element was added in the second collection.
</summary>
</member>
<member name="F:DiffLib.ChangeType.Deleted">
<summary>
The first element was removed from the second collection.
</summary>
</member>
<member name="F:DiffLib.ChangeType.Changed">
<summary>
The first element was changed/replaced with the second element in the second collection.
</summary>
</member>
<member name="T:DiffLib.Diff`1">
<summary>
This class implements the basic diff algorithm by recursively applying the Longest Common Substring
on pieces of the collections, and reporting sections that are similar, and those that are not,
in the appropriate sequence.
</summary>
<typeparam name="T">
The types of elements in the collections being compared.
</typeparam>
</member>
<member name="M:DiffLib.Diff`1.#ctor(System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEnumerable{`0})">
<summary>
Initializes a new instance of <see cref="T:DiffLib.Diff`1"/>
using the default <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> instance for the
<typeparamref name="T"/> type.
</summary>
<param name="collection1">
The first collection of items.
</param>
<param name="collection2">
The second collection of items.
</param>
<exception cref="T:System.ArgumentNullException">
<para><paramref name="collection1"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="collection2"/> is <c>null</c>.</para>
</exception>
</member>
<member name="M:DiffLib.Diff`1.#ctor(System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEqualityComparer{`0})">
<summary>
Initializes a new instance of <see cref="T:DiffLib.Diff`1"/>.
</summary>
<param name="collection1">
The first collection of items.
</param>
<param name="collection2">
The second collection of items.
</param>
<param name="comparer">
The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> that will be used to compare elements from
<paramref name="collection1"/> with elements from <paramref name="collection2"/>.
</param>
<exception cref="T:System.ArgumentNullException">
<para><paramref name="collection1"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="collection2"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="comparer"/> is <c>null</c>.</para>
</exception>
</member>
<member name="M:DiffLib.Diff`1.GetEnumerator">
<summary>
Returns an enumerator that iterates through the collection.
</summary>
<returns>
A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
</returns>
<filterpriority>1</filterpriority>
</member>
<member name="M:DiffLib.Diff`1.Generate">
<summary>
Generates the diff between the two collections.
</summary>
</member>
<member name="T:DiffLib.DiffChange">
<summary>
This class contains a single section of diff output from the <see cref="M:DiffLib.Diff`1.Generate"/>
method.
</summary>
</member>
<member name="M:DiffLib.DiffChange.#ctor(System.Boolean,System.Int32,System.Int32)">
<summary>
Initializes a new instance of <see cref="T:DiffLib.DiffChange"/>.
</summary>
<param name="equal">
If <c>true</c>, then the section specifies a section from the first
collection that is equal to a section from the second collection;
otherwise, if <c>false</c>, then the section from the first
collection was replaced with the section from the second collection.
</param>
<param name="length1">
The length of the section in the first collection. Can be 0 if
the section specifies that new content was added in the second
collection.
</param>
<param name="length2">
The length of the section in the second collection. Can be 0 if
the section specifies that old content was deleted in the second
collection.
</param>
<exception cref="T:System.ArgumentOutOfRangeException">
<para><paramref name="length1"/> is negative.</para>
<para>- or -</para>
<para><paramref name="length2"/> is negative.</para>
</exception>
<exception cref="T:System.ArgumentException">
<para><paramref name="equal"/> is <c>true</c> but <paramref name="length1"/> is not equal to <paramref name="length2"/>.</para>
</exception>
</member>
<member name="M:DiffLib.DiffChange.Equals(DiffLib.DiffChange)">
<summary>
Indicates whether the current object is equal to another object of the same type.
</summary>
<returns>
true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
</returns>
<param name="other">An object to compare with this object.</param>
</member>
<member name="M:DiffLib.DiffChange.Equals(System.Object)">
<summary>
Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
</summary>
<returns>
true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
</returns>
<param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.DiffChange.GetHashCode">
<summary>
Serves as a hash function for a particular type.
</summary>
<returns>
A hash code for the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.DiffChange.ToString">
<summary>
Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</summary>
<returns>
A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="P:DiffLib.DiffChange.Equal">
<summary>
Gets whether the <see cref="T:DiffLib.DiffChange"/> specifies equal sections in the two
collections, or differing sections.
</summary>
<value>
If <c>true</c>, then the section specifies a section from the first
collection that is equal to a section from the second collection;
otherwise, if <c>false</c>, then the section from the first
collection was replaced with the section from the second collection.
</value>
</member>
<member name="P:DiffLib.DiffChange.Length1">
<summary>
The length of the section in the first collection.
</summary>
</member>
<member name="P:DiffLib.DiffChange.Length2">
<summary>
The length of the section in the second collection.
</summary>
</member>
<member name="T:DiffLib.IAlignmentFilter`1">
<summary>
This interface must be implemented by classes that will do similarity-filtering
during alignment (<see cref="T:DiffLib.AlignedDiff`1"/>) to determine
if two aligned elements are similar enough to report
them as a change, instead of as a delete plus an add.
</summary>
<typeparam name="T">
The type of elements being compared.
</typeparam>
</member>
<member name="M:DiffLib.IAlignmentFilter`1.CanAlign(`0,`0)">
<summary>
Determines if the two values are similar enough to align them
as a change, instead of not aligning them but reporting them
as a delete plus an add instead.
</summary>
<param name="value1">
The first value to compare against <paramref name="value2"/>.
</param>
<param name="value2">
The second value to compare against <paramref name="value1"/>.
</param>
<returns>
<c>true</c> if the two values are similar enough to report
them as a change; false if the two values aren't similar enough
but needs to be reported as a delete plus an add.
</returns>
</member>
<member name="T:DiffLib.ISimilarityComparer`1">
<summary>
This interface must be implemented by classes that will do similarity-calculation
for use with the <see cref="T:DiffLib.AlignedDiff`1"/> class.
</summary>
<typeparam name="T">
The type of elements being compared.
</typeparam>
</member>
<member name="M:DiffLib.ISimilarityComparer`1.Compare(`0,`0)">
<summary>
Does a similarity comparison between the two values and returns their
similarity, a value ranging from 0.0 to 1.0, where 0.0 means they're
completely different and 1.0 means they have the same value.
</summary>
<param name="value1">
The first value to compare.
</param>
<param name="value2">
The second value to compare.
</param>
<returns>
A value ranging from 0.0 to 1.0, where 0.0 means they're
completely different and 1.0 means they have the same value.
</returns>
</member>
<member name="T:DiffLib.LongestCommonSubstring`1">
<summary>
This class implements the LCS algorithm, to find the longest common substring that exists
in two collections, and return the locations of those substrings.
</summary>
<typeparam name="T">
The types of elements in the collections being compared.
</typeparam>
</member>
<member name="M:DiffLib.LongestCommonSubstring`1.#ctor(System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEnumerable{`0})">
<summary>
Initializes a new instance of the <see cref="T:DiffLib.LongestCommonSubstring`1"/> class
using the default <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> instance for the
<typeparamref name="T"/> type.
</summary>
<param name="collection1">
The first collection of items.
</param>
<param name="collection2">
The second collection of items.
</param>
<exception cref="T:System.ArgumentNullException">
<para><paramref name="collection1"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="collection2"/> is <c>null</c>.</para>
</exception>
</member>
<member name="M:DiffLib.LongestCommonSubstring`1.#ctor(System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEqualityComparer{`0})">
<summary>
Initializes a new instance of the <see cref="T:DiffLib.LongestCommonSubstring`1"/> class.
</summary>
<param name="collection1">
The first collection of items.
</param>
<param name="collection2">
The second collection of items.
</param>
<param name="comparer">
The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> that will be used to compare elements from
<paramref name="collection1"/> with elements from <paramref name="collection2"/>.
</param>
<exception cref="T:System.ArgumentNullException">
<para><paramref name="collection1"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="collection2"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="comparer"/> is <c>null</c>.</para>
</exception>
</member>
<member name="M:DiffLib.LongestCommonSubstring`1.Find">
<summary>
Finds the longest common substring and returns its position in the two collections, and
its length, or <c>null</c> if no such common substring can be located.
</summary>
<returns>
A <see cref="T:DiffLib.LongestCommonSubstringResult"/> containing the positions of the two substrings, one position
for each collection, both 0-based, and the length of the substring. If no common substring can be found, <c>null</c>
will be returned.
</returns>
</member>
<member name="M:DiffLib.LongestCommonSubstring`1.Find(System.Int32,System.Int32,System.Int32,System.Int32)">
<summary>
Finds the longest common substring and returns its position in the two collections, and
its length, or <c>null</c> if no such common substring can be located.
</summary>
<param name="lower1">
The starting position in the first collection, 0-based. Included in the search.
</param>
<param name="upper1">
The ending position in the first collection, 0-based. <b>Not</b> included in the search.
</param>
<param name="lower2">
The starting position in the second collection, 0-based. Included in the search.
</param>
<param name="upper2">
The ending position in the second collection, 0-based. <b>Not</b> included in the search.
</param>
<returns>
A <see cref="T:DiffLib.LongestCommonSubstringResult"/> containing the positions of the two substrings, one position
for each collection, both 0-based, and the length of the substring. If no common substring can be found, <c>null</c>
will be returned.
</returns>
<exception cref="T:System.ArgumentOutOfRangeException">
<para><paramref name="lower1"/> is less than 0.</para>
<para>- or -</para>
<para><paramref name="lower1"/> is greater than <paramref name="upper1"/>.</para>
<para>- or -</para>
<para><paramref name="upper1"/> is greater than the length of the first collection.</para>
<para>- or -</para>
<para><paramref name="lower2"/> is less than 0.</para>
<para>- or -</para>
<para><paramref name="lower2"/> is greater than <paramref name="upper2"/>.</para>
<para>- or -</para>
<para><paramref name="upper2"/> is greater than the length of the second collection.</para>
</exception>
</member>
<member name="T:DiffLib.LongestCommonSubstringResult">
<summary>
This class holds the result of calling <see cref="M:DiffLib.LongestCommonSubstring`1.Find"/>.
</summary>
</member>
<member name="M:DiffLib.LongestCommonSubstringResult.#ctor(System.Int32,System.Int32,System.Int32)">
<summary>
Initializes a new instance of <see cref="T:DiffLib.LongestCommonSubstringResult"/>.
</summary>
<param name="positionInCollection1">
The position in the first collection, 0-based.
</param>
<param name="positionInCollection2">
The position in the second collection, 0-based.
</param>
<param name="length">
The length of the common substring.
</param>
<exception cref="T:System.ArgumentOutOfRangeException">
<para><paramref name="positionInCollection1"/> is negative.</para>
<para>- or -</para>
<para><paramref name="positionInCollection2"/> is negative.</para>
<para>- or -</para>
<para><paramref name="length"/> is zero or negative.</para>
</exception>
</member>
<member name="M:DiffLib.LongestCommonSubstringResult.Equals(DiffLib.LongestCommonSubstringResult)">
<summary>
Indicates whether the current object is equal to another object of the same type.
</summary>
<returns>
true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
</returns>
<param name="other">An object to compare with this object.</param>
</member>
<member name="M:DiffLib.LongestCommonSubstringResult.Equals(System.Object)">
<summary>
Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
</summary>
<returns>
true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
</returns>
<param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.LongestCommonSubstringResult.GetHashCode">
<summary>
Serves as a hash function for a particular type.
</summary>
<returns>
A hash code for the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="M:DiffLib.LongestCommonSubstringResult.ToString">
<summary>
Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</summary>
<returns>
A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
</returns>
<filterpriority>2</filterpriority>
</member>
<member name="P:DiffLib.LongestCommonSubstringResult.PositionInCollection1">
<summary>
The position in the first collection, 0-based.
</summary>
</member>
<member name="P:DiffLib.LongestCommonSubstringResult.PositionInCollection2">
<summary>
The position in the second collection, 0-based.
</summary>
</member>
<member name="P:DiffLib.LongestCommonSubstringResult.Length">
<summary>
The length of the common substring.
</summary>
</member>
<member name="T:DiffLib.AlignedDiff`1">
<summary>
This class implements a slightly more advanced diff algorithm than <see cref="T:DiffLib.Diff`1"/> by
taking the output from <see cref="T:DiffLib.Diff`1"/> and attempting to align individual elements inside
replace-blocks. This is mostly suitable for text file diffs.
</summary>
<typeparam name="T">
The types of elements in the collections being compared.
</typeparam>
</member>
<member name="M:DiffLib.AlignedDiff`1.#ctor(System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEnumerable{`0},System.Collections.Generic.IEqualityComparer{`0},DiffLib.ISimilarityComparer{`0},DiffLib.IAlignmentFilter{`0})">
<summary>
Initializes a new instance of <see cref="T:DiffLib.AlignedDiff`1"/>.
</summary>
<param name="collection1">
The first collection of items.
</param>
<param name="collection2">
The second collection of items.
</param>
<param name="equalityComparer">
The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> that will be used to compare elements from
<paramref name="collection1"/> with elements from <paramref name="collection2"/>.
</param>
<param name="similarityComparer">
The <see cref="T:DiffLib.ISimilarityComparer`1"/> that will be used to attempt to align elements
inside blocks that consists of elements from the first collection being replaced
with elements from the second collection.
</param>
<param name="alignmentFilter">
The <see cref="T:DiffLib.ISimilarityComparer`1"/> that will be used to determine if
two aligned elements are similar enough to be report them as a change from
one to another, or to report them as one being deleted and the other added in
its place.
</param>
<exception cref="T:System.ArgumentNullException">
<para><paramref name="collection1"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="collection2"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="equalityComparer"/> is <c>null</c>.</para>
<para>- or -</para>
<para><paramref name="alignmentFilter"/> is <c>null</c>.</para>
</exception>
</member>
<member name="M:DiffLib.AlignedDiff`1.GetEnumerator">
<summary>
Returns an enumerator that iterates through the collection.
</summary>
<returns>
A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
</returns>
<filterpriority>1</filterpriority>
</member>
<member name="M:DiffLib.AlignedDiff`1.Generate">
<summary>
Generates the diff, one line of output at a time.
</summary>
<returns>
A collection of <see cref="T:DiffLib.AlignedDiffChange`1"/> objects, one for
each line in the first or second collection (sometimes one instance for a line
from both, when lines are equal or similar.)
</returns>
</member>
<member name="T:DiffLib.StringSimilarityComparer">
<summary>
This class implements <see cref="T:DiffLib.ISimilarityComparer`1"/> for strings, doing a very basic "diff" between the two,
and calculating how much of the text occurs in both.
</summary>
</member>
<member name="M:DiffLib.StringSimilarityComparer.Compare(System.String,System.String)">
<summary>
Does a similarity comparison between the two values and returns their
similarity, a value ranging from 0.0 to 1.0, where 0.0 means they're
completely different and 1.0 means they have the same value.
</summary>
<param name="value1">
The first value to compare.
</param>
<param name="value2">
The second value to compare.
</param>
<returns>
A value ranging from 0.0 to 1.0, where 0.0 means they're
completely different and 1.0 means they have the same value.
</returns>
</member>
<member name="T:DiffLib.StringAlignmentFilter">
<summary>
This class implements <see cref="T:DiffLib.ISimilarityComparer`1"/> for strings, doing a very basic "diff" between the two,
and calculating how much of the text occurs in both.
</summary>
</member>
<member name="M:DiffLib.StringAlignmentFilter.#ctor">
<summary>
Initializes a new instance of the <see cref="T:DiffLib.StringAlignmentFilter"/> class.
</summary>
</member>
<member name="M:DiffLib.StringAlignmentFilter.#ctor(DiffLib.StringSimilarityFilterPredicate)">
<summary>
Initializes a new instance of the <see cref="T:DiffLib.StringAlignmentFilter"/> class.
</summary>
<param name="diffPredicate">
The diff predicate used to determine if the strings are
similar enough (see <see cref="T:DiffLib.StringSimilarityFilterPredicate"/> for details.
</param>
<exception cref="T:System.ArgumentNullException"><paramref name="diffPredicate"/> is <c>null</c>.</exception>
</member>
<member name="M:DiffLib.StringAlignmentFilter.CanAlign(System.String,System.String)">
<summary>
Determines if the two values are similar enough to align them
as a change, instead of not aligning them but reporting them
as a delete plus an add instead.
</summary>
<param name="value1">
The first value to compare against <paramref name="value2"/>.
</param>
<param name="value2">
The second value to compare against <paramref name="value1"/>.
</param>
<returns>
<c>true</c> if the two values are similar enough to report
them as a change; false if the two values aren't similar enough
but needs to be reported as a delete plus an add.
</returns>
</member>
<member name="T:DiffLib.StringSimilarityFilterPredicate">
<summary>
This delegate is used by <see cref="T:DiffLib.StringAlignmentFilter"/> to
determine if the two strings are similar enough to report them
as a change, instead of as a delete plus and add.
</summary>
<param name="value1">
The first string to compare.
</param>
<param name="value2">
The second string to compare.
</param>
<param name="diff">
The diff between <paramref name="value1"/> and <paramref name="value2"/>.
</param>
<returns>
<c>true</c> if the strings are similar enough (reported as a change);
otherwise, <c>false</c> (reported as a delete plus an add.)
</returns>
</member>
</members>
</doc>

BIN
packages/DiffLib.1.0.0.55/lib/net35-Client/DiffLib.dll vendored

Binary file not shown.

4
packages/repositories.config

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\ICSharpCode.Decompiler\Tests\packages.config" />
</repositories>
Loading…
Cancel
Save