Browse Source

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

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
ef639dd9bc
  1. 32
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 16
      ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
  3. 2
      ICSharpCode.Decompiler/ILAst/ILInlining.cs
  4. 2
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
  5. 88
      ILSpy/AnalyzerTreeView.cs
  6. 4
      ILSpy/BamlDecompiler.cs
  7. 4
      ILSpy/ContextMenuEntry.cs
  8. 117
      ILSpy/Controls/DockedPane.cs
  9. 136
      ILSpy/Controls/SearchBox.cs
  10. 29
      ILSpy/ILSpy.csproj
  11. 6
      ILSpy/Images/Images.cs
  12. 4
      ILSpy/LoadedAssembly.cs
  13. 50
      ILSpy/MainWindow.xaml
  14. 80
      ILSpy/MainWindow.xaml.cs
  15. 288
      ILSpy/SearchPane.cs
  16. 29
      ILSpy/SearchPane.xaml
  17. 11
      ILSpy/SessionSettings.cs
  18. 23
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  19. 9
      ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs
  20. 18
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  21. 39
      ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs
  22. 26
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs
  23. 34
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs
  24. 105
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs
  25. 101
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs
  26. 105
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs
  27. 29
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  28. 41
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs
  29. 21
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  30. 33
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  31. 32
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs
  32. 16
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  33. 45
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  34. 184
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  35. 107
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs
  36. 118
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  37. 72
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs
  38. 18
      ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs
  39. 2
      ILSpy/TreeNodes/Analyzer/Helpers.cs
  40. 23
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs
  41. 78
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  42. 3
      ILSpy/TreeNodes/EventTreeNode.cs
  43. 4
      ILSpy/TreeNodes/FieldTreeNode.cs
  44. 46
      ILSpy/TreeNodes/ResourceEntryNode.cs
  45. 2
      ILSpy/TreeNodes/XamlResourceNode.cs
  46. 90
      ILSpy/themes/generic.xaml
  47. 12
      Mono.Cecil/Mono.Cecil/MethodDefinition.cs
  48. 1
      README.txt

32
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -917,21 +917,29 @@ namespace ICSharpCode.Decompiler.Ast @@ -917,21 +917,29 @@ namespace ICSharpCode.Decompiler.Ast
astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef);
astField.Modifiers = ConvertModifiers(fieldDef);
if (fieldDef.HasConstant) {
if (fieldDef.Constant == null) {
initializer.Initializer = new NullReferenceExpression();
} else {
TypeCode c = Type.GetTypeCode(fieldDef.Constant.GetType());
if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !fieldDef.DeclaringType.IsEnum) {
initializer.Initializer = MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, fieldDef.Constant, false), fieldDef.FieldType);
} else {
initializer.Initializer = new PrimitiveExpression(fieldDef.Constant);
}
}
initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum);
}
ConvertAttributes(astField, fieldDef);
return astField;
}
static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false)
{
if (constant == null) {
if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1"))
return new DefaultValueExpression(ConvertType(type));
else
return new NullReferenceExpression();
} else {
TypeCode c = Type.GetTypeCode(constant.GetType());
if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) {
return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type);
} else {
return new PrimitiveExpression(constant);
}
}
}
public static IEnumerable<ParameterDeclaration> MakeParameters(MethodDefinition method, bool isLambda = false)
{
var parameters = MakeParameters(method.Parameters, isLambda);
@ -957,12 +965,16 @@ namespace ICSharpCode.Decompiler.Ast @@ -957,12 +965,16 @@ namespace ICSharpCode.Decompiler.Ast
if (ct != null && ct.PointerRank > 0)
ct.PointerRank--;
}
if (paramDef.HasCustomAttributes) {
foreach (CustomAttribute ca in paramDef.CustomAttributes) {
if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System")
astParam.ParameterModifier = ParameterModifier.Params;
}
}
if (paramDef.IsOptional) {
astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType);
}
ConvertCustomAttributes(astParam, paramDef);
ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module;

16
ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs

@ -182,6 +182,22 @@ namespace ICSharpCode.Decompiler.Ast @@ -182,6 +182,22 @@ namespace ICSharpCode.Decompiler.Ast
return true;
}
public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType)
{
var candidateContext = CreateGenericContext(candidate.DeclaringType);
var gCandidate = candidateContext.ApplyTo(candidate);
if (interfaceContextType is GenericInstanceType) {
var methodContext = new GenericContext<TypeDefinition>(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments);
var gMethod = methodContext.ApplyTo(method);
return MatchMethod(gCandidate, gMethod);
} else {
var methodContext = CreateGenericContext(interfaceContextType.Resolve());
var gMethod = candidateContext.ApplyTo(method);
return MatchMethod(gCandidate, gMethod);
}
}
private static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
{
var mCandidate = candidate.Item;

2
ICSharpCode.Decompiler/ILAst/ILInlining.cs

@ -162,7 +162,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -162,7 +162,7 @@ namespace ICSharpCode.Decompiler.ILAst
return true;
} else if (numLdloc.GetOrDefault(v) == 0 && numLdloca.GetOrDefault(v) == 0) {
// The variable is never loaded
if (inlinedExpression.HasNoSideEffects() && v.IsGenerated) {
if (inlinedExpression.HasNoSideEffects()) {
// Remove completely
body.RemoveAt(pos);
return true;

2
ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -179,7 +179,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -179,7 +179,7 @@ namespace ICSharpCode.Decompiler.ILAst
public static bool IsCompilerGeneratorEnumerator(TypeDefinition type)
{
if (!(type.Name.StartsWith("<", StringComparison.Ordinal) && type.IsCompilerGenerated()))
if (!(type.DeclaringType != null && type.IsCompilerGenerated()))
return false;
foreach (TypeReference i in type.Interfaces) {
if (i.Namespace == "System.Collections" && i.Name == "IEnumerator")

88
ILSpy/AnalyzerTreeView.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Analyzer tree view.
/// </summary>
public partial class AnalyzerTreeView : SharpTreeView, IPane
{
static AnalyzerTreeView instance;
public static AnalyzerTreeView Instance {
get {
if (instance == null) {
App.Current.VerifyAccess();
instance = new AnalyzerTreeView();
}
return instance;
}
}
private AnalyzerTreeView()
{
this.ShowRoot = false;
this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage };
ContextMenuProvider.Add(this);
}
public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInBottomPane("Analyzer", this);
}
public void Show(AnalyzerTreeNode node)
{
Show();
node.IsExpanded = true;
this.Root.Children.Add(node);
this.SelectedItem = node;
this.FocusNode(node);
}
void IPane.Closed()
{
this.Root.Children.Clear();
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)]
sealed class ShowAnalyzerCommand : SimpleCommand
{
public override void Execute(object parameter)
{
AnalyzerTreeView.Instance.Show();
}
}
}

4
ILSpy/BamlDecompiler.cs

@ -415,8 +415,8 @@ namespace ICSharpCode.ILSpy.Baml @@ -415,8 +415,8 @@ namespace ICSharpCode.ILSpy.Baml
BamlDecompiler decompiler = CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, asm.FileName);
MemoryStream bamlStream = new MemoryStream();
data.Position = 0;
data.CopyTo(bamlStream);
Data.Position = 0;
Data.CopyTo(bamlStream);
output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName, new ConnectMethodDecompiler(asm), new AssemblyResolver(asm)));
return true;

4
ILSpy/ContextMenuEntry.cs

@ -84,8 +84,10 @@ namespace ICSharpCode.ILSpy @@ -84,8 +84,10 @@ namespace ICSharpCode.ILSpy
void treeView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
SharpTreeNode[] selectedNodes = treeView.GetTopLevelSelection().ToArray();
if (selectedNodes.Length == 0)
if (selectedNodes.Length == 0) {
e.Handled = true; // don't show the menu
return;
}
ContextMenu menu = new ContextMenu();
foreach (var category in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
if (menu.Items.Count > 0) {

117
ILSpy/Controls/DockedPane.cs

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.Controls
{
class DockedPane : Control
{
static DockedPane()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DockedPane), new FrameworkPropertyMetadata(typeof(DockedPane)));
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(DockedPane));
public string Title {
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(object), typeof(DockedPane));
public object Content {
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Button closeButton = (Button)this.Template.FindName("PART_Close", this);
if (closeButton != null) {
closeButton.Click += closeButton_Click;
}
}
void closeButton_Click(object sender, RoutedEventArgs e)
{
if (CloseButtonClicked != null)
CloseButtonClicked(this, e);
}
public event EventHandler CloseButtonClicked;
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.F4 && e.KeyboardDevice.Modifiers == ModifierKeys.Control || e.Key == Key.Escape) {
if (CloseButtonClicked != null)
CloseButtonClicked(this, e);
e.Handled = true;
}
}
}
[MarkupExtensionReturnType(typeof(Color))]
class ControlColor : MarkupExtension
{
float val;
/// <summary>
/// Amount of highlight (0..1)
/// </summary>
public float Highlight { get; set; }
/// <summary>
/// val: Color value in the range 105..255.
/// </summary>
public ControlColor(float val)
{
if (!(val >= 105 && val <= 255))
throw new ArgumentOutOfRangeException("val");
this.val = val;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (val > 227) {
return Interpolate(227, SystemColors.ControlLightColor, 255, SystemColors.ControlLightLightColor);
} else if (val > 160) {
return Interpolate(160, SystemColors.ControlDarkColor, 227, SystemColors.ControlLightColor);
} else {
return Interpolate(105, SystemColors.ControlDarkDarkColor, 160, SystemColors.ControlDarkColor);
}
}
Color Interpolate(float v1, Color c1, float v2, Color c2)
{
float v = (val - v1) / (v2 - v1);
Color c = c1 * (1 - v) + c2 * v;
return c * (1 - Highlight) + SystemColors.HighlightColor * Highlight;
}
}
}

