Browse Source

Fix #2718, Fix #2719, Fix #2725: Remove WPF compiler-generated code.

pull/2749/head
Siegfried Pammer 3 years ago
parent
commit
5046e4cf60
  1. 73
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 29
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 76
      ICSharpCode.Decompiler/PartialTypeInfo.cs
  5. 4
      ILSpy.BamlDecompiler/BamlConnectionId.cs
  6. 6
      ILSpy.BamlDecompiler/BamlDecompilationResult.cs
  7. 25
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  8. 2
      ILSpy.BamlDecompiler/Properties/launchSettings.json
  9. 64
      ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs
  10. 4
      ILSpy.BamlDecompiler/XamlContext.cs
  11. 2
      ILSpy.BamlDecompiler/XamlDecompiler.cs
  12. 10
      ILSpy/Languages/CSharpLanguage.cs
  13. 24
      ILSpy/Languages/IResourceFileHandler.cs

73
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable; @@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -522,6 +523,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -522,6 +523,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
DecompileRun CreateDecompileRun()
{
return new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
}
void RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
@ -550,10 +559,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -550,10 +559,7 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileModuleAndAssemblyAttributes()
{
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
DecompileRun decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectAttributeNamespaces(module, decompileRun.Namespaces);
DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
@ -639,10 +645,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -639,10 +645,7 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileWholeModuleAsSingleFile(bool sortTypes)
{
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectNamespaces(module, decompileRun.Namespaces);
DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
@ -664,10 +667,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -664,10 +667,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary>
public ILTransformContext CreateILTransformContext(ILFunction function)
{
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
var decompileRun = CreateDecompileRun();
RequiredNamespaceCollector.CollectNamespaces(function.Method, module, decompileRun.Namespaces);
return new ILTransformContext(function, typeSystem, DebugInfoProvider, settings) {
CancellationToken = CancellationToken,
@ -912,10 +912,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -912,10 +912,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (types == null)
throw new ArgumentNullException(nameof(types));
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree();
foreach (var type in types)
@ -957,10 +954,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -957,10 +954,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (type.ParentModule != typeSystem.MainModule)
throw new NotSupportedException("Decompiling types that are not part of the main module is not supported.");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectNamespaces(type.MetadataToken, module, decompileRun.Namespaces);
DoDecompileTypes(new[] { (TypeDefinitionHandle)type.MetadataToken }, decompileRun, decompilationContext, syntaxTree);
@ -995,10 +989,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -995,10 +989,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (definitions == null)
throw new ArgumentNullException(nameof(definitions));
syntaxTree = new SyntaxTree();
var decompileRun = new DecompileRun(settings) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken
};
var decompileRun = CreateDecompileRun();
foreach (var entity in definitions)
{
if (entity.IsNil)
@ -1100,6 +1091,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1100,6 +1091,20 @@ namespace ICSharpCode.Decompiler.CSharp
return SyntaxTreeToString(Decompile(definitions));
}
readonly Dictionary<TypeDefinitionHandle, PartialTypeInfo> partialTypes = new();
public void AddPartialTypeDefinition(PartialTypeInfo info)
{
if (!partialTypes.TryGetValue(info.DeclaringTypeDefinitionHandle, out var existingInfo))
{
partialTypes.Add(info.DeclaringTypeDefinitionHandle, info);
}
else
{
existingInfo.AddDeclaredMembers(info);
}
}
IEnumerable<EntityDeclaration> AddInterfaceImplHelpers(
EntityDeclaration memberDecl, IMethod method,
TypeSystemAstBuilder astBuilder)
@ -1319,6 +1324,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1319,6 +1324,11 @@ namespace ICSharpCode.Decompiler.CSharp
var allOrderedEntities = typeDef.NestedTypes.Concat<IEntity>(allOrderedMembers).ToArray();
if (!partialTypes.TryGetValue((TypeDefinitionHandle)typeDef.MetadataToken, out var partialTypeInfo))
{
partialTypeInfo = null;
}
// Decompile members that are not compiler-generated.
foreach (var entity in allOrderedEntities)
{
@ -1326,7 +1336,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1326,7 +1336,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
continue;
}
DoDecompileMember(entity, recordDecompiler);
DoDecompileMember(entity, recordDecompiler, partialTypeInfo);
}
// Decompile compiler-generated members that are still needed.
@ -1338,7 +1348,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1338,7 +1348,7 @@ namespace ICSharpCode.Decompiler.CSharp
// Member is already decompiled.
continue;
}
DoDecompileMember(entity, recordDecompiler);
DoDecompileMember(entity, recordDecompiler, partialTypeInfo);
}
// Add all decompiled members to syntax tree in the correct order.
@ -1352,6 +1362,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1352,6 +1362,10 @@ namespace ICSharpCode.Decompiler.CSharp
// Remove the [DefaultMember] attribute if the class contains indexers
RemoveAttribute(typeDecl, KnownAttribute.DefaultMember);
}
if (partialTypeInfo != null)
{
typeDecl.Modifiers |= Modifiers.Partial;
}
if (settings.IntroduceRefModifiersOnStructs)
{
if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr))
@ -1406,8 +1420,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1406,8 +1420,13 @@ namespace ICSharpCode.Decompiler.CSharp
Instrumentation.DecompilerEventSource.Log.DoDecompileTypeDefinition(typeDef.FullName, watch.ElapsedMilliseconds);
}
void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler)
void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler, PartialTypeInfo partialType)
{
if (partialType != null && partialType.IsDeclaredMember(entity.MetadataToken))
{
return;
}
EntityDeclaration entityDecl;
switch (entity)
{

29
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -149,8 +149,9 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -149,8 +149,9 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
TargetDirectory = targetDirectory;
directories.Clear();
var files = WriteCodeFilesInProject(moduleDefinition, cancellationToken).ToList();
files.AddRange(WriteResourceFilesInProject(moduleDefinition));
var resources = WriteResourceFilesInProject(moduleDefinition).ToList();
var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.partialTypes ?? Enumerable.Empty<PartialTypeInfo>()).ToList(), cancellationToken).ToList();
files.AddRange(resources.Select(r => (r.itemType, r.fileName)));
files.AddRange(WriteMiscellaneousFilesInProject(moduleDefinition));
if (StrongNameKeyFile != null)
{
@ -202,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -202,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
return new[] { ("Compile", assemblyInfo) };
}
IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, CancellationToken cancellationToken)
IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
{
var metadata = module.Metadata;
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy(
@ -237,6 +238,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -237,6 +238,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
try
{
CSharpDecompiler decompiler = CreateDecompiler(ts);
foreach (var partialType in partialTypes)
{
decompiler.AddPartialTypeDefinition(partialType);
}
decompiler.CancellationToken = cancellationToken;
var syntaxTree = decompiler.DecompileTypes(file.ToArray());
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
@ -253,7 +260,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -253,7 +260,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#endregion
#region WriteResourceFilesInProject
protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceFilesInProject(Metadata.PEFile module)
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceFilesInProject(Metadata.PEFile module)
{
foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded))
{
@ -263,7 +270,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -263,7 +270,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
bool decodedIntoIndividualFiles;
var individualResources = new List<(string itemType, string fileName)>();
var individualResources = new List<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)>();
try
{
var resourcesFile = new ResourcesFile(stream);
@ -323,12 +330,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -323,12 +330,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
stream.Position = 0;
stream.CopyTo(fs);
}
yield return ("EmbeddedResource", fileName);
yield return ("EmbeddedResource", fileName, null);
}
}
}
protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
if (fileName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
@ -343,7 +350,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -343,7 +350,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
writer.AddResource(entry.Key, entry.Value);
}
}
return new[] { ("EmbeddedResource", resx) };
return new[] { ("EmbeddedResource", resx, (List<PartialTypeInfo>)null) };
}
catch (BadImageFormatException)
{
@ -358,7 +365,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -358,7 +365,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
entryStream.CopyTo(fs);
}
return new[] { ("EmbeddedResource", fileName) };
return new[] { ("EmbeddedResource", fileName, (List<PartialTypeInfo>)null) };
}
string GetFileNameForResource(string fullName)
@ -558,8 +565,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -558,8 +565,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// <summary>
/// Cleans up a node name for use as a file system name. If <paramref name="separateAtDots"/> is active,
/// dots are seen as segment separators. Each segment is limited to maxSegmentLength characters.
/// (see <see cref="GetLongPathSupport"/>) If <paramref name="treatAsFileName"/> is active,
/// we check for file a extension and try to preserve it, if it's valid.
/// If <paramref name="treatAsFileName"/> is active, we check for file a extension and try to preserve it,
/// if it's valid.
/// </summary>
static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName)
{

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -84,6 +84,7 @@ @@ -84,6 +84,7 @@
<Compile Include="CSharp\Annotations.cs" />
<Compile Include="CSharp\CallBuilder.cs" />
<Compile Include="CSharp\CSharpLanguageVersion.cs" />
<Compile Include="PartialTypeInfo.cs" />
<Compile Include="CSharp\ProjectDecompiler\IProjectFileWriter.cs" />
<Compile Include="CSharp\OutputVisitor\GenericGrammarAmbiguityVisitor.cs" />
<Compile Include="CSharp\ProjectDecompiler\IProjectInfoProvider.cs" />

76
ICSharpCode.Decompiler/PartialTypeInfo.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// Copyright (c) 2022 Siegfried Pammer
//
// 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.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{
public class PartialTypeInfo
{
readonly HashSet<EntityHandle> declaredMembers = new();
public PartialTypeInfo(ITypeDefinition declaringTypeDefinition)
{
DeclaringTypeDefinitionHandle = (TypeDefinitionHandle)declaringTypeDefinition.MetadataToken;
}
public PartialTypeInfo(TypeDefinitionHandle declaringTypeDefinitionHandle)
{
DeclaringTypeDefinitionHandle = declaringTypeDefinitionHandle;
}
public TypeDefinitionHandle DeclaringTypeDefinitionHandle { get; }
public void AddDeclaredMember(IMember member)
{
declaredMembers.Add(member.MetadataToken);
}
public void AddDeclaredMember(EntityHandle handle)
{
declaredMembers.Add(handle);
}
public bool IsDeclaredMember(IMember member)
{
return declaredMembers.Contains(member.MetadataToken);
}
public bool IsDeclaredMember(EntityHandle handle)
{
return declaredMembers.Contains(handle);
}
public void AddDeclaredMembers(PartialTypeInfo info)
{
foreach (var member in info.declaredMembers)
{
declaredMembers.Add(member);
}
}
public string DebugOutput => string.Join(", ", declaredMembers.Select(m => MetadataTokens.GetToken(m).ToString("X")));
}
}

4
ILSpy.BamlDecompiler/BamlConnectionId.cs

@ -20,6 +20,8 @@ @@ -20,6 +20,8 @@
THE SOFTWARE.
*/
using ICSharpCode.Decompiler.TypeSystem;
namespace ILSpy.BamlDecompiler
{
/// <summary>
@ -27,7 +29,7 @@ namespace ILSpy.BamlDecompiler @@ -27,7 +29,7 @@ namespace ILSpy.BamlDecompiler
/// </summary>
internal sealed class FieldAssignment
{
public string FieldName;
public IField Field;
}
/// <summary>

6
ILSpy.BamlDecompiler/BamlDecompilationResult.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Xml.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -31,11 +32,14 @@ namespace ILSpy.BamlDecompiler @@ -31,11 +32,14 @@ namespace ILSpy.BamlDecompiler
public FullTypeName? TypeName { get; }
public BamlDecompilationResult(XDocument xaml, FullTypeName? typeName, IEnumerable<string> assemblyReferences)
public List<EntityHandle> GeneratedMembers { get; }
public BamlDecompilationResult(XDocument xaml, FullTypeName? typeName, IEnumerable<string> assemblyReferences, IEnumerable<EntityHandle> generatedMembers)
{
this.Xaml = xaml;
this.TypeName = typeName;
this.AssemblyReferences = assemblyReferences.ToList();
this.GeneratedMembers = generatedMembers.ToList();
}
}
}

25
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -19,7 +19,9 @@ @@ -19,7 +19,9 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy;
@ -45,25 +47,34 @@ namespace ILSpy.BamlDecompiler @@ -45,25 +47,34 @@ namespace ILSpy.BamlDecompiler
public sealed class BamlResourceFileHandler : IResourceFileHandler
{
public string EntryType => "Page";
public bool CanHandle(string name, DecompilationOptions options) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
public bool CanHandle(string name, ResourceFileHandlerContext context) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, ResourceFileHandlerContext context)
{
BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver());
var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings() {
ThrowOnAssemblyResolveErrors = options.DecompilerSettings.ThrowOnAssemblyResolveErrors
ThrowOnAssemblyResolveErrors = context.DecompilationOptions.DecompilerSettings.ThrowOnAssemblyResolveErrors
});
decompiler.CancellationToken = options.CancellationToken;
decompiler.CancellationToken = context.DecompilationOptions.CancellationToken;
var result = decompiler.Decompile(stream);
if (result.TypeName.HasValue)
var typeDefinition = result.TypeName.HasValue ? typeSystem.MainModule.GetTypeDefinition(result.TypeName.Value.TopLevelTypeName) : null;
if (typeDefinition != null)
{
fileName = WholeProjectDecompiler.CleanUpPath(result.TypeName.Value.ReflectionName) + ".xaml";
fileName = WholeProjectDecompiler.CleanUpPath(typeDefinition.ReflectionName) + ".xaml";
var partialTypeInfo = new PartialTypeInfo(typeDefinition);
foreach (var member in result.GeneratedMembers)
{
partialTypeInfo.AddDeclaredMember(member);
}
context.AddPartialTypeInfo(partialTypeInfo);
}
else
{
fileName = Path.ChangeExtension(fileName, ".xaml");
}
result.Xaml.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
string saveFileName = Path.Combine(context.DecompilationOptions.SaveAsProjectDirectory, fileName);
Directory.CreateDirectory(Path.GetDirectoryName(saveFileName));
result.Xaml.Save(saveFileName);
return fileName;
}
}

