From 867d330f1cbfbc1f09eef63792deae14e301e03b Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 26 Aug 2017 15:59:20 +0200 Subject: [PATCH] Fix cancellation. --- .../CSharp/CSharpDecompiler.cs | 2 +- .../CSharp/ExpressionBuilder.cs | 8 +++++-- .../CSharp/StatementBuilder.cs | 8 +++++-- .../ReplaceMethodCallsWithOperators.cs | 8 +++++-- .../CSharp/WholeProjectDecompiler.cs | 22 ++++++++++++------- ILSpy/Languages/CSharpLanguage.cs | 4 +++- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 101b9d89c..814ff656c 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -633,7 +633,7 @@ namespace ICSharpCode.Decompiler.CSharp } AddDefinesForConditionalAttributes(function); - var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, method, function); + var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, method, function, CancellationToken); var body = statementBuilder.ConvertAsBlock(function.Body); entityDecl.AddChild(body, Roles.Body); diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index e1be931c7..5f2ed7bf4 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; using ExpressionType = System.Linq.Expressions.ExpressionType; using PrimitiveType = ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveType; +using System.Threading; namespace ICSharpCode.Decompiler.CSharp { @@ -65,12 +66,14 @@ namespace ICSharpCode.Decompiler.CSharp internal readonly ICompilation compilation; internal readonly CSharpResolver resolver; readonly TypeSystemAstBuilder astBuilder; + readonly CancellationToken cancellationToken; - public ExpressionBuilder(IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext) + public ExpressionBuilder(IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, CancellationToken cancellationToken) { Debug.Assert(decompilationContext != null); this.typeSystem = typeSystem; this.decompilationContext = decompilationContext; + this.cancellationToken = cancellationToken; this.compilation = decompilationContext.Compilation; this.resolver = new CSharpResolver(new CSharpTypeResolveContext(compilation.MainAssembly, null, decompilationContext.CurrentTypeDefinition, decompilationContext.CurrentMember)); this.astBuilder = new TypeSystemAstBuilder(resolver); @@ -111,6 +114,7 @@ namespace ICSharpCode.Decompiler.CSharp public TranslatedExpression Translate(ILInstruction inst, IType typeHint = null) { Debug.Assert(inst != null); + cancellationToken.ThrowIfCancellationRequested(); TranslationContext context = new TranslationContext { TypeHint = typeHint ?? SpecialType.UnknownType }; @@ -943,7 +947,7 @@ namespace ICSharpCode.Decompiler.CSharp AnonymousMethodExpression ame = new AnonymousMethodExpression(); ame.Parameters.AddRange(MakeParameters(method, function)); ame.HasParameterList = true; - StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(method)), this.decompilationContext, method, function); + StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(method)), this.decompilationContext, method, function, cancellationToken); var body = builder.ConvertAsBlock(function.Body); bool isLambda = false; bool isMultiLineLambda = false; diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 732604fa8..36be476c5 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -26,6 +26,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.IL.Patterns; using System; +using System.Threading; namespace ICSharpCode.Decompiler.CSharp { @@ -34,17 +35,20 @@ namespace ICSharpCode.Decompiler.CSharp internal readonly ExpressionBuilder exprBuilder; readonly ILFunction currentFunction; readonly IMethod currentMethod; + readonly CancellationToken cancellationToken; - public StatementBuilder(IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, IMethod currentMethod, ILFunction currentFunction) + public StatementBuilder(IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, IMethod currentMethod, ILFunction currentFunction, CancellationToken cancellationToken) { Debug.Assert(typeSystem != null && decompilationContext != null && currentMethod != null); - this.exprBuilder = new ExpressionBuilder(typeSystem, decompilationContext); + this.exprBuilder = new ExpressionBuilder(typeSystem, decompilationContext, cancellationToken); this.currentFunction = currentFunction; this.currentMethod = currentMethod; + this.cancellationToken = cancellationToken; } public Statement Convert(ILInstruction inst) { + cancellationToken.ThrowIfCancellationRequested(); return inst.AcceptVisitor(this); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs index 13febce36..e36bc998d 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs @@ -340,8 +340,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void IAstTransform.Run(AstNode node, TransformContext context) { - this.context = context; - node.AcceptVisitor(this); + try { + this.context = context; + node.AcceptVisitor(this); + } finally { + this.context = null; + } } } } diff --git a/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs index eff4a9e9c..7f8589ce9 100644 --- a/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs @@ -30,6 +30,7 @@ using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using Mono.Cecil; +using System.Threading; namespace ICSharpCode.Decompiler.CSharp { @@ -73,22 +74,22 @@ namespace ICSharpCode.Decompiler.CSharp /// protected string targetDirectory; - public void DecompileProject(ModuleDefinition moduleDefinition, string targetDirectory) + public void DecompileProject(ModuleDefinition moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) { string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(moduleDefinition.Assembly.Name.Name) + ".csproj"); using (var writer = new StreamWriter(projectFileName)) { - DecompileProject(moduleDefinition, targetDirectory, writer); + DecompileProject(moduleDefinition, targetDirectory, writer, cancellationToken); } } - public void DecompileProject(ModuleDefinition moduleDefinition, string targetDirectory, TextWriter projectFileWriter) + public void DecompileProject(ModuleDefinition moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) { if (string.IsNullOrEmpty(targetDirectory)) { throw new InvalidOperationException("Must set TargetDirectory"); } this.targetDirectory = targetDirectory; directories.Clear(); - var files = WriteCodeFilesInProject(moduleDefinition).ToList(); + var files = WriteCodeFilesInProject(moduleDefinition, cancellationToken).ToList(); files.AddRange(WriteResourceFilesInProject(moduleDefinition)); WriteProjectFile(projectFileWriter, files, moduleDefinition); } @@ -248,9 +249,10 @@ namespace ICSharpCode.Decompiler.CSharp return decompiler; } - IEnumerable> WriteAssemblyInfo(DecompilerTypeSystem ts) + IEnumerable> WriteAssemblyInfo(DecompilerTypeSystem ts, CancellationToken cancellationToken) { var decompiler = CreateDecompiler(ts); + decompiler.CancellationToken = cancellationToken; decompiler.AstTransforms.Add(new RemoveCompilerGeneratedAssemblyAttributes()); SyntaxTree syntaxTree = decompiler.DecompileModuleAndAssemblyAttributes(); @@ -264,7 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp return new Tuple[] { Tuple.Create("Compile", assemblyInfo) }; } - IEnumerable> WriteCodeFilesInProject(ModuleDefinition module) + IEnumerable> WriteCodeFilesInProject(ModuleDefinition module, CancellationToken cancellationToken) { var files = module.Types.Where(IncludeTypeWhenDecompilingProject).GroupBy( delegate(TypeDefinition type) { @@ -281,15 +283,19 @@ namespace ICSharpCode.Decompiler.CSharp DecompilerTypeSystem ts = new DecompilerTypeSystem(module); Parallel.ForEach( files, - new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism }, + new ParallelOptions { + MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, + CancellationToken = cancellationToken + }, delegate(IGrouping file) { using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) { CSharpDecompiler decompiler = CreateDecompiler(ts); + decompiler.CancellationToken = cancellationToken; var syntaxTree = decompiler.DecompileTypes(file.ToArray()); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions)); } }); - return files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts)); + return files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken)); } #endregion diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index c2544cb16..da5a0a1df 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -87,6 +87,7 @@ namespace ICSharpCode.ILSpy CSharpDecompiler CreateDecompiler(ModuleDefinition module, DecompilationOptions options) { CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings); + decompiler.CancellationToken = options.CancellationToken; while (decompiler.AstTransforms.Count > transformCount) decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1); return decompiler; @@ -283,7 +284,7 @@ namespace ICSharpCode.ILSpy if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { var decompiler = new ILSpyWholeProjectDecompiler(assembly, options); decompiler.ProjectGuid = App.CommandLineArguments.FixedGuid; - decompiler.DecompileProject(assembly.ModuleDefinition, options.SaveAsProjectDirectory, new TextOutputWriter(output)); + decompiler.DecompileProject(assembly.ModuleDefinition, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken); } else { base.DecompileAssembly(assembly, output, options); output.WriteLine(); @@ -311,6 +312,7 @@ namespace ICSharpCode.ILSpy // don't automatically load additional assemblies when an assembly node is selected in the tree view using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) { CSharpDecompiler decompiler = new CSharpDecompiler(assembly.ModuleDefinition, options.DecompilerSettings); + decompiler.CancellationToken = options.CancellationToken; if (options.FullDecompilation) { SyntaxTree st = decompiler.DecompileWholeModuleAsSingleFile(); output.WriteLine(st.ToString());