136
ILSpy/Controls/SearchBox.cs

@ -28,10 +28,10 @@ namespace ICSharpCode.ILSpy.Controls @@ -28,10 +28,10 @@ namespace ICSharpCode.ILSpy.Controls
public class SearchBox : TextBox
{
static SearchBox() {
DefaultStyleKeyProperty.OverrideMetadata(
typeof(SearchBox),
new FrameworkPropertyMetadata(typeof(SearchBox)));
}
DefaultStyleKeyProperty.OverrideMetadata(
typeof(SearchBox),
new FrameworkPropertyMetadata(typeof(SearchBox)));
}
#region Dependency properties
@ -46,20 +46,20 @@ namespace ICSharpCode.ILSpy.Controls @@ -46,20 +46,20 @@ namespace ICSharpCode.ILSpy.Controls
new FrameworkPropertyMetadata(TimeSpan.FromMilliseconds(200)));
#endregion
#region Public Properties
public string WatermarkText {
get { return (string)GetValue(WatermarkTextProperty); }
set { SetValue(WatermarkTextProperty, value); }
}
#region Public Properties
public string WatermarkText {
get { return (string)GetValue(WatermarkTextProperty); }
set { SetValue(WatermarkTextProperty, value); }
}
public Brush WatermarkColor {
get { return (Brush)GetValue(WatermarkColorProperty); }
set { SetValue(WatermarkColorProperty, value); }
}
public bool HasText {
public Brush WatermarkColor {
get { return (Brush)GetValue(WatermarkColorProperty); }
set { SetValue(WatermarkColorProperty, value); }
}
public bool HasText {
get { return (bool)GetValue(HasTextProperty); }
private set { SetValue(HasTextProperty, value); }
}
@ -68,83 +68,85 @@ namespace ICSharpCode.ILSpy.Controls @@ -68,83 +68,85 @@ namespace ICSharpCode.ILSpy.Controls
get { return (TimeSpan)GetValue(UpdateDelayProperty); }
set { SetValue(UpdateDelayProperty, value); }
}
#endregion
#region Handlers
#endregion
#region Handlers
private void IconBorder_MouseLeftButtonUp(object obj, MouseButtonEventArgs e) {
if (this.HasText)
this.Text = string.Empty;
}
private void IconBorder_MouseLeftButtonUp(object obj, MouseButtonEventArgs e) {
if (this.HasText)
this.Text = string.Empty;
}
#endregion
#region Overrides
DispatcherTimer timer;
protected override void OnTextChanged(TextChangedEventArgs e) {
base.OnTextChanged(e);
HasText = this.Text.Length > 0;
if (timer == null) {
timer = new DispatcherTimer();
timer.Tick += timer_Tick;
}
timer.Stop();
timer.Interval = this.UpdateDelay;
timer.Start();
}
#endregion
#region Overrides
DispatcherTimer timer;
protected override void OnTextChanged(TextChangedEventArgs e) {
base.OnTextChanged(e);
HasText = this.Text.Length > 0;
if (timer == null) {
timer = new DispatcherTimer();
timer.Tick += timer_Tick;
}
timer.Stop();
timer.Interval = this.UpdateDelay;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
timer = null;
var textBinding = GetBindingExpression(TextProperty);
if (textBinding != null) {
textBinding.UpdateSource();
}
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
timer = null;
var textBinding = GetBindingExpression(TextProperty);
if (textBinding != null) {
textBinding.UpdateSource();
}
}
protected override void OnLostFocus(RoutedEventArgs e)
{
if (!HasText) {
Label wl = (Label)GetTemplateChild("WatermarkLabel");
wl.Visibility = Visibility.Visible;
if (wl != null)
wl.Visibility = Visibility.Visible;
}
base.OnLostFocus(e);
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (!HasText) {
Label wl = (Label)GetTemplateChild("WatermarkLabel");
wl.Visibility = Visibility.Hidden;
if (wl != null)
wl.Visibility = Visibility.Hidden;
}
base.OnGotFocus(e);
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
public override void OnApplyTemplate() {
base.OnApplyTemplate();
Border iconBorder = GetTemplateChild("PART_IconBorder") as Border;
if (iconBorder != null) {
iconBorder.MouseLeftButtonUp += IconBorder_MouseLeftButtonUp;
}
}
Border iconBorder = GetTemplateChild("PART_IconBorder") as Border;
if (iconBorder != null) {
iconBorder.MouseLeftButtonUp += IconBorder_MouseLeftButtonUp;
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.Escape) {
if (e.Key == Key.Escape && this.Text.Length > 0) {
this.Text = string.Empty;
e.Handled = true;
} else {
base.OnKeyDown(e);
}
}
#endregion
#endregion
}
}

29
ILSpy/ILSpy.csproj

@ -85,6 +85,9 @@ @@ -85,6 +85,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AboutPage.cs" />
<Compile Include="AnalyzerTreeView.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="App.xaml.cs">
<SubType>Code</SubType>
<DependentUpon>App.xaml</DependentUpon>
@ -95,6 +98,11 @@ @@ -95,6 +98,11 @@
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands.cs" />
<Compile Include="ConnectMethodDecompiler.cs" />
<Compile Include="Controls\DockedPane.cs" />
<Compile Include="DecompilerSettingsPanel.xaml.cs">
<DependentUpon>DecompilerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="ExportCommandAttribute.cs" />
<Compile Include="Commands\DebuggerCommands.cs" />
<Compile Include="Controls\SearchBox.cs" />
@ -137,10 +145,20 @@ @@ -137,10 +145,20 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SearchPane.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventAccessorsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfacePropertyImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfaceMethodImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedInterfaceEventImplementedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeExposedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeExtensionMethodsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeInstantiationsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" />
<Compile Include="TreeNodes\IMemberTreeNode.cs" />
@ -184,13 +202,13 @@ @@ -184,13 +202,13 @@
<Compile Include="TextView\ReferenceElementGenerator.cs" />
<Compile Include="TextView\AvalonEditTextOutput.cs" />
<Compile Include="TextView\UIElementGenerator.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldAccessNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldAccessTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsesNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerMethodOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodOverridesTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyListTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyReferenceTreeNode.cs" />
<Compile Include="TreeNodes\AssemblyTreeNode.cs" />
@ -220,6 +238,9 @@ @@ -220,6 +238,9 @@
<Page Include="Options\DebuggerSettingsPanel.xaml" />
<Page Include="Options\DecompilerSettingsPanel.xaml" />
<Page Include="Options\OptionsDialog.xaml" />
<Page Include="SearchPane.xaml">
<DependentUpon>SearchPane.cs</DependentUpon>
</Page>
<Page Include="TextView\DecompilerTextView.xaml">
<DependentUpon>DecompilerTextView.cs</DependentUpon>
</Page>

6
ILSpy/Images/Images.cs

@ -112,12 +112,14 @@ namespace ICSharpCode.ILSpy @@ -112,12 +112,14 @@ namespace ICSharpCode.ILSpy
public static ImageSource GetIcon(TypeIcon icon, AccessOverlayIcon overlay)
{
return typeIconCache.GetIcon(icon, overlay, false);
lock (typeIconCache)
return typeIconCache.GetIcon(icon, overlay, false);
}
public static ImageSource GetIcon(MemberIcon icon, AccessOverlayIcon overlay, bool isStatic)
{
return memberIconCache.GetIcon(icon, overlay, isStatic);
lock (memberIconCache)
return memberIconCache.GetIcon(icon, overlay, isStatic);
}
#region icon caches & overlay management

4
ILSpy/LoadedAssembly.cs

