diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index cce7182f9..b79492d1f 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -3,14 +3,17 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; +using System.Xml; using System.Xml.Linq; - using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; +using Mono.Cecil; using Ricciolo.StylesExplorer.MarkupReflection; namespace ILSpy.BamlDecompiler @@ -45,17 +48,55 @@ namespace ILSpy.BamlDecompiler bool LoadBaml(AvalonEditTextOutput output) { var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; - MemoryStream bamlStream = new MemoryStream(); Data.Position = 0; - Data.CopyTo(bamlStream); - bamlStream.Position = 0; - + XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.AssemblyDefinition, Data); + output.Write(xamlDocument.ToString()); + return true; + } + + internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream) + { XDocument xamlDocument; - using (XmlBamlReader reader = new XmlBamlReader(bamlStream, new CecilTypeResolver(asm))) + using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) xamlDocument = XDocument.Load(reader); + ConvertToEmptyElements(xamlDocument.Root); + MoveNamespacesToRoot(xamlDocument); + return xamlDocument; + } + + static void MoveNamespacesToRoot(XDocument xamlDocument) + { + var additionalXmlns = new List { + new XAttribute("xmlns", XmlBamlReader.DefaultWPFNamespace), + new XAttribute(XName.Get("x", XNamespace.Xmlns.NamespaceName), XmlBamlReader.XWPFNamespace) + }; - output.Write(xamlDocument.ToString()); - return true; + foreach (var element in xamlDocument.Root.DescendantsAndSelf()) { + if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace && !additionalXmlns.Any(ka => ka.Value == element.Name.NamespaceName)) { + string newPrefix = new string(element.Name.LocalName.Where(c => char.IsUpper(c)).ToArray()).ToLowerInvariant(); + int current = additionalXmlns.Count(ka => ka.Name.Namespace == XNamespace.Xmlns && ka.Name.LocalName.TrimEnd(ch => char.IsNumber(ch)) == newPrefix); + if (current > 0) + newPrefix += (current + 1).ToString(); + XName defaultXmlns = XName.Get(newPrefix, XNamespace.Xmlns.NamespaceName); + if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace) + additionalXmlns.Add(new XAttribute(defaultXmlns, element.Name.NamespaceName)); + } + } + + foreach (var xmlns in additionalXmlns.Except(xamlDocument.Root.Attributes())) { + xamlDocument.Root.Add(xmlns); + } + } + + static void ConvertToEmptyElements(XElement element) + { + foreach (var el in element.Elements()) { + if (!el.IsEmpty && !el.HasElements && el.Value == "") { + el.RemoveNodes(); + continue; + } + ConvertToEmptyElements(el); + } } } } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/CecilType.cs b/ILSpy.BamlDecompiler/CecilType.cs index 41a0fc203..e84f95938 100644 --- a/ILSpy.BamlDecompiler/CecilType.cs +++ b/ILSpy.BamlDecompiler/CecilType.cs @@ -67,5 +67,15 @@ namespace ILSpy.BamlDecompiler { return string.Format("[CecilType Type={0}]", type); } + + public IType BaseType { + get { + TypeDefinition td = type.BaseType.Resolve(); + if (td == null) + throw new Exception("could not resolve '" + type.BaseType.FullName + "'!"); + + return new CecilType(td); + } + } } } diff --git a/ILSpy.BamlDecompiler/CecilTypeResolver.cs b/ILSpy.BamlDecompiler/CecilTypeResolver.cs index 853025b06..702c37c38 100644 --- a/ILSpy.BamlDecompiler/CecilTypeResolver.cs +++ b/ILSpy.BamlDecompiler/CecilTypeResolver.cs @@ -14,11 +14,18 @@ namespace ILSpy.BamlDecompiler /// public class CecilTypeResolver : ITypeResolver { - LoadedAssembly assembly; + IAssemblyResolver resolver; + AssemblyDefinition thisAssembly; - public CecilTypeResolver(LoadedAssembly assembly) + public CecilTypeResolver(IAssemblyResolver resolver, AssemblyDefinition asm) { - this.assembly = assembly; + this.resolver = resolver; + this.thisAssembly = asm; + } + + public bool IsLocalAssembly(string name) + { + return name == this.thisAssembly.Name.Name; } public IType GetTypeByAssemblyQualifiedName(string name) @@ -31,12 +38,12 @@ namespace ILSpy.BamlDecompiler string fullName = name.Substring(0, comma); string assemblyName = name.Substring(comma + 1).Trim(); - var type = assembly.AssemblyDefinition.MainModule.GetType(fullName); + var type = thisAssembly.MainModule.GetType(fullName); if (type == null) { - var otherAssembly = assembly.LookupReferencedAssembly(assemblyName); + var otherAssembly = resolver.Resolve(assemblyName); if (otherAssembly == null) throw new Exception("could not resolve '" + assemblyName + "'!"); - type = otherAssembly.AssemblyDefinition.MainModule.GetType(fullName); + type = otherAssembly.MainModule.GetType(fullName); } return new CecilType(type); @@ -49,5 +56,11 @@ namespace ILSpy.BamlDecompiler return new CecilDependencyPropertyDescriptor(name, ((CecilType)ownerType).type); } + + public string RuntimeVersion { + get { + return thisAssembly.MainModule.Runtime.ToString(); + } + } } } diff --git a/ILSpy.BamlDecompiler/Extensions.cs b/ILSpy.BamlDecompiler/Extensions.cs new file mode 100644 index 000000000..c76a581ea --- /dev/null +++ b/ILSpy.BamlDecompiler/Extensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Linq; + +namespace ILSpy.BamlDecompiler +{ + public static class Extensions + { + public static string TrimEnd(this string target, Func predicate) + { + if (target == null) + throw new ArgumentNullException("target"); + + while (predicate(target.LastOrDefault())) + target = target.Remove(target.Length - 1); + + return target; + } + } +} diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index 6514c632b..a681f07fd 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -77,6 +77,7 @@ + @@ -97,6 +98,7 @@ + diff --git a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs index f28440c93..a2c459d27 100644 --- a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs +++ b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs @@ -3,6 +3,7 @@ using System; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; #endregion @@ -22,6 +23,8 @@ using System.Runtime.InteropServices; // If you need to expose a type to COM, use [ComVisible(true)] on that type. [assembly: ComVisible(false)] +[assembly: InternalsVisibleTo("ILSpy.BamlDecompiler.Tests")] + // The assembly version has following format : // // Major.Minor.Build.Revision diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs index 9cc329459..b33379323 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs @@ -131,6 +131,17 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return null; } } + + public bool IsLocalAssembly(string name) + { + return false; + } + + public string RuntimeVersion { + get { + throw new NotImplementedException(); + } + } #endregion diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs index 1dbf1b21a..313863bd0 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs @@ -42,6 +42,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection if (_type == null) return false; return this._type.Equals(((DotNetType)type).Type); } + + public IType BaseType { + get { + return new DotNetType(this._type.BaseType.AssemblyQualifiedName); + } + } #endregion diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs index 7ec8c79e4..b420bf480 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs @@ -8,10 +8,11 @@ using System.Text; namespace Ricciolo.StylesExplorer.MarkupReflection { /// - /// Interface rappresenting a DotNet type + /// Interface representing a DotNet type /// public interface IType { + IType BaseType { get; } string AssemblyQualifiedName { get; } bool IsSubclassOf(IType type); bool Equals(IType type); diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs index 71e802a61..993126b32 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs @@ -9,6 +9,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection { public interface ITypeResolver { + string RuntimeVersion { get; } + bool IsLocalAssembly(string name); IType GetTypeByAssemblyQualifiedName(string name); IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType); } diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs index e58762f41..81d7bea20 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs @@ -34,12 +34,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection public KnownInfo(ITypeResolver resolver) { - KnownAssemblyTable = new string[5]; - KnownAssemblyTable[0] = "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; - KnownAssemblyTable[1] = "PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; - KnownAssemblyTable[2] = "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; - KnownAssemblyTable[3] = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; - KnownAssemblyTable[4] = "WindowBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + switch (resolver.RuntimeVersion) { + case "Net_2_0": + LoadKnownAssemblies30(); + break; + case "Net_4_0": + LoadKnownAssemblies40(); + break; + default: + throw new NotSupportedException(); + } KnownTypeTable = new TypeDeclaration[760]; KnownTypeTable[0] = new TypeDeclaration(resolver, string.Empty, string.Empty, 0); @@ -1305,6 +1309,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection KnownResourceTable.Add(0xa9, new ResourceName("SystemParameters.WorkArea")); } + void LoadKnownAssemblies30() + { + KnownAssemblyTable = new string[5]; + KnownAssemblyTable[0] = "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[1] = "PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[2] = "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[3] = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[4] = "WindowBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + } + + void LoadKnownAssemblies40() + { + KnownAssemblyTable = new string[5]; + KnownAssemblyTable[0] = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[1] = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[2] = "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[3] = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[4] = "WindowBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + } + #endregion public bool IsKnownType(string type) diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs index 93ed72c66..6417549f7 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs @@ -8,6 +8,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Reflection; using System.Text; using System.Xml; @@ -54,6 +55,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection private readonly TypeDeclaration XamlTypeDeclaration; private readonly XmlNameTable _nameTable = new NameTable(); private IDictionary _rootNamespaces; + + public const string XWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; + public const string DefaultWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; #endregion @@ -159,7 +163,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection public override bool MoveToFirstAttribute() { intoAttribute = false; - if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty) + if (nodes.Count > 0 && (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty)) { _currentNode = nodes.Dequeue(); return true; @@ -178,7 +182,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection public override bool MoveToNextAttribute() { intoAttribute = false; - if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty) + if (nodes.Count > 0 && (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty)) { _currentNode = nodes.Dequeue(); return true; @@ -196,7 +200,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection /// public override bool MoveToElement() { - while (nodes.Peek() is XmlBamlProperty) + while (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty) { nodes.Dequeue(); } @@ -284,13 +288,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection else currentType = (BamlRecordType)type; - if (currentType.ToString().EndsWith("End")) - Debug.Unindent(); - - Debug.WriteLine(currentType); - - if (currentType.ToString().StartsWith("Start")) - Debug.Indent(); +// Debug.WriteLine(currentType); } private bool SetNextNode() @@ -300,6 +298,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection _currentNode = nodes.Dequeue(); if ((_currentNode is XmlBamlProperty)) continue; + if ((_currentNode is XmlBamlSimpleProperty)) continue; if (this.NodeType == XmlNodeType.EndElement) { @@ -451,7 +450,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection break; default: throw new NotImplementedException("UnsupportedNode: " + currentType); - break; } } @@ -586,7 +584,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection String localName = String.Empty; XmlBamlNode node = this.CurrentNode; - if (node is XmlBamlProperty) + if (node is XmlBamlSimpleProperty) { + var simpleNode = (XmlBamlSimpleProperty)node; + localName = simpleNode.LocalName; + } else if (node is XmlBamlProperty) { PropertyDeclaration pd = ((XmlBamlProperty)node).PropertyDeclaration; localName = FormatPropertyDeclaration(pd, false, true, true); @@ -1057,9 +1058,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection private void ReadPropertyComplexEnd() { - if (!(elements.Peek() is XmlBamlPropertyElement)) - throw new InvalidCastException(); - XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement) elements.Peek(); CloseElement(); @@ -1191,10 +1189,22 @@ namespace Ricciolo.StylesExplorer.MarkupReflection } else element = new XmlBamlElement(); + + // the type is defined in the local assembly, i.e., the main assembly + // and this is the root element + TypeDeclaration oldDeclaration = null; + if (_resolver.IsLocalAssembly(declaration.Assembly) && parentElement == null) { + oldDeclaration = declaration; + declaration = GetKnownTypeDeclarationByName(declaration.Type.BaseType.AssemblyQualifiedName); + } element.TypeDeclaration = declaration; elements.Push(element); nodes.Enqueue(element); + + if (oldDeclaration != null) { + nodes.Enqueue(new XmlBamlSimpleProperty(XWPFNamespace, "Class", string.Format("{0}.{1}", oldDeclaration.Namespace, oldDeclaration.Name))); + } if (parentElement != null && complexPropertyOpened == 0) { @@ -1572,6 +1582,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return declaration; } + + TypeDeclaration GetKnownTypeDeclarationByName(string name) + { + foreach (var type in KnownInfo.KnownTypeTable) { + if (name == string.Format("{0}.{1}, {2}", type.Namespace, type.Name, type.Assembly)) + return type; + } + + throw new NotSupportedException(); + } internal string GetAssembly(short identifier) { @@ -1602,7 +1622,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection TypeDeclaration declaration; XmlBamlNode node = this.CurrentNode; - if (node is XmlBamlProperty) + if (node is XmlBamlSimpleProperty) + return ((XmlBamlSimpleProperty)node).NamespaceName; + else if (node is XmlBamlProperty) { declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType; TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration; @@ -1678,7 +1700,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection get { XmlBamlNode node = this.CurrentNode; - if (node is XmlBamlProperty) + if (node is XmlBamlSimpleProperty) + return ((XmlBamlSimpleProperty)node).Value; + else if (node is XmlBamlProperty) return ((XmlBamlProperty)node).Value.ToString(); else if (node is XmlBamlText) return ((XmlBamlText)node).Text; diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlSimpleProperty.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlSimpleProperty.cs new file mode 100644 index 000000000..be00e41e1 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlSimpleProperty.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + class XmlBamlSimpleProperty : XmlBamlNode + { + public string NamespaceName { get; private set; } + public string LocalName { get; private set; } + public string Value { get; private set; } + + public XmlBamlSimpleProperty(string namespaceName, string localName, string value) + { + if (string.IsNullOrWhiteSpace(namespaceName)) + throw new ArgumentException("namespaceName"); + if (string.IsNullOrWhiteSpace(localName)) + throw new ArgumentException("localName"); + if (value == null) + throw new ArgumentNullException("value"); + this.NamespaceName = namespaceName; + this.LocalName = localName; + this.Value = value; + } + + public override XmlNodeType NodeType { + get { return XmlNodeType.Attribute; } + } + } +} diff --git a/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml b/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml new file mode 100644 index 000000000..ab5d5afc6 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml.cs b/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml.cs new file mode 100644 index 000000000..12770ff11 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml.cs @@ -0,0 +1,26 @@ +// 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.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; + +namespace ILSpy.BamlDecompiler.Tests.Cases +{ + /// + /// Interaction logic for Simple.xaml + /// + public partial class Simple : Window + { + public Simple() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/Cases/SimpleDictionary.xaml b/ILSpy.BamlDecompiler/Tests/Cases/SimpleDictionary.xaml new file mode 100644 index 000000000..4eb8fb3c7 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/Cases/SimpleDictionary.xaml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj new file mode 100644 index 000000000..975dfc6ee --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -0,0 +1,112 @@ + + + + {1169E6D1-1899-43D4-A500-07CE4235B388} + Debug + x86 + Library + ILSpy.BamlDecompiler.Tests + ILSpy.BamlDecompiler.Tests + v4.0 + Client + False + False + 4 + false + + + x86 + False + Auto + 4194304 + 4096 + + + ..\bin\Debug\ + true + Full + False + True + DEBUG;TRACE + + + ..\bin\Release\ + false + None + True + False + TRACE + + + + ..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll + + + ..\..\ICSharpCode.Decompiler\Tests\nunit.framework.dll + + + + 3.0 + + + + 3.0 + + + + 3.5 + + + 4.0 + + + + 3.5 + + + + 3.0 + + + + + Simple.xaml + Code + + + + + + + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22} + ICSharpCode.Decompiler.Tests + + + {1E85EFF9-E370-4683-83E4-8A3D063FF791} + ILSpy + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1} + ICSharpCode.TreeView + + + {A6BAD2BA-76BA-461C-8B6D-418607591247} + ILSpy.BamlDecompiler + + + + + + + + + Always + + + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Tests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..30c5daa49 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ILSpy.BamlDecompiler.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ILSpy.BamlDecompiler.Tests")] +[assembly: AssemblyCopyright("Copyright 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] diff --git a/ILSpy.BamlDecompiler/Tests/TestRunner.cs b/ILSpy.BamlDecompiler/Tests/TestRunner.cs new file mode 100644 index 000000000..441116873 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/TestRunner.cs @@ -0,0 +1,73 @@ +// 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; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Resources; +using System.Xml.Linq; +using ICSharpCode.Decompiler.Tests.Helpers; +using ICSharpCode.ILSpy; +using Mono.Cecil; +using NUnit.Framework; +using Ricciolo.StylesExplorer.MarkupReflection; + +namespace ILSpy.BamlDecompiler.Tests +{ + [TestFixture] + public class TestRunner + { + [Test] + public void Simple() + { + RunTest("cases/simple"); + } + + [Test] + public void SimpleDictionary() + { + RunTest("cases/simpledictionary"); + } + + void RunTest(string name) + { + string asmPath = typeof(TestRunner).Assembly.Location; + var assembly = AssemblyDefinition.ReadAssembly(asmPath); + Resource res = assembly.MainModule.Resources.First(); + Stream bamlStream = LoadBaml(res, name + ".baml"); + Assert.IsNotNull(bamlStream); + XDocument document = BamlResourceEntryNode.LoadIntoDocument(new DefaultAssemblyResolver(), assembly, bamlStream); + string path = Path.Combine("..\\..\\Tests", name + ".xaml"); + + CodeAssert.AreEqual(document.ToString(), File.ReadAllText(path)); + } + + Stream LoadBaml(Resource res, string name) + { + EmbeddedResource er = res as EmbeddedResource; + if (er != null) { + Stream s = er.GetResourceStream(); + s.Position = 0; + ResourceReader reader; + try { + reader = new ResourceReader(s); + } + catch (ArgumentException) { + return null; + } + foreach (DictionaryEntry entry in reader.Cast().OrderBy(e => e.Key.ToString())) { + if (entry.Key.ToString() == name) { + if (entry.Value is Stream) + return (Stream)entry.Value; + if (entry.Value is byte[]) + return new MemoryStream((byte[])entry.Value); + } + } + } + + return null; + } + } +} diff --git a/ILSpy.sln b/ILSpy.sln index e3c407eb5..22cda9165 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.0.1.7146 +# SharpDevelop 4.1.0.7466-alpha Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}" ProjectSection(SolutionItems) = postProject doc\Command Line.txt = doc\Command Line.txt @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "Mono.Ceci EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler\Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -115,6 +117,14 @@ Global {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.Build.0 = Release|x86 {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.ActiveCfg = Release|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|x86.Build.0 = Debug|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|x86.ActiveCfg = Debug|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.Build.0 = Release|x86 + {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.ActiveCfg = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ILSpy/AnalyzerTreeView.cs b/ILSpy/AnalyzerTreeView.cs index d89174d18..94f4ed66c 100644 --- a/ILSpy/AnalyzerTreeView.cs +++ b/ILSpy/AnalyzerTreeView.cs @@ -17,15 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; -using System.Text; -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.ILSpy.TreeNodes.Analyzer; using ICSharpCode.TreeView; @@ -37,9 +28,11 @@ namespace ICSharpCode.ILSpy public partial class AnalyzerTreeView : SharpTreeView, IPane { static AnalyzerTreeView instance; - - public static AnalyzerTreeView Instance { - get { + + public static AnalyzerTreeView Instance + { + get + { if (instance == null) { App.Current.VerifyAccess(); instance = new AnalyzerTreeView(); @@ -47,42 +40,33 @@ namespace ICSharpCode.ILSpy return instance; } } - + private AnalyzerTreeView() { this.ShowRoot = false; this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage }; ContextMenuProvider.Add(this); } - + public void Show() { if (!IsVisible) MainWindow.Instance.ShowInBottomPane("Analyzer", this); } - + public void Show(AnalyzerTreeNode node) { Show(); - + node.IsExpanded = true; this.Root.Children.Add(node); this.SelectedItem = node; this.FocusNode(node); } - + void IPane.Closed() { this.Root.Children.Clear(); } } - - [ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)] - sealed class ShowAnalyzerCommand : SimpleCommand - { - public override void Execute(object parameter) - { - AnalyzerTreeView.Instance.Show(); - } - } } \ No newline at end of file diff --git a/ILSpy/Commands.cs b/ILSpy/Commands.cs deleted file mode 100644 index 8d89e9afc..000000000 --- a/ILSpy/Commands.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// 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 System.ComponentModel.Composition; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Input; -using ICSharpCode.ILSpy.TextView; -using ICSharpCode.ILSpy.TreeNodes; - -namespace ICSharpCode.ILSpy -{ - [ExportMainMenuCommand(Menu = "_File", Header = "E_xit", MenuOrder = 99999, MenuCategory = "Exit")] - sealed class ExitCommand : SimpleCommand - { - public override void Execute(object parameter) - { - MainWindow.Instance.Close(); - } - } - - [ExportToolbarCommand(ToolTip = "Back", ToolbarIcon = "Images/Back.png", ToolbarCategory = "Navigation", ToolbarOrder = 0)] - sealed class BrowseBackCommand : CommandWrapper { - public BrowseBackCommand() : base(NavigationCommands.BrowseBack) {} - } - - [ExportToolbarCommand(ToolTip = "Forward", ToolbarIcon = "Images/Forward.png", ToolbarCategory = "Navigation", ToolbarOrder = 1)] - sealed class BrowseForwardCommand : CommandWrapper { - public BrowseForwardCommand() : base(NavigationCommands.BrowseForward) {} - } - - [ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)] - [ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)] - sealed class OpenCommand : CommandWrapper { - public OpenCommand() : base(ApplicationCommands.Open) {} - } - - [ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuCategory = "Open", MenuOrder = 1)] - sealed class OpenFromGacCommand : SimpleCommand - { - public override void Execute(object parameter) - { - OpenFromGacDialog dlg = new OpenFromGacDialog(); - dlg.Owner = MainWindow.Instance; - if (dlg.ShowDialog() == true) { - MainWindow.Instance.OpenFiles(dlg.SelectedFileNames); - } - } - } - - [ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)] - [ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)] - sealed class RefreshCommand : CommandWrapper { - public RefreshCommand() : base(NavigationCommands.Refresh) {} - } - - [ExportMainMenuCommand(Menu = "_File", Header = "_Save Code...", MenuIcon = "Images/SaveFile.png", MenuCategory = "Save", MenuOrder = 0)] - sealed class SaveCommand : CommandWrapper - { - public SaveCommand() : base(ApplicationCommands.Save) {} - } - - #if DEBUG - [ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Decompile All", MenuCategory = "Open", MenuOrder = 2.5)] - sealed class DecompileAllCommand : SimpleCommand - { - public override bool CanExecute(object parameter) - { - return System.IO.Directory.Exists("c:\\temp\\decompiled"); - } - - public override void Execute(object parameter) - { - MainWindow.Instance.TextView.RunWithCancellation( - ct => Task.Factory.StartNew( - () => { - AvalonEditTextOutput output = new AvalonEditTextOutput(); - Parallel.ForEach( - MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), - new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, - delegate (LoadedAssembly asm) { - if (!asm.HasLoadError) { - Stopwatch w = Stopwatch.StartNew(); - Exception exception = null; - using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) { - try { - new CSharpLanguage().DecompileAssembly( - asm, new Decompiler.PlainTextOutput(writer), - new DecompilationOptions { FullDecompilation = true, CancellationToken = ct }); - } catch (Exception ex) { - writer.WriteLine(ex.ToString()); - exception = ex; - } - } - lock (output) { - output.Write(asm.ShortName + " - " + w.Elapsed); - if (exception != null) { - output.Write(" - "); - output.Write(exception.GetType().Name); - } - output.WriteLine(); - } - } - }); - return output; - } - ), - task => MainWindow.Instance.TextView.ShowText(task.Result)); - } - } - #endif - - class CommandWrapper : ICommand - { - ICommand wrappedCommand; - - public CommandWrapper(ICommand wrappedCommand) - { - this.wrappedCommand = wrappedCommand; - } - - public static ICommand Unwrap(ICommand command) - { - CommandWrapper w = command as CommandWrapper; - if (w != null) - return w.wrappedCommand; - else - return command; - } - - public event EventHandler CanExecuteChanged { - add { wrappedCommand.CanExecuteChanged += value; } - remove { wrappedCommand.CanExecuteChanged -= value; } - } - - public void Execute(object parameter) - { - wrappedCommand.Execute(parameter); - } - - public bool CanExecute(object parameter) - { - return wrappedCommand.CanExecute(parameter); - } - } - - public abstract class SimpleCommand : ICommand - { - public event EventHandler CanExecuteChanged { - add { CommandManager.RequerySuggested += value; } - remove { CommandManager.RequerySuggested -= value; } - } - - public abstract void Execute(object parameter); - - public virtual bool CanExecute(object parameter) - { - return true; - } - } -} diff --git a/ILSpy/Commands/BrowseBackCommand.cs b/ILSpy/Commands/BrowseBackCommand.cs new file mode 100644 index 000000000..e5af95db8 --- /dev/null +++ b/ILSpy/Commands/BrowseBackCommand.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + [ExportToolbarCommand(ToolTip = "Back", ToolbarIcon = "Images/Back.png", ToolbarCategory = "Navigation", ToolbarOrder = 0)] + sealed class BrowseBackCommand : CommandWrapper + { + public BrowseBackCommand() + : base(NavigationCommands.BrowseBack) + { + } + } +} diff --git a/ILSpy/Commands/BrowseForwardCommand.cs b/ILSpy/Commands/BrowseForwardCommand.cs new file mode 100644 index 000000000..1e0db84a7 --- /dev/null +++ b/ILSpy/Commands/BrowseForwardCommand.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + [ExportToolbarCommand(ToolTip = "Forward", ToolbarIcon = "Images/Forward.png", ToolbarCategory = "Navigation", ToolbarOrder = 1)] + sealed class BrowseForwardCommand : CommandWrapper + { + public BrowseForwardCommand() + : base(NavigationCommands.BrowseForward) + { + } + } +} diff --git a/ILSpy/Commands/CommandWrapper.cs b/ILSpy/Commands/CommandWrapper.cs new file mode 100644 index 000000000..f3d89138c --- /dev/null +++ b/ILSpy/Commands/CommandWrapper.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + class CommandWrapper : ICommand + { + private ICommand wrappedCommand; + + public CommandWrapper(ICommand wrappedCommand) + { + this.wrappedCommand = wrappedCommand; + } + + public static ICommand Unwrap(ICommand command) + { + CommandWrapper w = command as CommandWrapper; + if (w != null) + return w.wrappedCommand; + else + return command; + } + + public event EventHandler CanExecuteChanged + { + add { wrappedCommand.CanExecuteChanged += value; } + remove { wrappedCommand.CanExecuteChanged -= value; } + } + + public void Execute(object parameter) + { + wrappedCommand.Execute(parameter); + } + + public bool CanExecute(object parameter) + { + return wrappedCommand.CanExecute(parameter); + } + } +} diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs new file mode 100644 index 000000000..542c155e4 --- /dev/null +++ b/ILSpy/Commands/DecompileAllCommand.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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. + +#if DEBUG + +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using ICSharpCode.ILSpy.TextView; + +namespace ICSharpCode.ILSpy +{ + [ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Decompile All", MenuCategory = "Open", MenuOrder = 2.5)] + sealed class DecompileAllCommand : SimpleCommand + { + public override bool CanExecute(object parameter) + { + return System.IO.Directory.Exists("c:\\temp\\decompiled"); + } + + public override void Execute(object parameter) + { + MainWindow.Instance.TextView.RunWithCancellation(ct => Task.Factory.StartNew(() => { + AvalonEditTextOutput output = new AvalonEditTextOutput(); + Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) { + if (!asm.HasLoadError) { + Stopwatch w = Stopwatch.StartNew(); + Exception exception = null; + using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) { + try { + new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions { FullDecompilation = true, CancellationToken = ct }); + } + catch (Exception ex) { + writer.WriteLine(ex.ToString()); + exception = ex; + } + } + lock (output) { + output.Write(asm.ShortName + " - " + w.Elapsed); + if (exception != null) { + output.Write(" - "); + output.Write(exception.GetType().Name); + } + output.WriteLine(); + } + } + }); + return output; + }), task => MainWindow.Instance.TextView.ShowText(task.Result)); + } + } +} + +#endif \ No newline at end of file diff --git a/ILSpy/Commands/ExitCommand.cs b/ILSpy/Commands/ExitCommand.cs new file mode 100644 index 000000000..d064aa557 --- /dev/null +++ b/ILSpy/Commands/ExitCommand.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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; + +namespace ICSharpCode.ILSpy +{ + [ExportMainMenuCommand(Menu = "_File", Header = "E_xit", MenuOrder = 99999, MenuCategory = "Exit")] + sealed class ExitCommand : SimpleCommand + { + public override void Execute(object parameter) + { + MainWindow.Instance.Close(); + } + } +} \ No newline at end of file diff --git a/ILSpy/ExportCommandAttribute.cs b/ILSpy/Commands/ExportCommandAttribute.cs similarity index 100% rename from ILSpy/ExportCommandAttribute.cs rename to ILSpy/Commands/ExportCommandAttribute.cs diff --git a/ILSpy/Commands/OpenCommand.cs b/ILSpy/Commands/OpenCommand.cs new file mode 100644 index 000000000..74030365f --- /dev/null +++ b/ILSpy/Commands/OpenCommand.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + [ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)] + [ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)] + sealed class OpenCommand : CommandWrapper + { + public OpenCommand() + : base(ApplicationCommands.Open) + { + } + } +} diff --git a/ILSpy/Commands/OpenFromGacCommand.cs b/ILSpy/Commands/OpenFromGacCommand.cs new file mode 100644 index 000000000..ceeff5bdc --- /dev/null +++ b/ILSpy/Commands/OpenFromGacCommand.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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; + +namespace ICSharpCode.ILSpy +{ + [ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuCategory = "Open", MenuOrder = 1)] + sealed class OpenFromGacCommand : SimpleCommand + { + public override void Execute(object parameter) + { + OpenFromGacDialog dlg = new OpenFromGacDialog(); + dlg.Owner = MainWindow.Instance; + if (dlg.ShowDialog() == true) + MainWindow.Instance.OpenFiles(dlg.SelectedFileNames); + } + } +} diff --git a/ILSpy/Commands/RefreshCommand.cs b/ILSpy/Commands/RefreshCommand.cs new file mode 100644 index 000000000..21edd69c5 --- /dev/null +++ b/ILSpy/Commands/RefreshCommand.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + [ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)] + [ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)] + sealed class RefreshCommand : CommandWrapper + { + public RefreshCommand() + : base(NavigationCommands.Refresh) + { + } + } +} diff --git a/ILSpy/Commands/SaveCommand.cs b/ILSpy/Commands/SaveCommand.cs new file mode 100644 index 000000000..63989d863 --- /dev/null +++ b/ILSpy/Commands/SaveCommand.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + [ExportMainMenuCommand(Menu = "_File", Header = "_Save Code...", MenuIcon = "Images/SaveFile.png", MenuCategory = "Save", MenuOrder = 0)] + sealed class SaveCommand : CommandWrapper + { + public SaveCommand() + : base(ApplicationCommands.Save) + { + } + } +} diff --git a/ILSpy/Commands/ShowAnalyzerCommand.cs b/ILSpy/Commands/ShowAnalyzerCommand.cs new file mode 100644 index 000000000..1dcc74c6d --- /dev/null +++ b/ILSpy/Commands/ShowAnalyzerCommand.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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; + +namespace ICSharpCode.ILSpy +{ + [ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)] + sealed class ShowAnalyzerCommand : SimpleCommand + { + public override void Execute(object parameter) + { + AnalyzerTreeView.Instance.Show(); + } + } +} diff --git a/ILSpy/Commands/SimpleCommand.cs b/ILSpy/Commands/SimpleCommand.cs new file mode 100644 index 000000000..d8490a1a6 --- /dev/null +++ b/ILSpy/Commands/SimpleCommand.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Windows.Input; + +namespace ICSharpCode.ILSpy +{ + public abstract class SimpleCommand : ICommand + { + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public abstract void Execute(object parameter); + + public virtual bool CanExecute(object parameter) + { + return true; + } + } +} diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index e8264a3e7..d35d9fd11 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -93,6 +93,8 @@ + + @@ -107,18 +109,20 @@ - + + + DecompilerSettingsPanel.xaml Code - + - + @@ -126,19 +130,23 @@ - - + + + - + + + + OpenFromGacDialog.xaml Code @@ -148,6 +156,8 @@ Code + + Code @@ -155,6 +165,8 @@ DisplaySettingsPanel.xaml Code + + @@ -171,6 +183,9 @@ + + + @@ -335,6 +350,7 @@ + diff --git a/ILSpy/IPane.cs b/ILSpy/IPane.cs new file mode 100644 index 000000000..2447f8bdd --- /dev/null +++ b/ILSpy/IPane.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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; + +namespace ICSharpCode.ILSpy +{ + public interface IPane + { + void Closed(); + } +} diff --git a/ILSpy/Images/Delete.png b/ILSpy/Images/Delete.png index 824d938dd..560865f30 100644 Binary files a/ILSpy/Images/Delete.png and b/ILSpy/Images/Delete.png differ diff --git a/ILSpy/Images/OverlayInternal.png b/ILSpy/Images/OverlayInternal.png index fcc53bdde..3c1cbc606 100644 Binary files a/ILSpy/Images/OverlayInternal.png and b/ILSpy/Images/OverlayInternal.png differ diff --git a/ILSpy/Images/OverlayProtected.png b/ILSpy/Images/OverlayProtected.png index 0d125f7d2..8f789baff 100644 Binary files a/ILSpy/Images/OverlayProtected.png and b/ILSpy/Images/OverlayProtected.png differ diff --git a/ILSpy/Images/OverlayProtectedInternal.png b/ILSpy/Images/OverlayProtectedInternal.png index dacce33c4..82676812f 100644 Binary files a/ILSpy/Images/OverlayProtectedInternal.png and b/ILSpy/Images/OverlayProtectedInternal.png differ diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs similarity index 100% rename from ILSpy/CSharpLanguage.cs rename to ILSpy/Languages/CSharpLanguage.cs diff --git a/ILSpy/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs similarity index 100% rename from ILSpy/ILAstLanguage.cs rename to ILSpy/Languages/ILAstLanguage.cs diff --git a/ILSpy/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs similarity index 100% rename from ILSpy/ILLanguage.cs rename to ILSpy/Languages/ILLanguage.cs diff --git a/ILSpy/Language.cs b/ILSpy/Languages/Language.cs similarity index 88% rename from ILSpy/Language.cs rename to ILSpy/Languages/Language.cs index d957560b7..3275e54cd 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Languages/Language.cs @@ -19,8 +19,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel.Composition.Hosting; using System.Linq; using ICSharpCode.Decompiler; @@ -229,42 +227,4 @@ namespace ICSharpCode.ILSpy } } } - - public static class Languages - { - static ReadOnlyCollection allLanguages; - - /// - /// A list of all languages. - /// - public static ReadOnlyCollection AllLanguages - { - get - { - return allLanguages; - } - } - - - internal static void Initialize(CompositionContainer composition) - { - List languages = new List(); - languages.AddRange(composition.GetExportedValues()); - languages.Add(new ILLanguage(true)); -#if DEBUG - languages.AddRange(ILAstLanguage.GetDebugLanguages()); - languages.AddRange(CSharpLanguage.GetDebugLanguages()); -#endif - allLanguages = languages.AsReadOnly(); - } - - /// - /// Gets a language using its name. - /// If the language is not found, C# is returned instead. - /// - public static Language GetLanguage(string name) - { - return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First(); - } - } } diff --git a/ILSpy/Languages/Languages.cs b/ILSpy/Languages/Languages.cs new file mode 100644 index 000000000..5b9e18092 --- /dev/null +++ b/ILSpy/Languages/Languages.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.Composition.Hosting; +using System.Linq; + +namespace ICSharpCode.ILSpy +{ + public static class Languages + { + private static ReadOnlyCollection allLanguages; + + /// + /// A list of all languages. + /// + public static ReadOnlyCollection AllLanguages + { + get { return allLanguages; } + } + + internal static void Initialize(CompositionContainer composition) + { + List languages = new List(); + languages.AddRange(composition.GetExportedValues()); + languages.Add(new ILLanguage(true)); + #if DEBUG + languages.AddRange(ILAstLanguage.GetDebugLanguages()); + languages.AddRange(CSharpLanguage.GetDebugLanguages()); + #endif + allLanguages = languages.AsReadOnly(); + } + + /// + /// Gets a language using its name. + /// If the language is not found, C# is returned instead. + /// + public static Language GetLanguage(string name) + { + return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First(); + } + } +} diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 8285be9ae..2bb0ae05d 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -171,6 +171,11 @@ namespace ICSharpCode.ILSpy } } + public IAssemblyResolver GetAssemblyResolver() + { + return new MyAssemblyResolver(this); + } + public LoadedAssembly LookupReferencedAssembly(string fullName) { foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) { diff --git a/ILSpy/SearchPane.cs b/ILSpy/SearchPane.cs index d935b424c..1b829ea71 100644 --- a/ILSpy/SearchPane.cs +++ b/ILSpy/SearchPane.cs @@ -35,14 +35,6 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy { - /// - /// Notifies panes when they are closed. - /// - public interface IPane - { - void Closed(); - } - /// /// Search pane /// diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs index 02320cc09..f0247dc55 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { foundMethods = new ConcurrentDictionary(); - foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType)) { + foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType).OrderBy(n => n.Text)) { yield return child; } @@ -117,7 +117,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (found) { MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { - yield return new AnalyzedMethodTreeNode(codeLocation); + var node = new AnalyzedMethodTreeNode(codeLocation); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index 549152bb7..99aa27af6 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedEvent, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -86,7 +88,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) { MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; - yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : ""); + var node = new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : ""); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs index 850ab3141..edc14fd04 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using ICSharpCode.TreeView; using Mono.Cecil; @@ -74,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); var analyzer = new ScopedWhereUsedAnalyzer(analyzedField, FindReferencesInType); - foreach (var child in analyzer.PerformAnalysis(ct)) { + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -93,8 +94,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (Instruction instr in method.Body.Instructions) { if (CanBeReference(instr.OpCode.Code)) { FieldReference fr = instr.Operand as FieldReference; - if (fr != null && fr.Name == name && - Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && + if (fr != null && fr.Name == name && + Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) { found = true; break; @@ -107,7 +108,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (found) { MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { - yield return new AnalyzedMethodTreeNode(codeLocation); + var node = new AnalyzedMethodTreeNode(codeLocation); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs index 09cab0bf3..f6773be82 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (EventDefinition ev in type.Events.Where(e => e.Name == analyzedEvent.Name)) { MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod; - if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) - yield return new AnalyzedEventTreeNode(ev); + if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) { + var node = new AnalyzedEventTreeNode(ev); + node.Language = this.Language; + yield return node; + } yield break; } foreach (EventDefinition ev in type.Events.Where(e => e.Name.EndsWith(analyzedEvent.Name))) { MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod; if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) { - yield return new AnalyzedEventTreeNode(ev); + var node = new AnalyzedEventTreeNode(ev); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs index 960f48f89..3f139e040 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs @@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -81,14 +83,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer yield break; foreach (MethodDefinition method in type.Methods.Where(m => m.Name == analyzedMethod.Name)) { - if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef)) - yield return new AnalyzedMethodTreeNode(method); + if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef)) { + var node = new AnalyzedMethodTreeNode(method); + node.Language = this.Language; + yield return node; + } yield break; } foreach (MethodDefinition method in type.Methods) { if (method.HasOverrides && method.Overrides.Any(m => m.Resolve() == analyzedMethod)) { - yield return new AnalyzedMethodTreeNode(method); + var node = new AnalyzedMethodTreeNode(method); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs index 35d9bc3d0..56f89ad13 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (PropertyDefinition property in type.Properties.Where(e => e.Name == analyzedProperty.Name)) { MethodDefinition accessor = property.GetMethod ?? property.SetMethod; - if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) - yield return new AnalyzedPropertyTreeNode(property); + if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) { + var node = new AnalyzedPropertyTreeNode(property); + node.Language = this.Language; + yield return node; + } yield break; } foreach (PropertyDefinition property in type.Properties.Where(e => e.Name.EndsWith(analyzedProperty.Name))) { MethodDefinition accessor = property.GetMethod ?? property.SetMethod; if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) { - yield return new AnalyzedPropertyTreeNode(property); + var node = new AnalyzedPropertyTreeNode(property); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index 05a3f5d6a..4e8af7663 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -76,12 +76,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) { - SharpTreeNode newNode = null; + AnalyzerTreeNode newNode = null; try { if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) yield break; @@ -97,8 +99,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer // ignore this type definition. maybe add a notification about such cases. } - if (newNode != null) + if (newNode != null) { + newNode.Language = this.Language; yield return newNode; + } } public static bool CanShow(MethodDefinition method) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index f3f9504e6..175ce4efc 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Threading; using ICSharpCode.TreeView; using Mono.Cecil; @@ -71,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foundMethods = new ConcurrentDictionary(); var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - foreach (var child in analyzer.PerformAnalysis(ct)) { + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -100,7 +101,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (found) { MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { - yield return new AnalyzedMethodTreeNode(codeLocation); + var node= new AnalyzedMethodTreeNode(codeLocation); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs index 5553f5a98..1b18a9ae1 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs @@ -51,14 +51,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } protected override void LoadChildren() + { + analyzedMethod.Body = null; + foreach (var child in GetChildren().OrderBy(n => n.Text)) { + this.Children.Add(child); + } + } + + private IEnumerable GetChildren() { foreach (var f in GetUsedFields().Distinct()) { - this.Children.Add(new AnalyzedFieldTreeNode(f)); + var node = new AnalyzedFieldTreeNode(f); + node.Language = this.Language; + yield return node; } foreach (var m in GetUsedMethods().Distinct()) { - this.Children.Add(new AnalyzedMethodTreeNode(m)); + var node = new AnalyzedMethodTreeNode(m); + node.Language = this.Language; + yield return node; } - analyzedMethod.Body = null; } private IEnumerable GetUsedMethods() diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index 6a6ea0f32..8f264d7ff 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -72,7 +72,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedProperty, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -88,7 +90,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; - yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); + var node = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs index cd14c0575..26c2bca71 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using ICSharpCode.TreeView; using Mono.Cecil; @@ -68,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -80,23 +83,35 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer yield break; foreach (FieldDefinition field in type.Fields) { - if (TypeIsExposedBy(field)) - yield return new AnalyzedFieldTreeNode(field); + if (TypeIsExposedBy(field)) { + var node = new AnalyzedFieldTreeNode(field); + node.Language = this.Language; + yield return node; + } } foreach (PropertyDefinition property in type.Properties) { - if (TypeIsExposedBy(property)) - yield return new AnalyzedPropertyTreeNode(property); + if (TypeIsExposedBy(property)) { + var node = new AnalyzedPropertyTreeNode(property); + node.Language = this.Language; + yield return node; + } } foreach (EventDefinition eventDef in type.Events) { - if (TypeIsExposedBy(eventDef)) - yield return new AnalyzedEventTreeNode(eventDef); + if (TypeIsExposedBy(eventDef)) { + var node = new AnalyzedEventTreeNode(eventDef); + node.Language = this.Language; + yield return node; + } } foreach (MethodDefinition method in type.Methods) { - if (TypeIsExposedBy(method)) - yield return new AnalyzedMethodTreeNode(method); + if (TypeIsExposedBy(method)) { + var node = new AnalyzedMethodTreeNode(method); + node.Language = this.Language; + yield return node; + } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs index 3bd42506c..605190b88 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -79,7 +81,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (MethodDefinition method in type.Methods) { if (method.IsStatic && HasExtensionAttribute(method)) { if (method.HasParameters && method.Parameters[0].ParameterType.Resolve() == analyzedType) { - yield return new AnalyzedMethodTreeNode(method); + var node = new AnalyzedMethodTreeNode(method); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index 0c2d9465a..10b477bcf 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -74,7 +74,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer ScopedWhereUsedAnalyzer analyzer; analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { + yield return child; + } } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -102,8 +104,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer method.Body = null; - if (found) - yield return new AnalyzedMethodTreeNode(method); + if (found) { + var node = new AnalyzedMethodTreeNode(method); + node.Language = this.Language; + yield return node; + } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs index 26f5e4c65..f31eb5d5e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer InitializeAnalyzer(); var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); - foreach (var child in analyzer.PerformAnalysis(ct)) { + foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) { yield return child; } @@ -95,8 +95,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer possibleTypes = new List(); TypeReference type = analyzedMethod.DeclaringType.BaseType; - while (type !=null) - { + while (type != null) { possibleTypes.Add(type); type = type.Resolve().BaseType; } @@ -120,8 +119,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer MethodReference mr = instr.Operand as MethodReference; if (mr != null && mr.Name == name) { // explicit call to the requested method - if (instr.OpCode.Code == Code.Call - && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) + if (instr.OpCode.Code == Code.Call + && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) { found = true; prefix = "(as base) "; @@ -147,7 +146,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (found) { MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { - yield return new AnalyzedMethodTreeNode(codeLocation, prefix); + var node = new AnalyzedMethodTreeNode(codeLocation); + node.Language = this.Language; + yield return node; } } } diff --git a/ILSpy/TreeNodes/BaseTypesEntryNode.cs b/ILSpy/TreeNodes/BaseTypesEntryNode.cs new file mode 100644 index 000000000..821784ccb --- /dev/null +++ b/ILSpy/TreeNodes/BaseTypesEntryNode.cs @@ -0,0 +1,104 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Linq; +using ICSharpCode.Decompiler; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes +{ + sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode + { + private TypeReference tr; + private TypeDefinition def; + private bool isInterface; + + public BaseTypesEntryNode(TypeReference tr, bool isInterface) + { + if (tr == null) + throw new ArgumentNullException("tr"); + this.tr = tr; + this.def = tr.Resolve(); + this.isInterface = isInterface; + this.LazyLoading = true; + } + + public override bool ShowExpander + { + get { return def != null && (def.BaseType != null || def.HasInterfaces); } + } + + public override object Text + { + get { return this.Language.TypeToString(tr, true); } + } + + public override object Icon + { + get + { + if (def != null) + return TypeTreeNode.GetIcon(def); + else + return isInterface ? Images.Interface : Images.Class; + } + } + + protected override void LoadChildren() + { + if (def != null) + BaseTypesTreeNode.AddBaseTypes(this.Children, def); + } + + public override void ActivateItem(System.Windows.RoutedEventArgs e) + { + // on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime) + if (def == null) { + def = tr.Resolve(); + if (def != null) + this.LazyLoading = true; + // re-load children + } + e.Handled = ActivateItem(this, def); + } + + internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def) + { + if (def != null) { + var assemblyListNode = node.Ancestors().OfType().FirstOrDefault(); + if (assemblyListNode != null) { + assemblyListNode.Select(assemblyListNode.FindTypeNode(def)); + return true; + } + } + return false; + } + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, language.TypeToString(tr, true)); + } + + MemberReference IMemberTreeNode.Member + { + get { return tr; } + } + } +} diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs index 0209f7410..610458cdf 100644 --- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs +++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs @@ -17,9 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Linq; using System.Windows.Threading; - using ICSharpCode.Decompiler; using ICSharpCode.TreeView; using Mono.Cecil; @@ -32,26 +30,28 @@ namespace ICSharpCode.ILSpy.TreeNodes sealed class BaseTypesTreeNode : ILSpyTreeNode { readonly TypeDefinition type; - + public BaseTypesTreeNode(TypeDefinition type) { this.type = type; this.LazyLoading = true; } - - public override object Text { + + public override object Text + { get { return "Base Types"; } } - - public override object Icon { + + public override object Icon + { get { return Images.SuperTypes; } } - + protected override void LoadChildren() { AddBaseTypes(this.Children, type); } - + internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type) { if (type.BaseType != null) @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes children.Add(new BaseTypesEntryNode(i, true)); } } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren)); @@ -69,78 +69,4 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - - sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode - { - TypeReference tr; - TypeDefinition def; - bool isInterface; - - public BaseTypesEntryNode(TypeReference tr, bool isInterface) - { - if (tr == null) - throw new ArgumentNullException("tr"); - this.tr = tr; - this.def = tr.Resolve(); - this.isInterface = isInterface; - this.LazyLoading = true; - } - - public override bool ShowExpander { - get { - return def != null && (def.BaseType != null || def.HasInterfaces); - } - } - - public override object Text { - get { return this.Language.TypeToString(tr, true); } - } - - public override object Icon { - get { - if (def != null) - return TypeTreeNode.GetIcon(def); - else - return isInterface ? Images.Interface : Images.Class; - } - } - - protected override void LoadChildren() - { - if (def != null) - BaseTypesTreeNode.AddBaseTypes(this.Children, def); - } - - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - // on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime) - if (def == null) { - def = tr.Resolve(); - if (def != null) - this.LazyLoading = true; // re-load children - } - e.Handled = ActivateItem(this, def); - } - - internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def) - { - if (def != null) { - var assemblyListNode = node.Ancestors().OfType().FirstOrDefault(); - if (assemblyListNode != null) { - assemblyListNode.Select(assemblyListNode.FindTypeNode(def)); - return true; - } - } - return false; - } - - public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) - { - language.WriteCommentLine(output, language.TypeToString(tr, true)); - } - - MemberReference IMemberTreeNode.Member { - get { return tr; } - } - } -} +} \ No newline at end of file diff --git a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs new file mode 100644 index 000000000..326418633 --- /dev/null +++ b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System.Collections.Generic; +using System.Threading; +using ICSharpCode.Decompiler; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes +{ + class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode + { + private TypeDefinition type; + private AssemblyDefinition[] assemblies; + private ThreadingSupport threading; + + public DerivedTypesEntryNode(TypeDefinition type, AssemblyDefinition[] assemblies) + { + this.type = type; + this.assemblies = assemblies; + this.LazyLoading = true; + threading = new ThreadingSupport(); + } + + public override bool ShowExpander + { + get { return !type.IsSealed && base.ShowExpander; } + } + + public override object Text + { + get { return this.Language.TypeToString(type, true); } + } + + public override object Icon + { + get { return TypeTreeNode.GetIcon(type); } + } + + public override FilterResult Filter(FilterSettings settings) + { + if (!settings.ShowInternalApi && !IsPublicAPI) + return FilterResult.Hidden; + if (settings.SearchTermMatches(type.Name)) { + if (type.IsNested && !settings.Language.ShowMember(type)) + return FilterResult.Hidden; + else + return FilterResult.Match; + } else + return FilterResult.Recurse; + } + + public bool IsPublicAPI + { + get + { + switch (type.Attributes & TypeAttributes.VisibilityMask) { + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamORAssem: + return true; + default: + return false; + } + } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + IEnumerable FetchChildren(CancellationToken ct) + { + // FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread + return DerivedTypesTreeNode.FindDerivedTypes(type, assemblies, ct); + } + + public override void ActivateItem(System.Windows.RoutedEventArgs e) + { + e.Handled = BaseTypesEntryNode.ActivateItem(this, type); + } + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, language.TypeToString(type, true)); + } + + MemberReference IMemberTreeNode.Member + { + get { return type; } + } + } +} diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs index 2fd497395..0775f58e9 100644 --- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; - using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.Utils; using Mono.Cecil; @@ -35,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes readonly AssemblyList list; readonly TypeDefinition type; ThreadingSupport threading; - + public DerivedTypesTreeNode(AssemblyList list, TypeDefinition type) { this.list = list; @@ -43,27 +42,29 @@ namespace ICSharpCode.ILSpy.TreeNodes this.LazyLoading = true; this.threading = new ThreadingSupport(); } - - public override object Text { + + public override object Text + { get { return "Derived Types"; } } - - public override object Icon { + + public override object Icon + { get { return Images.SubTypes; } } - + protected override void LoadChildren() { threading.LoadChildren(this, FetchChildren); } - + IEnumerable FetchChildren(CancellationToken cancellationToken) { // FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread var assemblies = list.GetAssemblies().Select(node => node.AssemblyDefinition).Where(asm => asm != null).ToArray(); return FindDerivedTypes(type, assemblies, cancellationToken); } - + internal static IEnumerable FindDerivedTypes(TypeDefinition type, AssemblyDefinition[] assemblies, CancellationToken cancellationToken) { foreach (AssemblyDefinition asm in assemblies) { @@ -80,7 +81,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + static bool IsSameType(TypeReference typeRef, TypeDefinition type) { if (typeRef.FullName == type.FullName) @@ -96,66 +97,10 @@ namespace ICSharpCode.ILSpy.TreeNodes return false; return true; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { threading.Decompile(language, output, options, EnsureLazyChildren); } } - - class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode - { - TypeDefinition def; - AssemblyDefinition[] assemblies; - ThreadingSupport threading; - - public DerivedTypesEntryNode(TypeDefinition def, AssemblyDefinition[] assemblies) - { - this.def = def; - this.assemblies = assemblies; - this.LazyLoading = true; - threading = new ThreadingSupport(); - } - - public override bool ShowExpander { - get { - return !def.IsSealed && base.ShowExpander; - } - } - - public override object Text { - get { return this.Language.TypeToString(def, true); } - } - - public override object Icon { - get { - return TypeTreeNode.GetIcon(def); - } - } - - protected override void LoadChildren() - { - threading.LoadChildren(this, FetchChildren); - } - - IEnumerable FetchChildren(CancellationToken ct) - { - // FetchChildren() runs on the main thread; but the enumerator will be consumed on a background thread - return DerivedTypesTreeNode.FindDerivedTypes(def, assemblies, ct); - } - - public override void ActivateItem(System.Windows.RoutedEventArgs e) - { - e.Handled = BaseTypesEntryNode.ActivateItem(this, def); - } - - public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) - { - language.WriteCommentLine(output, language.TypeToString(def, true)); - } - - MemberReference IMemberTreeNode.Member { - get { return def; } - } - } -} +} \ No newline at end of file diff --git a/ILSpy/TreeNodes/FilterResult.cs b/ILSpy/TreeNodes/FilterResult.cs new file mode 100644 index 000000000..106bed1e3 --- /dev/null +++ b/ILSpy/TreeNodes/FilterResult.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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. + +namespace ICSharpCode.ILSpy.TreeNodes +{ + public enum FilterResult + { + /// + /// Hides the node. + /// + Hidden, + /// + /// Shows the node (and resets the search term for child nodes). + /// + Match, + /// + /// Hides the node only if all children are hidden (and resets the search term for child nodes). + /// + MatchAndRecurse, + /// + /// Hides the node only if all children are hidden (doesn't reset the search term for child nodes). + /// + Recurse + } +} diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index ea92d8f22..8b4835fe5 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; @@ -33,21 +32,24 @@ namespace ICSharpCode.ILSpy.TreeNodes { FilterSettings filterSettings; bool childrenNeedFiltering; - - public FilterSettings FilterSettings { + + public FilterSettings FilterSettings + { get { return filterSettings; } - set { + set + { if (filterSettings != value) { filterSettings = value; OnFilterSettingsChanged(); } } } - - public Language Language { + + public Language Language + { get { return filterSettings != null ? filterSettings.Language : Languages.AllLanguages[0]; } } - + public virtual FilterResult Filter(FilterSettings settings) { if (string.IsNullOrEmpty(settings.SearchTerm)) @@ -55,15 +57,15 @@ namespace ICSharpCode.ILSpy.TreeNodes else return FilterResult.Hidden; } - + protected static object HighlightSearchMatch(string text, string suffix = null) { // TODO: implement highlighting the search match return text + suffix; } - + public abstract void Decompile(Language language, ITextOutput output, DecompilationOptions options); - + /// /// Used to implement special view logic for some items. /// This method is called on the main thread when only a single item is selected. @@ -73,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { return false; } - + /// /// Used to implement special save logic for some items. /// This method is called on the main thread when only a single item is selected. @@ -83,7 +85,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { return false; } - + protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { @@ -96,7 +98,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } base.OnChildrenChanged(e); } - + void ApplyFilterToChild(ILSpyTreeNode child) { FilterResult r; @@ -126,7 +128,7 @@ namespace ICSharpCode.ILSpy.TreeNodes throw new InvalidEnumArgumentException(); } } - + FilterSettings StripSearchTerm(FilterSettings filterSettings) { if (filterSettings == null) @@ -137,7 +139,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } return filterSettings; } - + protected virtual void OnFilterSettingsChanged() { RaisePropertyChanged("Text"); @@ -148,13 +150,13 @@ namespace ICSharpCode.ILSpy.TreeNodes childrenNeedFiltering = true; } } - + protected override void OnIsVisibleChanged() { base.OnIsVisibleChanged(); EnsureChildrenFiltered(); } - + void EnsureChildrenFiltered() { EnsureLazyChildren(); @@ -165,24 +167,4 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - - public enum FilterResult - { - /// - /// Hides the node. - /// - Hidden, - /// - /// Shows the node (and resets the search term for child nodes). - /// - Match, - /// - /// Hides the node only if all children are hidden (and resets the search term for child nodes). - /// - MatchAndRecurse, - /// - /// Hides the node only if all children are hidden (doesn't reset the search term for child nodes). - /// - Recurse - } -} +} \ No newline at end of file diff --git a/Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb.csproj b/Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb.csproj index d0f6fe4ef..2d2dfd273 100644 --- a/Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb.csproj +++ b/Mono.Cecil/symbols/pdb/Mono.Cecil.Pdb.csproj @@ -1,4 +1,4 @@ - + net_4_0_Debug @@ -13,6 +13,7 @@ 512 true ..\..\mono.snk + 0649 true