From a09e984becf9d19fdc552f5bec1250314b2b083a Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Thu, 20 Jan 2011 18:14:37 +0200 Subject: [PATCH] First working versions: one can view all references public metadata --- .../Project/ICSharpCode.SharpDevelop.csproj | 2 + .../TreeNodes/InnerExpand/MemberNodes.cs | 55 +++-- .../TreeNodes/InnerExpand/NamespaceNode.cs | 85 ++++++- .../TreeNodes/InnerExpand/TypeNodes.cs | 227 +++++++++++++----- .../TreeNodes/ReferenceFolder.cs | 12 + .../ProjectBrowser/TreeNodes/ReferenceNode.cs | 72 +++++- .../DecompilerService/DecompilerService.cs | 186 ++++++++++++++ 7 files changed, 555 insertions(+), 84 deletions(-) create mode 100644 src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 10b38fabab..a7b0e82314 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -326,6 +326,7 @@ + @@ -855,6 +856,7 @@ + diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs index c13f1ea118..6fe62668eb 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs @@ -1,21 +1,42 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using Mono.Cecil; +using Services.DecompilerService; namespace ICSharpCode.SharpDevelop.Project.InnerExpand { public abstract class MemberNode : AbstractProjectBrowserTreeNode { + protected readonly MemberReference member; + protected readonly TypeDefinition type; + + public MemberNode(string name, MemberReference member, TypeDefinition type) + { + this.member = member; + this.type = type; + Text = name; + } + + public override void ActivateItem() + { + string filePath = null; + DecompilerService.ReadMetadata(type, out filePath); + FileService.OpenFile(filePath); + + base.ActivateItem(); + } + public override object AcceptVisitor(ProjectBrowserTreeNodeVisitor visitor, object data) { - throw new NotImplementedException(); + return visitor.Visit(this, data); } } #region Field nodes public class PublicFieldNode : MemberNode { - public PublicFieldNode() + public PublicFieldNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.Field"); } @@ -23,7 +44,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class InternalFieldNode : MemberNode { - public InternalFieldNode() + public InternalFieldNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.InteralField"); } @@ -31,7 +52,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class ProtectedFieldNode : MemberNode { - public ProtectedFieldNode() + public ProtectedFieldNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.ProtectedField"); } @@ -39,7 +60,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class PrivateFieldNode : MemberNode { - public PrivateFieldNode() + public PrivateFieldNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.PrivateField"); } @@ -49,7 +70,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #region Properties nodes public class PublicPropertyNode : MemberNode { - public PublicPropertyNode() + public PublicPropertyNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.Property"); } @@ -57,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class InternalPropertyNode : MemberNode { - public InternalPropertyNode() + public InternalPropertyNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.InteralProperty"); } @@ -65,7 +86,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class ProtectedPropertyNode : MemberNode { - public ProtectedPropertyNode() + public ProtectedPropertyNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.ProtectedProperty"); } @@ -73,7 +94,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class PrivatePropertyNode : MemberNode { - public PrivatePropertyNode() + public PrivatePropertyNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.PrivateProperty"); } @@ -84,7 +105,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class PublicMethodNode : MemberNode { - public PublicMethodNode() + public PublicMethodNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.Method"); } @@ -92,7 +113,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class InternalMethodNode : MemberNode { - public InternalMethodNode() + public InternalMethodNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.InternalMethod"); } @@ -100,7 +121,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class ProtectedMethodNode : MemberNode { - public ProtectedMethodNode() + public ProtectedMethodNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.ProtectedMethod"); } @@ -108,7 +129,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class PrivateMethodNode : MemberNode { - public PrivateMethodNode() + public PrivateMethodNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.PrivateMethod"); } @@ -119,7 +140,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #region Event node public class PublicEventNode : MemberNode { - public PublicEventNode() + public PublicEventNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.Event"); } @@ -127,7 +148,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class InternalEventNode : MemberNode { - public InternalEventNode() + public InternalEventNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.InternalEvent"); } @@ -135,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class ProtectedEventNode : MemberNode { - public ProtectedEventNode() + public ProtectedEventNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.ProtectedEvent"); } @@ -143,7 +164,7 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand public class PrivateEventNode : MemberNode { - public PrivateEventNode() + public PrivateEventNode(string name, MemberReference member, TypeDefinition type) : base(name, member, type) { SetIcon("Icons.16x16.PrivateEvent"); } diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/NamespaceNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/NamespaceNode.cs index 533539a942..7ad9bd1edd 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/NamespaceNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/NamespaceNode.cs @@ -1,22 +1,101 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; +using System.Windows; using System.Windows.Forms; using ICSharpCode.Core; +using Mono.Cecil; namespace ICSharpCode.SharpDevelop.Project.InnerExpand { - public class NamespaceNode : AbstractProjectBrowserTreeNode + public class NamespaceNode : CustomFolderNode { - public NamespaceNode() + readonly List types; + + public NamespaceNode(string name, List types) { SetIcon("Icons.16x16.NameSpace"); + Text = name; + this.types = types; + + this.PerformInitialization(); + } + + public void RefreshNodes(bool forceRefresh = false) + { + if (Nodes.Count > 0 && !forceRefresh) + return; + + Nodes.Clear(); + + foreach (var type in types) { + TypeNode node = null; + string name = type.Name; + + if (type.IsValueType) { + if (type.IsPublic) { + node = new PublicStructNode(name, type); + } else { + node = new PrivateStructNode(name, type); + } + } else { + if (type.IsEnum) { + if (type.IsPublic) { + node = new PublicEnumNode(name, type); + } else { + node = new PrivateEnumNode(name, type); + } + } else { + + if (type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate"){ + if (type.IsPublic) { + node = new PublicDelegateNode(name, type); + } else { + node = new PrivateDelegateNode(name, type); + } + } else { + if (type.IsClass) { + if (type.IsPublic) { + node = new PublicClassNode(name, type); + } else { + node = new PrivateClassNode(name, type); + } + } + else { + if (type.IsInterface) { + if (type.IsPublic) { + node = new PublicInterfaceNode(name, type); + } else { + node = new PrivateInterfaceNode(name, type); + } + } + } + } + } + } + + if (node != null) + node.InsertSorted(this); + } + } + + public override void Expanding() + { + foreach (var node in Nodes) { + if (!(node is TypeNode)) continue; + + var n = (TypeNode)node; + n.ShowMembers(); + } + + base.Expanding(); } public override object AcceptVisitor(ProjectBrowserTreeNodeVisitor visitor, object data) { - throw new NotImplementedException(); + return visitor.Visit(this, data); } } } \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs index 88f3cd5d84..1af6bf497f 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs @@ -1,45 +1,115 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Text; +using Mono.Cecil; +using Services.DecompilerService; namespace ICSharpCode.SharpDevelop.Project.InnerExpand { public abstract class TypeNode : AbstractProjectBrowserTreeNode - { + { + protected readonly TypeDefinition type; + + public TypeNode(string name, TypeDefinition type) + { + Text = name; + this.type = type; + + this.PerformInitialization(); + } + + public virtual void ShowMembers(bool forceRefresh = false) + { + if (Nodes.Count > 0 && !forceRefresh) + return; + + Nodes.Clear(); + + foreach (var ev in type.Events) { + if (ev.AddMethod == null && ev.RemoveMethod == null ) continue; + + if (ev.AddMethod != null && !ev.AddMethod.IsPublic && + ev.RemoveMethod != null && !ev.RemoveMethod.IsPublic) continue; + + new PublicEventNode(ev.Name, ev, type).InsertSorted(this); + } + + foreach (var property in type.Properties) { + if (property.GetMethod == null && property.SetMethod == null ) continue; + + if (property.GetMethod != null && !property.GetMethod.IsPublic && + property.SetMethod != null && !property.SetMethod.IsPublic) continue; + new PublicPropertyNode(property.Name, property, type).InsertSorted(this); + } + + foreach (var method in type.Methods) { + if (!method.IsPublic) continue; + if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_")) continue; + + StringBuilder sb = new StringBuilder(); + + if (!method.IsConstructor) { + sb.Append(method.Name); + } else { + sb.Append(method.DeclaringType.Name); + } + + sb.Append(DecompilerService.GetParameters(method)); + + new PublicMethodNode(sb.ToString(), method, type).InsertSorted(this); + } + } + + public override void ActivateItem() + { + string filePath = null; + DecompilerService.ReadMetadata(type, out filePath); + FileService.OpenFile(filePath); + + base.ActivateItem(); + } + public override object AcceptVisitor(ProjectBrowserTreeNodeVisitor visitor, object data) { - throw new NotImplementedException(); + return visitor.Visit(this, data); } } #region Classes - public class PublicClassNode : TypeNode - { - public PublicClassNode() + + public abstract class ClassNode : TypeNode + { + public ClassNode(string name, TypeDefinition type) : base(name, type) { } + } + + public class PublicClassNode : ClassNode + { + public PublicClassNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.Class"); } } - public class InternalClassNode : TypeNode - { - public InternalClassNode() + public class InternalClassNode : ClassNode + { + public InternalClassNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.InternalClass"); } } - public class ProtectedClassNode : TypeNode - { - public ProtectedClassNode() + public class ProtectedClassNode : ClassNode + { + public ProtectedClassNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.ProtectedClass"); } } - public class PrivateClassNode : TypeNode - { - public PrivateClassNode() + public class PrivateClassNode : ClassNode + { + public PrivateClassNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.PrivateClass"); } @@ -48,33 +118,39 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #endregion #region Interfaces - public class PublicInterfaceNode : TypeNode - { - public PublicInterfaceNode() + public abstract class InterfaceNode : TypeNode + { + public InterfaceNode(string name, TypeDefinition type) : base(name, type) { } + + } + + public class PublicInterfaceNode : InterfaceNode + { + public PublicInterfaceNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.Interface"); } } - public class InternalInterfaceNode : TypeNode - { - public InternalInterfaceNode() + public class InternalInterfaceNode : InterfaceNode + { + public InternalInterfaceNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.InternalInterface"); } } - public class ProtectedInterfaceNode : TypeNode - { - public ProtectedInterfaceNode() + public class ProtectedInterfaceNode : InterfaceNode + { + public ProtectedInterfaceNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.ProtectedInterface"); } } - public class PrivateInterfaceNode : TypeNode - { - public PrivateInterfaceNode() + public class PrivateInterfaceNode : InterfaceNode + { + public PrivateInterfaceNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.PrivateInterface"); } @@ -83,33 +159,41 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #endregion #region Structs - public class PublicStructNode : TypeNode - { - public PublicStructNode() + + public abstract class StructNode : TypeNode + { + public StructNode(string name, TypeDefinition type) : base(name, type) + { + } + } + + public class PublicStructNode : StructNode + { + public PublicStructNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.Struct"); } } - public class InternalStructNode : TypeNode - { - public InternalStructNode() + public class InternalStructNode : StructNode + { + public InternalStructNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.InternalStruct"); } } - public class ProtectedStructNode : TypeNode - { - public ProtectedStructNode() + public class ProtectedStructNode : StructNode + { + public ProtectedStructNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.ProtectedStruct"); } } - public class PrivateStructNode : TypeNode - { - public PrivateStructNode() + public class PrivateStructNode : StructNode + { + public PrivateStructNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.PrivateStruct"); } @@ -117,33 +201,40 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #endregion #region Enums - public class PublicEnumNode : TypeNode - { - public PublicEnumNode() + public abstract class EnumNode : TypeNode + { + public EnumNode(string name, TypeDefinition type) : base(name, type) + { + } + } + + public class PublicEnumNode : EnumNode + { + public PublicEnumNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.Enum"); } } - public class IntenalEnumNode : TypeNode - { - public IntenalEnumNode() + public class IntenalEnumNode : EnumNode + { + public IntenalEnumNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.InternalEnum"); } } - public class ProtectedEnumNode : TypeNode - { - public ProtectedEnumNode() + public class ProtectedEnumNode : EnumNode + { + public ProtectedEnumNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.ProtectedEnum"); } } - public class PrivateEnumNode : TypeNode - { - public PrivateEnumNode() + public class PrivateEnumNode : EnumNode + { + public PrivateEnumNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.PrivateEnum"); } @@ -151,33 +242,45 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand #endregion #region Delegates - public class PublicDelegateNode : TypeNode - { - public PublicDelegateNode() + public abstract class DelegateNode : TypeNode + { + public DelegateNode(string name, TypeDefinition type) : base(name, type) + { + } + + public override void ShowMembers(bool forceRefresh) + { + // do nothing + } + } + + public class PublicDelegateNode : DelegateNode + { + public PublicDelegateNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.Delegate"); } } - public class InternalDelegateNode : TypeNode - { - public InternalDelegateNode() + public class InternalDelegateNode : DelegateNode + { + public InternalDelegateNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.InternalDelegate"); } } - public class ProtectedDelegateNode : TypeNode - { - public ProtectedDelegateNode() + public class ProtectedDelegateNode : DelegateNode + { + public ProtectedDelegateNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.ProtectedDelegate"); } } - public class PrivateDelegateNode : TypeNode - { - public PrivateDelegateNode() + public class PrivateDelegateNode : DelegateNode + { + public PrivateDelegateNode(string name, TypeDefinition type) : base(name, type) { SetIcon("Icons.16x16.PrivateDelegate"); } diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceFolder.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceFolder.cs index e3a1ce4dbc..880088984c 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceFolder.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceFolder.cs @@ -42,6 +42,18 @@ namespace ICSharpCode.SharpDevelop.Project UpdateIcon(); } + public override void Expanding() + { + foreach (var node in Nodes) { + if (!(node is ReferenceNode)) continue; + + var n = (ReferenceNode)node; + n.ShowNamespaces(); + } + + base.Expanding(); + } + protected override void Initialize() { ShowReferences(); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs index b028ce4d6e..7d1a81c40e 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs @@ -2,12 +2,15 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; +using ICSharpCode.SharpDevelop.Project.InnerExpand; +using Mono.Cecil; namespace ICSharpCode.SharpDevelop.Project { - public class ReferenceNode : AbstractProjectBrowserTreeNode + public class ReferenceNode : CustomFolderNode { ReferenceProjectItem referenceProjectItem; @@ -21,10 +24,75 @@ namespace ICSharpCode.SharpDevelop.Project { this.referenceProjectItem = referenceProjectItem; Tag = referenceProjectItem; - + ContextmenuAddinTreePath = "/SharpDevelop/Pads/ProjectBrowser/ContextMenu/ReferenceNode"; SetIcon("Icons.16x16.Reference"); Text = referenceProjectItem.ShortName; + + this.PerformInitialization(); + + ParserService.LoadSolutionProjectsThreadEnded += delegate { ShowNamespaces(); }; + } + + Dictionary> namespaces = new Dictionary>(); + + public void ShowNamespaces(bool forceRefresh = false) + { + if (namespaces.Count > 0 && !forceRefresh) + return; + + namespaces.Clear(); + Nodes.Clear(); + + if (string.IsNullOrEmpty(referenceProjectItem.FileName)) return; + if (!File.Exists(referenceProjectItem.FileName)) return; + + if (Path.GetExtension(referenceProjectItem.FileName) == ".dll" || + Path.GetExtension(referenceProjectItem.FileName) == ".exe") + { + var asm = AssemblyDefinition.ReadAssembly(referenceProjectItem.FileName); + foreach (var module in asm.Modules) { + if (!module.HasTypes) continue; + + foreach (var type in module.Types) { + + if (string.IsNullOrEmpty(type.Namespace)) continue; + + if (!namespaces.ContainsKey(type.Namespace)) + namespaces.Add(type.Namespace, new List()); + + namespaces[type.Namespace].Add(type); + } + + foreach (var ns in namespaces.Keys) + { + var nsNode = new NamespaceNode(ns, namespaces[ns]); + nsNode.InsertSorted(this); + } + } + } + + if (Path.GetExtension(referenceProjectItem.FileName).EndsWith("proj")) { + // use parser service + } + } + + public override void Expanding() + { + foreach (var node in Nodes) { + if (!(node is NamespaceNode)) continue; + + var n = (NamespaceNode)node; + n.RefreshNodes(); + } + + base.Expanding(); + } + + public override void Refresh() + { + ShowNamespaces(true); + base.Refresh(); } #region Cut & Paste diff --git a/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs b/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs new file mode 100644 index 0000000000..6e1d208ede --- /dev/null +++ b/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs @@ -0,0 +1,186 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Text; + +using Mono.Cecil; + +namespace Services.DecompilerService +{ + public static class DecompilerService + { + public static void ReadMetadata(TypeDefinition type, out string filePath) + { + if (type == null) + { + filePath = null; + return; + } + + StringBuilder sb = new StringBuilder(); + + sb.Append("using System;"); + + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + + sb.Append("namespace " + type.Namespace); + sb.Append(Environment.NewLine); + sb.Append("{"); + sb.Append(Environment.NewLine); + + // attributes + if (type.HasCustomAttributes) { + foreach (var attr in type.CustomAttributes) { + sb.Append("\t["); + sb.Append(attr.AttributeType.Name); + sb.Append("]"); + sb.Append(Environment.NewLine); + } + } + + // main definition + sb.Append("\tpublic "); + + if (type.IsValueType) + sb.Append("struct "); + else + if (type.IsEnum) + sb.Append("enum "); + else { + if (type.IsClass) { + if (type.IsAbstract) + sb.Append("abstract "); + if (type.IsSealed) + sb.Append("sealed "); + sb.Append("class "); + } + + if (type.IsInterface) + sb.Append("interface "); + } + + sb.Append(type.Name); + + // inheritance + if (type.BaseType != null) { + sb.Append(" : "); + sb.Append(type.BaseType.Name); + } + + sb.Append(Environment.NewLine); + sb.Append("\t{"); + sb.Append(Environment.NewLine); + + if (type.HasEvents) { + sb.Append("\t");sb.Append("\t");sb.Append("// Public Events"); + sb.Append(Environment.NewLine); + + foreach (var ev in type.Events) { + sb.Append("\t");sb.Append("\t"); + sb.Append("public event ");sb.Append(ev.EventType.FullName);sb.Append(" ");sb.Append(ev.Name); + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + } + } + + if (type.HasProperties) { + sb.Append("\t");sb.Append("\t");sb.Append("// Public Properties"); + sb.Append(Environment.NewLine); + + foreach (var property in type.Properties) { + + if (property.GetMethod != null && !property.GetMethod.IsPublic && + property.SetMethod != null && !property.SetMethod.IsPublic) + continue; + + sb.Append("\t");sb.Append("\t"); + sb.Append("public ");sb.Append(property.PropertyType.FullName);sb.Append(" ");sb.Append(property.Name); + sb.Append(" {"); + if (property.GetMethod != null && property.GetMethod.IsPublic) + sb.Append(" get;"); + if (property.SetMethod != null && property.SetMethod.IsPublic) + sb.Append(" set;"); + sb.Append(" }"); + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + } + } + + if (type.HasMethods) { + sb.Append("\t");sb.Append("\t");sb.Append("// Public Methods"); + sb.Append(Environment.NewLine); + + foreach (var method in type.Methods) { + + if (method.IsPrivate) continue; + + if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_")) continue; + + sb.Append("\t");sb.Append("\t"); + sb.Append("public "); + if (method.IsStatic) + sb.Append("static "); + + if (!method.IsConstructor) { + sb.Append(method.ReturnType.FullName);sb.Append(" ");sb.Append(method.Name); + } else { + sb.Append(type.Name); + } + + sb.Append(GetParameters(method)); + + sb.Append(";"); + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + } + } + + sb.Append("\t}"); + sb.Append(Environment.NewLine); + sb.Append("}"); + + // temp file + string tempFolder = Path.GetTempPath(); + string file = type.Name + ".temp.cs"; + filePath = Path.Combine(tempFolder, file); + + using (StreamWriter sr = new StreamWriter(filePath)) { + sr.Write(sb.ToString()); + } + } + + public static string GetParameters(MethodDefinition method) + { + StringBuilder sb = new StringBuilder(); + + if (!method.HasParameters) + sb.Append("()"); + else { + sb.Append("("); + for (int i = 0 ; i < method.Parameters.Count; ++i) { + var p = method.Parameters[i]; + + if (p.IsOut) + sb.Append("out "); + else + if (p.ParameterType.IsByReference) + sb.Append("ref "); + + sb.Append(p.ParameterType.Name.Replace("&", string.Empty)); + sb.Append(" "); + + sb.Append(p.Name); + + if (i < method.Parameters.Count - 1) + sb.Append(", "); + } + sb.Append(")"); + } + + return sb.ToString(); + } + } +}