Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move active code from LanguageSettings to LanguageService #3302

Merged
merged 3 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading