Browse Source

Implemented drilling down into references.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
d121d6e57c
  1. 38
      ILSpy/AssemblyListTreeNode.cs
  2. 31
      ILSpy/AssemblyReferenceTreeNode.cs
  3. 67
      ILSpy/AssemblyTreeNode.cs
  4. 4
      ILSpy/GacInterop.cs
  5. 31
      ILSpy/MainWindow.xaml.cs
  6. 5
      ILSpy/OpenFromGacDialog.xaml
  7. 10
      ILSpy/ReferenceFolderTreeNode.cs

38
ILSpy/AssemblyListTreeNode.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.ILSpy @@ -17,7 +17,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Represents a list of assemblies.
/// </summary>
sealed class AssemblyListTreeNode : SharpTreeNode, IAssemblyResolver
sealed class AssemblyListTreeNode : SharpTreeNode
{
public override bool CanDelete(SharpTreeNode[] nodes)
{
@ -80,40 +80,6 @@ namespace ICSharpCode.ILSpy @@ -80,40 +80,6 @@ namespace ICSharpCode.ILSpy
return newNode;
}
AssemblyTreeNode OpenGacAssembly(string fullName)
{
App.Current.Dispatcher.VerifyAccess();
string file = GacInterop.FindAssemblyInNetGac(AssemblyNameReference.Parse(fullName));
if (file != null) {
return OpenAssembly(file);
} else {
return null;
}
}
AssemblyDefinition IAssemblyResolver.Resolve(AssemblyNameReference name)
{
var node = OpenGacAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
var node = OpenGacAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(string fullName)
{
var node = OpenGacAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(string fullName, ReaderParameters parameters)
{
var node = OpenGacAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
public Action<SharpTreeNode> Select = delegate {};
}
}

31
ILSpy/AssemblyReferenceTreeNode.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Linq;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -10,15 +11,20 @@ namespace ICSharpCode.ILSpy @@ -10,15 +11,20 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Node within assembly reference list.
/// </summary>
public class AssemblyReferenceTreeNode : SharpTreeNode
sealed class AssemblyReferenceTreeNode : SharpTreeNode
{
readonly AssemblyNameReference r;
readonly AssemblyTreeNode parentAssembly;
public AssemblyReferenceTreeNode(AssemblyNameReference r)
public AssemblyReferenceTreeNode(AssemblyNameReference r, AssemblyTreeNode parentAssembly)
{
if (parentAssembly == null)
throw new ArgumentNullException("parentAssembly");
if (r == null)
throw new ArgumentNullException("r");
this.r = r;
this.parentAssembly = parentAssembly;
this.LazyLoading = true;
}
public override object Text {
@ -29,6 +35,25 @@ namespace ICSharpCode.ILSpy @@ -29,6 +35,25 @@ namespace ICSharpCode.ILSpy
get { return Images.Assembly; }
}
// TODO: allow drilling down into references used by this reference
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode;
if (assemblyListNode != null) {
assemblyListNode.Select(parentAssembly.LookupReferencedAssembly(r.FullName));
e.Handled = true;
}
}
protected override void LoadChildren()
{
var refNode = parentAssembly.LookupReferencedAssembly(r.FullName);
if (refNode != null) {
AssemblyDefinition asm = refNode.AssemblyDefinition;
if (asm != null) {
foreach (var childRef in asm.MainModule.AssemblyReferences)
this.Children.Add(new AssemblyReferenceTreeNode(childRef, refNode));
}
}
}
}
}

67
ILSpy/AssemblyTreeNode.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.ILSpy @@ -16,7 +16,7 @@ namespace ICSharpCode.ILSpy
{
sealed class AssemblyTreeNode : SharpTreeNode
{
readonly IAssemblyResolver assemblyResolver;
readonly AssemblyListTreeNode assemblyList;
readonly string fileName;
string shortName;
readonly Task<AssemblyDefinition> assemblyTask;
@ -24,13 +24,13 @@ namespace ICSharpCode.ILSpy @@ -24,13 +24,13 @@ namespace ICSharpCode.ILSpy
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
readonly SynchronizationContext syncContext;
public AssemblyTreeNode(string fileName, IAssemblyResolver assemblyResolver)
public AssemblyTreeNode(string fileName, AssemblyListTreeNode assemblyList)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
this.fileName = fileName;
this.assemblyResolver = assemblyResolver;
this.assemblyList = assemblyList;
this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
this.shortName = Path.GetFileNameWithoutExtension(fileName);
this.syncContext = SynchronizationContext.Current;
@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy
{
// runs on background thread
ReaderParameters p = new ReaderParameters();
p.AssemblyResolver = assemblyResolver;
p.AssemblyResolver = new MyAssemblyResolver(this);
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName, p);
foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
classes.Add(new TypeTreeNode(type));
@ -74,10 +74,44 @@ namespace ICSharpCode.ILSpy @@ -74,10 +74,44 @@ namespace ICSharpCode.ILSpy
return assembly;
}
sealed class MyAssemblyResolver : IAssemblyResolver
{
readonly AssemblyTreeNode parent;
public MyAssemblyResolver(AssemblyTreeNode parent)
{
this.parent = parent;
}
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
var node = parent.LookupReferencedAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
var node = parent.LookupReferencedAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
public AssemblyDefinition Resolve(string fullName)
{
var node = parent.LookupReferencedAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
{
var node = parent.LookupReferencedAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
}
protected override void LoadChildren()
{
assemblyTask.Wait();
this.Children.Add(new ReferenceFolderTreeNode(assemblyTask.Result.MainModule));
this.Children.Add(new ReferenceFolderTreeNode(assemblyTask.Result.MainModule, this));
foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear();
}
@ -150,5 +184,28 @@ namespace ICSharpCode.ILSpy @@ -150,5 +184,28 @@ namespace ICSharpCode.ILSpy
dataObject.SetData(DataFormat, nodes.OfType<AssemblyTreeNode>().Select(n => n.fileName).ToArray());
return dataObject;
}
public AssemblyTreeNode LookupReferencedAssembly(string fullName)
{
foreach (AssemblyTreeNode node in assemblyList.Children) {
if (fullName.Equals(node.AssemblyDefinition.FullName, StringComparison.OrdinalIgnoreCase))
return node;
}
var name = AssemblyNameReference.Parse(fullName);
string file = GacInterop.FindAssemblyInNetGac(name);
if (file == null) {
string dir = Path.GetDirectoryName(this.fileName);
if (File.Exists(Path.Combine(dir, name.Name + ".dll")))
file = Path.Combine(dir, name.Name + ".dll");
else if (File.Exists(Path.Combine(dir, name.Name + ".exe")))
file = Path.Combine(dir, name.Name + ".exe");
}
if (file != null) {
return assemblyList.OpenAssembly(file);
} else {
return null;
}
}
}
}

