diff --git a/ILSpy.sln b/ILSpy.sln
index 5df99973a..5ade10b79 100644
--- a/ILSpy.sln
+++ b/ILSpy.sln
@@ -1,18 +1,40 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
-# SharpDevelop 4.0.1.7084
+# SharpDevelop 4.0.1.7088
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "SharpTreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "Mono.Cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.Build.0 = Debug|x86
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.ActiveCfg = Debug|x86
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.Build.0 = Release|x86
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.ActiveCfg = Release|x86
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.Build.0 = Debug|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.Build.0 = Release|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|x86.ActiveCfg = Release|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_2_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
EndGlobalSection
EndGlobal
diff --git a/ILSpy/App.xaml b/ILSpy/App.xaml
index 3bd2f1a77..92638e3aa 100644
--- a/ILSpy/App.xaml
+++ b/ILSpy/App.xaml
@@ -1,8 +1,12 @@
+ StartupUri="MainWindow.xaml">
-
+
\ No newline at end of file
diff --git a/ILSpy/AssemblyTreeNode.cs b/ILSpy/AssemblyTreeNode.cs
new file mode 100644
index 000000000..b1b2ff5a7
--- /dev/null
+++ b/ILSpy/AssemblyTreeNode.cs
@@ -0,0 +1,105 @@
+// 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.Linq;
+
+using ICSharpCode.TreeView;
+using Mono.Cecil;
+
+namespace ICSharpCode.ILSpy
+{
+ sealed class AssemblyTreeNode : SharpTreeNode
+ {
+ readonly AssemblyDefinition assembly;
+ readonly List classes = new List();
+ public ObservableCollection Namespaces { get; private set; }
+ readonly Dictionary typeDict = new Dictionary();
+ readonly Dictionary namespaces = new Dictionary();
+
+ public AssemblyTreeNode(AssemblyDefinition assembly)
+ {
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+ this.assembly = assembly;
+ this.Namespaces = new ObservableCollection();
+ InitClassList();
+ BuildNestedTypeLists();
+ BuildNamespaceList();
+ }
+
+ public override object Text {
+ get { return assembly.Name.Name; }
+ }
+
+ public override object Icon {
+ get { return Images.Assembly; }
+ }
+
+ void InitClassList()
+ {
+ foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
+ var viewmodel = 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));
+ }
+ }
+ }
+
+ void BuildNestedTypeLists()
+ {
+ foreach (var typeModel in typeDict.Values) {
+ 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) {
+ 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);
+ }
+ }
+
+ bool showInternalAPI;
+
+ public bool ShowInternalAPI {
+ get { return showInternalAPI; }
+ set {
+ if (showInternalAPI != value) {
+ showInternalAPI = value;
+ BuildNestedTypeLists();
+ BuildNamespaceList();
+ RaisePropertyChanged("ShowInternalAPI");
+ }
+ }
+ }
+ }
+}
diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 659dff6d2..7bc88d0f3 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -64,13 +64,18 @@
Code
App.xaml
-
+
+
+
+
Code
MainWindow.xaml
+
+
@@ -106,11 +111,22 @@
-
+
+
+
+
+
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+ Mono.Cecil
+
+
+ {DDE2A481-8271-4EAC-A330-8FA6A38D13D1}
+ ICSharpCode.TreeView
+
\ No newline at end of file
diff --git a/ILSpy/Images/Assembly.png b/ILSpy/Images/Assembly.png
new file mode 100644
index 000000000..85a4dfa0b
Binary files /dev/null and b/ILSpy/Images/Assembly.png differ
diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs
new file mode 100644
index 000000000..54bb6ac84
--- /dev/null
+++ b/ILSpy/Images/Images.cs
@@ -0,0 +1,55 @@
+// 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.Windows.Media.Imaging;
+
+namespace ICSharpCode.ILSpy
+{
+ static class Images
+ {
+ static BitmapImage LoadBitmap(string name)
+ {
+ BitmapImage image = new BitmapImage(new Uri("pack://application:,,,/Images/" + name + ".png"));
+ image.Freeze();
+ return image;
+ }
+
+ public static readonly BitmapImage Assembly = LoadBitmap("Assembly");
+ public static readonly BitmapImage Namespace = LoadBitmap("NameSpace");
+
+
+ public static readonly BitmapImage Class = LoadBitmap("Class");
+ public static readonly BitmapImage Delegate = LoadBitmap("Delegate");
+ public static readonly BitmapImage Enum = LoadBitmap("Enum");
+ public static readonly BitmapImage Interface = LoadBitmap("Interface");
+ public static readonly BitmapImage Struct = LoadBitmap("Struct");
+ public static readonly BitmapImage Field = LoadBitmap("Field");
+ public static readonly BitmapImage Method = LoadBitmap("Method");
+ public static readonly BitmapImage Literal = LoadBitmap("Literal");
+
+ public static readonly BitmapImage InternalClass = LoadBitmap("InternalClass");
+ public static readonly BitmapImage InternalDelegate = LoadBitmap("InternalDelegate");
+ public static readonly BitmapImage InternalEnum = LoadBitmap("InternalEnum");
+ public static readonly BitmapImage InternalInterface = LoadBitmap("InternalInterface");
+ public static readonly BitmapImage InternalStruct = LoadBitmap("InternalStruct");
+ public static readonly BitmapImage InternalField = LoadBitmap("InternalField");
+ public static readonly BitmapImage InternalMethod = LoadBitmap("InternalMethod");
+
+ public static readonly BitmapImage PrivateClass = LoadBitmap("PrivateClass");
+ public static readonly BitmapImage PrivateDelegate = LoadBitmap("PrivateDelegate");
+ public static readonly BitmapImage PrivateEnum = LoadBitmap("PrivateEnum");
+ public static readonly BitmapImage PrivateInterface = LoadBitmap("PrivateInterface");
+ public static readonly BitmapImage PrivateStruct = LoadBitmap("PrivateStruct");
+ public static readonly BitmapImage PrivateField = LoadBitmap("PrivateField");
+ public static readonly BitmapImage PrivateMethod = LoadBitmap("PrivateMethod");
+
+ public static readonly BitmapImage ProtectedClass = LoadBitmap("ProtectedClass");
+ public static readonly BitmapImage ProtectedDelegate = LoadBitmap("ProtectedDelegate");
+ public static readonly BitmapImage ProtectedEnum = LoadBitmap("ProtectedEnum");
+ public static readonly BitmapImage ProtectedInterface = LoadBitmap("ProtectedInterface");
+ public static readonly BitmapImage ProtectedStruct = LoadBitmap("ProtectedStruct");
+ public static readonly BitmapImage ProtectedField = LoadBitmap("ProtectedField");
+ public static readonly BitmapImage ProtectedMethod = LoadBitmap("ProtectedMethod");
+ }
+}
diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml
index 0e1331b87..08c7e012c 100644
--- a/ILSpy/MainWindow.xaml
+++ b/ILSpy/MainWindow.xaml
@@ -1,9 +1,16 @@
-
-
-
+ xmlns:tv="http://icsharpcode.net/sharpdevelop/treeview"
+ Title="ILSpy"
+ Width="790"
+ Height="500"
+ MinWidth="250"
+ MinHeight="200"
+ UseLayoutRounding="True"
+ Hyperlink.RequestNavigate="Window_RequestNavigate"
+ TextOptions.TextFormattingMode="Display"
+>
+
+
\ No newline at end of file
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index 5877b7ddd..fbc922239 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -2,25 +2,33 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Diagnostics;
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.TreeView;
+using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
///
- /// Interaction logic for Window1.xaml
+ /// The main window of the application.
///
public partial class MainWindow : Window
{
+ SharpTreeNodeCollection assemblies;
+
public MainWindow()
{
InitializeComponent();
+
+ treeView.Root = new SharpTreeNode();
+ assemblies = treeView.Root.Children;
+
+ assemblies.Add(new AssemblyTreeNode(AssemblyDefinition.ReadAssembly(typeof(object).Assembly.Location)));
+ }
+
+ void Window_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
+ {
+ Process.Start(e.Uri.ToString());
}
}
}
\ No newline at end of file
diff --git a/ILSpy/Mono.Cecil.Rocks/MethodBodyRocks.cs b/ILSpy/Mono.Cecil.Rocks/MethodBodyRocks.cs
new file mode 100644
index 000000000..d12cc80bf
--- /dev/null
+++ b/ILSpy/Mono.Cecil.Rocks/MethodBodyRocks.cs
@@ -0,0 +1,426 @@
+//
+// MethodBodyRocks.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// Copyright (c) 2008 - 2010 Jb Evain
+//
+// 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.Cil;
+
+namespace Mono.Cecil.Rocks {
+
+#if INSIDE_ROCKS
+ public
+#endif
+ static class MethodBodyRocks {
+
+ public static ParameterDefinition GetParameter (this MethodBody self, int index)
+ {
+ var method = self.Method;
+
+ if (method.HasThis) {
+ if (index == 0)
+ return self.ThisParameter;
+
+ index--;
+ }
+
+ var parameters = method.Parameters;
+
+ if (index < 0 || index >= parameters.Count)
+ return null;
+
+ return parameters [index];
+ }
+
+ public static void SimplifyMacros (this MethodBody self)
+ {
+ if (self == null)
+ throw new ArgumentNullException ("self");
+
+ foreach (var instruction in self.Instructions) {
+ if (instruction.OpCode.OpCodeType != OpCodeType.Macro)
+ continue;
+
+ switch (instruction.OpCode.Code) {
+ case Code.Ldarg_0:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (0));
+ break;
+ case Code.Ldarg_1:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (1));
+ break;
+ case Code.Ldarg_2:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (2));
+ break;
+ case Code.Ldarg_3:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (3));
+ break;
+ case Code.Ldloc_0:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [0]);
+ break;
+ case Code.Ldloc_1:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [1]);
+ break;
+ case Code.Ldloc_2:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [2]);
+ break;
+ case Code.Ldloc_3:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [3]);
+ break;
+ case Code.Stloc_0:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [0]);
+ break;
+ case Code.Stloc_1:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [1]);
+ break;
+ case Code.Stloc_2:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [2]);
+ break;
+ case Code.Stloc_3:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [3]);
+ break;
+ case Code.Ldarg_S:
+ instruction.OpCode = OpCodes.Ldarg;
+ break;
+ case Code.Ldarga_S:
+ instruction.OpCode = OpCodes.Ldarga;
+ break;
+ case Code.Starg_S:
+ instruction.OpCode = OpCodes.Starg;
+ break;
+ case Code.Ldloc_S:
+ instruction.OpCode = OpCodes.Ldloc;
+ break;
+ case Code.Ldloca_S:
+ instruction.OpCode = OpCodes.Ldloca;
+ break;
+ case Code.Stloc_S:
+ instruction.OpCode = OpCodes.Stloc;
+ break;
+ case Code.Ldc_I4_M1:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, -1);
+ break;
+ case Code.Ldc_I4_0:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 0);
+ break;
+ case Code.Ldc_I4_1:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 1);
+ break;
+ case Code.Ldc_I4_2:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 2);
+ break;
+ case Code.Ldc_I4_3:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 3);
+ break;
+ case Code.Ldc_I4_4:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 4);
+ break;
+ case Code.Ldc_I4_5:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 5);
+ break;
+ case Code.Ldc_I4_6:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 6);
+ break;
+ case Code.Ldc_I4_7:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 7);
+ break;
+ case Code.Ldc_I4_8:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 8);
+ break;
+ case Code.Ldc_I4_S:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, (int) (sbyte) instruction.Operand);
+ break;
+ case Code.Br_S:
+ instruction.OpCode = OpCodes.Br;
+ break;
+ case Code.Brfalse_S:
+ instruction.OpCode = OpCodes.Brfalse;
+ break;
+ case Code.Brtrue_S:
+ instruction.OpCode = OpCodes.Brtrue;
+ break;
+ case Code.Beq_S:
+ instruction.OpCode = OpCodes.Beq;
+ break;
+ case Code.Bge_S:
+ instruction.OpCode = OpCodes.Bge;
+ break;
+ case Code.Bgt_S:
+ instruction.OpCode = OpCodes.Bgt;
+ break;
+ case Code.Ble_S:
+ instruction.OpCode = OpCodes.Ble;
+ break;
+ case Code.Blt_S:
+ instruction.OpCode = OpCodes.Blt;
+ break;
+ case Code.Bne_Un_S:
+ instruction.OpCode = OpCodes.Bne_Un;
+ break;
+ case Code.Bge_Un_S:
+ instruction.OpCode = OpCodes.Bge_Un;
+ break;
+ case Code.Bgt_Un_S:
+ instruction.OpCode = OpCodes.Bgt_Un;
+ break;
+ case Code.Ble_Un_S:
+ instruction.OpCode = OpCodes.Ble_Un;
+ break;
+ case Code.Blt_Un_S:
+ instruction.OpCode = OpCodes.Blt_Un;
+ break;
+ case Code.Leave_S:
+ instruction.OpCode = OpCodes.Leave;
+ break;
+ }
+ }
+ }
+
+ static void ExpandMacro (Instruction instruction, OpCode opcode, object operand)
+ {
+ instruction.OpCode = opcode;
+ instruction.Operand = operand;
+ }
+
+ static void MakeMacro (Instruction instruction, OpCode opcode)
+ {
+ instruction.OpCode = opcode;
+ instruction.Operand = null;
+ }
+
+ public static void OptimizeMacros (this MethodBody self)
+ {
+ if (self == null)
+ throw new ArgumentNullException ("self");
+
+ var method = self.Method;
+
+ foreach (var instruction in self.Instructions) {
+ int index;
+ switch (instruction.OpCode.Code) {
+ case Code.Ldarg:
+ index = ((ParameterDefinition) instruction.Operand).Index;
+ if (index == -1 && instruction.Operand == self.ThisParameter)
+ index = 0;
+ else if (method.HasThis)
+ index++;
+
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldarg_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldarg_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldarg_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldarg_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldarg_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Ldloc:
+ index = ((VariableDefinition) instruction.Operand).Index;
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldloc_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldloc_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldloc_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldloc_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldloc_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Stloc:
+ index = ((VariableDefinition) instruction.Operand).Index;
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Stloc_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Stloc_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Stloc_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Stloc_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Stloc_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Ldarga:
+ index = ((ParameterDefinition) instruction.Operand).Index;
+ if (index == -1 && instruction.Operand == self.ThisParameter)
+ index = 0;
+ else if (method.HasThis)
+ index++;
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldarga_S, instruction.Operand);
+ break;
+ case Code.Ldloca:
+ if (((VariableDefinition) instruction.Operand).Index < 256)
+ ExpandMacro (instruction, OpCodes.Ldloca_S, instruction.Operand);
+ break;
+ case Code.Ldc_I4:
+ int i = (int) instruction.Operand;
+ switch (i) {
+ case -1:
+ MakeMacro (instruction, OpCodes.Ldc_I4_M1);
+ break;
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldc_I4_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldc_I4_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldc_I4_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldc_I4_3);
+ break;
+ case 4:
+ MakeMacro (instruction, OpCodes.Ldc_I4_4);
+ break;
+ case 5:
+ MakeMacro (instruction, OpCodes.Ldc_I4_5);
+ break;
+ case 6:
+ MakeMacro (instruction, OpCodes.Ldc_I4_6);
+ break;
+ case 7:
+ MakeMacro (instruction, OpCodes.Ldc_I4_7);
+ break;
+ case 8:
+ MakeMacro (instruction, OpCodes.Ldc_I4_8);
+ break;
+ default:
+ if (i >= -128 && i < 128)
+ ExpandMacro (instruction, OpCodes.Ldc_I4_S, (sbyte) i);
+ break;
+ }
+ break;
+ }
+ }
+
+ OptimizeBranches (self);
+ }
+
+ static void OptimizeBranches (MethodBody body)
+ {
+ ComputeOffsets (body);
+
+ foreach (var instruction in body.Instructions) {
+ if (instruction.OpCode.OperandType != OperandType.InlineBrTarget)
+ continue;
+
+ if (OptimizeBranch (instruction))
+ ComputeOffsets (body);
+ }
+ }
+
+ static bool OptimizeBranch (Instruction instruction)
+ {
+ var offset = ((Instruction) instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4);
+ if (!(offset >= -128 && offset <= 127))
+ return false;
+
+ switch (instruction.OpCode.Code) {
+ case Code.Br:
+ instruction.OpCode = OpCodes.Br_S;
+ break;
+ case Code.Brfalse:
+ instruction.OpCode = OpCodes.Brfalse_S;
+ break;
+ case Code.Brtrue:
+ instruction.OpCode = OpCodes.Brtrue_S;
+ break;
+ case Code.Beq:
+ instruction.OpCode = OpCodes.Beq_S;
+ break;
+ case Code.Bge:
+ instruction.OpCode = OpCodes.Bge_S;
+ break;
+ case Code.Bgt:
+ instruction.OpCode = OpCodes.Bgt_S;
+ break;
+ case Code.Ble:
+ instruction.OpCode = OpCodes.Ble_S;
+ break;
+ case Code.Blt:
+ instruction.OpCode = OpCodes.Blt_S;
+ break;
+ case Code.Bne_Un:
+ instruction.OpCode = OpCodes.Bne_Un_S;
+ break;
+ case Code.Bge_Un:
+ instruction.OpCode = OpCodes.Bge_Un_S;
+ break;
+ case Code.Bgt_Un:
+ instruction.OpCode = OpCodes.Bgt_Un_S;
+ break;
+ case Code.Ble_Un:
+ instruction.OpCode = OpCodes.Ble_Un_S;
+ break;
+ case Code.Blt_Un:
+ instruction.OpCode = OpCodes.Blt_Un_S;
+ break;
+ case Code.Leave:
+ instruction.OpCode = OpCodes.Leave_S;
+ break;
+ }
+
+ return true;
+ }
+
+ static void ComputeOffsets (MethodBody body)
+ {
+ var offset = 0;
+ foreach (var instruction in body.Instructions) {
+ instruction.Offset = offset;
+ offset += instruction.GetSize ();
+ }
+ }
+ }
+}
diff --git a/ILSpy/NamespaceTreeNode.cs b/ILSpy/NamespaceTreeNode.cs
new file mode 100644
index 000000000..493426058
--- /dev/null
+++ b/ILSpy/NamespaceTreeNode.cs
@@ -0,0 +1,33 @@
+// 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.ObjectModel;
+using ICSharpCode.TreeView;
+
+namespace ICSharpCode.ILSpy
+{
+ sealed class NamespaceTreeNode : SharpTreeNode
+ {
+ string name;
+
+ public string Name {
+ get { return name; }
+ }
+
+ public NamespaceTreeNode(string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ this.name = name.Length == 0 ? "-" : name;
+ }
+
+ public override object Text {
+ get { return name; }
+ }
+
+ public override object Icon {
+ get { return Images.Namespace; }
+ }
+ }
+}
diff --git a/ILSpy/TreeTraversal.cs b/ILSpy/TreeTraversal.cs
new file mode 100644
index 000000000..ae428ac51
--- /dev/null
+++ b/ILSpy/TreeTraversal.cs
@@ -0,0 +1,97 @@
+// Copyright (c) 2010 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;
+
+namespace ICSharpCode.ILSpy
+{
+ ///
+ /// Static helper methods for traversing trees.
+ ///
+ public static class TreeTraversal
+ {
+ ///
+ /// Converts a tree data structure into a flat list by traversing it in pre-order.
+ ///
+ /// The root element of the tree.
+ /// The function that gets the children of an element.
+ /// Iterator that enumerates the tree structure in pre-order.
+ public static IEnumerable PreOrder(T root, Func> recursion)
+ {
+ return PreOrder(new T[] { root }, recursion);
+ }
+
+ ///
+ /// Converts a tree data structure into a flat list by traversing it in pre-order.
+ ///
+ /// The root elements of the forest.
+ /// The function that gets the children of an element.
+ /// Iterator that enumerates the tree structure in pre-order.
+ public static IEnumerable PreOrder(IEnumerable input, Func> recursion)
+ {
+ Stack> stack = new Stack>();
+ try {
+ stack.Push(input.GetEnumerator());
+ while (stack.Count > 0) {
+ while (stack.Peek().MoveNext()) {
+ T element = stack.Peek().Current;
+ yield return element;
+ IEnumerable children = recursion(element);
+ if (children != null) {
+ stack.Push(children.GetEnumerator());
+ }
+ }
+ stack.Pop().Dispose();
+ }
+ } finally {
+ while (stack.Count > 0) {
+ stack.Pop().Dispose();
+ }
+ }
+ }
+
+ ///
+ /// Converts a tree data structure into a flat list by traversing it in post-order.
+ ///
+ /// The root element of the tree.
+ /// The function that gets the children of an element.
+ /// Iterator that enumerates the tree structure in post-order.
+ public static IEnumerable PostOrder(T root, Func> recursion)
+ {
+ return PostOrder(new T[] { root }, recursion);
+ }
+
+ ///
+ /// Converts a tree data structure into a flat list by traversing it in post-order.
+ ///
+ /// The root elements of the forest.
+ /// The function that gets the children of an element.
+ /// Iterator that enumerates the tree structure in post-order.
+ public static IEnumerable PostOrder(IEnumerable input, Func> recursion)
+ {
+ Stack> stack = new Stack>();
+ try {
+ stack.Push(input.GetEnumerator());
+ while (stack.Count > 0) {
+ while (stack.Peek().MoveNext()) {
+ T element = stack.Peek().Current;
+ IEnumerable children = recursion(element);
+ if (children != null) {
+ stack.Push(children.GetEnumerator());
+ } else {
+ yield return element;
+ }
+ }
+ stack.Pop().Dispose();
+ if (stack.Count > 0)
+ yield return stack.Peek().Current;
+ }
+ } finally {
+ while (stack.Count > 0) {
+ stack.Pop().Dispose();
+ }
+ }
+ }
+ }
+}
diff --git a/ILSpy/TypeTreeNode.cs b/ILSpy/TypeTreeNode.cs
new file mode 100644
index 000000000..977cd1d57
--- /dev/null
+++ b/ILSpy/TypeTreeNode.cs
@@ -0,0 +1,132 @@
+// 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.Windows.Media;
+
+using ICSharpCode.TreeView;
+using Mono.Cecil;
+
+namespace ICSharpCode.ILSpy
+{
+ sealed class TypeTreeNode : SharpTreeNode
+ {
+ readonly TypeDefinition type;
+
+ public ObservableCollection NestedTypes { get; private set; }
+
+ public TypeTreeNode(TypeDefinition type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ this.type = type;
+
+ this.NestedTypes = new ObservableCollection();
+ }
+
+ public string Name {
+ get { return type.Name; }
+ }
+
+ public string Namespace {
+ get { return type.Namespace; }
+ }
+
+ public override object Text {
+ get { return type.Name; }
+ }
+
+ enum ClassType
+ {
+ Class,
+ Enum,
+ Struct,
+ Interface,
+ Delegate
+ }
+
+ ClassType GetClassType()
+ {
+ if (type.IsValueType) {
+ if (type.IsEnum)
+ return ClassType.Enum;
+ else
+ return ClassType.Struct;
+ } else {
+ if (type.IsInterface)
+ return ClassType.Interface;
+ else if (type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName)
+ return ClassType.Delegate;
+ else
+ return ClassType.Class;
+ }
+ }
+
+ 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 {
+ get {
+ switch (this.Visibility) {
+ case TypeAttributes.Public:
+ case TypeAttributes.NestedPublic:
+ switch (this.GetClassType()) {
+ case ClassType.Delegate: return Images.Delegate;
+ case ClassType.Enum: return Images.Enum;
+ case ClassType.Interface: return Images.Interface;
+ case ClassType.Struct: return Images.Struct;
+ default: return Images.Class;
+ }
+ case TypeAttributes.NotPublic:
+ case TypeAttributes.NestedAssembly:
+ case TypeAttributes.NestedFamANDAssem:
+ switch (this.GetClassType()) {
+ case ClassType.Delegate: return Images.InternalDelegate;
+ case ClassType.Enum: return Images.InternalEnum;
+ case ClassType.Interface: return Images.InternalInterface;
+ case ClassType.Struct: return Images.InternalStruct;
+ default: return Images.InternalClass;
+ }
+ case TypeAttributes.NestedFamily:
+ case TypeAttributes.NestedFamORAssem:
+ switch (this.GetClassType()) {
+ case ClassType.Delegate: return Images.ProtectedDelegate;
+ case ClassType.Enum: return Images.ProtectedEnum;
+ case ClassType.Interface: return Images.ProtectedInterface;
+ case ClassType.Struct: return Images.ProtectedStruct;
+ default: return Images.ProtectedClass;
+ }
+ case TypeAttributes.NestedPrivate:
+ switch (this.GetClassType()) {
+ case ClassType.Delegate: return Images.PrivateDelegate;
+ case ClassType.Enum: return Images.PrivateEnum;
+ case ClassType.Interface: return Images.PrivateInterface;
+ case ClassType.Struct: return Images.PrivateStruct;
+ default: return Images.PrivateClass;
+ }
+ default:
+ throw new NotSupportedException(this.Visibility.ToString());
+ }
+ }
+ }
+ }
+}