You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.6 KiB
133 lines
3.6 KiB
// 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.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using ICSharpCode.TreeView;
|
|
using Mono.Cecil;
|
|
|
|
namespace ICSharpCode.ILSpy
|
|
{
|
|
sealed class AssemblyTreeNode : SharpTreeNode
|
|
{
|
|
readonly string fileName;
|
|
readonly string name;
|
|
readonly Task<AssemblyDefinition> assemblyTask;
|
|
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();
|
|
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
|
|
|
|
public AssemblyTreeNode(string fileName)
|
|
{
|
|
if (fileName == null)
|
|
throw new ArgumentNullException("fileName");
|
|
|
|
this.fileName = fileName;
|
|
this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
|
|
this.name = Path.GetFileNameWithoutExtension(fileName);
|
|
|
|
this.LazyLoading = true;
|
|
}
|
|
|
|
public string FileName {
|
|
get { return fileName; }
|
|
}
|
|
|
|
public override object Text {
|
|
get { return name; }
|
|
}
|
|
|
|
public override object Icon {
|
|
get { return Images.Assembly; }
|
|
}
|
|
|
|
AssemblyDefinition LoadAssembly()
|
|
{
|
|
// runs on background thread
|
|
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName);
|
|
foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
|
|
classes.Add(new TypeTreeNode(type));
|
|
}
|
|
return assembly;
|
|
}
|
|
|
|
protected override void LoadChildren()
|
|
{
|
|
assemblyTask.Wait();
|
|
this.Children.Add(new ReferenceFolderTreeNode(assemblyTask.Result.MainModule));
|
|
foreach (NamespaceTreeNode ns in namespaces.Values) {
|
|
ns.Children.Clear();
|
|
}
|
|
foreach (TypeTreeNode type in classes) {
|
|
if (showInternalAPI == false && type.IsPublicAPI == false)
|
|
continue;
|
|
NamespaceTreeNode ns;
|
|
if (!namespaces.TryGetValue(type.Namespace, out ns)) {
|
|
ns = new NamespaceTreeNode(type.Namespace);
|
|
namespaces[type.Namespace] = ns;
|
|
}
|
|
ns.Children.Add(type);
|
|
}
|
|
foreach (NamespaceTreeNode ns in namespaces.Values.OrderBy(n => n.Name)) {
|
|
if (ns.Children.Count > 0)
|
|
this.Children.Add(ns);
|
|
}
|
|
}
|
|
|
|
/// <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 {
|
|
get { return showInternalAPI; }
|
|
set {
|
|
if (showInternalAPI != value) {
|
|
showInternalAPI = value;
|
|
InvalidateChildren();
|
|
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;
|
|
}
|
|
}
|
|
}
|