2
ILSpy.BamlDecompiler/Properties/launchSettings.json

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
"profiles": {
"ILSpy.BamlDecompiler": {
"commandName": "Executable",
"executablePath": "C:\\Users\\sie_p\\Projects\\ILSpy\\ILSpy\\bin\\Debug\\net472\\ILSpy.exe",
"executablePath": "$(SolutionDir)\\ILSpy\\bin\\Debug\\net6.0-windows\\ILSpy.exe",
"commandLineArgs": "/separate"
}
}

64
ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs

@ -25,13 +25,14 @@ using System.Xml.Linq; @@ -25,13 +25,14 @@ using System.Xml.Linq;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ILSpy.BamlDecompiler.Xaml;
namespace ILSpy.BamlDecompiler.Rewrite
{
using ICSharpCode.Decompiler.TypeSystem;
internal class ConnectionIdRewritePass : IRewritePass
{
static readonly TopLevelTypeName componentConnectorTypeName
@ -61,8 +62,12 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -61,8 +62,12 @@ namespace ILSpy.BamlDecompiler.Rewrite
if ((index = fieldAssignments.FindIndex(item => item.key.Contains(annotation.Id))) > -1)
{
var xName = ctx.GetKnownNamespace("Name", XamlContext.KnownNamespace_Xaml, element);
FieldAssignment fieldAssignment = fieldAssignments[index].value;
if (element.Attribute("Name") is null && element.Attribute(xName) is null)
element.Add(new XAttribute(xName, fieldAssignments[index].value.FieldName));
{
element.Add(new XAttribute(xName, fieldAssignment.Field.Name));
}
ctx.GeneratedMembers.Add(fieldAssignment.Field.MetadataToken);
found = true;
}
if ((index = eventMappings.FindIndex(item => item.key.Contains(annotation.Id))) > -1)
@ -121,32 +126,61 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -121,32 +126,61 @@ namespace ILSpy.BamlDecompiler.Rewrite
return;
var connect = connectorInterface.GetMethods(m => m.Name == "Connect").SingleOrDefault();
IMethod method = null;
MethodDefinition metadataEntry = default;
IMethod connectMethod = null;
MethodDefinition connectMetadataEntry = default;
var module = ctx.TypeSystem.MainModule.PEFile;
foreach (IMethod m in type.Methods)
{
if (m.ExplicitlyImplementedInterfaceMembers.Any(md => md.MemberDefinition.Equals(connect)))
if (connectMethod == null && m.ExplicitlyImplementedInterfaceMembers.Any(md => md.MemberDefinition.Equals(connect)))
{
method = m;
metadataEntry = module.Metadata
.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
break;
connectMethod = m;
connectMetadataEntry = module.Metadata
.GetMethodDefinition((MethodDefinitionHandle)connectMethod.MetadataToken);
}
else if (m.Parameters.Count == 0
&& m.ReturnType.Kind == TypeKind.Void
&& !m.IsStatic
&& m.Accessibility == Accessibility.Public
&& m.Name == "InitializeComponent"
&& m.GetAttributes().Any(a => a.AttributeType.ReflectionName == "System.CodeDom.Compiler.GeneratedCodeAttribute"))
{
ctx.GeneratedMembers.Add(m.MetadataToken);
}
else if (m.Parameters.Count == 0
&& m.ReturnType.Kind == TypeKind.Void
&& m.IsStatic
&& m.Accessibility == Accessibility.Public
&& m.Name == "Main"
&& m.DeclaringTypeDefinition.GetNonInterfaceBaseTypes().Any(t => t.ReflectionName == "System.Windows.Application")
&& m.GetAttributes().Any(a => a.AttributeType.ReflectionName == "System.CodeDom.Compiler.GeneratedCodeAttribute"))
{
ctx.GeneratedMembers.Add(m.MetadataToken);
}
}
if (type.Fields.FirstOrDefault(f => f.Name == "_contentLoaded" && f.Type.IsKnownType(KnownTypeCode.Boolean)) is {
Accessibility: Accessibility.Private, IsStatic: false
} contentLoadedField)
{
ctx.GeneratedMembers.Add(contentLoadedField.MetadataToken);
}
if (method == null || metadataEntry.RelativeVirtualAddress <= 0)
if (connectMethod == null || connectMetadataEntry.RelativeVirtualAddress <= 0)
return;
var body = module.Reader.GetMethodBody(metadataEntry.RelativeVirtualAddress);
ctx.GeneratedMembers.Add(connectMethod.MetadataToken);
var body = module.Reader.GetMethodBody(connectMetadataEntry.RelativeVirtualAddress);
var genericContext = new GenericContext(
classTypeParameters: method.DeclaringType?.TypeParameters,
methodTypeParameters: method.TypeParameters);
classTypeParameters: connectMethod.DeclaringType?.TypeParameters,
methodTypeParameters: connectMethod.TypeParameters);
// decompile method and optimize the switch
var ilReader = new ILReader(ctx.TypeSystem.MainModule);
var function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, body, genericContext,
var function = ilReader.ReadIL((MethodDefinitionHandle)connectMethod.MetadataToken, body, genericContext,
ILFunctionKind.TopLevelFunction, ctx.CancellationToken);
var context = new ILTransformContext(function, ctx.TypeSystem, null) {
@ -224,7 +258,7 @@ namespace ILSpy.BamlDecompiler.Rewrite @@ -224,7 +258,7 @@ namespace ILSpy.BamlDecompiler.Rewrite
|| !(arg.MatchLdLoc(out var t) && t.Kind == VariableKind.Parameter && t.Index == 1))
return false;
field = new FieldAssignment { FieldName = fld.Name };
field = new FieldAssignment { Field = fld };
return true;
}

