mirror of https://github.com/icsharpcode/ILSpy.git
11 changed files with 250 additions and 218 deletions
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
using System.Linq; |
||||
|
||||
using ICSharpCode.ILSpy.Util; |
||||
using ICSharpCode.ILSpyX; |
||||
using ICSharpCode.ILSpyX.TreeView; |
||||
|
||||
namespace ICSharpCode.ILSpy.Analyzers; |
||||
|
||||
public sealed class AnalyzerRootNode : AnalyzerTreeNode |
||||
{ |
||||
public AnalyzerRootNode() |
||||
{ |
||||
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e); |
||||
} |
||||
|
||||
void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
if (e.Action == NotifyCollectionChangedAction.Reset) |
||||
{ |
||||
this.Children.Clear(); |
||||
} |
||||
else |
||||
{ |
||||
var removedAssemblies = e.OldItems?.Cast<LoadedAssembly>().ToArray() ?? []; |
||||
var addedAssemblies = e.NewItems?.Cast<LoadedAssembly>().ToArray() ?? []; |
||||
|
||||
HandleAssemblyListChanged(removedAssemblies, addedAssemblies); |
||||
} |
||||
} |
||||
|
||||
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies) |
||||
{ |
||||
this.Children.RemoveAll( |
||||
delegate (SharpTreeNode n) { |
||||
AnalyzerTreeNode an = n as AnalyzerTreeNode; |
||||
return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); |
||||
}); |
||||
return true; |
||||
} |
||||
} |
@ -1,158 +0,0 @@
@@ -1,158 +0,0 @@
|
||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
using System.ComponentModel.Composition; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
|
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
using ICSharpCode.ILSpy.Analyzers.TreeNodes; |
||||
using ICSharpCode.ILSpy.Docking; |
||||
using ICSharpCode.ILSpy.ViewModels; |
||||
using ICSharpCode.ILSpyX; |
||||
using ICSharpCode.ILSpy.Controls.TreeView; |
||||
using ICSharpCode.ILSpy.Util; |
||||
using ICSharpCode.ILSpyX.TreeView; |
||||
|
||||
using TomsToolbox.Wpf.Composition.Mef; |
||||
|
||||
namespace ICSharpCode.ILSpy.Analyzers |
||||
{ |
||||
/// <summary>
|
||||
/// Analyzer tree view.
|
||||
/// </summary>
|
||||
[DataTemplate(typeof(AnalyzerPaneModel))] |
||||
[PartCreationPolicy(CreationPolicy.Shared)] |
||||
[Export] |
||||
public class AnalyzerTreeView : SharpTreeView |
||||
{ |
||||
public AnalyzerTreeView() |
||||
{ |
||||
this.ShowRoot = false; |
||||
this.BorderThickness = new(); |
||||
this.Root = new AnalyzerRootNode(); |
||||
ContextMenuProvider.Add(this); |
||||
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e); |
||||
} |
||||
|
||||
|
||||
void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
if (e.Action == NotifyCollectionChangedAction.Reset) |
||||
{ |
||||
this.Root.Children.Clear(); |
||||
} |
||||
else |
||||
{ |
||||
List<LoadedAssembly> removedAssemblies = new List<LoadedAssembly>(); |
||||
if (e.OldItems != null) |
||||
removedAssemblies.AddRange(e.OldItems.Cast<LoadedAssembly>()); |
||||
List<LoadedAssembly> addedAssemblies = new List<LoadedAssembly>(); |
||||
if (e.NewItems != null) |
||||
addedAssemblies.AddRange(e.NewItems.Cast<LoadedAssembly>()); |
||||
((AnalyzerRootNode)this.Root).HandleAssemblyListChanged(removedAssemblies, addedAssemblies); |
||||
} |
||||
} |
||||
|
||||
public void Show() |
||||
{ |
||||
DockWorkspace.Instance.ShowToolPane(AnalyzerPaneModel.PaneContentId); |
||||
} |
||||
|
||||
public void Show(AnalyzerTreeNode node) |
||||
{ |
||||
Show(); |
||||
|
||||
node.IsExpanded = true; |
||||
this.Root.Children.Add(node); |
||||
this.SelectedItem = node; |
||||
this.FocusNode(node); |
||||
} |
||||
|
||||
public void ShowOrFocus(AnalyzerTreeNode node) |
||||
{ |
||||
if (node is AnalyzerEntityTreeNode) |
||||
{ |
||||
var an = node as AnalyzerEntityTreeNode; |
||||
var found = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(n => n.Member == an.Member); |
||||
if (found != null) |
||||
{ |
||||
Show(); |
||||
|
||||
found.IsExpanded = true; |
||||
this.SelectedItem = found; |
||||
this.FocusNode(found); |
||||
return; |
||||
} |
||||
} |
||||
Show(node); |
||||
} |
||||
|
||||
public void Analyze(IEntity entity) |
||||
{ |
||||
if (entity == null) |
||||
{ |
||||
throw new ArgumentNullException(nameof(entity)); |
||||
} |
||||
|
||||
if (entity.MetadataToken.IsNil) |
||||
{ |
||||
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); |
||||
return; |
||||
} |
||||
|
||||
switch (entity) |
||||
{ |
||||
case ITypeDefinition td: |
||||
ShowOrFocus(new AnalyzedTypeTreeNode(td)); |
||||
break; |
||||
case IField fd: |
||||
if (!fd.IsConst) |
||||
ShowOrFocus(new AnalyzedFieldTreeNode(fd)); |
||||
break; |
||||
case IMethod md: |
||||
ShowOrFocus(new AnalyzedMethodTreeNode(md)); |
||||
break; |
||||
case IProperty pd: |
||||
ShowOrFocus(new AnalyzedPropertyTreeNode(pd)); |
||||
break; |
||||
case IEvent ed: |
||||
ShowOrFocus(new AnalyzedEventTreeNode(ed)); |
||||
break; |
||||
default: |
||||
throw new ArgumentOutOfRangeException(nameof(entity), $"Entity {entity.GetType().FullName} is not supported."); |
||||
} |
||||
} |
||||
|
||||
sealed class AnalyzerRootNode : AnalyzerTreeNode |
||||
{ |
||||
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies) |
||||
{ |
||||
this.Children.RemoveAll( |
||||
delegate (SharpTreeNode n) { |
||||
AnalyzerTreeNode an = n as AnalyzerTreeNode; |
||||
return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); |
||||
}); |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<treeView:SharpTreeView |
||||
x:Class="ICSharpCode.ILSpy.Analyzers.AnalyzerTreeView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:toms="urn:TomsToolbox" |
||||
xmlns:treeView="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" |
||||
xmlns:analyzers="clr-namespace:ICSharpCode.ILSpy.Analyzers" |
||||
mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" |
||||
d:DataContext="{d:DesignInstance analyzers:AnalyzerTreeViewModel}" |
||||
ShowRoot="False" |
||||
BorderThickness="0" |
||||
Root="{Binding Root}" |
||||
toms:MultiSelectorExtensions.SelectionBinding="{Binding SelectedItems}" |
||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" |
||||
SelectionChanged="AnalyzerTreeView_OnSelectionChanged"> |
||||
|
||||
<UIElement.InputBindings> |
||||
<KeyBinding Key="R" Modifiers="Control" Command="{Binding AnalyzeCommand}" /> |
||||
</UIElement.InputBindings> |
||||
|
||||
</treeView:SharpTreeView> |
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2019 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.Composition; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
using ICSharpCode.ILSpy.Analyzers.TreeNodes; |
||||
using ICSharpCode.ILSpy.TreeNodes; |
||||
using ICSharpCode.ILSpy.ViewModels; |
||||
|
||||
using TomsToolbox.Wpf; |
||||
|
||||
namespace ICSharpCode.ILSpy.Analyzers |
||||
{ |
||||
[ExportToolPane] |
||||
[PartCreationPolicy(CreationPolicy.Shared)] |
||||
[Export] |
||||
public class AnalyzerTreeViewModel : ToolPaneModel |
||||
{ |
||||
private AnalyzerTreeNode selectedItem; |
||||
|
||||
public const string PaneContentId = "analyzerPane"; |
||||
|
||||
public AnalyzerTreeViewModel() |
||||
{ |
||||
ContentId = PaneContentId; |
||||
Title = Properties.Resources.Analyze; |
||||
ShortcutKey = new(Key.R, ModifierKeys.Control); |
||||
AssociatedCommand = ILSpyCommands.Analyze; |
||||
} |
||||
|
||||
public AnalyzerRootNode Root { get; } = new(); |
||||
|
||||
public AnalyzerTreeNode SelectedItem { |
||||
get => selectedItem; |
||||
set => SetProperty(ref selectedItem, value); |
||||
} |
||||
|
||||
public ICommand AnalyzeCommand => new DelegateCommand(AnalyzeSelected); |
||||
|
||||
public ObservableCollection<AnalyzerTreeNode> SelectedItems { get; } = []; |
||||
|
||||
private void AnalyzeSelected() |
||||
{ |
||||
foreach (var node in SelectedItems.OfType<IMemberTreeNode>()) |
||||
{ |
||||
Analyze(node.Member); |
||||
} |
||||
} |
||||
|
||||
void AddOrSelect(AnalyzerTreeNode node) |
||||
{ |
||||
Show(); |
||||
|
||||
AnalyzerTreeNode target = default; |
||||
|
||||
if (node is AnalyzerEntityTreeNode { Member: { } member }) |
||||
{ |
||||
target = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(item => item.Member == member); |
||||
} |
||||
|
||||
if (target == null) |
||||
{ |
||||
this.Root.Children.Add(node); |
||||
target = node; |
||||
} |
||||
|
||||
target.IsExpanded = true; |
||||
this.SelectedItem = target; |
||||
} |
||||
|
||||
public void Analyze(IEntity entity) |
||||
{ |
||||
if (entity == null) |
||||
{ |
||||
throw new ArgumentNullException(nameof(entity)); |
||||
} |
||||
|
||||
if (entity.MetadataToken.IsNil) |
||||
{ |
||||
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); |
||||
return; |
||||
} |
||||
|
||||
switch (entity) |
||||
{ |
||||
case ITypeDefinition td: |
||||
AddOrSelect(new AnalyzedTypeTreeNode(td)); |
||||
break; |
||||
case IField fd: |
||||
if (!fd.IsConst) |
||||
AddOrSelect(new AnalyzedFieldTreeNode(fd)); |
||||
break; |
||||
case IMethod md: |
||||
AddOrSelect(new AnalyzedMethodTreeNode(md)); |
||||
break; |
||||
case IProperty pd: |
||||
AddOrSelect(new AnalyzedPropertyTreeNode(pd)); |
||||
break; |
||||
case IEvent ed: |
||||
AddOrSelect(new AnalyzedEventTreeNode(ed)); |
||||
break; |
||||
default: |
||||
throw new ArgumentOutOfRangeException(nameof(entity), $@"Entity {entity.GetType().FullName} is not supported."); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue