Browse Source

Work on TreeView.

pull/1/head
Daniel Grunwald 16 years ago
parent
commit
fd0c9cfe7d
  1. 38
      ILSpy/AssemblyListTreeNode.cs
  2. 106
      ILSpy/AssemblyTreeNode.cs
  3. 47
      ILSpy/FieldTreeNode.cs
  4. 3
      ILSpy/ILSpy.csproj
  5. 2
      ILSpy/MainWindow.xaml
  6. 23
      ILSpy/MainWindow.xaml.cs
  7. 45
      ILSpy/MethodTreeNode.cs
  8. 59
      ILSpy/TypeTreeNode.cs

38
ILSpy/AssemblyListTreeNode.cs

@ -0,0 +1,38 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents a list of assemblies.
/// </summary>
public sealed class AssemblyListTreeNode : SharpTreeNode
{
public override bool CanDelete(SharpTreeNode[] nodes)
{
return nodes.All(n => n is AssemblyTreeNode);
}
public override void Delete(SharpTreeNode[] nodes)
{
DeleteCore(nodes);
}
public override void DeleteCore(SharpTreeNode[] nodes)
{
foreach (SharpTreeNode node in nodes)
this.Children.Remove(node);
}
public override DropEffect CanDrop(System.Windows.IDataObject data, DropEffect requestedEffect)
{
return requestedEffect;
}
}
}

106
ILSpy/AssemblyTreeNode.cs

@ -4,8 +4,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil; using Mono.Cecil;
@ -13,62 +15,46 @@ namespace ICSharpCode.ILSpy
{ {
sealed class AssemblyTreeNode : SharpTreeNode sealed class AssemblyTreeNode : SharpTreeNode
{ {
readonly AssemblyDefinition assembly; readonly string fileName;
readonly string name;
readonly Task<AssemblyDefinition> assemblyTask;
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>(); readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();
public ObservableCollection<NamespaceTreeNode> Namespaces { get; private set; }
readonly Dictionary<TypeDefinition, TypeTreeNode> typeDict = new Dictionary<TypeDefinition, TypeTreeNode>();
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>(); readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
public AssemblyTreeNode(AssemblyDefinition assembly) public AssemblyTreeNode(string fileName)
{ {
if (assembly == null) if (fileName == null)
throw new ArgumentNullException("assembly"); throw new ArgumentNullException("fileName");
this.assembly = assembly;
this.Namespaces = new ObservableCollection<NamespaceTreeNode>(); this.fileName = fileName;
InitClassList(); this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
BuildNestedTypeLists(); this.name = Path.GetFileNameWithoutExtension(fileName);
BuildNamespaceList();
this.LazyLoading = true;
} }
public override object Text { public override object Text {
get { return assembly.Name.Name; } get { return name; }
} }
public override object Icon { public override object Icon {
get { return Images.Assembly; } get { return Images.Assembly; }
} }
void InitClassList() AssemblyDefinition LoadAssembly()
{ {
// runs on background thread
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName);
foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) { foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
var viewmodel = new TypeTreeNode(type); classes.Add(new TypeTreeNode(type));
typeDict.Add(type, viewmodel);
if (type.IsNested == false) {
classes.Add(viewmodel);
}
foreach (TypeDefinition nestedType in TreeTraversal.PreOrder(type.NestedTypes, t => t.NestedTypes)) {
typeDict.Add(nestedType, new TypeTreeNode(nestedType));
}
} }
return assembly;
} }
void BuildNestedTypeLists() protected override void LoadChildren()
{ {
foreach (var typeModel in typeDict.Values) { assemblyTask.Wait();
typeModel.NestedTypes.Clear();
}
foreach (var pair in typeDict) {
if (showInternalAPI == false && pair.Value.IsPublicAPI == false)
continue;
if (pair.Key.IsNested) {
typeDict[pair.Key.DeclaringType].NestedTypes.Add(pair.Value);
}
}
}
void BuildNamespaceList()
{
this.Children.Clear();
foreach (NamespaceTreeNode ns in namespaces.Values) { foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear(); ns.Children.Clear();
} }
@ -88,18 +74,56 @@ namespace ICSharpCode.ILSpy
} }
} }
bool showInternalAPI; /// <summary>
/// Invalidates the list of children.
/// </summary>
void InvalidateChildren()
{
this.Children.Clear();
if (this.IsExpanded)
this.LoadChildren();
else
this.LazyLoading = true;
}
bool showInternalAPI = true;
public bool ShowInternalAPI { public bool ShowInternalAPI {
get { return showInternalAPI; } get { return showInternalAPI; }
set { set {
if (showInternalAPI != value) { if (showInternalAPI != value) {
showInternalAPI = value; showInternalAPI = value;
BuildNestedTypeLists(); InvalidateChildren();
BuildNamespaceList();
RaisePropertyChanged("ShowInternalAPI"); RaisePropertyChanged("ShowInternalAPI");
} }
} }
} }
public override bool CanDrag(SharpTreeNode[] nodes)
{
return nodes.All(n => n is AssemblyTreeNode);
}
public override bool CanDelete(SharpTreeNode[] nodes)
{
return Parent != null && Parent.CanDelete(nodes); // handle deletion in the AssemblyListTreeNode
}
public override void Delete(SharpTreeNode[] nodes)
{
Parent.Delete(nodes); // handle deletion in the AssemblyListTreeNode
}
public override void DeleteCore(SharpTreeNode[] nodes)
{
Parent.DeleteCore(nodes); // handle deletion in the AssemblyListTreeNode
}
public override IDataObject Copy(SharpTreeNode[] nodes)
{
DataObject dataObject = new DataObject();
dataObject.SetData("ILSpyAssemblies", nodes.OfType<AssemblyTreeNode>());
return dataObject;
}
} }
} }

47
ILSpy/FieldTreeNode.cs

@ -0,0 +1,47 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents a field in the TreeView.
/// </summary>
sealed class FieldTreeNode : SharpTreeNode
{
readonly FieldDefinition field;
public FieldTreeNode(FieldDefinition field)
{
if (field == null)
throw new ArgumentNullException("field");
this.field = field;
}
public override object Text {
get { return field.Name; }
}
public override object Icon {
get {
if (field.IsLiteral)
return Images.Literal;
switch (field.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:
return Images.Field;
case FieldAttributes.Assembly:
case FieldAttributes.FamANDAssem:
return Images.InternalField;
case FieldAttributes.Family:
case FieldAttributes.FamORAssem:
return Images.ProtectedField;
default:
return Images.PrivateField;
}
}
}
}
}

3
ILSpy/ILSpy.csproj

@ -64,8 +64,11 @@
<SubType>Code</SubType> <SubType>Code</SubType>
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="AssemblyListTreeNode.cs" />
<Compile Include="AssemblyTreeNode.cs" /> <Compile Include="AssemblyTreeNode.cs" />
<Compile Include="FieldTreeNode.cs" />
<Compile Include="Images\Images.cs" /> <Compile Include="Images\Images.cs" />
<Compile Include="MethodTreeNode.cs" />
<Compile Include="Mono.Cecil.Rocks\MethodBodyRocks.cs" /> <Compile Include="Mono.Cecil.Rocks\MethodBodyRocks.cs" />
<Compile Include="NamespaceTreeNode.cs" /> <Compile Include="NamespaceTreeNode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

2
ILSpy/MainWindow.xaml

@ -11,6 +11,6 @@
Hyperlink.RequestNavigate="Window_RequestNavigate" Hyperlink.RequestNavigate="Window_RequestNavigate"
TextOptions.TextFormattingMode="Display" TextOptions.TextFormattingMode="Display"
> >
<tv:SharpTreeView Name="treeView" ShowRoot="False" AllowDropOrder="True"> <tv:SharpTreeView Name="treeView" ShowRoot="False" AllowDropOrder="True" AllowDrop="True">
</tv:SharpTreeView> </tv:SharpTreeView>
</Window> </Window>

23
ILSpy/MainWindow.xaml.cs