4
ILSpy/GacInterop.cs

@ -75,6 +75,10 @@ namespace ICSharpCode.ILSpy @@ -75,6 +75,10 @@ namespace ICSharpCode.ILSpy
public static string FindAssemblyInNetGac (AssemblyNameReference reference)
{
// without public key, it can't be in the GAC
if (reference.PublicKeyToken == null)
return null;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < gacs.Length; j++) {
var gac = Path.Combine (gac_paths [i], gacs [j]);

31
ILSpy/MainWindow.xaml.cs

@ -40,6 +40,10 @@ namespace ICSharpCode.ILSpy @@ -40,6 +40,10 @@ namespace ICSharpCode.ILSpy
textEditor.Text = "// Welcome to ILSpy!";
treeView.Root = assemblyList;
assemblyList.Select = delegate(SharpTreeNode obj) {
treeView.SelectedItem = obj;
treeView.ScrollIntoView(obj);
};
foreach (Assembly asm in initialAssemblies)
assemblyList.OpenAssembly(asm.Location);
@ -53,13 +57,23 @@ namespace ICSharpCode.ILSpy @@ -53,13 +57,23 @@ namespace ICSharpCode.ILSpy
dlg.Multiselect = true;
dlg.RestoreDirectory = true;
if (dlg.ShowDialog() == true) {
treeView.UnselectAll();
foreach (string file in dlg.FileNames) {
var asm = assemblyList.OpenAssembly(file);
if (asm != null)
treeView.SelectedItems.Add(asm);
OpenFiles(dlg.FileNames);
}
}
void OpenFiles(string[] fileNames)
{
treeView.UnselectAll();
SharpTreeNode lastNode = null;
foreach (string file in fileNames) {
var asm = assemblyList.OpenAssembly(file);
if (asm != null) {
treeView.SelectedItems.Add(asm);
lastNode = asm;
}
}
if (lastNode != null)
treeView.ScrollIntoView(lastNode);
}
void ExitClick(object sender, RoutedEventArgs e)
@ -79,12 +93,7 @@ namespace ICSharpCode.ILSpy @@ -79,12 +93,7 @@ namespace ICSharpCode.ILSpy
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = this;
if (dlg.ShowDialog() == true) {
treeView.UnselectAll();
foreach (string file in dlg.SelectedFileNames) {
var asm = assemblyList.OpenAssembly(file);
if (asm != null)
treeView.SelectedItems.Add(asm);
}
OpenFiles(dlg.SelectedFileNames);
}
}
}

5
ILSpy/OpenFromGacDialog.xaml

@ -20,7 +20,10 @@ @@ -20,7 +20,10 @@
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<TextBox Name="filterTextBox" TextChanged="FilterTextBox_TextChanged" />
<DockPanel>
<Label DockPanel.Dock="Left" Target="{Binding ElementName=filterTextBox}">_Search:</Label>
<TextBox Name="filterTextBox" TextChanged="FilterTextBox_TextChanged" />
</DockPanel>
<ListView Name="listView" Grid.Row="1" Margin="0, 8" local:SortableGridViewColumn.SortMode="Automatic" SelectionChanged="ListView_SelectionChanged">
<ListView.View>
<GridView>

10
ILSpy/ReferenceFolderTreeNode.cs

@ -10,13 +10,15 @@ namespace ICSharpCode.ILSpy @@ -10,13 +10,15 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// References folder.
/// </summary>
public sealed class ReferenceFolderTreeNode : SharpTreeNode
sealed class ReferenceFolderTreeNode : SharpTreeNode
{
ModuleDefinition module;
readonly ModuleDefinition module;
readonly AssemblyTreeNode parentAssembly;
public ReferenceFolderTreeNode(ModuleDefinition module)
public ReferenceFolderTreeNode(ModuleDefinition module, AssemblyTreeNode parentAssembly)
{
this.module = module;
this.parentAssembly = parentAssembly;
this.LazyLoading = true;
}
@ -35,7 +37,7 @@ namespace ICSharpCode.ILSpy @@ -35,7 +37,7 @@ namespace ICSharpCode.ILSpy
protected override void LoadChildren()
{
foreach (var r in module.AssemblyReferences)
this.Children.Add(new AssemblyReferenceTreeNode(r));
this.Children.Add(new AssemblyReferenceTreeNode(r, parentAssembly));
foreach (var r in module.ModuleReferences)
this.Children.Add(new ModuleReferenceTreeNode(r));
}

Loading…
Cancel
Save