Skip to content

Commit

Permalink
Merge pull request #3302 from tom-englert/dev/WpfRefactoring
Browse files Browse the repository at this point in the history
Move active code from LanguageSettings to LanguageService
  • Loading branch information
siegfriedpammer authored Oct 20, 2024
2 parents 8c440f4 + 7643991 commit 21e5d0f
Show file tree
Hide file tree
Showing 30 changed files with 237 additions and 175 deletions.
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,5 @@ dotnet_naming_rule.private_fields_rule.symbols = private_fields_symbols

# MEF006: No importing constructor
dotnet_diagnostic.MEF006.severity = silent
# MEF002: Import attributes, to be removed after final DI migration
dotnet_diagnostic.MEF002.severity = silent
2 changes: 1 addition & 1 deletion ILSpy.ReadyToRun/ReadyToRunLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi

public override RichText GetRichTextTooltip(IEntity entity)
{
return Languages.ILLanguage.GetRichTextTooltip(entity);
return LanguageService.Instance.ILLanguage.GetRichTextTooltip(entity);
}

private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, MetadataFile file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void VerifyReturnsOnlyInterfaceMembers()
var analyzer = new MemberImplementsInterfaceAnalyzer();

// Act
var results = analyzer.Analyze(symbol, new AnalyzerContext() { AssemblyList = new ILSpyX.AssemblyList(), Language = new CSharpLanguage() });
var results = analyzer.Analyze(symbol, new AnalyzerContext() { AssemblyList = new ILSpyX.AssemblyList(), Language = new CSharpLanguage([]) });

// Assert
Assert.That(results, Is.Not.Null);
Expand Down
2 changes: 1 addition & 1 deletion ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void Setup()
testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location);
assemblyList.OpenAssembly(typeof(void).Assembly.Location);
testAssemblyTypeSystem = testAssembly.GetTypeSystemOrNull();
language = new CSharpLanguage();
language = new CSharpLanguage([]);
typeDefinition = testAssemblyTypeSystem.FindType(typeof(TestCases.Main.MainAssembly)).GetDefinition();
}

Expand Down
2 changes: 1 addition & 1 deletion ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void Setup()
assemblyList = new AssemblyList();
testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location);
testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetMetadataFileOrNull(), testAssembly.GetAssemblyResolver());
language = new CSharpLanguage();
language = new CSharpLanguage([]);
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion ILSpy/Analyzers/AnalyzerTreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.Analyzers
{
public abstract class AnalyzerTreeNode : SharpTreeNode
{
public Language Language => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
public Language Language => LanguageService.Instance.Language;

public override bool CanDelete()
{
Expand Down
10 changes: 5 additions & 5 deletions ILSpy/AssemblyTree/AssemblyTreeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e
{
switch (e.PropertyName)
{
case nameof(LanguageSettings.Language) or nameof(LanguageSettings.LanguageVersion):
case nameof(LanguageSettings.LanguageId) or nameof(LanguageSettings.LanguageVersionId):
RefreshDecompiledView();
break;
default:
Expand Down Expand Up @@ -152,7 +152,7 @@ private bool HandleCommandLineArguments(CommandLineArguments args)
{
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
SettingsService.Instance.SessionSettings.LanguageSettings.Language = Languages.GetLanguage(args.Language);
LanguageService.Instance.Language = LanguageService.Instance.GetLanguage(args.Language);
return true;
}

Expand Down Expand Up @@ -787,7 +787,7 @@ public void DecompileSelectedNodes(DecompilerTextViewState? newState = null)
return;
}

var options = SettingsService.Instance.CreateDecompilationOptions(activeTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(activeTabPage);
options.TextViewState = newState;
activeTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, options));
}
Expand All @@ -797,9 +797,9 @@ public void RefreshDecompiledView()
DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState);
}

public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
public Language CurrentLanguage => LanguageService.Instance.Language;

public LanguageVersion CurrentLanguageVersion => SettingsService.Instance.SessionSettings.LanguageSettings.LanguageVersion;
public LanguageVersion? CurrentLanguageVersion => LanguageService.Instance.LanguageVersion;

