mirror of https://github.com/icsharpcode/ILSpy.git
12 changed files with 923 additions and 18 deletions
@ -1,18 +1,40 @@ |
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00 |
Microsoft Visual Studio Solution File, Format Version 11.00 |
||||||
# Visual Studio 2010 |
# 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}" |
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}" |
||||||
EndProject |
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 |
Global |
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||||
Debug|x86 = Debug|x86 |
Debug|x86 = Debug|x86 |
||||||
Release|x86 = Release|x86 |
Release|x86 = Release|x86 |
||||||
|
Debug|Any CPU = Debug|Any CPU |
||||||
|
Release|Any CPU = Release|Any CPU |
||||||
EndGlobalSection |
EndGlobalSection |
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||||
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|x86.Build.0 = Debug|x86 |
{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}.Debug|x86.ActiveCfg = Debug|x86 |
||||||
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.Build.0 = Release|x86 |
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.Build.0 = Release|x86 |
||||||
{1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|x86.ActiveCfg = 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 |
EndGlobalSection |
||||||
EndGlobal |
EndGlobal |
||||||
|
|||||||
@ -1,8 +1,12 @@ |
|||||||
<Application x:Class="ICSharpCode.ILSpy.App" |
<Application x:Class="ICSharpCode.ILSpy.App" |
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
StartupUri="Window1.xaml"> |
StartupUri="MainWindow.xaml"> |
||||||
<Application.Resources> |
<Application.Resources> |
||||||
|
<Style x:Key="DialogWindow" TargetType="{x:Type Window}"> |
||||||
|
<Setter Property="ShowInTaskbar" Value="False"/> |
||||||
|
<Setter Property="UseLayoutRounding" Value="True"/> |
||||||
|
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/> |
||||||
|
</Style> |
||||||
</Application.Resources> |
</Application.Resources> |
||||||
</Application> |
</Application> |
||||||
@ -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<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>(); |
||||||
|
|
||||||
|
public AssemblyTreeNode(AssemblyDefinition assembly) |
||||||
|
{ |
||||||
|
if (assembly == null) |
||||||
|
throw new ArgumentNullException("assembly"); |
||||||
|
this.assembly = assembly; |
||||||
|
this.Namespaces = new ObservableCollection<NamespaceTreeNode>(); |
||||||
|
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"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
After Width: | Height: | Size: 466 B |
@ -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"); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,9 +1,16 @@ |
|||||||
<Window x:Class="ICSharpCode.ILSpy.MainWindow" |
<Window x:Class="ICSharpCode.ILSpy.MainWindow" |
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
Title="ILSpy" Height="300" Width="300" |
xmlns:tv="http://icsharpcode.net/sharpdevelop/treeview" |
||||||
> |
Title="ILSpy" |
||||||
<Grid> |
Width="790" |
||||||
|
Height="500" |
||||||
</Grid> |
MinWidth="250" |
||||||
|
MinHeight="200" |
||||||
|
UseLayoutRounding="True" |
||||||
|
Hyperlink.RequestNavigate="Window_RequestNavigate" |
||||||
|
TextOptions.TextFormattingMode="Display" |
||||||
|
> |
||||||
|
<tv:SharpTreeView Name="treeView" ShowRoot="False" AllowDropOrder="True"> |
||||||
|
</tv:SharpTreeView> |
||||||
</Window> |
</Window> |
||||||
@ -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 (); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -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; } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -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 |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Static helper methods for traversing trees.
|
||||||
|
/// </summary>
|
||||||
|
public static class TreeTraversal |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Converts a tree data structure into a flat list by traversing it in pre-order.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="root">The root element of the tree.</param>
|
||||||
|
/// <param name="recursion">The function that gets the children of an element.</param>
|
||||||
|
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
|
||||||
|
public static IEnumerable<T> PreOrder<T>(T root, Func<T, IEnumerable<T>> recursion) |
||||||
|
{ |
||||||
|
return PreOrder(new T[] { root }, recursion); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a tree data structure into a flat list by traversing it in pre-order.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The root elements of the forest.</param>
|
||||||
|
/// <param name="recursion">The function that gets the children of an element.</param>
|
||||||
|
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
|
||||||
|
public static IEnumerable<T> PreOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion) |
||||||
|
{ |
||||||
|
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); |
||||||
|
try { |
||||||
|
stack.Push(input.GetEnumerator()); |
||||||
|
while (stack.Count > 0) { |
||||||
|
while (stack.Peek().MoveNext()) { |
||||||
|
T element = stack.Peek().Current; |
||||||
|
yield return element; |
||||||
|
IEnumerable<T> children = recursion(element); |
||||||
|
if (children != null) { |
||||||
|
stack.Push(children.GetEnumerator()); |
||||||
|
} |
||||||
|
} |
||||||
|
stack.Pop().Dispose(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
while (stack.Count > 0) { |
||||||
|
stack.Pop().Dispose(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a tree data structure into a flat list by traversing it in post-order.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="root">The root element of the tree.</param>
|
||||||
|
/// <param name="recursion">The function that gets the children of an element.</param>
|
||||||
|
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
|
||||||
|
public static IEnumerable<T> PostOrder<T>(T root, Func<T, IEnumerable<T>> recursion) |
||||||
|
{ |
||||||
|
return PostOrder(new T[] { root }, recursion); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a tree data structure into a flat list by traversing it in post-order.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The root elements of the forest.</param>
|
||||||
|
/// <param name="recursion">The function that gets the children of an element.</param>
|
||||||
|
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
|
||||||
|
public static IEnumerable<T> PostOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion) |
||||||
|
{ |
||||||
|
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>(); |
||||||
|
try { |
||||||
|
stack.Push(input.GetEnumerator()); |
||||||
|
while (stack.Count > 0) { |
||||||
|
while (stack.Peek().MoveNext()) { |
||||||
|
T element = stack.Peek().Current; |
||||||
|
IEnumerable<T> 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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -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<TypeTreeNode> NestedTypes { get; private set; } |
||||||
|
|
||||||
|
public TypeTreeNode(TypeDefinition type) |
||||||
|
{ |
||||||
|
if (type == null) |
||||||
|
throw new ArgumentNullException("type"); |
||||||
|
this.type = type; |
||||||
|
|
||||||
|
this.NestedTypes = new ObservableCollection<TypeTreeNode>(); |
||||||
|
} |
||||||
|
|
||||||
|
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()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue