Browse Source

Implement Visual Studio solution generation for icsharpcode#972

pull/1550/head
dymanoid 6 years ago
parent
commit
5e6a261b86
  1. 275
      ICSharpCode.Decompiler/CSharp/SolutionCreator.cs
  2. 9
      ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 6
      ILSpy/Languages/CSharpLanguage.cs
  5. 4
      ILSpy/Languages/ILLanguage.cs
  6. 6
      ILSpy/Languages/Language.cs
  7. 54
      ILSpy/SolutionWriter.cs
  8. 4
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  9. 4
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  10. 12
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  11. 3
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  12. 4
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  13. 3
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  14. 3
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  15. 3
      ILSpy/TreeNodes/EventTreeNode.cs
  16. 3
      ILSpy/TreeNodes/FieldTreeNode.cs
  17. 2
      ILSpy/TreeNodes/ILSpyTreeNode.cs
  18. 3
      ILSpy/TreeNodes/MethodTreeNode.cs
  19. 3
      ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
  20. 3
      ILSpy/TreeNodes/NamespaceTreeNode.cs
  21. 3
      ILSpy/TreeNodes/PropertyTreeNode.cs
  22. 4
      ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
  23. 4
      ILSpy/TreeNodes/ResourceListTreeNode.cs
  24. 3
      ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
  25. 3
      ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
  26. 4
      ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
  27. 4
      ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
  28. 6
      ILSpy/TreeNodes/ThreadingSupport.cs
  29. 3
      ILSpy/TreeNodes/TypeTreeNode.cs

275
ICSharpCode.Decompiler/CSharp/SolutionCreator.cs

