diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index bf4378057..2117ff020 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -56,12 +56,13 @@ namespace ILSpy.BamlDecompiler internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream) { XDocument xamlDocument; - using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) + using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm))) { xamlDocument = XDocument.Load(reader); - ConvertConnectionIds(xamlDocument, asm); - ConvertToEmptyElements(xamlDocument.Root); - MoveNamespacesToRoot(xamlDocument); - return xamlDocument; + ConvertConnectionIds(xamlDocument, asm); + ConvertToEmptyElements(xamlDocument.Root); + MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions); + return xamlDocument; + } } static void ConvertConnectionIds(XDocument xamlDocument, AssemblyDefinition asm) @@ -74,12 +75,35 @@ namespace ILSpy.BamlDecompiler } } - static void MoveNamespacesToRoot(XDocument xamlDocument) + class XAttributeComparer : IEqualityComparer + { + public bool Equals(XAttribute x, XAttribute y) + { + if (ReferenceEquals(x, y)) + return true; + if (x == null || y == null) + return false; + return x.ToString() == y.ToString(); + } + + public int GetHashCode(XAttribute obj) + { + return obj.ToString().GetHashCode(); + } + } + + static void MoveNamespacesToRoot(XDocument xamlDocument, IEnumerable missingXmlns) { - var additionalXmlns = new List { + var additionalXmlns = new HashSet(new XAttributeComparer()) { new XAttribute("xmlns", XmlBamlReader.DefaultWPFNamespace), new XAttribute(XName.Get("x", XNamespace.Xmlns.NamespaceName), XmlBamlReader.XWPFNamespace) }; + + additionalXmlns.AddRange( + missingXmlns + .Where(ns => !string.IsNullOrWhiteSpace(ns.Prefix)) + .Select(ns => new XAttribute(XName.Get(ns.Prefix, XNamespace.Xmlns.NamespaceName), ns.Namespace)) + ); foreach (var element in xamlDocument.Root.DescendantsAndSelf()) { if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace && !additionalXmlns.Any(ka => ka.Value == element.Name.NamespaceName)) { diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index ca39df548..a5be0206f 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -112,7 +112,7 @@ - + diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs index 4cc372400..bf2609c34 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs @@ -1,14 +1,13 @@ // Copyright (c) Cristian Civera (cristian@aspitalia.com) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) +using System.Collections.Generic; using System.Xml; namespace Ricciolo.StylesExplorer.MarkupReflection { class XmlBamlElement : XmlBamlNode { - XmlNamespaceCollection _namespaces = new XmlNamespaceCollection(); - public XmlBamlElement() { } @@ -19,11 +18,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection this.Namespaces.AddRange(parent.Namespaces); } - public XmlNamespaceCollection Namespaces { - get { return _namespaces; } - } + public List Namespaces { get; } = new List(); - public XmlBamlElement Parent { get; private set; } + public XmlBamlElement Parent { get; } public TypeDeclaration TypeDeclaration { get; set; } diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs index 5a88fd509..219fe8ee4 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs @@ -29,7 +29,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection Stack elements = new Stack(); Stack readingElements = new Stack(); NodesCollection nodes = new NodesCollection(); - List _mappings = new List(); + List mappings = new List(); XmlBamlNode _currentNode; readonly KnownInfo KnownInfo; @@ -94,15 +94,17 @@ namespace Ricciolo.StylesExplorer.MarkupReflection readonly XmlNameTable _nameTable = new NameTable(); 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"; + public const string XWPFNamespace = XmlToClrNamespaceMapping.XamlNamespace; + public const string DefaultWPFNamespace = XmlToClrNamespaceMapping.PresentationNamespace; + + public ISet XmlnsDefinitions { get; } = new HashSet(); public XmlBamlReader(Stream stream, ITypeResolver resolver) { if (stream == null) - throw new ArgumentNullException("stream"); + throw new ArgumentNullException(nameof(stream)); if (resolver == null) - throw new ArgumentNullException("resolver"); + throw new ArgumentNullException(nameof(resolver)); _resolver = resolver; reader = new BamlBinaryReader(stream); @@ -111,86 +113,31 @@ namespace Ricciolo.StylesExplorer.MarkupReflection KnownInfo = new KnownInfo(resolver); } - /// - ///When overridden in a derived class, gets the value of the attribute with the specified . - /// - /// - /// - ///The value of the specified attribute. If the attribute is not found, null is returned. - /// - /// - ///The qualified name of the attribute. public override string GetAttribute(string name) { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, gets the value of the attribute with the specified and . - /// - /// - /// - ///The value of the specified attribute. If the attribute is not found, null is returned. This method does not move the reader. - /// - /// - ///The namespace URI of the attribute. - ///The local name of the attribute. public override string GetAttribute(string name, string namespaceURI) { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, gets the value of the attribute with the specified index. - /// - /// - /// - ///The value of the specified attribute. This method does not move the reader. - /// - /// - ///The index of the attribute. The index is zero-based. (The first attribute has index 0.) public override string GetAttribute(int i) { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, moves to the attribute with the specified . - /// - /// - /// - ///true if the attribute is found; otherwise, false. If false, the reader's position does not change. - /// - /// - ///The qualified name of the attribute. public override bool MoveToAttribute(string name) { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, moves to the attribute with the specified and . - /// - /// - /// - ///true if the attribute is found; otherwise, false. If false, the reader's position does not change. - /// - /// - ///The local name of the attribute. - ///The namespace URI of the attribute. public override bool MoveToAttribute(string name, string ns) { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, moves to the first attribute. - /// - /// - /// - ///true if an attribute exists (the reader moves to the first attribute); otherwise, false (the position of the reader does not change). - /// - /// public override bool MoveToFirstAttribute() { intoAttribute = false; @@ -202,14 +149,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return false; } - /// - ///When overridden in a derived class, moves to the next attribute. - /// - /// - /// - ///true if there is a next attribute; false if there are no more attributes. - /// - /// public override bool MoveToNextAttribute() { intoAttribute = false; @@ -221,14 +160,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return false; } - /// - ///When overridden in a derived class, moves to the element that contains the current attribute node. - /// - /// - /// - ///true if the reader is positioned on an attribute (the reader moves to the element that owns the attribute); false if the reader is not positioned on an attribute (the position of the reader does not change). - /// - /// public override bool MoveToElement() { while (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty) @@ -239,14 +170,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return true; } - /// - ///When overridden in a derived class, parses the attribute value into one or more Text, EntityReference, or EndEntity nodes. - /// - /// - /// - ///true if there are nodes to return.false if the reader is not positioned on an attribute node when the initial call is made or if all the attribute values have been read.An empty attribute, such as, misc="", returns true with a single node with a value of String.Empty. - /// - /// public override bool ReadAttributeValue() { if (!intoAttribute) @@ -257,15 +180,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return false; } - /// - ///When overridden in a derived class, reads the next node from the stream. - /// - /// - /// - ///true if the next node was read successfully; false if there are no more nodes to read. - /// - /// - ///An error occurred while parsing the XML. public override bool Read() { return ReadInternal(); @@ -288,7 +202,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection long position = reader.BaseStream.Position; - ComputeBytesToSkip(); + bytesToSkip = ComputeBytesToSkip(); ProcessNext(); if (bytesToSkip > 0) @@ -318,12 +232,13 @@ namespace Ricciolo.StylesExplorer.MarkupReflection currentType = BamlRecordType.DocumentEnd; else currentType = (BamlRecordType)type; - - if (currentType.ToString().EndsWith("End")) +#if DEBUG + if (currentType.ToString().EndsWith("End", StringComparison.Ordinal)) Debug.Unindent(); Debug.WriteLine(string.Format("{0} (0x{0:x})", currentType)); - if (currentType.ToString().EndsWith("Start")) + if (currentType.ToString().EndsWith("Start", StringComparison.Ordinal)) Debug.Indent(); +#endif } bool SetNextNode() @@ -507,9 +422,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection nodes.Enqueue(new XmlBamlText(text)); } - void ComputeBytesToSkip() + int ComputeBytesToSkip() { - bytesToSkip = 0; switch (currentType) { case BamlRecordType.PropertyWithConverter: @@ -528,8 +442,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection case BamlRecordType.AttributeInfo: case BamlRecordType.StringInfo: case BamlRecordType.TypeSerializerInfo: - bytesToSkip = reader.ReadCompressedInt32(); - break; + return reader.ReadCompressedInt32(); + default: + return 0; } } @@ -552,77 +467,44 @@ namespace Ricciolo.StylesExplorer.MarkupReflection } } - /// - ///When overridden in a derived class, changes the to Closed. - /// - /// + public override void Close() { - //if (reader != null) - // reader.Close(); reader = null; } - /// - ///When overridden in a derived class, resolves a namespace prefix in the current element's scope. - /// - /// - /// - ///The namespace URI to which the prefix maps or null if no matching prefix is found. - /// - /// - ///The prefix whose namespace URI you want to resolve. To match the default namespace, pass an empty string. + public override string LookupNamespace(string prefix) { if (readingElements.Count == 0) return null; - XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; + var namespaces = readingElements.Peek().Namespaces; - for (int x = 0; x < namespaces.Count; x++) - { - if (String.CompareOrdinal(namespaces[x].Prefix, prefix) == 0) - return namespaces[x].Namespace; + for (int i = 0; i < namespaces.Count; i++) { + if (String.CompareOrdinal(namespaces[i].Prefix, prefix) == 0) + return namespaces[i].Namespace; } return null; } - /// - ///When overridden in a derived class, resolves the entity reference for EntityReference nodes. - /// - /// - ///The reader is not positioned on an EntityReference node; this implementation of the reader cannot resolve entities ( returns false). + public override void ResolveEntity() { throw new NotImplementedException(); } - /// - ///When overridden in a derived class, gets the type of the current node. - /// - /// - /// - ///One of the values representing the type of the current node. - /// - /// + public override XmlNodeType NodeType { - get - { + get { if (intoAttribute) return XmlNodeType.Text; return this.CurrentNode.NodeType; } } - /// - ///When overridden in a derived class, gets the local name of the current node. - /// - /// - /// - ///The name of the current node with the prefix removed. For example, LocalName is book for the element <bk:book>.For node types that do not have a name (like Text, Comment, and so on), this property returns String.Empty. - /// - /// + public override string LocalName { get @@ -1033,37 +915,38 @@ namespace Ricciolo.StylesExplorer.MarkupReflection keys.Add(new KeyMapping(text) { Position = position }); } - + void ReadXmlnsProperty() { string prefix = reader.ReadString(); string @namespace = reader.ReadString(); string[] textArray = new string[(uint)reader.ReadInt16()]; - for (int i = 0; i < textArray.Length; i++) - { + for (int i = 0; i < textArray.Length; i++) { textArray[i] = this.assemblyTable[reader.ReadInt16()]; } - XmlNamespaceCollection namespaces = elements.Peek().Namespaces; - // Mapping locale, ci aggiunto l'assembly - if (@namespace.StartsWith("clr-namespace:") && @namespace.IndexOf("assembly=") < 0) - { - XmlPIMapping mappingToChange = null; - foreach (XmlPIMapping mapping in this.Mappings) - { - if (String.CompareOrdinal(mapping.XmlNamespace, @namespace) == 0) - { + var namespaces = elements.Peek().Namespaces; + + // The XmlnsProperty record corresponds to an assembly + // We need to add the assembly name to the entry. + if (@namespace.StartsWith("clr-namespace:", StringComparison.Ordinal) && @namespace.IndexOf("assembly=", StringComparison.Ordinal) < 0) { + XmlToClrNamespaceMapping mappingToChange = null; + foreach (XmlToClrNamespaceMapping mapping in mappings) { + if (String.CompareOrdinal(mapping.XmlNamespace, @namespace) == 0) { mappingToChange = mapping; break; } } if (mappingToChange == null) throw new InvalidOperationException("Cannot find mapping"); - - @namespace = String.Format("{0};assembly={1}", @namespace, mappingToChange.Assembly.Replace(" ", "")); - mappingToChange.XmlNamespace = @namespace; + if (mappingToChange.AssemblyId > 0) { + @namespace = String.Format("{0};assembly={1}", @namespace, mappingToChange.AssemblyName.Replace(" ", "")); + mappingToChange.XmlNamespace = @namespace; + } } - namespaces.Add(new XmlNamespace(prefix, @namespace)); + var ns = new XmlNamespace(prefix, @namespace); + XmlnsDefinitions.Add(ns); + namespaces.Add(ns); } void ReadElementEnd() @@ -1292,22 +1175,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection nodes.Enqueue(property); } - XmlPIMapping FindByClrNamespaceAndAssemblyId(TypeDeclaration declaration) + XmlToClrNamespaceMapping FindByClrNamespaceAndAssemblyId(TypeDeclaration declaration) { return FindByClrNamespaceAndAssemblyName(declaration.Namespace, declaration.Assembly); } - XmlPIMapping FindByClrNamespaceAndAssemblyName(string clrNamespace, string assemblyName) + XmlToClrNamespaceMapping FindByClrNamespaceAndAssemblyName(string clrNamespace, string assemblyName) { - if (clrNamespace == XamlTypeDeclaration.Namespace && assemblyName == XamlTypeDeclaration.Assembly) - return new XmlPIMapping(XmlPIMapping.XamlNamespace, assemblyName, clrNamespace); - for (int x = 0; x < Mappings.Count; x++) { - XmlPIMapping xp = Mappings[x]; - if (string.Equals(xp.Assembly, assemblyName, StringComparison.Ordinal) && string.Equals(xp.ClrNamespace, clrNamespace, StringComparison.Ordinal)) + if (assemblyName == XamlTypeDeclaration.Assembly) { + if (clrNamespace == XamlTypeDeclaration.Namespace) + return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.XamlNamespace, -1, XamlTypeDeclaration.Assembly, XamlTypeDeclaration.Namespace); + return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.PresentationNamespace, -1, assemblyName, clrNamespace); + } + + for (int x = 0; x < mappings.Count; x++) { + XmlToClrNamespaceMapping xp = mappings[x]; + if (string.Equals(xp.AssemblyName, assemblyName, StringComparison.Ordinal) && string.Equals(xp.ClrNamespace, clrNamespace, StringComparison.Ordinal)) return xp; } - return null; + return new XmlToClrNamespaceMapping(XmlToClrNamespaceMapping.PresentationNamespace, -1, assemblyName, clrNamespace); } void ReadPIMapping() @@ -1316,7 +1203,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection string clrNamespace = reader.ReadString(); short assemblyId = reader.ReadInt16(); - Mappings.Add(new XmlPIMapping(xmlNamespace, GetAssembly(assemblyId), clrNamespace)); + mappings.Add(new XmlToClrNamespaceMapping(xmlNamespace, assemblyId, GetAssembly(assemblyId), clrNamespace)); } void ReadContentProperty() @@ -1484,7 +1371,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection else throw new InvalidOperationException("Invalid resource: " + resource.GetType()); - string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); + string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.XamlNamespace, false); if (String.IsNullOrEmpty(prefix)) return String.Format("{{Static {0}}}", name); else @@ -1498,7 +1385,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection string GetTypeExtension(short typeIdentifier) { - string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); + string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.XamlNamespace, false); if (String.IsNullOrEmpty(prefix)) return String.Format("{{Type {0}}}", FormatTypeDeclaration(GetTypeDeclaration(typeIdentifier))); else @@ -1507,7 +1394,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection string FormatTypeDeclaration(TypeDeclaration typeDeclaration) { - XmlPIMapping mapping = FindByClrNamespaceAndAssemblyName(typeDeclaration.Namespace, typeDeclaration.Assembly); + XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyName(typeDeclaration.Namespace, typeDeclaration.Assembly); string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; string name = typeDeclaration.Name; if (name.EndsWith("Extension")) @@ -1534,7 +1421,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection bool differentType = ((propertyDeclaration.DeclaringType != propertyDeclaration.DeclaringType || !isDescendant)); if (withPrefix) { - XmlPIMapping mapping = FindByClrNamespaceAndAssemblyName(propertyDeclaration.DeclaringType.Namespace, propertyDeclaration.DeclaringType.Assembly); + XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyName(propertyDeclaration.DeclaringType.Namespace, propertyDeclaration.DeclaringType.Assembly); string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; if (!String.IsNullOrEmpty(prefix)) { @@ -1559,7 +1446,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection PropertyDeclaration pd = this.GetPropertyDeclaration(propertyId); object staticResource = GetStaticResource(index); - string prefix = this.LookupPrefix(XmlPIMapping.PresentationNamespace, false); + string prefix = this.LookupPrefix(XmlToClrNamespaceMapping.PresentationNamespace, false); string value = String.Format("{{{0}{1}StaticResource {2}}}", prefix, (String.IsNullOrEmpty(prefix)) ? String.Empty : ":", staticResource); XmlBamlProperty property = new XmlBamlProperty(elements.Peek(), PropertyType.Value, pd); @@ -1658,12 +1545,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection get { return _currentNode; } } - /// - ///When overridden in a derived class, gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned. - /// - /// - ///The namespace URI of the current node; otherwise an empty string. - /// public override string NamespaceURI { get { if (intoAttribute) return String.Empty; @@ -1676,8 +1557,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType; TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration; - XmlPIMapping propertyMapping = FindByClrNamespaceAndAssemblyId(declaration) ?? XmlPIMapping.GetPresentationMapping(GetAssembly); - XmlPIMapping elementMapping = FindByClrNamespaceAndAssemblyId(elementDeclaration) ?? XmlPIMapping.GetPresentationMapping(GetAssembly); + XmlToClrNamespaceMapping propertyMapping = FindByClrNamespaceAndAssemblyId(declaration); + XmlToClrNamespaceMapping elementMapping = FindByClrNamespaceAndAssemblyId(elementDeclaration); if (((XmlBamlProperty)node).PropertyDeclaration.Name == "Name" && _resolver.IsLocalAssembly(((XmlBamlProperty)node).Parent.TypeDeclaration.Assembly)) @@ -1699,36 +1580,23 @@ namespace Ricciolo.StylesExplorer.MarkupReflection else return String.Empty; - XmlPIMapping mapping = FindByClrNamespaceAndAssemblyId(declaration); - if (mapping == null) - mapping = XmlPIMapping.GetPresentationMapping(GetAssembly); + XmlToClrNamespaceMapping mapping = FindByClrNamespaceAndAssemblyId(declaration); return mapping.XmlNamespace; } } - /// - ///When overridden in a derived class, gets the namespace prefix associated with the current node. - /// - /// - ///The namespace prefix associated with the current node. - /// + public override string Prefix { - get - { + get { if (!intoAttribute) return ((IXmlNamespaceResolver)this).LookupPrefix(this.NamespaceURI) ?? String.Empty; return String.Empty; } } - /// - ///When overridden in a derived class, gets a value indicating whether the current node can have a . - /// - /// - ///true if the node on which the reader is currently positioned can have a Value; otherwise, false. If false, the node has a value of String.Empty. - /// + public override bool HasValue { get { return this.Value != null; } @@ -1742,16 +1610,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection get { return _resolver; } } - /// - ///When overridden in a derived class, gets the text value of the current node. - /// - /// - ///The value returned depends on the of the node. The following table lists node types that have a value to return. All other node types return String.Empty.Node type Value AttributeThe value of the attribute. CDATAThe content of the CDATA section. CommentThe content of the comment. DocumentTypeThe internal subset. ProcessingInstructionThe entire content, excluding the target. SignificantWhitespaceThe white space between markup in a mixed content model. TextThe content of the text node. WhitespaceThe white space between markup. XmlDeclarationThe content of the declaration. - /// public override string Value { - get - { + get { XmlBamlNode node = this.CurrentNode; if (node is XmlBamlSimpleProperty) return ((XmlBamlSimpleProperty)node).Value; @@ -1766,116 +1627,39 @@ namespace Ricciolo.StylesExplorer.MarkupReflection } } - /// - /// Return root namespaces - /// - public IDictionary RootNamespaces - { - get { return _rootNamespaces; } - } + public IDictionary RootNamespaces => _rootNamespaces; - /// - ///When overridden in a derived class, gets the depth of the current node in the XML document. - /// - /// - ///The depth of the current node in the XML document. - /// - public override int Depth - { - get { return this.readingElements.Count; } - } + public override int Depth => readingElements.Count; - /// - ///When overridden in a derived class, gets the base URI of the current node. - /// - /// - ///The base URI of the current node. - /// - public override string BaseURI - { - get { return String.Empty; } - } + public override string BaseURI => string.Empty; - /// - ///When overridden in a derived class, gets a value indicating whether the current node is an empty element (for example, <MyElement/>). - /// - /// - ///true if the current node is an element ( equals XmlNodeType.Element) that ends with />; otherwise, false. - /// - public override bool IsEmptyElement - { - get { return false; } - } + public override bool IsEmptyElement => false; + + public override bool EOF => _eof; - /// - ///When overridden in a derived class, gets the number of attributes on the current node. - /// - /// - ///The number of attributes on the current node. - /// public override int AttributeCount { get { throw new NotImplementedException(); } } - /// - ///When overridden in a derived class, gets a value indicating whether the reader is positioned at the end of the stream. - /// - /// - ///true if the reader is positioned at the end of the stream; otherwise, false. - /// - public override bool EOF { - get { return _eof; } - } - - /// - ///When overridden in a derived class, gets the state of the reader. - /// - /// - ///One of the values. - /// public override ReadState ReadState { get { if (!initialized) return ReadState.Initial; - else if (reader == null) + if (reader == null) return ReadState.Closed; - else if (this.EOF) + if (this.EOF) return ReadState.EndOfFile; - else - return ReadState.Interactive; + return ReadState.Interactive; } } - public List Mappings - { - get { return _mappings; } - } - - /// - ///When overridden in a derived class, gets the associated with this implementation. - /// - /// - ///The XmlNameTable enabling you to get the atomized version of a string within the node. - /// - public override XmlNameTable NameTable - { - get { return _nameTable; } - } + public override XmlNameTable NameTable => _nameTable; #region IXmlNamespaceResolver Members - /// - ///Gets a collection of defined prefix-namespace Mappings that are currently in scope. - /// - /// - /// - ///An that contains the current in-scope namespaces. - /// - /// - ///An value that specifies the type of namespace nodes to return. IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) { - XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; + var namespaces = readingElements.Peek().Namespaces; Dictionary list = new Dictionary(); foreach (XmlNamespace ns in namespaces) { @@ -1885,29 +1669,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection return list; } - /// - ///Gets the namespace URI mapped to the specified prefix. - /// - /// - /// - ///The namespace URI that is mapped to the prefix; null if the prefix is not mapped to a namespace URI. - /// - /// - ///The prefix whose namespace URI you wish to find. string IXmlNamespaceResolver.LookupNamespace(string prefix) { return this.LookupNamespace(prefix); } - /// - ///Gets the prefix that is mapped to the specified namespace URI. - /// - /// - /// - ///The prefix that is mapped to the namespace URI; null if the namespace URI is not mapped to a prefix. - /// - /// - ///The namespace URI whose prefix you wish to find. string IXmlNamespaceResolver.LookupPrefix(string namespaceName) { return this.LookupPrefix(namespaceName, true); @@ -1922,12 +1688,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection elements = this.elements; if (elements.Count == 0) return null; - XmlNamespaceCollection namespaces = elements.Peek().Namespaces; - - return LookupPrefix(namespaceName, namespaces); + return LookupPrefix(namespaceName, elements.Peek().Namespaces); } - static string LookupPrefix(string namespaceName, XmlNamespaceCollection namespaces) + static string LookupPrefix(string namespaceName, IList namespaces) { for (int x = 0; x < namespaces.Count; x++) { @@ -1940,8 +1704,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection #endregion - #region IntegerCollectionType - internal enum IntegerCollectionType : byte { Byte = 2, @@ -1950,7 +1712,5 @@ namespace Ricciolo.StylesExplorer.MarkupReflection Unknown = 0, UShort = 3 } - - #endregion } } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs index c064931b5..5094a9f39 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs @@ -1,47 +1,33 @@ // Copyright (c) Cristian Civera (cristian@aspitalia.com) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) -using System.Collections.Generic; +using System; namespace Ricciolo.StylesExplorer.MarkupReflection { - internal class XmlNamespace + public class XmlNamespace { - private string _prefix; - private string _namespace; - public XmlNamespace(string prefix, string ns) { - _prefix = prefix; - _namespace = ns; + Prefix = prefix; + Namespace = ns; } - public string Prefix - { - get { return _prefix; } - } + public string Prefix { get; } - public string Namespace - { - get { return _namespace; } - } + public string Namespace { get; } public override bool Equals(object obj) { - if (obj is XmlNamespace) - { - XmlNamespace o = (XmlNamespace)obj; - return (o.Prefix.Equals(this.Prefix) && o.Namespace.Equals(this.Namespace)); - } - return base.Equals(obj); + XmlNamespace o = obj as XmlNamespace; + if (o == null) + return false; + return o.Prefix.Equals(Prefix) && o.Namespace.Equals(Namespace); } public override int GetHashCode() { - return _prefix.GetHashCode() + _namespace.GetHashCode() >> 20; + return Prefix.GetHashCode() + Namespace.GetHashCode() >> 20; } } - - internal class XmlNamespaceCollection : List - {} } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs deleted file mode 100644 index 750b2a909..000000000 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Cristian Civera (cristian@aspitalia.com) -// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) - -using System; - -namespace Ricciolo.StylesExplorer.MarkupReflection -{ - /// - /// Rappresenta la mappatura tra namespace XML e namespace CLR con relativo assembly - /// - public class XmlPIMapping - { - string _xmlNamespace; - string assemblyName; - string _clrNamespace; - - public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; - public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; - public const string PresentationOptionsNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"; - public const string McNamespace = "http://schemas.openxmlformats.org/markup-compatibility/2006"; - - public XmlPIMapping(string xmlNamespace, string assembly, string clrNamespace) - { - _xmlNamespace = xmlNamespace; - assemblyName = assembly; - _clrNamespace = clrNamespace; - } - - /// - /// Restituisce o imposta il namespace XML - /// - public string XmlNamespace - { - get { return _xmlNamespace; } - set { _xmlNamespace = value;} - } - - /// - /// Name of the assembly. - /// - public string Assembly { - get { return assemblyName; } - } - - /// - /// Restituisce il namespace clr - /// - public string ClrNamespace - { - get { return _clrNamespace; } - } - - public static XmlPIMapping GetPresentationMapping(Func assemblyResolve) - { - return new XmlPIMapping(PresentationNamespace, assemblyResolve(0), string.Empty); - } - } -} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlToClrNamespaceMapping.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlToClrNamespaceMapping.cs new file mode 100644 index 000000000..b9d790aef --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlToClrNamespaceMapping.cs @@ -0,0 +1,31 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + /// + /// Represents a mapping between an XML namespace and a CLR namespace and assembly. + /// + public class XmlToClrNamespaceMapping + { + public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; + public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; + public const string PresentationOptionsNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"; + public const string McNamespace = "http://schemas.openxmlformats.org/markup-compatibility/2006"; + + public XmlToClrNamespaceMapping(string xmlNamespace, short assemblyId, string assemblyName, string clrNamespace) + { + XmlNamespace = xmlNamespace; + AssemblyId = assemblyId; + AssemblyName = assemblyName; + ClrNamespace = clrNamespace; + } + + public short AssemblyId { get; } + public string XmlNamespace { get; set; } + public string AssemblyName { get; } + public string ClrNamespace { get; } + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs index 61819f0d9..9d49ac9d9 100644 --- a/ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler/Tests/BamlTestRunner.cs @@ -21,68 +21,73 @@ namespace ILSpy.BamlDecompiler.Tests { RunTest("cases/simple"); } - + [Test] public void SimpleDictionary() { RunTest("cases/simpledictionary"); } - + [Test] public void Resources() { RunTest("cases/resources"); } - + [Test] - [Ignore("Broken on AppVeyor CI (extra x:ConnectionId attribute)")] public void SimpleNames() { RunTest("cases/simplenames"); } - + [Test] public void AvalonDockBrushes() { RunTest("cases/avalondockbrushes"); } - + [Test] public void AvalonDockCommon() { RunTest("cases/avalondockcommon"); } - + [Test] public void AttachedEvent() { RunTest("cases/attachedevent"); } - + [Test] public void Dictionary1() { RunTest("cases/dictionary1"); } + [Test] + public void Issue775() + { + RunTest("cases/issue775"); + } + [Test] public void MarkupExtension() { RunTest("cases/markupextension"); } - + [Test] public void SimplePropertyElement() { RunTest("cases/simplepropertyelement"); } - + [Test] public void Issue445() { RunTest("cases/issue445"); } - + [Test] public void NamespacePrefix() { @@ -94,13 +99,13 @@ namespace ILSpy.BamlDecompiler.Tests { RunTest("cases/escapesequence"); } - + #region RunTest void RunTest(string name) { RunTest(name, typeof(BamlTestRunner).Assembly.Location, Path.Combine("..\\..\\Tests", name + ".xaml")); } - + void RunTest(string name, string asmPath, string sourcePath) { var resolver = new DefaultAssemblyResolver(); @@ -135,8 +140,7 @@ namespace ILSpy.BamlDecompiler.Tests ResourceReader reader; try { reader = new ResourceReader(s); - } - catch (ArgumentException) { + } catch (ArgumentException) { return null; } foreach (DictionaryEntry entry in reader.Cast().OrderBy(e => e.Key.ToString())) { @@ -148,7 +152,7 @@ namespace ILSpy.BamlDecompiler.Tests } } } - + return null; } #endregion diff --git a/ILSpy.BamlDecompiler/Tests/Cases/Issue775.xaml b/ILSpy.BamlDecompiler/Tests/Cases/Issue775.xaml new file mode 100644 index 000000000..c46d34891 --- /dev/null +++ b/ILSpy.BamlDecompiler/Tests/Cases/Issue775.xaml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml b/ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml index 565fb2e1c..93cf3737c 100644 --- a/ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml +++ b/ILSpy.BamlDecompiler/Tests/Cases/MarkupExtension.xaml @@ -1,4 +1,4 @@ -