diff --git a/ICSharpCode.Decompiler/CSharp/SolutionCreator.cs b/ICSharpCode.Decompiler/CSharp/SolutionCreator.cs
new file mode 100644
index 000000000..7c3f26e0e
--- /dev/null
+++ b/ICSharpCode.Decompiler/CSharp/SolutionCreator.cs
@@ -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
+{
+ ///
+ /// A container class that holds information about a Visual Studio project.
+ ///
+ public sealed class ProjectItem : ProjectId
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The full path of the project file.
+ /// The project platform.
+ /// The project GUID.
+ ///
+ /// Thrown when
+ /// or is null or empty.
+ public ProjectItem(string projectFile, string projectPlatform, Guid projectGuid)
+ : base(projectPlatform, projectGuid)
+ {
+ ProjectName = Path.GetFileNameWithoutExtension(projectFile);
+ FilePath = projectFile;
+ }
+
+ ///
+ /// Gets the name of the project.
+ ///
+ public string ProjectName { get; }
+
+ ///
+ /// Gets the full path to the project file.
+ ///
+ public string FilePath { get; }
+ }
+
+ ///
+ /// A container class that holds platform and GUID information about a Visual Studio project.
+ ///
+ public class ProjectId
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The project platform.
+ /// The project GUID.
+ ///
+ /// Thrown when
+ /// or is null or empty.
+ 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;
+ }
+
+ ///
+ /// Gets the GUID of this project.
+ ///
+ public Guid Guid { get; }
+
+ ///
+ /// Gets the platform name of this project. Only single platform per project is supported.
+ ///
+ public string PlatformName { get; }
+ }
+
+ ///
+ /// A helper class that can write a Visual Studio Solution file for the provided projects.
+ ///
+ public static class SolutionCreator
+ {
+ private static readonly XNamespace ProjectFileNamespace = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
+
+ ///
+ /// Writes a solution file to the specified .
+ ///
+ /// The full path of the file to write.
+ /// The projects contained in this solution.
+ ///
+ /// Thrown when is null or empty.
+ /// Thrown when is null.
+ /// Thrown when contains no items.
+ public static void WriteSolutionFile(string targetFile, IEnumerable 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 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 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 WriteSolutionConfigurations(TextWriter writer, IEnumerable 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 projects,
+ IEnumerable 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 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 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;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
index d467ba883..6ec5d6802 100644
--- a/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
@@ -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
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
}
#region WriteProjectFile
- void WriteProjectFile(TextWriter writer, IEnumerable> files, Metadata.PEFile module)
+ ProjectId WriteProjectFile(TextWriter writer, IEnumerable> 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
w.WriteEndDocument();
}
+
+ return new ProjectId(platformName, guid);
}
protected virtual bool IsGacAssembly(Metadata.IAssemblyReference r, Metadata.PEFile asm)
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 8ab2fbd69..6efca3120 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -61,6 +61,7 @@
+
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index 2441e0eb2..57cab0ee8 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -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
}
WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem);
}
+
+ return true;
}
}
diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs
index e2ab9d1f3..da26caeb2 100644
--- a/ILSpy/Languages/ILLanguage.cs
+++ b/ILSpy/Languages/ILLanguage.cs
@@ -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
dis.WriteModuleContents(module);
}
}
+
+ return true;
}
}
}
diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs
index a1aad8d64..76f435244 100644
--- a/ILSpy/Languages/Language.cs
+++ b/ILSpy/Languages/Language.cs
@@ -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
} else {
WriteCommentLine(output, metadata.GetString(metadata.GetModuleDefinition().Name));
}
+
+ return true;
}
public virtual void WriteCommentLine(ITextOutput output, string comment)
diff --git a/ILSpy/SolutionWriter.cs b/ILSpy/SolutionWriter.cs
index a4ebf5779..45fd3ce67 100644
--- a/ILSpy/SolutionWriter.cs
+++ b/ILSpy/SolutionWriter.cs
@@ -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
{
var solutionDirectory = Path.GetDirectoryName(solutionFilePath);
var statusOutput = new ConcurrentBag();
+ var projects = new ConcurrentBag();
+
var result = new AvalonEditTextOutput();
var duplicates = new HashSet();
@@ -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
return result;
}
- private static void WriteProject(AssemblyTreeNode assemblyNode, string targetDirectory, ConcurrentBag statusOutput, CancellationToken ct)
+ private static void WriteProject(
+ AssemblyTreeNode assemblyNode,
+ string targetDirectory,
+ ConcurrentBag statusOutput,
+ ConcurrentBag targetContainer,
+ CancellationToken ct)
{
var loadedAssembly = assemblyNode.LoadedAssembly;
@@ -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;
}
}
}
diff --git a/ILSpy/TreeNodes/AssemblyListTreeNode.cs b/ILSpy/TreeNodes/AssemblyListTreeNode.cs
index e53a3a883..3b8e5a519 100644
--- a/ILSpy/TreeNodes/AssemblyListTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyListTreeNode.cs
@@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public Action 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
output.WriteLine();
asm.Decompile(language, output, options);
}
+
+ return true;
}
#region Find*Node
diff --git a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
index 8aa8f8c0d..192820246 100644
--- a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
@@ -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
output.Unindent();
output.WriteLine();
}
+
+ return true;
}
}
}
diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs
index 60f34e6b2..39669c15f 100644
--- a/ILSpy/TreeNodes/AssemblyTreeNode.cs
+++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs
@@ -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
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)
diff --git a/ILSpy/TreeNodes/BaseTypesEntryNode.cs b/ILSpy/TreeNodes/BaseTypesEntryNode.cs
index 3c96c40dd..41edd0f8c 100644
--- a/ILSpy/TreeNodes/BaseTypesEntryNode.cs
+++ b/ILSpy/TreeNodes/BaseTypesEntryNode.cs
@@ -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 {
diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs
index 8cbdb2304..58565a938 100644
--- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs
+++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs
@@ -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;
}
}
}
\ No newline at end of file
diff --git a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs
index 91da3e033..f3d9fe29f 100644
--- a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs
+++ b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs
@@ -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;
diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs
index 3b6e50a30..8518e08e3 100644
--- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs
+++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs
@@ -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;
}
}
}
\ No newline at end of file
diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs
index 1aadff896..c1797f794 100644
--- a/ILSpy/TreeNodes/EventTreeNode.cs
+++ b/ILSpy/TreeNodes/EventTreeNode.cs
@@ -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 {
diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs
index 5d4d2f7b0..5d3323beb 100644
--- a/ILSpy/TreeNodes/FieldTreeNode.cs
+++ b/ILSpy/TreeNodes/FieldTreeNode.cs
@@ -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 {
diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs
index 11fe3b278..515188374 100644
--- a/ILSpy/TreeNodes/ILSpyTreeNode.cs
+++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs
@@ -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);
///
/// Used to implement special view logic for some items.
diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs
index 9e4d95e45..89c12ec10 100644
--- a/ILSpy/TreeNodes/MethodTreeNode.cs
+++ b/ILSpy/TreeNodes/MethodTreeNode.cs
@@ -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)
diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
index 4d51f46af..a363c46db 100644
--- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
+++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
@@ -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;
}
}
}
diff --git a/ILSpy/TreeNodes/NamespaceTreeNode.cs b/ILSpy/TreeNodes/NamespaceTreeNode.cs
index d054603dc..3b9ff4845 100644
--- a/ILSpy/TreeNodes/NamespaceTreeNode.cs
+++ b/ILSpy/TreeNodes/NamespaceTreeNode.cs
@@ -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().Select(t => t.TypeDefinition), output, options);
+ return true;
}
}
}
diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs
index 14769ea66..3267a1e1a 100644
--- a/ILSpy/TreeNodes/PropertyTreeNode.cs
+++ b/ILSpy/TreeNodes/PropertyTreeNode.cs
@@ -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 {
diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
index 331f8da08..9121e213f 100644
--- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
+++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs
@@ -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
output.Unindent();
output.WriteLine();
}
-
+ return true;
}
}
}
diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs
index c67c9d4b1..79cc1df50 100644
--- a/ILSpy/TreeNodes/ResourceListTreeNode.cs
+++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs
@@ -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;
}
}
}
diff --git a/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
index fb8b2199f..3805db739 100644
--- a/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
+++ b/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
@@ -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;
}
}
}
diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
index ec74ad193..cf5a3d5ac 100644
--- a/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
+++ b/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
@@ -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)
diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
index 3433f70d7..c9adaa49c 100644
--- a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
+++ b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
@@ -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
smartOutput.AddButton(Images.Save, Resources.Save, delegate { Save(MainWindow.Instance.TextView); });
output.WriteLine();
}
+
+ return true;
}
public override bool View(DecompilerTextView textView)
diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
index c1d908481..a44edeae4 100644
--- a/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
+++ b/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
@@ -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
}
output.WriteLine();
}
+
+ return true;
}
internal class SerializedObjectRepresentation
diff --git a/ILSpy/TreeNodes/ThreadingSupport.cs b/ILSpy/TreeNodes/ThreadingSupport.cs
index e95787efc..8df078cad 100644
--- a/ILSpy/TreeNodes/ThreadingSupport.cs
+++ b/ILSpy/TreeNodes/ThreadingSupport.cs
@@ -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
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;
}
}
diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs
index 3ef91c411..4464a3521 100644
--- a/ILSpy/TreeNodes/TypeTreeNode.cs
+++ b/ILSpy/TreeNodes/TypeTreeNode.cs
@@ -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);