@ -0,0 +1,275 @@ @@ -0,0 +1,275 @@
// Copyright (c) 2016 Daniel Grunwald
//
// 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.IO;
using System.Linq;
using System.Xml.Linq;
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
/// A container class that holds information about a Visual Studio project.
/// </summary>
public sealed class ProjectItem : ProjectId
{
/// <summary>
/// Initializes a new instance of the <see cref="ProjectItem"/> class.
/// </summary>
/// <param name="projectFile">The full path of the project file.</param>
/// <param name="projectPlatform">The project platform.</param>
/// <param name="projectGuid">The project GUID.</param>
///
/// <exception cref="ArgumentException">Thrown when <paramref name="projectFile"/>
/// or <paramref name="projectPlatform"/> is null or empty.</exception>
public ProjectItem(string projectFile, string projectPlatform, Guid projectGuid)
: base(projectPlatform, projectGuid)
{
ProjectName = Path.GetFileNameWithoutExtension(projectFile);
FilePath = projectFile;
}
/// <summary>
/// Gets the name of the project.
/// </summary>
public string ProjectName { get; }
/// <summary>
/// Gets the full path to the project file.
/// </summary>
public string FilePath { get; }
}
/// <summary>
/// A container class that holds platform and GUID information about a Visual Studio project.
/// </summary>
public class ProjectId
{
/// <summary>
/// Initializes a new instance of the <see cref="ProjectId"/> class.
/// </summary>
/// <param name="projectPlatform">The project platform.</param>
/// <param name="projectGuid">The project GUID.</param>
///
/// <exception cref="ArgumentException">Thrown when <paramref name="projectFile"/>
/// or <paramref name="projectPlatform"/> is null or empty.</exception>
public ProjectId(string projectPlatform, Guid projectGuid)
{
if (string.IsNullOrWhiteSpace(projectPlatform)) {
throw new ArgumentException("The platform cannot be null or empty.", nameof(projectPlatform));
}
Guid = projectGuid;
PlatformName = projectPlatform;
}
/// <summary>
/// Gets the GUID of this project.
/// </summary>
public Guid Guid { get; }
/// <summary>
/// Gets the platform name of this project. Only single platform per project is supported.
/// </summary>
public string PlatformName { get; }
}
/// <summary>
/// A helper class that can write a Visual Studio Solution file for the provided projects.
/// </summary>
public static class SolutionCreator
{
private static readonly XNamespace ProjectFileNamespace = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
/// <summary>
/// Writes a solution file to the specified <paramref name="targetFile"/>.
/// </summary>
/// <param name="targetFile">The full path of the file to write.</param>
/// <param name="projects">The projects contained in this solution.</param>
///
/// <exception cref="ArgumentException">Thrown when <paramref name="targetFile"/> is null or empty.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="projects"/> is null.</exception>
/// <exception cref="InvalidOperationException">Thrown when <paramref name="projects"/> contains no items.</exception>
public static void WriteSolutionFile(string targetFile, IEnumerable<ProjectItem> projects)
{
if (string.IsNullOrWhiteSpace(targetFile)) {
throw new ArgumentException("The target file cannot be null or empty.", nameof(targetFile));
}
if (projects == null) {
throw new ArgumentNullException(nameof(projects));
}
if (!projects.Any()) {
throw new InvalidOperationException("At least one project is expected.");
}
using (var writer = new StreamWriter(targetFile)) {
WriteSolutionFile(writer, projects, Path.GetDirectoryName(targetFile));
}
FixProjectReferences(projects);
}
private static void WriteSolutionFile(TextWriter writer, IEnumerable<ProjectItem> projects, string solutionPath)
{
WriteHeader(writer);
WriteProjects(writer, projects, solutionPath);
writer.WriteLine("Global");
var platforms = WriteSolutionConfigurations(writer, projects);
WriteProjectConfigurations(writer, projects, platforms);
writer.WriteLine("\tGlobalSection(SolutionProperties) = preSolution");
writer.WriteLine("\t\tHideSolutionNode = FALSE");
writer.WriteLine("\tEndGlobalSection");
writer.WriteLine("EndGlobal");
}
private static void WriteHeader(TextWriter writer)
{
writer.WriteLine("Microsoft Visual Studio Solution File, Format Version 12.00");
writer.WriteLine("# Visual Studio 14");
writer.WriteLine("VisualStudioVersion = 14.0.24720.0");
writer.WriteLine("MinimumVisualStudioVersion = 10.0.40219.1");
}
private static void WriteProjects(TextWriter writer, IEnumerable<ProjectItem> projects, string solutionPath)
{
var solutionGuid = Guid.NewGuid().ToString("B").ToUpperInvariant();
foreach (var project in projects) {
var projectRelativePath = GetRelativePath(solutionPath, project.FilePath);
var projectGuid = project.Guid.ToString("B").ToUpperInvariant();
writer.WriteLine($"Project(\"{solutionGuid}\") = \"{project.ProjectName}\", \"{projectRelativePath}\", \"{projectGuid}\"");
writer.WriteLine("EndProject");
}
}
private static IEnumerable<string> WriteSolutionConfigurations(TextWriter writer, IEnumerable<ProjectItem> projects)
{
var platforms = projects.GroupBy(p => p.PlatformName).Select(g => g.Key).ToList();
platforms.Sort();
writer.WriteLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
foreach (var platform in platforms) {
writer.WriteLine($"\t\tDebug|{platform} = Debug|{platform}");
}
foreach (var platform in platforms) {
writer.WriteLine($"\t\tRelease|{platform} = Release|{platform}");
}
writer.WriteLine("\tEndGlobalSection");
return platforms;
}
private static void WriteProjectConfigurations(
TextWriter writer,
IEnumerable<ProjectItem> projects,
IEnumerable<string> solutionPlatforms)
{
writer.WriteLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
foreach (var project in projects) {
var projectGuid = project.Guid.ToString("B").ToUpperInvariant();
foreach (var platform in solutionPlatforms) {
writer.WriteLine($"\t\t{projectGuid}.Debug|{platform}.ActiveCfg = Debug|{project.PlatformName}");
writer.WriteLine($"\t\t{projectGuid}.Debug|{platform}.Build.0 = Debug|{project.PlatformName}");
}
foreach (var platform in solutionPlatforms) {
writer.WriteLine($"\t\t{projectGuid}.Release|{platform}.ActiveCfg = Release|{project.PlatformName}");
writer.WriteLine($"\t\t{projectGuid}.Release|{platform}.Build.0 = Release|{project.PlatformName}");
}
}
writer.WriteLine("\tEndGlobalSection");
}
private static void FixProjectReferences(IEnumerable<ProjectItem> projects)
{
var projectsMap = projects.ToDictionary(p => p.ProjectName, p => p);
foreach (var project in projects) {
var projectDirectory = Path.GetDirectoryName(project.FilePath);
XDocument projectDoc = XDocument.Load(project.FilePath);
var referencesItemGroups = projectDoc.Root
.Elements(ProjectFileNamespace + "ItemGroup")
.Where(e => e.Elements(ProjectFileNamespace + "Reference").Any());
foreach (var itemGroup in referencesItemGroups) {
FixProjectReferences(projectDirectory, itemGroup, projectsMap);
}
projectDoc.Save(project.FilePath);
}
}
private static void FixProjectReferences(string projectDirectory, XElement itemGroup, IDictionary<string, ProjectItem> projects)
{
foreach (var item in itemGroup.Elements(ProjectFileNamespace + "Reference").ToList()) {
var assemblyName = item.Attribute("Include")?.Value;
if (assemblyName != null && projects.TryGetValue(assemblyName, out var referencedProject)) {
item.Remove();
var projectReference = new XElement(ProjectFileNamespace + "ProjectReference",
new XElement(ProjectFileNamespace + "Project", referencedProject.Guid.ToString("B").ToUpperInvariant()),
new XElement(ProjectFileNamespace + "Name", referencedProject.ProjectName));
projectReference.SetAttributeValue("Include", GetRelativePath(projectDirectory, referencedProject.FilePath));
itemGroup.Add(projectReference);
}
}
}
private static string GetRelativePath(string fromPath, string toPath)
{
Uri fromUri = new Uri(AppendDirectorySeparatorChar(fromPath));
Uri toUri = new Uri(AppendDirectorySeparatorChar(toPath));
if (fromUri.Scheme != toUri.Scheme) {
return toPath;
}
Uri relativeUri = fromUri.MakeRelativeUri(toUri);
string relativePath = Uri.UnescapeDataString(relativeUri.ToString());
if (string.Equals(toUri.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) {
relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
}
return relativePath;
}
private static string AppendDirectorySeparatorChar(string path)
{
return Path.HasExtension(path) || path.EndsWith(Path.DirectorySeparatorChar.ToString())
? path
: path + Path.DirectorySeparatorChar;
}
}
}

9
ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs

@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
public void DecompileProject(PEFile moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken))
public ProjectId DecompileProject(PEFile moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken))
{
if (string.IsNullOrEmpty(targetDirectory)) {
throw new InvalidOperationException("Must set TargetDirectory");
@ -110,7 +110,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -110,7 +110,7 @@ namespace ICSharpCode.Decompiler.CSharp
directories.Clear();
var files = WriteCodeFilesInProject(moduleDefinition, cancellationToken).ToList();
files.AddRange(WriteResourceFilesInProject(moduleDefinition));
WriteProjectFile(projectFileWriter, files, moduleDefinition);
return WriteProjectFile(projectFileWriter, files, moduleDefinition);
}
enum LanguageTargets
@ -120,11 +120,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -120,11 +120,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
#region WriteProjectFile
void WriteProjectFile(TextWriter writer, IEnumerable<Tuple<string, string>> files, Metadata.PEFile module)
ProjectId WriteProjectFile(TextWriter writer, IEnumerable<Tuple<string, string>> files, Metadata.PEFile module)
{
const string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
string platformName = GetPlatformName(module);
Guid guid = this.ProjectGuid ?? Guid.NewGuid();
using (XmlTextWriter w = new XmlTextWriter(writer)) {
w.Formatting = Formatting.Indented;
w.WriteStartDocument();
@ -281,6 +282,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -281,6 +282,8 @@ namespace ICSharpCode.Decompiler.CSharp
w.WriteEndDocument();
}
return new ProjectId(platformName, guid);
}
protected virtual bool IsGacAssembly(Metadata.IAssemblyReference r, Metadata.PEFile asm)

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
<Compile Include="CSharp\CSharpLanguageVersion.cs" />
<Compile Include="CSharp\RequiredNamespaceCollector.cs" />
<Compile Include="CSharp\SequencePointBuilder.cs" />
<Compile Include="CSharp\SolutionCreator.cs" />
<Compile Include="CSharp\Syntax\AstNode.cs" />
<Compile Include="CSharp\Syntax\AstNodeCollection.cs" />
<Compile Include="CSharp\Syntax\AstType.cs" />

6
ILSpy/Languages/CSharpLanguage.cs

@ -343,12 +343,12 @@ namespace ICSharpCode.ILSpy @@ -343,12 +343,12 @@ namespace ICSharpCode.ILSpy
}
}
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
public override object DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{
var module = assembly.GetPEFileOrNull();
if (options.FullDecompilation && options.SaveAsProjectDirectory != null) {
var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
return decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
} else {
AddReferenceAssemblyWarningMessage(module, output);
AddReferenceWarningMessage(module, output);
@ -415,6 +415,8 @@ namespace ICSharpCode.ILSpy @@ -415,6 +415,8 @@ namespace ICSharpCode.ILSpy
}
WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem);
}
return true;
}
}

4
ILSpy/Languages/ILLanguage.cs

@ -150,7 +150,7 @@ namespace ICSharpCode.ILSpy @@ -150,7 +150,7 @@ namespace ICSharpCode.ILSpy
dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken));
}
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
public override object DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{
output.WriteLine("// " + assembly.FileName);
output.WriteLine();
@ -174,6 +174,8 @@ namespace ICSharpCode.ILSpy @@ -174,6 +174,8 @@ namespace ICSharpCode.ILSpy
dis.WriteModuleContents(module);
}
}
return true;
}
}
}

6
ILSpy/Languages/Language.cs

@ -131,11 +131,11 @@ namespace ICSharpCode.ILSpy @@ -131,11 +131,11 @@ namespace ICSharpCode.ILSpy
WriteCommentLine(output, nameSpace);
}
public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
public virtual object DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, assembly.FileName);
var asm = assembly.GetPEFileOrNull();
if (asm == null) return;
if (asm == null) return false;
var metadata = asm.Metadata;
if (metadata.IsAssembly) {
var name = metadata.GetAssemblyDefinition();
@ -147,6 +147,8 @@ namespace ICSharpCode.ILSpy @@ -147,6 +147,8 @@ namespace ICSharpCode.ILSpy
} else {
WriteCommentLine(output, metadata.GetString(metadata.GetModuleDefinition().Name));
}
return true;
}
public virtual void WriteCommentLine(ITextOutput output, string comment)

54
ILSpy/SolutionWriter.cs

