diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 5116658a5..db60e45f2 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -337,6 +337,8 @@ namespace Decompiler Modifiers ConvertModifiers(MethodDefinition methodDef) { + if (methodDef == null) + return Modifiers.None; Modifiers modifiers = Modifiers.None; if (methodDef.IsPrivate) modifiers |= Modifiers.Private; @@ -431,7 +433,7 @@ namespace Decompiler PropertyDeclaration CreateProperty(PropertyDefinition propDef) { PropertyDeclaration astProp = new PropertyDeclaration(); - astProp.Modifiers = ConvertModifiers(propDef.GetMethod); + astProp.Modifiers = ConvertModifiers(propDef.GetMethod ?? propDef.SetMethod); astProp.Name = propDef.Name; astProp.ReturnType = ConvertType(propDef.PropertyType, propDef); if (propDef.GetMethod != null) { diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 1f131d3b5..b80aa09ac 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -21,7 +21,17 @@ namespace Decompiler { AstMethodBodyBuilder builder = new AstMethodBodyBuilder(); builder.methodDef = methodDef; - return builder.CreateMethodBody(); + if (Debugger.IsAttached) { + return builder.CreateMethodBody(); + } else { + try { + return builder.CreateMethodBody(); + } catch (OperationCanceledException) { + throw; + } catch (Exception ex) { + throw new ICSharpCode.Decompiler.DecompilerException(methodDef, ex); + } + } } static readonly Dictionary typeNameToVariableNameDict = new Dictionary { diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs new file mode 100644 index 000000000..bb5379a6b --- /dev/null +++ b/ICSharpCode.Decompiler/DecompilerException.cs @@ -0,0 +1,27 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Runtime.Serialization; +using Mono.Cecil; + +namespace ICSharpCode.Decompiler +{ + /// + /// Desctiption of DecompilerException. + /// + public class DecompilerException : Exception, ISerializable + { + public MethodDefinition DecompiledMethod { get; set; } + + public DecompilerException(MethodDefinition decompiledMethod, Exception innerException) + : base("Error decompiling " + decompiledMethod.FullName, innerException) + { + } + + // This constructor is needed for serialization. + protected DecompilerException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 9beef196d..fdda5b4ab 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -64,6 +64,7 @@ + diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 3368f1594..e8800f8b0 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -101,6 +101,20 @@ namespace ICSharpCode.ILSpy codeDomBuilder.GenerateCode(output, transformAbortCondition); } + public override void DecompileAssembly(AssemblyDefinition assembly, string fileName, ITextOutput output, DecompilationOptions options) + { + if (options.FullDecompilation) { + foreach (TypeDefinition type in assembly.MainModule.Types) { + AstBuilder codeDomBuilder = new AstBuilder(); + codeDomBuilder.AddType(type); + codeDomBuilder.GenerateCode(output, transformAbortCondition); + output.WriteLine(); + } + } else { + base.DecompileAssembly(assembly, fileName, output, options); + } + } + public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes) { AstType astType = AstBuilder.ConvertType(type, typeAttributes); diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 9abe7a2a0..7a79cc166 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy } decompilerTextView.SaveToDisk(sessionSettings.FilterSettings.Language, treeView.GetTopLevelSelection().OfType(), - new DecompilationOptions()); + new DecompilationOptions() { FullDecompilation = true }); } #endregion diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index a652c618c..034fa8da3 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -225,7 +225,7 @@ namespace ICSharpCode.ILSpy.TextView RunWithCancellation( delegate (CancellationToken ct) { // creation of the background task context.Options.CancellationToken = ct; - return RunDecompiler(context, outputLengthLimit); + return DecompileAsync(context, outputLengthLimit); }, delegate (Task task) { // handling the result try { @@ -250,7 +250,7 @@ namespace ICSharpCode.ILSpy.TextView }); } - static Task RunDecompiler(DecompilationContext context, int outputLengthLimit) + static Task DecompileAsync(DecompilationContext context, int outputLengthLimit) { Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length); @@ -274,10 +274,11 @@ namespace ICSharpCode.ILSpy.TextView } catch (AggregateException ex) { tcs.SetException(ex); } catch (OperationCanceledException ex) { + tcs.SetException(ex); #else } catch (Exception ex) { - #endif tcs.SetException(ex); + #endif } })); thread.Start(); @@ -392,29 +393,7 @@ namespace ICSharpCode.ILSpy.TextView RunWithCancellation( delegate (CancellationToken ct) { context.Options.CancellationToken = ct; - return Task.Factory.StartNew( - delegate { - using (StreamWriter w = new StreamWriter(fileName)) { - try { - DecompileNodes(context, new PlainTextOutput(w)); - } catch (OperationCanceledException) { - w.WriteLine(); - w.WriteLine("Decompiled was cancelled."); - throw; - } - } - AvalonEditTextOutput output = new AvalonEditTextOutput(); - output.WriteLine("Decompilation complete."); - output.WriteLine(); - output.AddButton( - null, "Open Explorer", - delegate { - Process.Start("explorer", "/select,\"" + fileName + "\""); - } - ); - output.WriteLine(); - return output; - }, TaskCreationOptions.LongRunning); + return SaveToDiskAsync(context, fileName); }, delegate (Task task) { try { @@ -433,6 +412,42 @@ namespace ICSharpCode.ILSpy.TextView } }); } + + Task SaveToDiskAsync(DecompilationContext context, string fileName) + { + TaskCompletionSource tcs = new TaskCompletionSource(); + Thread thread = new Thread(new ThreadStart( + delegate { + try { + using (StreamWriter w = new StreamWriter(fileName)) { + try { + DecompileNodes(context, new PlainTextOutput(w)); + } catch (OperationCanceledException) { + w.WriteLine(); + w.WriteLine("Decompiled was cancelled."); + throw; + } + } + AvalonEditTextOutput output = new AvalonEditTextOutput(); + output.WriteLine("Decompilation complete."); + output.WriteLine(); + output.AddButton(null, "Open Explorer", delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); }); + output.WriteLine(); + tcs.SetResult(output); + #if DEBUG + } catch (OperationCanceledException ex) { + tcs.SetException(ex); + } catch (AggregateException ex) { + tcs.SetException(ex); + #else + } catch (Exception ex) { + tcs.SetException(ex); + #endif + } + })); + thread.Start(); + return tcs.Task; + } /// /// Cleans up a node name for use as a file name.