@ -49,6 +49,10 @@ namespace ICSharpCode.ILSpy @@ -49,6 +49,10 @@ namespace ICSharpCode.ILSpy
this.shortName = Path.GetFileNameWithoutExtension(fileName);
}
/// <summary>
/// Gets the Cecil AssemblyDefinition.
/// Can be null when there was a load error.
/// </summary>
public AssemblyDefinition AssemblyDefinition {
get {
try {

50
ILSpy/MainWindow.xaml

@ -44,7 +44,6 @@ @@ -44,7 +44,6 @@
<Image Width="16" Height="16" Source="Images/PrivateInternal.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Show _analyzer" Name="showAnalyzer" IsCheckable="True" Checked="ShowAnalyzer_Checked" Unchecked="ShowAnalyzer_Unchecked" />
</MenuItem>
</Menu>
<!-- ToolBar -->
@ -103,19 +102,13 @@ @@ -103,19 +102,13 @@
<RowDefinition
Height="*" />
</Grid.RowDefinitions>
<!-- Left pane: Search bar + Tree View -->
<DockPanel>
<!-- Search bar -->
<controls:SearchBox DockPanel.Dock="Top" WatermarkText="Search" WatermarkColor="Gray" ToolTip="Search"
Text="{Binding FilterSettings.SearchTerm}" />
<!-- Tree View of assemblies and classes -->
<tv:SharpTreeView
Name="treeView"
SelectionChanged="TreeView_SelectionChanged"
ShowRoot="False"
AllowDropOrder="True"
AllowDrop="True" />
</DockPanel>
<!-- Left pane: Tree View of assemblies and classes -->
<tv:SharpTreeView
Name="treeView"
SelectionChanged="TreeView_SelectionChanged"
ShowRoot="False"
AllowDropOrder="True"
AllowDrop="True" />
<GridSplitter
Grid.ZIndex="1"
Grid.Column="1"
@ -125,16 +118,18 @@ @@ -125,16 +118,18 @@
VerticalAlignment="Stretch"
BorderBrush="Transparent" />
<!-- Right pane: Text Editor -->
<Grid Grid.Column="2" Name="rightPane">
<Grid Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="0" Name="topPaneRow" />
<RowDefinition Height="1" />
<RowDefinition Height="0.7*" MinHeight="100" Name="textViewRow" />
<RowDefinition Height="1" />
<RowDefinition Height="0" Name="analyzerRow" />
<RowDefinition Height="0" Name="bottomPaneRow" />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Name="updateAvailablePanel" Visibility="Collapsed">
<DockPanel>
@ -146,7 +141,7 @@ @@ -146,7 +141,7 @@
</DockPanel>
</Border>
<!-- decompilerTextView is inserted into row 1 by code -->
<controls:DockedPane x:Name="topPane" Grid.Row="1" Title="Top" Visibility="Collapsed" CloseButtonClicked="TopPane_CloseButtonClicked" />
<GridSplitter
Grid.ZIndex="1"
@ -156,13 +151,22 @@ @@ -156,13 +151,22 @@
BorderBrush="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Visibility="{Binding IsChecked, ElementName=showAnalyzer, Converter={StaticResource BooleanToVisibilityConverter}}" />
Visibility="{Binding Visibility, ElementName=topPane}" />
<!-- decompilerTextView is into the mainPane by code -->
<ContentPresenter Name="mainPane" Grid.Row="3"/>
<GridSplitter
Grid.ZIndex="1"
Grid.Row="4"
Margin="0,-2,0,-5"
BorderThickness="0,2,0,5"
BorderBrush="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Visibility="{Binding Visibility, ElementName=bottomPane}" />
<DockPanel Grid.Row="3"
Visibility="{Binding IsChecked, ElementName=showAnalyzer, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label DockPanel.Dock="Top">Analyzer</Label>
<tv:SharpTreeView Name="analyzerTree" ShowRoot="False" />
</DockPanel>
<controls:DockedPane x:Name="bottomPane" Grid.Row="5" Title="Bottom" Visibility="Collapsed" CloseButtonClicked="BottomPane_CloseButtonClicked" />
</Grid>
</Grid>
</DockPanel>

80
ILSpy/MainWindow.xaml.cs

@ -86,8 +86,7 @@ namespace ICSharpCode.ILSpy @@ -86,8 +86,7 @@ namespace ICSharpCode.ILSpy
InitializeComponent();
App.CompositionContainer.ComposeParts(this);
Grid.SetRow(decompilerTextView, 1);
rightPane.Children.Add(decompilerTextView);
mainPane.Content = decompilerTextView;
if (sessionSettings.SplitterPosition > 0 && sessionSettings.SplitterPosition < 1) {
leftColumn.Width = new GridLength(sessionSettings.SplitterPosition, GridUnitType.Star);
@ -98,7 +97,6 @@ namespace ICSharpCode.ILSpy @@ -98,7 +97,6 @@ namespace ICSharpCode.ILSpy
InitMainMenu();
InitToolbar();
ContextMenuProvider.Add(treeView);
ContextMenuProvider.Add(analyzerTree);
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
@ -616,22 +614,6 @@ namespace ICSharpCode.ILSpy @@ -616,22 +614,6 @@ namespace ICSharpCode.ILSpy
#endregion
#region Analyzer
public void AddToAnalyzer(AnalyzerTreeNode node)
{
if (analyzerTree.Root == null)
analyzerTree.Root = new AnalyzerTreeNode { Language = sessionSettings.FilterSettings.Language };
if (!showAnalyzer.IsChecked)
showAnalyzer.IsChecked = true;
node.IsExpanded = true;
analyzerTree.Root.Children.Add(node);
analyzerTree.SelectedItem = node;
analyzerTree.FocusNode(node);
}
#endregion
protected override void OnStateChanged(EventArgs e)
{
base.OnStateChanged(e);
@ -647,26 +629,64 @@ namespace ICSharpCode.ILSpy @@ -647,26 +629,64 @@ namespace ICSharpCode.ILSpy
sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.SplitterPosition = leftColumn.Width.Value / (leftColumn.Width.Value + rightColumn.Width.Value);
if (showAnalyzer.IsChecked)
sessionSettings.AnalyzerSplitterPosition = analyzerRow.Height.Value / (analyzerRow.Height.Value + textViewRow.Height.Value);
if (topPane.Visibility == Visibility.Visible)
sessionSettings.BottomPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value);
if (bottomPane.Visibility == Visibility.Visible)
sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value);
sessionSettings.Save();
}
void ShowAnalyzer_Checked(object sender, RoutedEventArgs e)
#region Top/Bottom Pane management
public void ShowInTopPane(string title, object content)
{
topPaneRow.MinHeight = 100;
if (sessionSettings.TopPaneSplitterPosition > 0 && sessionSettings.TopPaneSplitterPosition < 1) {
textViewRow.Height = new GridLength(1 - sessionSettings.TopPaneSplitterPosition, GridUnitType.Star);
topPaneRow.Height = new GridLength(sessionSettings.TopPaneSplitterPosition, GridUnitType.Star);
}
topPane.Title = title;
topPane.Content = content;
topPane.Visibility = Visibility.Visible;
}
void TopPane_CloseButtonClicked(object sender, EventArgs e)
{
sessionSettings.TopPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value);
topPaneRow.MinHeight = 0;
topPaneRow.Height = new GridLength(0);
topPane.Visibility = Visibility.Collapsed;
IPane pane = topPane.Content as IPane;
topPane.Content = null;
if (pane != null)
pane.Closed();
}
public void ShowInBottomPane(string title, object content)
{
analyzerRow.MinHeight = 100;
if (sessionSettings.AnalyzerSplitterPosition > 0 && sessionSettings.AnalyzerSplitterPosition < 1) {
textViewRow.Height = new GridLength(1 - sessionSettings.AnalyzerSplitterPosition, GridUnitType.Star);
analyzerRow.Height = new GridLength(sessionSettings.AnalyzerSplitterPosition, GridUnitType.Star);
bottomPaneRow.MinHeight = 100;
if (sessionSettings.BottomPaneSplitterPosition > 0 && sessionSettings.BottomPaneSplitterPosition < 1) {
textViewRow.Height = new GridLength(1 - sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star);
bottomPaneRow.Height = new GridLength(sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star);
}
bottomPane.Title = title;
bottomPane.Content = content;
bottomPane.Visibility = Visibility.Visible;
}
void ShowAnalyzer_Unchecked(object sender, RoutedEventArgs e)
void BottomPane_CloseButtonClicked(object sender, EventArgs e)
{
sessionSettings.AnalyzerSplitterPosition = analyzerRow.Height.Value / (analyzerRow.Height.Value + textViewRow.Height.Value);
analyzerRow.MinHeight = 0;
analyzerRow.Height = new GridLength(0);
sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value);
bottomPaneRow.MinHeight = 0;
bottomPaneRow.Height = new GridLength(0);
bottomPane.Visibility = Visibility.Collapsed;
IPane pane = bottomPane.Content as IPane;
bottomPane.Content = null;
if (pane != null)
pane.Closed();
}
#endregion
public void UnselectAll()
{

288
ILSpy/SearchPane.cs

@ -0,0 +1,288 @@ @@ -0,0 +1,288 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Notifies panes when they are closed.
/// </summary>
public interface IPane
{
void Closed();
}
/// <summary>
/// Search pane
/// </summary>
public partial class SearchPane : UserControl, IPane
{
static SearchPane instance;
RunningSearch currentSearch;
public static SearchPane Instance {
get {
if (instance == null) {
App.Current.VerifyAccess();
instance = new SearchPane();
}
return instance;
}
}
private SearchPane()
{
InitializeComponent();
}
public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInTopPane("Search", this);
Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Func<bool>(searchBox.Focus));
}
public static readonly DependencyProperty SearchTermProperty =
DependencyProperty.Register("SearchTerm", typeof(string), typeof(SearchPane),
new FrameworkPropertyMetadata(string.Empty, OnSearchTermChanged));
public string SearchTerm {
get { return (string)GetValue(SearchTermProperty); }
set { SetValue(SearchTermProperty, value); }
}
static void OnSearchTermChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
((SearchPane)o).StartSearch((string)e.NewValue);
}
void StartSearch(string searchTerm)
{
if (currentSearch != null) {
currentSearch.Cancel();
}
if (string.IsNullOrEmpty(searchTerm)) {
currentSearch = null;
listBox.ItemsSource = null;
} else {
MainWindow mainWindow = MainWindow.Instance;
currentSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm, mainWindow.CurrentLanguage);
listBox.ItemsSource = currentSearch.Results;
new Thread(currentSearch.Run).Start();
}
}
void IPane.Closed()
{
this.SearchTerm = string.Empty;
}
void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
JumpToSelectedItem();
e.Handled = true;
}
void ListBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space || e.Key == Key.Return) {
e.Handled = true;
JumpToSelectedItem();
}
}
void JumpToSelectedItem()
{
SearchResult result = listBox.SelectedItem as SearchResult;
if (result != null) {
MainWindow.Instance.JumpToReference(result.Member);
}
}
}
sealed class RunningSearch
{
readonly Dispatcher dispatcher;
readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly LoadedAssembly[] assemblies;
readonly string searchTerm;
readonly Language language;
public readonly ObservableCollection<SearchResult> Results = new ObservableCollection<SearchResult>();
int resultCount;
public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, Language language)
{
this.dispatcher = Dispatcher.CurrentDispatcher;
this.assemblies = assemblies;
this.searchTerm = searchTerm;
this.language = language;
}
public void Cancel()
{
cts.Cancel();
}
public void Run()
{
try {
foreach (var loadedAssembly in assemblies) {
AssemblyDefinition asm = loadedAssembly.AssemblyDefinition;
if (asm == null)
continue;
CancellationToken cancellationToken = cts.Token;
foreach (TypeDefinition type in asm.MainModule.Types) {
cancellationToken.ThrowIfCancellationRequested();
PerformSearch(type);
}
}
} catch (OperationCanceledException) {
// ignore cancellation
}
}
void AddResult(SearchResult result)
{
if (++resultCount == 1000) {
result = new SearchResult { Name = "Search aborted, more than 1000 results found." };
cts.Cancel();
}
dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(delegate { this.Results.Add(result); }));
cts.Token.ThrowIfCancellationRequested();
}
bool IsMatch(string text)
{
if (text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0)
return true;
else
return false;
}
void PerformSearch(TypeDefinition type)
{
if (IsMatch(type.Name)) {
AddResult(new SearchResult {
Member = type,
Image = TypeTreeNode.GetIcon(type),
Name = language.TypeToString(type, includeNamespace: false),
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace,
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace
});
}
foreach (TypeDefinition nestedType in type.NestedTypes) {
PerformSearch(nestedType);
}
foreach (FieldDefinition field in type.Fields) {
if (IsMatch(field.Name)) {
AddResult(new SearchResult {
Member = field,
Image = FieldTreeNode.GetIcon(field),
Name = field.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
foreach (PropertyDefinition property in type.Properties) {
if (IsMatch(property.Name)) {
AddResult(new SearchResult {
Member = property,
Image = PropertyTreeNode.GetIcon(property),
Name = property.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
foreach (EventDefinition ev in type.Events) {
if (IsMatch(ev.Name)) {
AddResult(new SearchResult {
Member = ev,
Image = EventTreeNode.GetIcon(ev),
Name = ev.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
foreach (MethodDefinition method in type.Methods) {
if (IsMatch(method.Name)) {
AddResult(new SearchResult {
Member = method,
Image = MethodTreeNode.GetIcon(method),
Name = method.Name,
LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true)
});
}
}
}
}
class SearchResult : INotifyPropertyChanged
{
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
public MemberReference Member { get; set; }
public string Location { get; set; }
public string Name { get; set; }
public ImageSource Image { get; set; }
public ImageSource LocationImage { get; set; }
public override string ToString()
{
return Name;
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon="Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)]
sealed class ShowSearchCommand : SimpleCommand
{
public override void Execute(object parameter)
{
SearchPane.Instance.Show();
}
}
}

29
ILSpy/SearchPane.xaml

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
<UserControl x:Class="ICSharpCode.ILSpy.SearchPane"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
x:Name="self">
<DockPanel>
<controls:SearchBox DockPanel.Dock="Top" WatermarkText="Search" WatermarkColor="Gray" ToolTip="Search"
Text="{Binding SearchTerm, ElementName=self}" x:Name="searchBox" />
<ListBox Name="listBox" HorizontalContentAlignment="Stretch" SelectionMode="Single" MouseDoubleClick="ListBox_MouseDoubleClick" KeyDown="ListBox_KeyDown">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Width="16" Height="16" Source="{Binding Image}" HorizontalAlignment="Left" />
<TextBlock Text="{Binding Name}" Grid.Column="1" />
<StackPanel Orientation="Horizontal" Grid.Column="2" HorizontalAlignment="Right">
<Image Width="16" Height="16" Source="{Binding LocationImage}" Margin="4,0,4,0" />
<TextBlock Text="{Binding Location}" TextTrimming="CharacterEllipsis" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</UserControl>

11
ILSpy/SessionSettings.cs

@ -49,7 +49,8 @@ namespace ICSharpCode.ILSpy @@ -49,7 +49,8 @@ namespace ICSharpCode.ILSpy
this.WindowState = FromString((string)doc.Element("WindowState"), WindowState.Normal);
this.WindowBounds = FromString((string)doc.Element("WindowBounds"), new Rect(10, 10, 750, 550));
this.SplitterPosition = FromString((string)doc.Element("SplitterPosition"), 0.4);
this.AnalyzerSplitterPosition = FromString((string)doc.Element("AnalyzerSplitterPosition"), 0.3);
this.TopPaneSplitterPosition = FromString((string)doc.Element("TopPaneSplitterPosition"), 0.3);
this.BottomPaneSplitterPosition = FromString((string)doc.Element("BottomPaneSplitterPosition"), 0.3);
}
public event PropertyChangedEventHandler PropertyChanged;
@ -68,8 +69,11 @@ namespace ICSharpCode.ILSpy @@ -68,8 +69,11 @@ namespace ICSharpCode.ILSpy
public WindowState WindowState = WindowState.Normal;
public Rect WindowBounds;
/// <summary>
/// position of the left/right splitter
/// </summary>
public double SplitterPosition;
public double AnalyzerSplitterPosition;
public double TopPaneSplitterPosition, BottomPaneSplitterPosition;
public void Save()
{
@ -84,7 +88,8 @@ namespace ICSharpCode.ILSpy @@ -84,7 +88,8 @@ namespace ICSharpCode.ILSpy
doc.Add(new XElement("WindowState", ToString(this.WindowState)));
doc.Add(new XElement("WindowBounds", ToString(this.WindowBounds)));
doc.Add(new XElement("SplitterPosition", ToString(this.SplitterPosition)));
doc.Add(new XElement("AnalyzerSplitterPosition", ToString(this.AnalyzerSplitterPosition)));
doc.Add(new XElement("TopPaneSplitterPosition", ToString(this.TopPaneSplitterPosition)));
doc.Add(new XElement("BottomPaneSplitterPosition", ToString(this.BottomPaneSplitterPosition)));
ILSpySettings.SaveSettings(doc);
}

23
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -24,42 +24,47 @@ using Mono.Cecil; @@ -24,42 +24,47 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
[ExportContextMenuEntry(Header = "Analyze", Icon = "images/Search.png")]
sealed class AnalyzeContextMenuEntry : IContextMenuEntry
internal sealed class AnalyzeContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(SharpTreeNode[] selectedNodes)
{
return selectedNodes.All(n => n is IMemberTreeNode);
}
public bool IsEnabled(SharpTreeNode[] selectedNodes)
{
foreach (IMemberTreeNode node in selectedNodes) {
if (!(node.Member is FieldDefinition
if (!(node.Member is TypeDefinition
|| node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)
|| Analyzer.AnalyzedEventTreeNode.CanShow(node.Member)))
return false;
}
return true;
}
public void Execute(SharpTreeNode[] selectedNodes)
{
// TODO: figure out when equivalent nodes are already present
// and focus those instead.
foreach (IMemberTreeNode node in selectedNodes) {
TypeDefinition type = node.Member as TypeDefinition;
if (type != null)
AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type));
FieldDefinition field = node.Member as FieldDefinition;
if (field != null)
MainWindow.Instance.AddToAnalyzer(new AnalyzedFieldNode(field));
AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field));
MethodDefinition method = node.Member as MethodDefinition;
if (method != null)
MainWindow.Instance.AddToAnalyzer(new AnalyzedMethodTreeNode(method));
AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member);
if(propertyAnalyzer != null)
MainWindow.Instance.AddToAnalyzer(propertyAnalyzer);
if (propertyAnalyzer != null)
AnalyzerTreeView.Instance.Show(propertyAnalyzer);
var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(node.Member);
if (eventAnalyzer != null)
MainWindow.Instance.AddToAnalyzer(eventAnalyzer);
AnalyzerTreeView.Instance.Show(eventAnalyzer);
}
}
}

9
ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs

@ -21,15 +21,12 @@ using Mono.Cecil; @@ -21,15 +21,12 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode
{
EventDefinition analyzedEvent;
public AnalyzedEventAccessorsTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
if (analyzedEvent.AddMethod != null)
this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.AddMethod, "add"));
@ -54,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -54,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return !MainWindow.Instance.CurrentLanguage.ShowMember(property.AddMethod ?? property.RemoveMethod);
}
class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode
internal class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode
{
string name;
private string name;
public AnalyzedEventAccessorTreeNode(MethodDefinition analyzedMethod, string name)
: base(analyzedMethod)

18
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.Utils;
@ -28,10 +27,10 @@ using Mono.Cecil; @@ -28,10 +27,10 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode
{
readonly EventDefinition analyzedEvent;
readonly ThreadingSupport threading;
private readonly EventDefinition analyzedEvent;
private readonly ThreadingSupport threading;
public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent)
{
@ -45,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -45,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public override object Text
{
get { return "Overriden By"; }
get { return "Overridden By"; }
}
public override object Icon
@ -67,19 +66,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -67,19 +66,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedEvent.Name;
@ -102,7 +102,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -102,7 +102,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
public static bool CanShowAnalyzer(EventDefinition property)
public static bool CanShow(EventDefinition property)
{
var accessor = property.AddMethod ?? property.RemoveMethod;
return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface;

39
ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs

@ -18,46 +18,51 @@ @@ -18,46 +18,51 @@
using System;
using Mono.Cecil;
using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedEventTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedEventTreeNode : AnalyzerTreeNode
{
EventDefinition analyzedEvent;
string prefix;
private readonly EventDefinition analyzedEvent;
private readonly string prefix;
public AnalyzedEventTreeNode(EventDefinition analyzedEvent, string prefix = "")
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
this.prefix = prefix;
this.LazyLoading = true;
}
public override object Icon {
public override object Icon
{
get { return EventTreeNode.GetIcon(analyzedEvent); }
}
public override object Text {
get {
public override object Text
{
get
{
// TODO: This way of formatting is not suitable for events which explicitly implement interfaces.
return prefix + Language.TypeToString(analyzedEvent.DeclaringType, true) + "." + EventTreeNode.GetText(analyzedEvent, Language); }
return prefix + Language.TypeToString(analyzedEvent.DeclaringType, true) + "." + EventTreeNode.GetText(analyzedEvent, Language);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedEvent);
}
protected override void LoadChildren()
{
if(AnalyzedEventAccessorsTreeNode.CanShow(analyzedEvent))
if (AnalyzedEventAccessorsTreeNode.CanShow(analyzedEvent))
this.Children.Add(new AnalyzedEventAccessorsTreeNode(analyzedEvent));
if (AnalyzedEventOverridesTreeNode.CanShowAnalyzer(analyzedEvent))
if (AnalyzedEventOverridesTreeNode.CanShow(analyzedEvent))
this.Children.Add(new AnalyzedEventOverridesTreeNode(analyzedEvent));
if (AnalyzedInterfaceEventImplementedByTreeNode.CanShow(analyzedEvent))
this.Children.Add(new AnalyzedInterfaceEventImplementedByTreeNode(analyzedEvent));
}
public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member)
@ -75,7 +80,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -75,7 +80,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return false;
return AnalyzedEventAccessorsTreeNode.CanShow(property)
|| AnalyzedEventOverridesTreeNode.CanShowAnalyzer(property);
|| AnalyzedEventOverridesTreeNode.CanShow(property);
}
}
}

26
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs → ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs

@ -18,23 +18,20 @@ @@ -18,23 +18,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedFieldAccessNode : AnalyzerTreeNode
internal sealed class AnalyzedFieldAccessTreeNode : AnalyzerTreeNode
{
readonly bool showWrites; // true: show writes; false: show read access
readonly FieldDefinition analyzedField;
readonly ThreadingSupport threading;
private readonly bool showWrites; // true: show writes; false: show read access
private readonly FieldDefinition analyzedField;
private readonly ThreadingSupport threading;
public AnalyzedFieldAccessNode(FieldDefinition analyzedField, bool showWrites)
public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites)
{
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");
@ -69,13 +66,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -69,13 +66,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedField, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
string name = analyzedField.Name;
string declTypeName = analyzedField.DeclaringType.FullName;
@ -87,18 +84,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -87,18 +84,23 @@ 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 && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) {
if (fr != null && fr.Name == name &&
Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) &&
fr.Resolve() == analyzedField) {
found = true;
break;
}
}
}
method.Body = null;
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
}
bool CanBeReference(Code code)
private bool CanBeReference(Code code)
{
switch (code) {
case Code.Ldfld:

34
ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs → ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs

@ -21,43 +21,47 @@ using Mono.Cecil; @@ -21,43 +21,47 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedFieldNode : AnalyzerTreeNode, IMemberTreeNode
internal class AnalyzedFieldTreeNode : AnalyzerTreeNode, IMemberTreeNode
{
FieldDefinition analyzedField;
public AnalyzedFieldNode(FieldDefinition analyzedField)
private readonly FieldDefinition analyzedField;
public AnalyzedFieldTreeNode(FieldDefinition analyzedField)
{
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");
this.analyzedField = analyzedField;
this.LazyLoading = true;
}
public override object Icon {
public override object Icon
{
get { return FieldTreeNode.GetIcon(analyzedField); }
}
public override object Text {
get {
public override object Text
{
get
{
return Language.TypeToString(analyzedField.DeclaringType, true) +
"." + analyzedField.Name + " : " + this.Language.TypeToString(analyzedField.FieldType, false, analyzedField);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedField);
}
protected override void LoadChildren()
{
this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, false));
this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, false));
if (!analyzedField.IsLiteral)
this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, true));
this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true));
}
MemberReference IMemberTreeNode.Member {
MemberReference IMemberTreeNode.Member
{
get { return analyzedField; }
}
}

