Browse Source

Fix #1457: Refactor IModule usage in BAML decompiler.

pull/1464/head
Siegfried Pammer 7 years ago
parent
commit
cc915f5e85
  1. 10
      ILSpy.BamlDecompiler/Baml/BamlContext.cs
  2. 8
      ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs
  3. 2
      ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs
  4. 13
      ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs
  5. 18
      ILSpy.BamlDecompiler/Xaml/XamlType.cs
  6. 10
      ILSpy.BamlDecompiler/XamlContext.cs
  7. 18
      ILSpy.BamlDecompiler/XmlnsDictionary.cs

10
ILSpy.BamlDecompiler/Baml/BamlContext.cs

@ -32,7 +32,7 @@ namespace ILSpy.BamlDecompiler.Baml {
public IDecompilerTypeSystem TypeSystem { get; } public IDecompilerTypeSystem TypeSystem { get; }
public KnownThings KnownThings { get; } public KnownThings KnownThings { get; }
Dictionary<ushort, IModule> assemblyMap = new Dictionary<ushort, IModule>(); Dictionary<ushort, (string FullAssemblyName, IModule Assembly)> assemblyMap = new Dictionary<ushort, (string FullAssemblyName, IModule Assembly)>();
public Dictionary<ushort, AssemblyInfoRecord> AssemblyIdMap { get; } public Dictionary<ushort, AssemblyInfoRecord> AssemblyIdMap { get; }
public Dictionary<ushort, AttributeInfoRecord> AttributeIdMap { get; } public Dictionary<ushort, AttributeInfoRecord> AttributeIdMap { get; }
@ -76,18 +76,18 @@ namespace ILSpy.BamlDecompiler.Baml {
return ctx; return ctx;
} }
public IModule ResolveAssembly(ushort id) { public (string FullAssemblyName, IModule Assembly) ResolveAssembly(ushort id) {
id &= 0xfff; id &= 0xfff;
if (!assemblyMap.TryGetValue(id, out var assembly)) { if (!assemblyMap.TryGetValue(id, out var assembly)) {
if (AssemblyIdMap.TryGetValue(id, out var assemblyRec)) { if (AssemblyIdMap.TryGetValue(id, out var assemblyRec)) {
var assemblyName = Metadata.AssemblyNameReference.Parse(assemblyRec.AssemblyFullName); var assemblyName = Metadata.AssemblyNameReference.Parse(assemblyRec.AssemblyFullName);
if (assemblyName.Name == TypeSystem.MainModule.AssemblyName) if (assemblyName.Name == TypeSystem.MainModule.AssemblyName)
assembly = TypeSystem.MainModule; assembly = (assemblyRec.AssemblyFullName, TypeSystem.MainModule);
else else
assembly = TypeSystem.ReferencedModules.FirstOrDefault(m => m.FullAssemblyName == assemblyName.FullName); assembly = (assemblyRec.AssemblyFullName, TypeSystem.ReferencedModules.FirstOrDefault(m => m.FullAssemblyName == assemblyName.FullName));
} else } else
assembly = null; assembly = (null, null);
assemblyMap[id] = assembly; assemblyMap[id] = assembly;
} }

8
ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs

@ -50,11 +50,11 @@ namespace ILSpy.BamlDecompiler.Handlers {
var record = (XmlnsPropertyRecord)((BamlRecordNode)node).Record; var record = (XmlnsPropertyRecord)((BamlRecordNode)node).Record;
foreach (var asmId in record.AssemblyIds) { foreach (var asmId in record.AssemblyIds) {
var assembly = ctx.Baml.ResolveAssembly(asmId); var assembly = ctx.Baml.ResolveAssembly(asmId);
ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly, record.XmlNamespace)); ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly.FullAssemblyName, record.XmlNamespace));
if (assembly.IsMainModule) { if (assembly.Assembly?.IsMainModule == true) {
foreach (var clrNs in ResolveCLRNamespaces(assembly, record.XmlNamespace)) foreach (var clrNs in ResolveCLRNamespaces(assembly.Assembly, record.XmlNamespace))
ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly, record.XmlNamespace, clrNs)); ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly.FullAssemblyName, record.XmlNamespace, clrNs));
} }
} }

2
ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs

@ -43,7 +43,7 @@ namespace ILSpy.BamlDecompiler.Rewrite {
var newType = typeDef.DirectBaseTypes.First().GetDefinition(); var newType = typeDef.DirectBaseTypes.First().GetDefinition();
if (newType == null) if (newType == null)
return; return;
var xamlType = new XamlType(newType.ParentModule, newType.Namespace, newType.Name); var xamlType = new XamlType(newType.ParentModule, newType.ParentModule.FullAssemblyName, newType.Namespace, newType.Name);
xamlType.ResolveNamespace(elem, ctx); xamlType.ResolveNamespace(elem, ctx);
elem.Name = xamlType.ToXName(ctx); elem.Name = xamlType.ToXName(ctx);

13
ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs

@ -21,26 +21,27 @@
*/ */
using System; using System;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
namespace ILSpy.BamlDecompiler.Xaml { namespace ILSpy.BamlDecompiler.Xaml {
internal class NamespaceMap { internal class NamespaceMap {
public string XmlnsPrefix { get; set; } public string XmlnsPrefix { get; set; }
public IModule Assembly { get; set; } public string FullAssemblyName { get; set; }
public string XMLNamespace { get; set; } public string XMLNamespace { get; set; }
public string CLRNamespace { get; set; } public string CLRNamespace { get; set; }
public NamespaceMap(string prefix, IModule asm, string xmlNs) public NamespaceMap(string prefix, string fullAssemblyName, string xmlNs)
: this(prefix, asm, xmlNs, null) { : this(prefix, fullAssemblyName, xmlNs, null) {
} }
public NamespaceMap(string prefix, IModule asm, string xmlNs, string clrNs) { public NamespaceMap(string prefix, string fullAssemblyName, string xmlNs, string clrNs) {
XmlnsPrefix = prefix; XmlnsPrefix = prefix;
Assembly = asm; FullAssemblyName = fullAssemblyName;
XMLNamespace = xmlNs; XMLNamespace = xmlNs;
CLRNamespace = clrNs; CLRNamespace = clrNs;
} }
public override string ToString() => $"{XmlnsPrefix}:[{Assembly?.Name}|{CLRNamespace ?? XMLNamespace}]"; public override string ToString() => $"{XmlnsPrefix}:[{FullAssemblyName}|{CLRNamespace ?? XMLNamespace}]";
} }
} }

18
ILSpy.BamlDecompiler/Xaml/XamlType.cs

@ -25,20 +25,26 @@ using System.Xml.Linq;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
namespace ILSpy.BamlDecompiler.Xaml { namespace ILSpy.BamlDecompiler.Xaml {
internal class XamlType { internal class XamlType
{
/// <summary>
/// Assembly that contains the type defintion. Can be null.
/// </summary>
public IModule Assembly { get; } public IModule Assembly { get; }
public string FullAssemblyName { get; }
public string TypeNamespace { get; } public string TypeNamespace { get; }
public string TypeName { get; } public string TypeName { get; }
public XNamespace Namespace { get; private set; } public XNamespace Namespace { get; private set; }
public IType ResolvedType { get; set; } public IType ResolvedType { get; set; }
public XamlType(IModule assembly, string ns, string name) public XamlType(IModule assembly, string fullAssemblyName, string ns, string name)
: this(assembly, ns, name, null) { : this(assembly, fullAssemblyName, ns, name, null) {
} }
public XamlType(IModule assembly, string ns, string name, XNamespace xmlns) { public XamlType(IModule assembly, string fullAssemblyName, string ns, string name, XNamespace xmlns) {
Assembly = assembly; Assembly = assembly;
FullAssemblyName = fullAssemblyName;
TypeNamespace = ns; TypeNamespace = ns;
TypeName = name; TypeName = name;
Namespace = xmlns; Namespace = xmlns;
@ -53,9 +59,9 @@ namespace ILSpy.BamlDecompiler.Xaml {
string xmlNs = null; string xmlNs = null;
if (elem.Annotation<XmlnsScope>() != null) if (elem.Annotation<XmlnsScope>() != null)
xmlNs = elem.Annotation<XmlnsScope>().LookupXmlns(Assembly, TypeNamespace); xmlNs = elem.Annotation<XmlnsScope>().LookupXmlns(FullAssemblyName, TypeNamespace);
if (xmlNs == null) if (xmlNs == null)
xmlNs = ctx.XmlNs.LookupXmlns(Assembly, TypeNamespace); xmlNs = ctx.XmlNs.LookupXmlns(FullAssemblyName, TypeNamespace);
// Sometimes there's no reference to System.Xaml even if x:Type is used // Sometimes there's no reference to System.Xaml even if x:Type is used
if (xmlNs == null) if (xmlNs == null)
xmlNs = ctx.TryGetXmlNamespace(Assembly, TypeNamespace); xmlNs = ctx.TryGetXmlNamespace(Assembly, TypeNamespace);

10
ILSpy.BamlDecompiler/XamlContext.cs

@ -83,7 +83,7 @@ namespace ILSpy.BamlDecompiler {
if (piMap == null) if (piMap == null)
continue; continue;
XmlNs.SetPIMapping(piMap.XmlNamespace, piMap.ClrNamespace, Baml.ResolveAssembly(piMap.AssemblyId)); XmlNs.SetPIMapping(piMap.XmlNamespace, piMap.ClrNamespace, Baml.ResolveAssembly(piMap.AssemblyId).FullAssemblyName);
} }
} }
@ -93,21 +93,23 @@ namespace ILSpy.BamlDecompiler {
IType type; IType type;
IModule assembly; IModule assembly;
string fullAssemblyName;
if (id > 0x7fff) { if (id > 0x7fff) {
type = Baml.KnownThings.Types((KnownTypes)(short)-unchecked((short)id)); type = Baml.KnownThings.Types((KnownTypes)(short)-unchecked((short)id));
assembly = type.GetDefinition().ParentModule; assembly = type.GetDefinition().ParentModule;
fullAssemblyName = assembly.FullAssemblyName;
} }
else { else {
var typeRec = Baml.TypeIdMap[id]; var typeRec = Baml.TypeIdMap[id];
assembly = Baml.ResolveAssembly(typeRec.AssemblyId); (fullAssemblyName, assembly) = Baml.ResolveAssembly(typeRec.AssemblyId);
type = ReflectionHelper.ParseReflectionName(typeRec.TypeFullName).Resolve(new SimpleTypeResolveContext(TypeSystem)); type = ReflectionHelper.ParseReflectionName(typeRec.TypeFullName).Resolve(new SimpleTypeResolveContext(TypeSystem));
} }
var clrNs = type.Namespace; var clrNs = type.Namespace;
var xmlNs = XmlNs.LookupXmlns(assembly, clrNs); var xmlNs = XmlNs.LookupXmlns(fullAssemblyName, clrNs);
typeMap[id] = xamlType = new XamlType(assembly, clrNs, type.Name, GetXmlNamespace(xmlNs)) { typeMap[id] = xamlType = new XamlType(assembly, fullAssemblyName, clrNs, type.Name, GetXmlNamespace(xmlNs)) {
ResolvedType = type ResolvedType = type
}; };

18
ILSpy.BamlDecompiler/XmlnsDictionary.cs

@ -21,6 +21,7 @@
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ILSpy.BamlDecompiler.Xaml; using ILSpy.BamlDecompiler.Xaml;
@ -34,10 +35,9 @@ namespace ILSpy.BamlDecompiler {
Element = elem; Element = elem;
} }
public string LookupXmlns(string fullAssemblyName, string clrNs) {
public string LookupXmlns(IModule asm, string clrNs) {
foreach (var ns in this) { foreach (var ns in this) {
if (asm.FullAssemblyName == ns.Assembly?.FullAssemblyName && ns.CLRNamespace == clrNs) if (fullAssemblyName == ns.FullAssemblyName && ns.CLRNamespace == clrNs)
return ns.XMLNamespace; return ns.XMLNamespace;
} }
@ -58,16 +58,16 @@ namespace ILSpy.BamlDecompiler {
public void Add(NamespaceMap map) => CurrentScope.Add(map); public void Add(NamespaceMap map) => CurrentScope.Add(map);
public void SetPIMapping(string xmlNs, string clrNs, IModule assembly) { public void SetPIMapping(string xmlNs, string clrNs, string fullAssemblyName) {
if (!piMappings.ContainsKey(xmlNs)) { if (!piMappings.ContainsKey(xmlNs)) {
var map = new NamespaceMap(null, assembly, xmlNs, clrNs); var map = new NamespaceMap(null, fullAssemblyName, xmlNs, clrNs);
piMappings[xmlNs] = map; piMappings[xmlNs] = map;
} }
} }
NamespaceMap PIFixup(NamespaceMap map) { NamespaceMap PIFixup(NamespaceMap map) {
if (piMappings.TryGetValue(map.XMLNamespace, out var piMap)) { if (piMappings.TryGetValue(map.XMLNamespace, out var piMap)) {
map.Assembly = piMap.Assembly; map.FullAssemblyName = piMap.FullAssemblyName;
map.CLRNamespace = piMap.CLRNamespace; map.CLRNamespace = piMap.CLRNamespace;
} }
return map; return map;
@ -101,16 +101,16 @@ namespace ILSpy.BamlDecompiler {
return null; return null;
} }
public string LookupXmlns(IModule asm, string clrNs) { public string LookupXmlns(string fullAssemblyName, string clrNs) {
foreach (var map in piMappings) { foreach (var map in piMappings) {
if (asm.FullAssemblyName == map.Value.Assembly?.FullAssemblyName && map.Value.CLRNamespace == clrNs) if (fullAssemblyName == map.Value.FullAssemblyName && map.Value.CLRNamespace == clrNs)
return map.Key; return map.Key;
} }
var scope = CurrentScope; var scope = CurrentScope;
while (scope != null) { while (scope != null) {
foreach (var ns in scope) { foreach (var ns in scope) {
if (asm.FullAssemblyName == ns.Assembly?.FullAssemblyName && ns.CLRNamespace == clrNs) if (fullAssemblyName == ns.FullAssemblyName && ns.CLRNamespace == clrNs)
return ns.XMLNamespace; return ns.XMLNamespace;
} }

Loading…
Cancel
Save