4
ILSpy.BamlDecompiler/XamlContext.cs

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
using System.Xml.Linq;
@ -40,6 +41,7 @@ namespace ILSpy.BamlDecompiler @@ -40,6 +41,7 @@ namespace ILSpy.BamlDecompiler
TypeSystem = typeSystem;
NodeMap = new Dictionary<BamlRecord, BamlBlockNode>();
XmlNs = new XmlnsDictionary();
GeneratedMembers = new List<EntityHandle>();
XClassNames = new List<string>();
}
@ -57,6 +59,8 @@ namespace ILSpy.BamlDecompiler @@ -57,6 +59,8 @@ namespace ILSpy.BamlDecompiler
public List<string> XClassNames { get; }
public List<EntityHandle> GeneratedMembers { get; }
public XmlnsDictionary XmlNs { get; }
public static XamlContext Construct(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerSettings bamlDecompilerOptions)

2
ILSpy.BamlDecompiler/XamlDecompiler.cs

@ -121,7 +121,7 @@ namespace ILSpy.BamlDecompiler @@ -121,7 +121,7 @@ namespace ILSpy.BamlDecompiler
var assemblyReferences = ctx.Baml.AssemblyIdMap.Select(a => a.Value.AssemblyFullName);
var typeName = ctx.XClassNames.FirstOrDefault() is string s ? (FullTypeName?)new FullTypeName(s) : null;
return new BamlDecompilationResult(xaml, typeName, assemblyReferences);
return new BamlDecompilationResult(xaml, typeName, assemblyReferences, ctx.GeneratedMembers);
}
}
}

