mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Generalize progress reporting for decompilation and PDB generation.
This commit is contained in:
@@ -33,8 +33,8 @@ namespace ICSharpCode.Decompiler.PowerShell
|
||||
lock (syncObject)
|
||||
{
|
||||
completed++;
|
||||
progress = new ProgressRecord(1, "Decompiling " + fileName, $"Completed {completed} of {value.TotalNumberOfFiles}: {value.Status}") {
|
||||
PercentComplete = (int)(completed * 100.0 / value.TotalNumberOfFiles)
|
||||
progress = new ProgressRecord(1, "Decompiling " + fileName, $"Completed {completed} of {value.TotalUnits}: {value.Status}") {
|
||||
PercentComplete = (int)(completed * 100.0 / value.TotalUnits)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,17 +81,17 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
var lastFilesWritten = 0;
|
||||
var totalFiles = -1;
|
||||
|
||||
Action<WritePortablePdbProgress> reportFunc = progress => {
|
||||
Action<DecompilationProgress> reportFunc = progress => {
|
||||
if (totalFiles == -1)
|
||||
{
|
||||
// Initialize value on first call
|
||||
totalFiles = progress.TotalFiles;
|
||||
totalFiles = progress.TotalUnits;
|
||||
}
|
||||
|
||||
Assert.AreEqual(progress.TotalFiles, totalFiles);
|
||||
Assert.AreEqual(progress.FilesWritten, lastFilesWritten + 1);
|
||||
Assert.AreEqual(progress.TotalUnits, totalFiles);
|
||||
Assert.AreEqual(progress.UnitsCompleted, lastFilesWritten + 1);
|
||||
|
||||
lastFilesWritten = progress.FilesWritten;
|
||||
lastFilesWritten = progress.UnitsCompleted;
|
||||
};
|
||||
|
||||
using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, nameof(ProgressReporting) + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||
@@ -107,16 +107,16 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
Assert.AreEqual(totalFiles, lastFilesWritten);
|
||||
}
|
||||
|
||||
private class TestProgressReporter : IProgress<WritePortablePdbProgress>
|
||||
private class TestProgressReporter : IProgress<DecompilationProgress>
|
||||
{
|
||||
private Action<WritePortablePdbProgress> reportFunc;
|
||||
private Action<DecompilationProgress> reportFunc;
|
||||
|
||||
public TestProgressReporter(Action<WritePortablePdbProgress> reportFunc)
|
||||
public TestProgressReporter(Action<DecompilationProgress> reportFunc)
|
||||
{
|
||||
this.reportFunc = reportFunc;
|
||||
}
|
||||
|
||||
public void Report(WritePortablePdbProgress value)
|
||||
public void Report(DecompilationProgress value)
|
||||
{
|
||||
reportFunc(value);
|
||||
}
|
||||
|
||||
@@ -223,8 +223,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
|
||||
return Path.Combine(dir, file);
|
||||
}
|
||||
}, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
int total = files.Count;
|
||||
var progress = ProgressIndicator;
|
||||
var progressReporter = ProgressIndicator;
|
||||
var progress = new DecompilationProgress { TotalUnits = files.Count, Title = "Exporting project..." };
|
||||
DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings);
|
||||
Parallel.ForEach(
|
||||
Partitioner.Create(files, loadBalance: true),
|
||||
@@ -253,7 +253,9 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
|
||||
throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException);
|
||||
}
|
||||
}
|
||||
progress?.Report(new DecompilationProgress(total, file.Key));
|
||||
progress.Status = file.Key;
|
||||
Interlocked.Increment(ref progress.UnitsCompleted);
|
||||
progressReporter?.Report(progress);
|
||||
});
|
||||
return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
|
||||
}
|
||||
@@ -705,16 +707,4 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
|
||||
return TargetServices.DetectTargetFramework(module).Moniker != null;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct DecompilationProgress
|
||||
{
|
||||
public readonly int TotalNumberOfFiles;
|
||||
public readonly string Status;
|
||||
|
||||
public DecompilationProgress(int total, string status = null)
|
||||
{
|
||||
this.TotalNumberOfFiles = total;
|
||||
this.Status = status ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,6 @@ using ICSharpCode.Decompiler.Util;
|
||||
|
||||
namespace ICSharpCode.Decompiler.DebugInfo
|
||||
{
|
||||
public struct WritePortablePdbProgress
|
||||
{
|
||||
public int TotalFiles { get; internal set; }
|
||||
public int FilesWritten { get; internal set; }
|
||||
}
|
||||
|
||||
public class PortablePdbWriter
|
||||
{
|
||||
static readonly FileVersionInfo decompilerVersion = FileVersionInfo.GetVersionInfo(typeof(CSharpDecompiler).Assembly.Location);
|
||||
@@ -63,7 +57,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
|
||||
Stream targetStream,
|
||||
bool noLogo = false,
|
||||
BlobContentId? pdbId = null,
|
||||
IProgress<WritePortablePdbProgress> progress = null)
|
||||
IProgress<DecompilationProgress> progress = null)
|
||||
{
|
||||
MetadataBuilder metadata = new MetadataBuilder();
|
||||
MetadataReader reader = file.Metadata;
|
||||
@@ -87,9 +81,10 @@ namespace ICSharpCode.Decompiler.DebugInfo
|
||||
}
|
||||
|
||||
var sourceFiles = reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName).ToList();
|
||||
WritePortablePdbProgress currentProgress = new WritePortablePdbProgress() {
|
||||
TotalFiles = sourceFiles.Count,
|
||||
FilesWritten = 0
|
||||
DecompilationProgress currentProgress = new() {
|
||||
TotalUnits = sourceFiles.Count,
|
||||
UnitsCompleted = 0,
|
||||
Title = "Generating portable PDB..."
|
||||
};
|
||||
|
||||
foreach (var sourceFile in sourceFiles)
|
||||
@@ -99,7 +94,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
|
||||
|
||||
if (progress != null)
|
||||
{
|
||||
currentProgress.FilesWritten++;
|
||||
currentProgress.UnitsCompleted++;
|
||||
progress.Report(currentProgress);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace ICSharpCode.Decompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Information used for (optional) progress reporting by the decompiler.
|
||||
/// </summary>
|
||||
public struct DecompilationProgress
|
||||
{
|
||||
/// <summary>
|
||||
/// The total number of units to process. If set to a value <= 0, an indeterminate progress bar is displayed.
|
||||
/// </summary>
|
||||
public int TotalUnits;
|
||||
|
||||
/// <summary>
|
||||
/// The number of units currently completed. Should be a positive number.
|
||||
/// </summary>
|
||||
public int UnitsCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// Optional information displayed alongside the progress bar.
|
||||
/// </summary>
|
||||
public string? Status;
|
||||
|
||||
/// <summary>
|
||||
/// Optional custom title for the operation.
|
||||
/// </summary>
|
||||
public string? Title;
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,7 @@
|
||||
<Compile Include="CSharp\Annotations.cs" />
|
||||
<Compile Include="CSharp\CallBuilder.cs" />
|
||||
<Compile Include="CSharp\CSharpLanguageVersion.cs" />
|
||||
<Compile Include="DecompilationProgress.cs" />
|
||||
<Compile Include="NRTAttributes.cs" />
|
||||
<Compile Include="PartialTypeInfo.cs" />
|
||||
<Compile Include="CSharp\ProjectDecompiler\IProjectFileWriter.cs" />
|
||||
|
||||
@@ -75,12 +75,14 @@ namespace ICSharpCode.ILSpy
|
||||
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
|
||||
AvalonEditTextOutput output = new AvalonEditTextOutput();
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
options.CancellationToken = ct;
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
|
||||
{
|
||||
try
|
||||
{
|
||||
var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(), options.DecompilerSettings);
|
||||
PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream);
|
||||
decompiler.CancellationToken = ct;
|
||||
PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream, progress: options.Progress);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using ICSharpCode.Decompiler;
|
||||
using ICSharpCode.ILSpy.Options;
|
||||
using ICSharpCode.ILSpyX;
|
||||
|
||||
@@ -55,6 +56,14 @@ namespace ICSharpCode.ILSpy
|
||||
/// </remarks>
|
||||
public CancellationToken CancellationToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress reporter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If decompilers do not implement progress reporting, an indeterminate wait bar is displayed.
|
||||
/// </remarks>
|
||||
public IProgress<DecompilationProgress> Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the settings for the decompiler.
|
||||
/// </summary>
|
||||
|
||||
@@ -404,6 +404,7 @@ namespace ICSharpCode.ILSpy
|
||||
options.DecompilerSettings.UseSdkStyleProjectFormat = false;
|
||||
}
|
||||
var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
|
||||
decompiler.ProgressIndicator = options.Progress;
|
||||
return decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -105,7 +105,11 @@ namespace ICSharpCode.ILSpy
|
||||
|
||||
public DisplaySettings CurrentDisplaySettings { get; internal set; }
|
||||
|
||||
public DecompilationOptions CreateDecompilationOptions() => new DecompilationOptions(CurrentLanguageVersion, CurrentDecompilerSettings, CurrentDisplaySettings);
|
||||
public DecompilationOptions CreateDecompilationOptions()
|
||||
{
|
||||
var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress<DecompilationProgress>;
|
||||
return new DecompilationOptions(CurrentLanguageVersion, CurrentDecompilerSettings, CurrentDisplaySettings) { Progress = decompilerView };
|
||||
}
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user