105
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode
{
private readonly EventDefinition analyzedEvent;
private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Implemented By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType);
if (implementedInterfaceRef == null)
yield break;
foreach (EventDefinition ev in type.Events.Where(e => e.Name == analyzedEvent.Name)) {
MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod;
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedEventTreeNode(ev);
yield break;
}
foreach (EventDefinition ev in type.Events.Where(e => e.Name.EndsWith(analyzedEvent.Name))) {
MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod;
if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedEventTreeNode(ev);
}
}
}
public static bool CanShow(EventDefinition ev)
{
return ev.DeclaringType.IsInterface;
}
}
}

101
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode
{
private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Implemented By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType);
if (implementedInterfaceRef == null)
yield break;
foreach (MethodDefinition method in type.Methods.Where(m => m.Name == analyzedMethod.Name)) {
if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedMethodTreeNode(method);
yield break;
}
foreach (MethodDefinition method in type.Methods) {
if (method.HasOverrides && method.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedMethodTreeNode(method);
}
}
}
public static bool CanShow(MethodDefinition method)
{
return method.DeclaringType.IsInterface;
}
}
}

105
ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode
{
private readonly PropertyDefinition analyzedProperty;
private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
this.analyzedProperty = analyzedProperty;
this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Implemented By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType);
if (implementedInterfaceRef == null)
yield break;
foreach (PropertyDefinition property in type.Properties.Where(e => e.Name == analyzedProperty.Name)) {
MethodDefinition accessor = property.GetMethod ?? property.SetMethod;
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedPropertyTreeNode(property);
yield break;
}
foreach (PropertyDefinition property in type.Properties.Where(e => e.Name.EndsWith(analyzedProperty.Name))) {
MethodDefinition accessor = property.GetMethod ?? property.SetMethod;
if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedPropertyTreeNode(property);
}
}
}
public static bool CanShow(PropertyDefinition property)
{
return property.DeclaringType.IsInterface;
}
}
}