10
ILSpy/Languages/CSharpLanguage.cs

@ -509,15 +509,17 @@ namespace ICSharpCode.ILSpy @@ -509,15 +509,17 @@ namespace ICSharpCode.ILSpy
this.options = options;
}
protected override IEnumerable<(string itemType, string fileName)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
protected override IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
var context = new ResourceFileHandlerContext(options);
foreach (var handler in App.ExportProvider.GetExportedValues<IResourceFileHandler>())
{
if (handler.CanHandle(fileName, options))
if (handler.CanHandle(fileName, context))
{
entryStream.Position = 0;
fileName = handler.WriteResourceToFile(assembly, fileName, entryStream, options);
return new[] { (handler.EntryType, fileName) };
fileName = handler.WriteResourceToFile(assembly, fileName, entryStream, context);
return new[] { (handler.EntryType, fileName, context.PartialTypes) };
}
}
return base.WriteResourceToFile(fileName, resourceName, entryStream);

24
ILSpy/Languages/IResourceFileHandler.cs

@ -16,8 +16,10 @@ @@ -16,8 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy
@ -25,7 +27,25 @@ namespace ICSharpCode.ILSpy @@ -25,7 +27,25 @@ namespace ICSharpCode.ILSpy
public interface IResourceFileHandler
{
string EntryType { get; }
bool CanHandle(string name, DecompilationOptions options);
string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options);
bool CanHandle(string name, ResourceFileHandlerContext context);
string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, ResourceFileHandlerContext context);
}
public class ResourceFileHandlerContext
{
readonly List<PartialTypeInfo> partialTypes = new();
internal List<PartialTypeInfo> PartialTypes => partialTypes;
public DecompilationOptions DecompilationOptions { get; }
public ResourceFileHandlerContext(DecompilationOptions options)
{
this.DecompilationOptions = options;
}
public void AddPartialTypeInfo(PartialTypeInfo info)
{
this.PartialTypes.Add(info);
}
}
}

Loading…
Cancel
Save