diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs index 071f29599..2950a3200 100644 --- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs +++ b/ILSpy/Commands/SaveCodeContextMenuEntry.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.ILSpy.TextView { var assemblies = selectedNodes.OfType() .Select(n => n.LoadedAssembly) - .Where(a => a.IsLoadedAsValidAssembly).ToArray(); + .Where(a => a.IsLoadedAsValidAssembly).ToList(); SolutionWriter.CreateSolution(tabPage, textView, selectedPath, currentLanguage, assemblies); } return; diff --git a/ILSpy/SolutionWriter.cs b/ILSpy/SolutionWriter.cs index 06d71e701..62f6ef6c2 100644 --- a/ILSpy/SolutionWriter.cs +++ b/ILSpy/SolutionWriter.cs @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy /// Thrown when > or /// is null. public static void CreateSolution(TabPageModel tabPage, DecompilerTextView textView, string solutionFilePath, - Language language, IEnumerable assemblies) + Language language, List assemblies) { if (textView == null) { @@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy textView .RunWithCancellation(ct => writer.CreateSolution(tabPage, assemblies, language, ct)) - .Then(output => textView.ShowText(output)) + .Then(textView.ShowText) .HandleExceptions(); } @@ -94,41 +94,29 @@ namespace ICSharpCode.ILSpy projects = new ConcurrentBag(); } - async Task CreateSolution(TabPageModel tabPage, IEnumerable assemblies, Language language, CancellationToken ct) + async Task CreateSolution(TabPageModel tabPage, List allAssemblies, Language language, CancellationToken ct) { var result = new AvalonEditTextOutput(); - var assembliesByShortName = assemblies.ToLookup(_ => _.ShortName); + var assembliesByShortName = allAssemblies.GroupBy(_ => _.ShortName).ToDictionary(_ => _.Key, _ => _.ToList()); bool first = true; bool abort = false; - foreach (var item in assembliesByShortName) + foreach (var (shortName, assemblies) in assembliesByShortName) { - var enumerator = item.GetEnumerator(); - if (!enumerator.MoveNext()) - continue; - var firstAssembly = enumerator.Current; - if (!enumerator.MoveNext()) + if (assemblies.Count == 1) + { continue; + } + if (first) { result.WriteLine("Duplicate assembly names selected, cannot generate a solution:"); abort = true; + first = false; } - result.Write("- " + firstAssembly.Text + " conflicts with "); - - first = true; - do - { - var asm = enumerator.Current; - if (!first) - result.Write(", "); - result.Write(asm.Text); - first = false; - } while (enumerator.MoveNext()); - result.WriteLine(); - first = false; + result.WriteLine("- " + assemblies[0].Text + " conflicts with " + string.Join(", ", assemblies.Skip(1))); } if (abort) @@ -141,7 +129,7 @@ namespace ICSharpCode.ILSpy // Explicitly create an enumerable partitioner here to avoid Parallel.ForEach's special cases for lists, // as those seem to use static partitioning which is inefficient if assemblies take differently // long to decompile. - await Task.Run(() => Parallel.ForEach(Partitioner.Create(assemblies), + await Task.Run(() => Parallel.ForEach(Partitioner.Create(allAssemblies), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, item => WriteProject(tabPage, item, language, solutionDirectory, ct))) .ConfigureAwait(false); @@ -153,7 +141,7 @@ namespace ICSharpCode.ILSpy } else { - await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects.ToList())) + await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects.ToList()), ct) .ConfigureAwait(false); } } @@ -184,14 +172,14 @@ namespace ICSharpCode.ILSpy if (statusOutput.Count == 0) { result.WriteLine("Successfully decompiled the following assemblies into Visual Studio projects:"); - foreach (var item in assemblies.Select(n => n.Text.ToString())) + foreach (var n in allAssemblies) { - result.WriteLine(item); + result.WriteLine(n.Text.ToString()); } result.WriteLine(); - if (assemblies.Count() == projects.Count) + if (allAssemblies.Count == projects.Count) { result.WriteLine("Created the Visual Studio Solution file."); }