public IEnumerable<ILSpyTreeNode> SelectedNodes {
get {
Expand Down
19 changes: 13 additions & 6 deletions ILSpy/Commands/DecompileAllCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
Expand All @@ -31,14 +32,20 @@
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpyX;

using TomsToolbox.Essentials;

namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class DecompileAllCommand : SimpleCommand
{
private readonly IReadOnlyCollection<IResourceFileHandler> resourceFileHandlers;

[ImportingConstructor]
public DecompileAllCommand([ImportMany] IEnumerable<IResourceFileHandler> resourceFileHandlers)
{
this.resourceFileHandlers = resourceFileHandlers.ToArray();
}

public override bool CanExecute(object parameter)
{
return System.IO.Directory.Exists("c:\\temp\\decompiled");
Expand All @@ -60,10 +67,10 @@ public override void Execute(object parameter)
{
try
{
var options = SettingsService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
options.CancellationToken = ct;
options.FullDecompilation = true;
new CSharpLanguage().DecompileAssembly(asm, new PlainTextOutput(writer), options);
new CSharpLanguage(resourceFileHandlers).DecompileAssembly(asm, new PlainTextOutput(writer), options);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -95,10 +102,10 @@ sealed class Decompile100TimesCommand : SimpleCommand
public override void Execute(object parameter)
{
const int numRuns = 100;
var language = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
var language = LanguageService.Instance.Language;
var nodes = MainWindow.Instance.AssemblyTreeModel.SelectedNodes.ToArray();
DockWorkspace dockWorkspace = DockWorkspace.Instance;
var options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
dockWorkspace.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
options.CancellationToken = ct;
Stopwatch w = Stopwatch.StartNew();
Expand Down
2 changes: 1 addition & 1 deletion ILSpy/Commands/DisassembleAllCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public override void Execute(object parameter)
{
try
{
var options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
options.FullDecompilation = true;
options.CancellationToken = ct;
new ILLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), options);
Expand Down
2 changes: 1 addition & 1 deletion ILSpy/Commands/GeneratePdbContextMenuEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ internal static void GeneratePdbForAssembly(LoadedAssembly assembly)
if (dlg.ShowDialog() != true)
return;
DockWorkspace dockWorkspace = DockWorkspace.Instance;
DecompilationOptions options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
DecompilationOptions options = LanguageService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
string fileName = dlg.FileName;
dockWorkspace.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Expand Down
4 changes: 2 additions & 2 deletions ILSpy/Commands/SaveCodeContextMenuEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
var settingsService = SettingsService.Instance;
var dockWorkspace = Docking.DockWorkspace.Instance;

var currentLanguage = settingsService.SessionSettings.LanguageSettings.Language;
var currentLanguage = LanguageService.Instance.Language;
var tabPage = dockWorkspace.ActiveTabPage;
tabPage.ShowTextView(textView => {
if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection)
Expand All @@ -88,7 +88,7 @@ public static void Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
// Fallback: if nobody was able to handle the request, use default behavior.
// try to save all nodes to disk.
var options = settingsService.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
options.FullDecompilation = true;
textView.SaveToDisk(currentLanguage, selectedNodes.OfType<ILSpyTreeNode>(), options);
});
Expand Down
63 changes: 14 additions & 49 deletions ILSpy/LanguageSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
// DEALINGS IN THE SOFTWARE.

using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

using ICSharpCode.ILSpyX;

using TomsToolbox.Wpf;

#nullable enable

namespace ICSharpCode.ILSpy
{
/// <summary>
Expand All @@ -42,9 +43,8 @@ public LanguageSettings(XElement element, ISettingsSection parent)
{
Parent = parent;
this.ShowApiLevel = (ApiVisibility?)(int?)element.Element("ShowAPILevel") ?? ApiVisibility.PublicAndInternal;
this.Language = Languages.GetLanguage((string)element.Element("Language")) ?? Languages.AllLanguages.First();
this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion"))
?? Language.LanguageVersions.LastOrDefault();
this.LanguageId = (string?)element.Element("Language");
this.LanguageVersionId = (string?)element.Element("LanguageVersion");
}

public ISettingsSection Parent { get; }
Expand All @@ -54,8 +54,8 @@ public XElement SaveAsXml()
return new XElement(
"FilterSettings",
new XElement("ShowAPILevel", (int)this.ShowApiLevel),
new XElement("Language", this.Language.Name),
new XElement("LanguageVersion", this.LanguageVersion?.Version)
new XElement("Language", this.LanguageId),
new XElement("LanguageVersion", this.LanguageVersionId)
);
}

Expand Down Expand Up @@ -111,7 +111,7 @@ public bool ApiVisAll {
}
}

Language language;
string? languageId;

/// <summary>
/// Gets/Sets the current language.
Expand All @@ -120,37 +120,12 @@ public bool ApiVisAll {
/// While this isn't related to filtering, having it as part of the FilterSettings
/// makes it easy to pass it down into all tree nodes.
/// </remarks>
public Language Language {
get { return language; }
set {
if (language != value)
{
if (language != null && language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
language = value;
OnPropertyChanged();
if (language.HasLanguageVersions)
{
if (languageVersionHistory.TryGetValue(value, out var version))
{
LanguageVersion = version;
}
else
{
LanguageVersion = Language.LanguageVersions.Last();
}
}
else
{
LanguageVersion = default;
}
}
}
public string? LanguageId {
get => languageId;
set => SetProperty(ref languageId, value);
}

LanguageVersion languageVersion;
string? languageVersionId;

/// <summary>
/// Gets/Sets the current language version.
Expand All @@ -159,19 +134,9 @@ public Language Language {
/// While this isn't related to filtering, having it as part of the FilterSettings
/// makes it easy to pass it down into all tree nodes.
/// </remarks>
public LanguageVersion LanguageVersion {
get { return languageVersion; }
set {
if (languageVersion != value)
{
languageVersion = value;
if (language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
OnPropertyChanged();
}
}
public string? LanguageVersionId {
get { return languageVersionId; }
set => SetProperty(ref languageVersionId, value);
}

// This class has been initially called FilterSettings, but then has been Hijacked to store language settings as well.
Expand Down
26 changes: 18 additions & 8 deletions ILSpy/Languages/CSharpLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX;
Expand All @@ -56,26 +55,34 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
public class CSharpLanguage : Language
{
readonly IReadOnlyCollection<IResourceFileHandler> resourceFileHandlers;

string name = "C#";
bool showAllMembers = false;
int transformCount = int.MaxValue;

[ImportingConstructor]
public CSharpLanguage([ImportMany] IEnumerable<IResourceFileHandler> resourceFileHandlers)
{
this.resourceFileHandlers = resourceFileHandlers.ToArray();
}

#if DEBUG
internal static IEnumerable<CSharpLanguage> GetDebugLanguages()
internal static IEnumerable<CSharpLanguage> GetDebugLanguages(IReadOnlyCollection<IResourceFileHandler> resourceFileHandlers)
{
string lastTransformName = "no transforms";
int transformCount = 0;
foreach (var transform in CSharpDecompiler.GetAstTransforms())
{
yield return new CSharpLanguage {
yield return new CSharpLanguage(resourceFileHandlers) {
transformCount = transformCount,
name = "C# - " + lastTransformName,
showAllMembers = true
};
lastTransformName = "after " + transform.GetType().Name;
transformCount++;
}
yield return new CSharpLanguage {
yield return new CSharpLanguage(resourceFileHandlers) {
name = "C# - " + lastTransformName,
showAllMembers = true
};
Expand Down Expand Up @@ -430,8 +437,9 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput
{
options.DecompilerSettings.UseSdkStyleProjectFormat = false;
}
var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
decompiler.ProgressIndicator = options.Progress;
var decompiler = new ILSpyWholeProjectDecompiler(assembly, options, resourceFileHandlers) {
ProgressIndicator = options.Progress
};
return decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
}
else
Expand Down Expand Up @@ -542,18 +550,20 @@ class ILSpyWholeProjectDecompiler : WholeProjectDecompiler
{
readonly LoadedAssembly assembly;
readonly DecompilationOptions options;
private readonly IReadOnlyCollection<IResourceFileHandler> resourceFileHandlers;

public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options)
public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options, IReadOnlyCollection<IResourceFileHandler> resourceFileHandlers)
: base(options.DecompilerSettings, assembly.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences, options.DecompilerSettings.ApplyWindowsRuntimeProjections), null, assembly.GetAssemblyReferenceClassifier(options.DecompilerSettings.ApplyWindowsRuntimeProjections), assembly.GetDebugInfoOrNull())
{
this.assembly = assembly;
this.options = options;
this.resourceFileHandlers = resourceFileHandlers;
}

protected override IEnumerable<ProjectItemInfo> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
var context = new ResourceFileHandlerContext(options);
foreach (var handler in App.ExportProvider.GetExportedValues<IResourceFileHandler>())
foreach (var handler in resourceFileHandlers)
{
if (handler.CanHandle(fileName, context))
{
Expand Down
2 changes: 1 addition & 1 deletion ILSpy/Languages/ILLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public override RichText GetRichTextTooltip(IEntity entity)
var settingsService = SettingsService.Instance;
var dockWorkspace = DockWorkspace.Instance;

var disasm = CreateDisassembler(output, settingsService.CreateDecompilationOptions(dockWorkspace.ActiveTabPage));
var disasm = CreateDisassembler(output, LanguageService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage));
MetadataFile module = entity.ParentModule?.MetadataFile;
if (module == null)
{
Expand Down
Loading

0 comments on commit 21e5d0f

Please sign in to comment.