Skip to content

Commit

Permalink
Move active code from LanguageSettings to LanguageService, to make La…
Browse files Browse the repository at this point in the history
…nguageSettings independent of other services injected via DI
  • Loading branch information
tom-englert committed Oct 10, 2024
1 parent 69edba6 commit 1806608
Show file tree
Hide file tree
Showing 29 changed files with 234 additions and 174 deletions.
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 @@ -66,7 +66,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 @@ -92,7 +92,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)

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Debug)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Debug)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Debug)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Debug)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Release)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Release)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Release)

Import attributes are not supported by all DI containers, consider to replace it with code.

Check warning on line 65 in ILSpy/Languages/CSharpLanguage.cs

View workflow job for this annotation

GitHub Actions / Build (Release)

Import attributes are not supported by all DI containers, consider to replace it with code.
{
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 1806608

Please sign in to comment.