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()); + } + } + } + } +}