@ -27,6 +27,7 @@ using System.Threading; @@ -27,6 +27,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using Microsoft.Win32;
@ -130,6 +131,8 @@ namespace ICSharpCode.ILSpy @@ -130,6 +131,8 @@ namespace ICSharpCode.ILSpy
{
var solutionDirectory = Path.GetDirectoryName(solutionFilePath);
var statusOutput = new ConcurrentBag<string>();
var projects = new ConcurrentBag<ProjectItem>();
var result = new AvalonEditTextOutput();
var duplicates = new HashSet<string>();
@ -140,20 +143,45 @@ namespace ICSharpCode.ILSpy @@ -140,20 +143,45 @@ namespace ICSharpCode.ILSpy
Stopwatch stopwatch = Stopwatch.StartNew();
await Task.Run(() => Parallel.ForEach(assemblyNodes, n => WriteProject(n, solutionDirectory, statusOutput, ct)))
.ConfigureAwait(false);
try {
await Task.Run(() => Parallel.ForEach(assemblyNodes, n => WriteProject(n, solutionDirectory, statusOutput, projects, ct)))
.ConfigureAwait(false);
await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects))
.ConfigureAwait(false);
} catch (AggregateException ae) {
if (ae.Flatten().InnerExceptions.All(e => e is OperationCanceledException)) {
result.WriteLine();
result.WriteLine("Generation was cancelled.");
return result;
}
result.WriteLine();
result.WriteLine("Failed to generate the Visual Studio Solution. Errors:");
ae.Handle(e => {
result.WriteLine(e.Message);
return true;
});
return result;
}
foreach (var item in statusOutput) {
result.WriteLine(item);
}
if (statusOutput.Count == 0) {
result.WriteLine("Successfully decompiled the following assemblies to a Visual Studio Solution:");
result.WriteLine("Successfully decompiled the following assemblies into Visual Studio projects:");
foreach (var item in assemblyNodes.Select(n => n.Text.ToString())) {
result.WriteLine(item);
}
result.WriteLine();
if (assemblyNodes.Count() == projects.Count) {
result.WriteLine("Created the Visual Studio Solution file.");
}
result.WriteLine();
result.WriteLine("Elapsed time: " + stopwatch.Elapsed.TotalSeconds.ToString("F1") + " seconds.");
result.WriteLine();
@ -163,7 +191,12 @@ namespace ICSharpCode.ILSpy @@ -163,7 +191,12 @@ namespace ICSharpCode.ILSpy
return result;
}
private static void WriteProject(AssemblyTreeNode assemblyNode, string targetDirectory, ConcurrentBag<string> statusOutput, CancellationToken ct)
private static void WriteProject(
AssemblyTreeNode assemblyNode,
string targetDirectory,
ConcurrentBag<string> statusOutput,
ConcurrentBag<ProjectItem> targetContainer,
CancellationToken ct)
{
var loadedAssembly = assemblyNode.LoadedAssembly;
@ -186,12 +219,17 @@ namespace ICSharpCode.ILSpy @@ -186,12 +219,17 @@ namespace ICSharpCode.ILSpy
FullDecompilation = true,
CancellationToken = ct,
SaveAsProjectDirectory = targetDirectory };
assemblyNode.Decompile(assemblyNode.Language, projectFileOutput, options);
if (assemblyNode.Decompile(assemblyNode.Language, projectFileOutput, options) is ProjectId projectInfo) {
targetContainer.Add(new ProjectItem(projectFileName, projectInfo.PlatformName, projectInfo.Guid));
}
}
} catch (Exception e) {
}
catch (OperationCanceledException) {
throw;
}
catch (Exception e) {
statusOutput.Add($"Failed to decompile the assembly '{loadedAssembly.FileName}':{Environment.NewLine}{e}");
return;
}
}
}

4
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public Action<SharpTreeNode> Select = delegate { };
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "List: " + assemblyList.ListName);
output.WriteLine();
@ -150,6 +150,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -150,6 +150,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
output.WriteLine();
asm.Decompile(language, output, options);
}
return true;
}
#region Find*Node

4
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
var loaded = parentAssembly.LoadedAssembly.LoadedAssemblyReferencesInfo.TryGetInfo(r.FullName, out var info);
if (r.IsWindowsRuntime) {
@ -98,6 +98,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -98,6 +98,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
output.Unindent();
output.WriteLine();
}
return true;
}
}
}

12
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -240,7 +240,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -240,7 +240,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Recurse;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
void HandleException(Exception ex, string message)
{
@ -259,21 +259,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -259,21 +259,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
switch (ex.InnerException) {
case BadImageFormatException badImage:
HandleException(badImage, "This file does not contain a managed assembly.");
return;
return null;
case FileNotFoundException fileNotFound:
HandleException(fileNotFound, "The file was not found.");
return;
return null;
case DirectoryNotFoundException dirNotFound:
HandleException(dirNotFound, "The directory was not found.");
return;
return null;
case PEFileNotSupportedException notSupported:
HandleException(notSupported, notSupported.Message);
return;
return null;
default:
throw;
}
}
language.DecompileAssembly(LoadedAssembly, output, options);
return language.DecompileAssembly(LoadedAssembly, output, options);
}
public override bool Save(DecompilerTextView textView)

3
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -97,9 +97,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -97,9 +97,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return false;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
return true;
}
IEntity IMemberTreeNode.Member {

4
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -69,12 +69,14 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -69,12 +69,14 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren));
foreach (ILSpyTreeNode child in this.Children) {
child.Decompile(language, output, options);
}
return true;
}
}
}

3
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -90,9 +90,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -90,9 +90,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
e.Handled = BaseTypesEntryNode.ActivateItem(this, type);
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
return true;
}
IEntity IMemberTreeNode.Member => type;

3
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -92,9 +92,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -92,9 +92,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return typeRef.GetFullTypeName(referenceMetadata) == typeDef.GetFullTypeName(definitionMetadata);
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
threading.Decompile(language, output, options, EnsureLazyChildren);
return true;
}
}
}

3
ILSpy/TreeNodes/EventTreeNode.cs

@ -67,9 +67,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -67,9 +67,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileEvent(EventDefinition, output, options);
return true;
}
public override bool IsPublicAPI {

3
ILSpy/TreeNodes/FieldTreeNode.cs

@ -68,9 +68,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -68,9 +68,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileField(FieldDefinition, output, options);
return true;
}
public override bool IsPublicAPI {

2
ILSpy/TreeNodes/ILSpyTreeNode.cs

@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
}
public abstract void Decompile(Language language, ITextOutput output, DecompilationOptions options);
public abstract object Decompile(Language language, ITextOutput output, DecompilationOptions options);
/// <summary>
/// Used to implement special view logic for some items.

3
ILSpy/TreeNodes/MethodTreeNode.cs

@ -83,9 +83,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -83,9 +83,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileMethod(MethodDefinition, output, options);
return true;
}
public override FilterResult Filter(FilterSettings settings)

3
ILSpy/TreeNodes/ModuleReferenceTreeNode.cs

@ -72,10 +72,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -72,10 +72,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, moduleName);
language.WriteCommentLine(output, containsMetadata ? "contains metadata" : "contains no metadata");
return true;
}
}
}

3
ILSpy/TreeNodes/NamespaceTreeNode.cs

@ -56,9 +56,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -56,9 +56,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Recurse;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileNamespace(name, this.Children.OfType<TypeTreeNode>().Select(t => t.TypeDefinition), output, options);
return true;
}
}
}

3
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -74,9 +74,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -74,9 +74,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileProperty(PropertyDefinition, output, options);
return true;
}
public override bool IsPublicAPI {

4
ILSpy/TreeNodes/ReferenceFolderTreeNode.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, metadata));
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, $"Detected Target-Framework-Id: {parentAssembly.LoadedAssembly.GetTargetFrameworkIdAsync().Result}");
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren));
@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
output.Unindent();
output.WriteLine();
}
return true;
}
}
}

4
ILSpy/TreeNodes/ResourceListTreeNode.cs

@ -64,13 +64,15 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -64,13 +64,15 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Recurse;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren));
foreach (ILSpyTreeNode child in this.Children) {
child.Decompile(language, output, options);
output.WriteLine();
}
return true;
}
}
}

3
ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs

@ -75,9 +75,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -75,9 +75,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
EnsureLazyChildren();
return true;
}
}
}

3
ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs

@ -73,9 +73,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -73,9 +73,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
return result;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, string.Format("{0} = {1}", key, data));
return true;
}
public override bool Save(DecompilerTextView textView)

4
ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, string.Format("{0} ({1}, {2})", r.Name, r.ResourceType, r.Attributes));
@ -76,6 +76,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -76,6 +76,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
smartOutput.AddButton(Images.Save, Resources.Save, delegate { Save(MainWindow.Instance.TextView); });
output.WriteLine();
}
return true;
}
public override bool View(DecompilerTextView textView)

4
ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return true;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
EnsureLazyChildren();
base.Decompile(language, output, options);
@ -168,6 +168,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -168,6 +168,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
output.WriteLine();
}
return true;
}
internal class SerializedObjectRepresentation

6
ILSpy/TreeNodes/ThreadingSupport.cs

@ -128,8 +128,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -128,8 +128,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Match;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
return false;
}
}
@ -151,8 +152,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -151,8 +152,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Match;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
return false;
}
}

3
ILSpy/TreeNodes/TypeTreeNode.cs

@ -103,9 +103,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -103,9 +103,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool CanExpandRecursively => true;
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
public override object Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileType(TypeDefinition, output, options);
return true;
}
public override object Icon => GetIcon(TypeDefinition);

Loading…
Cancel
Save