@ -3,9 +3,10 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
using System.Windows; using System.Windows;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -16,14 +17,30 @@ namespace ICSharpCode.ILSpy
{ {
SharpTreeNodeCollection assemblies; SharpTreeNodeCollection assemblies;
static readonly Assembly[] initialAssemblies = {
typeof(object).Assembly,
typeof(Uri).Assembly,
typeof(System.Linq.Enumerable).Assembly,
typeof(System.Xml.XmlDocument).Assembly,
typeof(System.Windows.Markup.MarkupExtension).Assembly,
typeof(System.Windows.Rect).Assembly,
typeof(System.Windows.UIElement).Assembly,
typeof(System.Windows.FrameworkElement).Assembly,
typeof(ICSharpCode.TreeView.SharpTreeView).Assembly,
typeof(Mono.Cecil.AssemblyDefinition).Assembly,
typeof(ICSharpCode.NRefactory.SupportedLanguage).Assembly,
typeof(MainWindow).Assembly
};
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
treeView.Root = new SharpTreeNode(); treeView.Root = new AssemblyListTreeNode();
assemblies = treeView.Root.Children; assemblies = treeView.Root.Children;
assemblies.Add(new AssemblyTreeNode(AssemblyDefinition.ReadAssembly(typeof(object).Assembly.Location))); foreach (Assembly asm in initialAssemblies)
assemblies.Add(new AssemblyTreeNode(asm.Location));
} }
void Window_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) void Window_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)

45
ILSpy/MethodTreeNode.cs

@ -0,0 +1,45 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Tree Node representing a field, method, property, or event.
/// </summary>
public sealed class MethodTreeNode : SharpTreeNode
{
MethodDefinition method;
public MethodTreeNode(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
this.method = method;
}
public override object Text {
get { return method.Name; }
}
public override object Icon {
get {
switch (method.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
return Images.Method;
case MethodAttributes.Assembly:
case MethodAttributes.FamANDAssem:
return Images.InternalMethod;
case MethodAttributes.Family:
case MethodAttributes.FamORAssem:
return Images.ProtectedMethod;
default:
return Images.PrivateMethod;
}
}
}
}
}

59
ILSpy/TypeTreeNode.cs

@ -15,15 +15,13 @@ namespace ICSharpCode.ILSpy
{ {
readonly TypeDefinition type; readonly TypeDefinition type;
public ObservableCollection<TypeTreeNode> NestedTypes { get; private set; }
public TypeTreeNode(TypeDefinition type) public TypeTreeNode(TypeDefinition type)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException("type"); throw new ArgumentNullException("type");
this.type = type; this.type = type;
this.NestedTypes = new ObservableCollection<TypeTreeNode>(); this.LazyLoading = true;
} }
public string Name { public string Name {
@ -38,6 +36,40 @@ namespace ICSharpCode.ILSpy
get { return type.Name; } get { return type.Name; }
} }
public TypeAttributes Visibility {
get {
return type.Attributes & TypeAttributes.VisibilityMask;
}
}
public bool IsPublicAPI {
get {
switch (this.Visibility) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
return true;
default:
return false;
}
}
}
protected override void LoadChildren()
{
foreach (TypeDefinition nestedType in type.NestedTypes) {
this.Children.Add(new TypeTreeNode(nestedType));
}
foreach (FieldDefinition field in type.Fields) {
this.Children.Add(new FieldTreeNode(field));
}
foreach (MethodDefinition method in type.Methods) {
this.Children.Add(new MethodTreeNode(method));
}
}
#region Icon
enum ClassType enum ClassType
{ {
Class, Class,
@ -64,26 +96,6 @@ namespace ICSharpCode.ILSpy
} }
} }
public TypeAttributes Visibility {
get {
return type.Attributes & TypeAttributes.VisibilityMask;
}
}
public bool IsPublicAPI {
get {
switch (this.Visibility) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
return true;
default:
return false;
}
}
}
public override object Icon { public override object Icon {
get { get {
switch (this.Visibility) { switch (this.Visibility) {
@ -128,5 +140,6 @@ namespace ICSharpCode.ILSpy
} }
} }
} }
#endregion
} }
} }

Loading…
Cancel
Save