29
ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs → ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// <summary>
/// Searches for overrides of the analyzed method.
/// </summary>
class AnalyzerMethodOverridesTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode
{
readonly MethodDefinition analyzedMethod;
readonly ThreadingSupport threading;
private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzerMethodOverridesTreeNode(MethodDefinition analyzedMethod)
public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
@ -64,33 +64,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -64,33 +64,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
protected override void OnCollapsing()
{
if (threading.IsRunning)
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedMethod.Name;
string declTypeName = analyzedMethod.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes))
{
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
SharpTreeNode newNode = null;
try {
@ -109,14 +108,18 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -109,14 +108,18 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
catch (ReferenceResolvingException) {
// ignore this type definition. maybe add a notification about such cases.
}
if (newNode != null)
yield return newNode;
}
}
public static bool CanShowAnalyzer(MethodDefinition method)
public static bool CanShow(MethodDefinition method)
{
return method.IsVirtual && !method.IsFinal && !method.DeclaringType.IsSealed && !method.DeclaringType.IsInterface; // interfaces are temporarly disabled
return method.IsVirtual &&
!method.IsFinal &&
!method.DeclaringType.IsSealed &&
!method.DeclaringType.IsInterface; // interface methods are definitions not implementations - cannot be overridden
}
}
}

41
ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs

@ -21,11 +21,11 @@ using Mono.Cecil; @@ -21,11 +21,11 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode
internal class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode
{
MethodDefinition analyzedMethod;
string prefix;
private readonly MethodDefinition analyzedMethod;
private readonly string prefix;
public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "")
{
if (analyzedMethod == null)
@ -34,32 +34,39 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -34,32 +34,39 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
this.prefix = prefix;
this.LazyLoading = true;
}
public override object Icon {
public override object Icon
{
get { return MethodTreeNode.GetIcon(analyzedMethod); }
}
public override object Text {
get {
return prefix + Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language); }
public override object Text
{
get
{
return prefix + Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedMethod);
}
protected override void LoadChildren()
{
if (analyzedMethod.HasBody)
this.Children.Add(new AnalyzedMethodUsesNode(analyzedMethod));
this.Children.Add(new AnalyzedMethodUsesTreeNode(analyzedMethod));
this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod));
if (AnalyzerMethodOverridesTreeNode.CanShowAnalyzer(analyzedMethod))
this.Children.Add(new AnalyzerMethodOverridesTreeNode(analyzedMethod));
if (AnalyzedMethodOverridesTreeNode.CanShow(analyzedMethod))
this.Children.Add(new AnalyzedMethodOverridesTreeNode(analyzedMethod));
if (AnalyzedInterfaceMethodImplementedByTreeNode.CanShow(analyzedMethod))
this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod));
}
MemberReference IMemberTreeNode.Member {
MemberReference IMemberTreeNode.Member
{
get { return analyzedMethod; }
}
}

21
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -18,20 +18,17 @@ @@ -18,20 +18,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode
{
MethodDefinition analyzedMethod;
ThreadingSupport threading;
private readonly MethodDefinition analyzedMethod;
private readonly ThreadingSupport threading;
public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod)
{
@ -67,7 +64,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -67,7 +64,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
@ -75,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -75,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return analyzer.PerformAnalysis(ct);
}
IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
string name = analyzedMethod.Name;
foreach (MethodDefinition method in type.Methods) {
@ -84,11 +81,17 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -84,11 +81,17 @@ 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 && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) {
if (mr != null &&
mr.Name == name &&
Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) &&
mr.Resolve() == analyzedMethod) {
found = true;
break;
}
}
method.Body = null;
if (found)
yield return new AnalyzedMethodTreeNode(method);
}

33
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs → ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -27,38 +27,41 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -27,38 +27,41 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// <summary>
/// Shows the methods that are used by this method.
/// </summary>
sealed class AnalyzedMethodUsesNode : AnalyzerTreeNode
internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerTreeNode
{
MethodDefinition analyzedMethod;
public AnalyzedMethodUsesNode(MethodDefinition analyzedMethod)
private readonly MethodDefinition analyzedMethod;
public AnalyzedMethodUsesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod;
this.LazyLoading = true;
}
public override object Text {
public override object Text
{
get { return "Uses"; }
}
public override object Icon {
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
foreach (var f in GetUsedFields().Distinct()) {
this.Children.Add(new AnalyzedFieldNode(f));
this.Children.Add(new AnalyzedFieldTreeNode(f));
}
foreach (var m in GetUsedMethods().Distinct()) {
this.Children.Add(new AnalyzedMethodTreeNode(m));
}
analyzedMethod.Body = null;
}
IEnumerable<MethodDefinition> GetUsedMethods()
private IEnumerable<MethodDefinition> GetUsedMethods()
{
foreach (Instruction instr in analyzedMethod.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
@ -69,8 +72,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -69,8 +72,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
}
IEnumerable<FieldDefinition> GetUsedFields()
private IEnumerable<FieldDefinition> GetUsedFields()
{
foreach (Instruction instr in analyzedMethod.Body.Instructions) {
FieldReference fr = instr.Operand as FieldReference;

32
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs

@ -21,16 +21,13 @@ using Mono.Cecil; @@ -21,16 +21,13 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode
{
PropertyDefinition analyzedProperty;
public AnalyzedPropertyAccessorsTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
this.analyzedProperty = analyzedProperty;
if (analyzedProperty.GetMethod != null)
this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get"));
if (analyzedProperty.SetMethod != null)
@ -38,31 +35,34 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -38,31 +35,34 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (var accessor in analyzedProperty.OtherMethods)
this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null));
}
public override object Icon {
public override object Icon
{
get { return Images.Search; }
}
public override object Text {
public override object Text
{
get { return "Accessors"; }
}
public static bool CanShow(PropertyDefinition property)
{
return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod);
}
class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode
private class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode
{
string name;
private readonly string name;
public AnalyzedPropertyAccessorTreeNode(MethodDefinition analyzedMethod, string name)
: base(analyzedMethod)
{
this.name = name;
}
public override object Text {
public override object Text
{
get { return name ?? base.Text; }
}
}

16
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
@ -29,10 +28,10 @@ using Mono.Cecil; @@ -29,10 +28,10 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode
{
readonly PropertyDefinition analyzedProperty;
readonly ThreadingSupport threading;
private readonly PropertyDefinition analyzedProperty;
private readonly ThreadingSupport threading;
public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty)
{
@ -68,19 +67,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -68,19 +67,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedProperty.Name;
@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
public static bool CanShowAnalyzer(PropertyDefinition property)
public static bool CanShow(PropertyDefinition property)
{
var accessor = property.GetMethod ?? property.SetMethod;
return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface;

45
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -17,52 +17,55 @@ @@ -17,52 +17,55 @@
// DEALINGS IN THE SOFTWARE.
using System;
using Mono.Cecil;
using ICSharpCode.Decompiler;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyTreeNode : AnalyzerTreeNode
internal sealed class AnalyzedPropertyTreeNode : AnalyzerTreeNode
{
PropertyDefinition analyzedProperty;
bool isIndexer;
string prefix;
private readonly PropertyDefinition analyzedProperty;
private readonly bool isIndexer;
private readonly string prefix;
public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "")
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedMethod");
throw new ArgumentNullException("analyzedProperty");
this.isIndexer = analyzedProperty.IsIndexer();
this.analyzedProperty = analyzedProperty;
this.prefix = prefix;
this.LazyLoading = true;
}
public override object Icon {
public override object Icon
{
get { return PropertyTreeNode.GetIcon(analyzedProperty, isIndexer); }
}
public override object Text {
get {
public override object Text
{
get
{
// TODO: This way of formatting is not suitable for properties which explicitly implement interfaces.
return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language, isIndexer); }
return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language, isIndexer);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedProperty);
}
protected override void LoadChildren()
{
if(AnalyzedPropertyAccessorsTreeNode.CanShow(analyzedProperty))
if (AnalyzedPropertyAccessorsTreeNode.CanShow(analyzedProperty))
this.Children.Add(new AnalyzedPropertyAccessorsTreeNode(analyzedProperty));
if (AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(analyzedProperty))
if (AnalyzedPropertyOverridesTreeNode.CanShow(analyzedProperty))
this.Children.Add(new AnalyzedPropertyOverridesTreeNode(analyzedProperty));
//if (analyzedProperty.HasBody)
// this.Children.Add(new AnalyzedMethodUsesNode(analyzedProperty));
//this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedProperty));
if (AnalyzedInterfacePropertyImplementedByTreeNode.CanShow(analyzedProperty))
this.Children.Add(new AnalyzedInterfacePropertyImplementedByTreeNode(analyzedProperty));
}
public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member)
@ -80,7 +83,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -80,7 +83,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return false;
return AnalyzedPropertyAccessorsTreeNode.CanShow(property)
|| AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(property);
|| AnalyzedPropertyOverridesTreeNode.CanShow(property);
}
}
}

184
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -0,0 +1,184 @@ @@ -0,0 +1,184 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode
{
private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Exposed By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
if (analyzedType.IsEnum && type == analyzedType)
yield break;
if (!this.Language.ShowMember(type))
yield break;
foreach (FieldDefinition field in type.Fields) {
if (TypeIsExposedBy(field))
yield return new AnalyzedFieldTreeNode(field);
}
foreach (PropertyDefinition property in type.Properties) {
if (TypeIsExposedBy(property))
yield return new AnalyzedPropertyTreeNode(property);
}
foreach (EventDefinition eventDef in type.Events) {
if (TypeIsExposedBy(eventDef))
yield return new AnalyzedEventTreeNode(eventDef);
}
foreach (MethodDefinition method in type.Methods) {
if (TypeIsExposedBy(method))
yield return new AnalyzedMethodTreeNode(method);
}
}
private bool TypeIsExposedBy(FieldDefinition field)
{
if (field.IsPrivate)
return false;
if (field.FieldType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(PropertyDefinition property)
{
if (IsPrivate(property))
return false;
if (property.PropertyType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(EventDefinition eventDef)
{
if (IsPrivate(eventDef))
return false;
if (eventDef.EventType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(MethodDefinition method)
{
// if the method has overrides, it is probably an explicit interface member
// and should be considered part of the public API even though it is marked private.
if (method.IsPrivate) {
if (!method.HasOverrides)
return false;
else if (!method.Overrides[0].DeclaringType.Resolve().IsInterface)
return false;
}
// exclude methods with 'semantics'. for example, property getters & setters.
// HACK: this is a potentially fragile implementation, as the MethodSemantics may be extended to other uses at a later date.
if (method.SemanticsAttributes != MethodSemanticsAttributes.None)
return false;
if (method.ReturnType.Resolve() == analyzedType)
return true;
if (method.HasParameters) {
foreach (var parameter in method.Parameters) {
if (parameter.ParameterType.Resolve() == analyzedType)
return true;
}
}
return false;
}
private static bool IsPrivate(PropertyDefinition property)
{
bool isGetterPublic = (property.GetMethod != null && !property.GetMethod.IsPrivate);
bool isSetterPublic = (property.SetMethod != null && !property.SetMethod.IsPrivate);
return !(isGetterPublic || isSetterPublic);
}
private static bool IsPrivate(EventDefinition eventDef)
{
bool isAdderPublic = (eventDef.AddMethod != null && !eventDef.AddMethod.IsPrivate);
bool isRemoverPublic = (eventDef.RemoveMethod != null && !eventDef.RemoveMethod.IsPrivate);
return !(isAdderPublic || isRemoverPublic);
}
public static bool CanShow(TypeDefinition type)
{
return true;
}
}
}

107
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode
{
private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Extension Methods"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!HasExtensionAttribute(type))
yield break;
foreach (MethodDefinition method in type.Methods) {
if (method.IsStatic && HasExtensionAttribute(method)) {
if (method.HasParameters && method.Parameters[0].ParameterType.Resolve() == analyzedType) {
yield return new AnalyzedMethodTreeNode(method);
}
}
}
}
bool HasExtensionAttribute(ICustomAttributeProvider p)
{
if (p.HasCustomAttributes) {
foreach (CustomAttribute ca in p.CustomAttributes) {
TypeReference t = ca.AttributeType;
if (t.Name == "ExtensionAttribute" && t.Namespace == "System.Runtime.CompilerServices")
return true;
}
}
return false;
}
public static bool CanShow(TypeDefinition type)
{
// show on all types except static classes
return !(type.IsAbstract && type.IsSealed);
}
}
}

118
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.TreeView;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode
{
private readonly TypeDefinition analyzedType;
private readonly ThreadingSupport threading;
private readonly bool isSystemObject;
public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
this.isSystemObject = (analyzedType.FullName == "System.Object");
}
public override object Text
{
get { return "Instantiated By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
foreach (MethodDefinition method in type.Methods) {
bool found = false;
if (!method.HasBody)
continue;
// ignore chained constructors
// (since object is the root of everything, we can short circuit the test in this case)
if (method.Name == ".ctor" &&
(isSystemObject || analyzedType == type || TypesHierarchyHelpers.IsBaseType(analyzedType, type, false)))
continue;
foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == ".ctor") {
if (Helpers.IsReferencedBy(analyzedType, mr.DeclaringType)) {
found = true;
break;
}
}
}
method.Body = null;
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
}
public static bool CanShow(TypeDefinition type)
{
if (type.IsClass && !type.IsEnum) {
return type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate);
}
return false;
}
}
}

72
ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode
{
private readonly TypeDefinition analyzedType;
public AnalyzedTypeTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType;
this.LazyLoading = true;
}
public override object Icon
{
get { return TypeTreeNode.GetIcon(analyzedType); }
}
public override object Text
{
get
{
return Language.TypeToString(analyzedType, true);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedType);
}
protected override void LoadChildren()
{
if (AnalyzedTypeInstantiationsTreeNode.CanShow(analyzedType))
this.Children.Add(new AnalyzedTypeInstantiationsTreeNode(analyzedType));
if (AnalyzedTypeExposedByTreeNode.CanShow(analyzedType))
this.Children.Add(new AnalyzedTypeExposedByTreeNode(analyzedType));
if (AnalyzedTypeExtensionMethodsTreeNode.CanShow(analyzedType))
this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType));
}
MemberReference IMemberTreeNode.Member
{
get { return analyzedType; }
}
}
}

18
ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs

@ -24,11 +24,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -24,11 +24,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
public class AnalyzerTreeNode : SharpTreeNode
{
Language language;
public Language Language {
private Language language;
public Language Language
{
get { return language; }
set {
set
{
if (language != value) {
language = value;
foreach (var child in this.Children.OfType<AnalyzerTreeNode>())
@ -36,22 +38,22 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -36,22 +38,22 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
}
public override bool CanDelete()
{
return Parent != null && Parent.IsRoot;
}
public override void DeleteCore()
{
Parent.Children.Remove(this);
}
public override void Delete()
{
DeleteCore();
}
protected override void OnChildrenChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null) {

2
ILSpy/TreeNodes/Analyzer/Helpers.cs

@ -24,7 +24,7 @@ using Mono.Cecil; @@ -24,7 +24,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
static class Helpers
internal static class Helpers
{
public static bool IsReferencedBy(TypeDefinition type, TypeReference typeRef)
{

23
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -20,9 +20,8 @@ using System; @@ -20,9 +20,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Mono.Cecil;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
@ -38,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -38,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private Accessibility typeAccessibility = Accessibility.Public;
private Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction;
private ScopedWhereUsedScopeAnalyzer(TypeDefinition type, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
public ScopedWhereUsedScopeAnalyzer(TypeDefinition type, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
{
this.typeScope = type;
this.assemblyScope = type.Module.Assembly;
@ -109,7 +108,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -109,7 +108,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return FindReferencesInTypeScope(ct);
}
if (memberAccessibility == Accessibility.Internal ||
memberAccessibility == Accessibility.FamilyAndInternal ||
typeAccessibility == Accessibility.Internal ||
@ -137,7 +135,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -137,7 +135,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
private Accessibility GetNestedTypeAccessibility(TypeDefinition type)
private static Accessibility GetNestedTypeAccessibility(TypeDefinition type)
{
Accessibility result;
switch (type.Attributes & TypeAttributes.VisibilityMask) {
@ -178,22 +176,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -178,22 +176,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
Public
}
IEnumerable<T> FindReferencesInAssemblyAndFriends(CancellationToken ct)
private IEnumerable<T> FindReferencesInAssemblyAndFriends(CancellationToken ct)
{
var assemblies = GetAssemblyAndAnyFriends(assemblyScope, ct);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((AssemblyDefinition a) => FindReferencesInAssembly(a, ct));
}
IEnumerable<T> FindReferencesGlobal(CancellationToken ct)
private IEnumerable<T> FindReferencesGlobal(CancellationToken ct)
{
var assemblies = GetReferencingAssemblies(assemblyScope, ct);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((AssemblyDefinition asm) => FindReferencesInAssembly(asm, ct));
}
IEnumerable<T> FindReferencesInAssembly(AssemblyDefinition asm, CancellationToken ct)
private IEnumerable<T> FindReferencesInAssembly(AssemblyDefinition asm, CancellationToken ct)
{
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
@ -204,7 +203,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -204,7 +203,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<T> FindReferencesInTypeScope(CancellationToken ct)
private IEnumerable<T> FindReferencesInTypeScope(CancellationToken ct)
{
foreach (TypeDefinition type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
@ -215,7 +214,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -215,7 +214,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<AssemblyDefinition> GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct)
private IEnumerable<AssemblyDefinition> GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct)
{
yield return asm;
@ -237,7 +236,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -237,7 +236,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
}
IEnumerable<AssemblyDefinition> GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct)
private IEnumerable<AssemblyDefinition> GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct)
{
yield return asm;

78
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -41,35 +41,39 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -41,35 +41,39 @@ namespace ICSharpCode.ILSpy.TreeNodes
public sealed class AssemblyTreeNode : ILSpyTreeNode
{
readonly LoadedAssembly assembly;
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
public AssemblyTreeNode(LoadedAssembly assembly)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
this.assembly = assembly;
assembly.ContinueWhenLoaded(OnAssemblyLoaded, TaskScheduler.FromCurrentSynchronizationContext());
this.LazyLoading = true;
}
public AssemblyList AssemblyList {
public AssemblyList AssemblyList
{
get { return assembly.AssemblyList; }
}
public LoadedAssembly LoadedAssembly {
public LoadedAssembly LoadedAssembly
{
get { return assembly; }
}
public override object Text {
public override object Text
{
get { return HighlightSearchMatch(assembly.ShortName); }
}
public override object Icon {
get {
public override object Icon
{
get
{
if (assembly.IsLoaded) {
return assembly.HasLoadError ? Images.AssemblyWarning : Images.Assembly;
} else {
@ -77,11 +81,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -77,11 +81,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
}
public override bool ShowExpander {
public override bool ShowExpander
{
get { return !assembly.HasLoadError; }
}
void OnAssemblyLoaded(Task<AssemblyDefinition> assemblyTask)
{
// change from "Loading" icon to final icon
@ -90,14 +95,15 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -90,14 +95,15 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (assemblyTask.IsFaulted) {
RaisePropertyChanged("ShowExpander"); // cannot expand assemblies with load error
// observe the exception so that the Task's finalizer doesn't re-throw it
try { assemblyTask.Wait(); } catch (AggregateException) {}
try { assemblyTask.Wait(); }
catch (AggregateException) { }
} else {
RaisePropertyChanged("Text"); // shortname might have changed
}
}
Dictionary<TypeDefinition, TypeTreeNode> typeDict = new Dictionary<TypeDefinition, TypeTreeNode>();
protected override void LoadChildren()
{
AssemblyDefinition assemblyDefinition = assembly.AssemblyDefinition;
@ -106,7 +112,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -106,7 +112,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return;
}
ModuleDefinition mainModule = assemblyDefinition.MainModule;
this.Children.Add(new ReferenceFolderTreeNode(mainModule, this));
if (mainModule.HasResources)
this.Children.Add(new ResourceListTreeNode(mainModule));
@ -128,7 +134,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -128,7 +134,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.Children.Add(ns);
}
}
public TypeTreeNode FindTypeNode(TypeDefinition def)
{
if (def == null)
@ -140,41 +146,41 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -140,41 +146,41 @@ namespace ICSharpCode.ILSpy.TreeNodes
else
return null;
}
public override bool CanDrag(SharpTreeNode[] nodes)
{
return nodes.All(n => n is AssemblyTreeNode);
}
public override void StartDrag(DependencyObject dragSource, SharpTreeNode[] nodes)
{
DragDrop.DoDragDrop(dragSource, Copy(nodes), DragDropEffects.All);
}
public override bool CanDelete()
{
return true;
}
public override void Delete()
{
DeleteCore();
}
public override void DeleteCore()
{
assembly.AssemblyList.Unload(assembly);
}
internal const string DataFormat = "ILSpyAssemblies";
public override IDataObject Copy(SharpTreeNode[] nodes)
{
DataObject dataObject = new DataObject();
dataObject.SetData(DataFormat, nodes.OfType<AssemblyTreeNode>().Select(n => n.LoadedAssembly.FileName).ToArray());
return dataObject;
}
public override FilterResult Filter(FilterSettings settings)
{
if (settings.SearchTermMatches(assembly.ShortName))
@ -182,13 +188,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -182,13 +188,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
else
return FilterResult.Recurse;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
assembly.WaitUntilLoaded(); // necessary so that load errors are passed on to the caller
language.DecompileAssembly(assembly, output, options);
}
public override bool Save(DecompilerTextView textView)
{
Language language = this.Language;
@ -215,12 +221,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -215,12 +221,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
}
textView.SaveToDisk(language, new[]{this}, options, dlg.FileName);
textView.SaveToDisk(language, new[] { this }, options, dlg.FileName);
}
return true;
}
}
[ExportContextMenuEntry(Header = "_Remove", Icon = "images/Delete.png")]
sealed class RemoveAssembly : IContextMenuEntry
{
@ -228,12 +234,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -228,12 +234,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
return selectedNodes.All(n => n is AssemblyTreeNode);
}
public bool IsEnabled(SharpTreeNode[] selectedNodes)
{
return true;
}
public void Execute(SharpTreeNode[] selectedNodes)
{
foreach (var node in selectedNodes) {

3
ILSpy/TreeNodes/EventTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using Mono.Cecil;
@ -67,7 +68,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -67,7 +68,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
get { return GetIcon(ev); }
}
public static object GetIcon(EventDefinition eventDef)
public static ImageSource GetIcon(EventDefinition eventDef)
{
MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
if (accessor != null)

4
ILSpy/TreeNodes/FieldTreeNode.cs

@ -76,10 +76,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -76,10 +76,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
case FieldAttributes.Family:
case FieldAttributes.FamORAssem:
return AccessOverlayIcon.Protected;
case FieldAttributes.Private:
return AccessOverlayIcon.Private;
default:
throw new NotSupportedException();
return AccessOverlayIcon.Private;
}
}

46
ILSpy/TreeNodes/ResourceEntryNode.cs

@ -37,17 +37,25 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -37,17 +37,25 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public class ResourceEntryNode : ILSpyTreeNode
{
protected readonly string key;
protected readonly Stream data;
public override object Text {
private readonly string key;
private readonly Stream data;
public override object Text
{
get { return key.ToString(); }
}
public override object Icon {
public override object Icon
{
get { return Images.Resource; }
}
protected Stream Data
{
get { return data; }
}
public ResourceEntryNode(string key, Stream data)
{
if (key == null)
@ -57,7 +65,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,7 +65,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.key = key;
this.data = data;
}
public static ILSpyTreeNode Create(string key, Stream data)
{
ILSpyTreeNode result = null;
@ -68,12 +76,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -68,12 +76,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
return result ?? new ResourceEntryNode(key, data);
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, string.Format("{0} = {1}", key, data));
}
public override bool Save(DecompilerTextView textView)
{
SaveFileDialog dlg = new SaveFileDialog();
@ -87,12 +95,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -87,12 +95,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
return true;
}
}
[Export(typeof(IResourceNodeFactory))]
sealed class ImageResourceNodeFactory : IResourceNodeFactory
{
static readonly string[] imageFileExtensions = { ".png", ".gif", ".bmp", ".jpg", ".ico" };
public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource)
{
EmbeddedResource er = resource as EmbeddedResource;
@ -101,7 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -101,7 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
return null;
}
public ILSpyTreeNode CreateNode(string key, Stream data)
{
foreach (string fileExt in imageFileExtensions) {
@ -111,10 +119,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -111,10 +119,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
return null;
}
}
sealed class ImageResourceEntryNode : ResourceEntryNode
{
public ImageResourceEntryNode(string key, Stream data) : base(key, data)
public ImageResourceEntryNode(string key, Stream data)
: base(key, data)
{
}
@ -127,17 +136,18 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -127,17 +136,18 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
try {
AvalonEditTextOutput output = new AvalonEditTextOutput();
data.Position = 0;
Data.Position = 0;
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = data;
image.StreamSource = Data;
image.EndInit();
output.AddUIElement(() => new Image { Source = image });
output.WriteLine();
output.AddButton(Images.Save, "Save", delegate { Save(null); });
textView.Show(output, null);
return true;
} catch (Exception) {
}
catch (Exception) {
return false;
}
}

2
ILSpy/TreeNodes/XamlResourceNode.cs

@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy.Xaml @@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy.Xaml
try {
// cache read XAML because stream will be closed after first read
if (xaml == null) {
using (var reader = new StreamReader(data)) {
using (var reader = new StreamReader(Data)) {
xaml = reader.ReadToEnd();
}
}

90
ILSpy/themes/generic.xaml

@ -2,6 +2,10 @@ @@ -2,6 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Controls/SearchBoxStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- SortableGridViewColumn.
Displays an up arrow or down arrow in the column header when the grid is sorted using that column.
-->
@ -23,7 +27,87 @@ @@ -23,7 +27,87 @@
</StackPanel>
</DataTemplate>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Controls/SearchBoxStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- DockedPane -->
<Style TargetType="{x:Type controls:DockedPane}">
<Style.Resources>
<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 243}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 235}" Offset="0.5"/>
<GradientStop Color="{controls:ControlColor 221}" Offset="0.5"/>
<GradientStop Color="{controls:ControlColor 205}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{controls:ControlColor 150}"/>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border SnapsToDevicePixels="true" x:Name="buttonBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" />
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="buttonBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 250, Highlight=0.3}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 224, Highlight=0.4}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="buttonBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 224}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 248}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DockedPane}">
<Border BorderThickness="1" BorderBrush="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" CornerRadius="0,2,0,0">
<DockPanel>
<Border BorderThickness="0,0,0,1" BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" DockPanel.Dock="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{TemplateBinding Title}" Margin="3,0" Foreground="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Button x:Name="PART_Close" Grid.Column="2" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" Style="{DynamicResource CloseButtonStyle}" ToolTip="Close">
<Path x:Name="Path" Stretch="Fill" StrokeThickness="0.5" Stroke="#FF333333" Fill="#FF969696" Data="F1 M 0,1.3333L 1.33333,0L 4,2.6666L 6.6666,0 8,1.3333L 5.3333,4L 8,6.6666L 6.6666,8L 4,5.3333L 1.3333,8L 0,6.6666L 2.6666,4L 0,1.3333 Z " HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Button>
</Grid>
</Border>
<ContentPresenter Content="{TemplateBinding Content}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

12
Mono.Cecil/Mono.Cecil/MethodDefinition.cs

@ -133,8 +133,9 @@ namespace Mono.Cecil { @@ -133,8 +133,9 @@ namespace Mono.Cecil {
public MethodBody Body {
get {
if (body != null)
return body;
MethodBody localBody = this.body;
if (localBody != null)
return localBody;
if (!HasBody)
return null;
@ -144,7 +145,12 @@ namespace Mono.Cecil { @@ -144,7 +145,12 @@ namespace Mono.Cecil {
return body = new MethodBody (this);
}
set { body = value; }
set {
// we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe
lock (Module.SyncRoot) {
body = value;
}
}
}
public bool HasPInvokeInfo {

1
README.txt

@ -13,6 +13,7 @@ Included open-source libraries: @@ -13,6 +13,7 @@ Included open-source libraries:
ILSpy Contributors:
Daniel Grunwald
David Srbecky
Ed Harvey
Siegfried Pammer
Artur Zgodzinski
Eusebiu Marcu

Loading…
Cancel
Save