Browse Source

Move active code from LanguageSettings to LanguageService, to make LanguageSettings independent of other services injected via DI

pull/3302/head
tom-englert 7 months ago
parent
commit
47d52fcacf
  1. 2
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  2. 2
      ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs
  3. 2
      ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs
  4. 2
      ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs
  5. 2
      ILSpy/Analyzers/AnalyzerTreeNode.cs
  6. 10
      ILSpy/AssemblyTree/AssemblyTreeModel.cs
  7. 19
      ILSpy/Commands/DecompileAllCommand.cs
  8. 2
      ILSpy/Commands/DisassembleAllCommand.cs
  9. 2
      ILSpy/Commands/GeneratePdbContextMenuEntry.cs
  10. 4
      ILSpy/Commands/SaveCodeContextMenuEntry.cs
  11. 63
      ILSpy/LanguageSettings.cs
  12. 26
      ILSpy/Languages/CSharpLanguage.cs
  13. 2
      ILSpy/Languages/ILLanguage.cs
  14. 152
      ILSpy/Languages/LanguageService.cs
  15. 69
      ILSpy/Languages/Languages.cs
  16. 6
      ILSpy/MainWindow.xaml
  17. 1
      ILSpy/MainWindowViewModel.cs
  18. 2
      ILSpy/SolutionWriter.cs
  19. 6
      ILSpy/TextView/DecompilerTextView.cs
  20. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  21. 3
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  22. 2
      ILSpy/TreeNodes/EventTreeNode.cs
  23. 2
      ILSpy/TreeNodes/FieldTreeNode.cs
  24. 4
      ILSpy/TreeNodes/ILSpyTreeNode.cs
  25. 4
      ILSpy/TreeNodes/MethodTreeNode.cs
  26. 4
      ILSpy/TreeNodes/PropertyTreeNode.cs
  27. 2
      ILSpy/TreeNodes/TypeTreeNode.cs
  28. 5
      ILSpy/Util/SettingsService.cs
  29. 6
      ILSpy/Views/DebugSteps.xaml.cs

2
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -218,7 +218,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -218,7 +218,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
public override RichText GetRichTextTooltip(IEntity entity)
{
return Languages.ILLanguage.GetRichTextTooltip(entity);
return LanguageService.Instance.ILLanguage.GetRichTextTooltip(entity);
}
private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, MetadataFile file)

2
ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs

@ -145,7 +145,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers @@ -145,7 +145,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers
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);

2
ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers
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();
}

2
ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers @@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers
assemblyList = new AssemblyList();
testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location);
testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetMetadataFileOrNull(), testAssembly.GetAssemblyResolver());
language = new CSharpLanguage();
language = new CSharpLanguage([]);
}
[Test]

2
ILSpy/Analyzers/AnalyzerTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -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()
{

10
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
{
switch (e.PropertyName)
{
case nameof(LanguageSettings.Language) or nameof(LanguageSettings.LanguageVersion):
case nameof(LanguageSettings.LanguageId) or nameof(LanguageSettings.LanguageVersionId):
RefreshDecompiledView();
break;
default:
@ -152,7 +152,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -152,7 +152,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
{
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;
}
@ -787,7 +787,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -787,7 +787,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
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));
}
@ -797,9 +797,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -797,9 +797,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree
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 {

19
ILSpy/Commands/DecompileAllCommand.cs

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
@ -31,14 +32,20 @@ using ICSharpCode.ILSpy.Properties; @@ -31,14 +32,20 @@ using ICSharpCode.ILSpy.Properties;
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");
@ -60,10 +67,10 @@ namespace ICSharpCode.ILSpy @@ -60,10 +67,10 @@ namespace ICSharpCode.ILSpy
{
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)
{
@ -95,10 +102,10 @@ namespace ICSharpCode.ILSpy @@ -95,10 +102,10 @@ namespace ICSharpCode.ILSpy
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();

2
ILSpy/Commands/DisassembleAllCommand.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy
{
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);

2
ILSpy/Commands/GeneratePdbContextMenuEntry.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy @@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy
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();

4
ILSpy/Commands/SaveCodeContextMenuEntry.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.TextView
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)
@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.TextView
// 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);
});

63
ILSpy/LanguageSettings.cs

@ -17,13 +17,14 @@ @@ -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>
@ -42,9 +43,8 @@ namespace ICSharpCode.ILSpy @@ -42,9 +43,8 @@ namespace ICSharpCode.ILSpy
{
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; }
@ -54,8 +54,8 @@ namespace ICSharpCode.ILSpy @@ -54,8 +54,8 @@ namespace ICSharpCode.ILSpy
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)
);
}
@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy @@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy
}
}
Language language;
string? languageId;
/// <summary>
/// Gets/Sets the current language.
@ -120,37 +120,12 @@ namespace ICSharpCode.ILSpy @@ -120,37 +120,12 @@ namespace ICSharpCode.ILSpy
/// 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.
@ -159,19 +134,9 @@ namespace ICSharpCode.ILSpy @@ -159,19 +134,9 @@ namespace ICSharpCode.ILSpy
/// 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.

26
ILSpy/Languages/CSharpLanguage.cs

@ -38,7 +38,6 @@ using ICSharpCode.Decompiler.Metadata; @@ -38,7 +38,6 @@ using ICSharpCode.Decompiler.Metadata;
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;
@ -56,18 +55,26 @@ namespace ICSharpCode.ILSpy @@ -56,18 +55,26 @@ 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
@ -75,7 +82,7 @@ namespace ICSharpCode.ILSpy @@ -75,7 +82,7 @@ namespace ICSharpCode.ILSpy
lastTransformName = "after " + transform.GetType().Name;
transformCount++;
}
yield return new CSharpLanguage {
yield return new CSharpLanguage(resourceFileHandlers) {
name = "C# - " + lastTransformName,
showAllMembers = true
};
@ -430,8 +437,9 @@ namespace ICSharpCode.ILSpy @@ -430,8 +437,9 @@ namespace ICSharpCode.ILSpy
{
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
@ -542,18 +550,20 @@ namespace ICSharpCode.ILSpy @@ -542,18 +550,20 @@ namespace ICSharpCode.ILSpy
{
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))
{

2
ILSpy/Languages/ILLanguage.cs

@ -201,7 +201,7 @@ namespace ICSharpCode.ILSpy @@ -201,7 +201,7 @@ namespace ICSharpCode.ILSpy
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)
{

152
ILSpy/Languages/LanguageService.cs

@ -0,0 +1,152 @@ @@ -0,0 +1,152 @@
// Copyright (c) 2011 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
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy
{
public class LanguageService : ObservableObjectBase
{
public static readonly LanguageService Instance = new(App.ExportProvider.GetExportedValues<Language>(), App.ExportProvider.GetExportedValues<IResourceFileHandler>(), SettingsService.Instance);
private readonly LanguageSettings languageSettings;
private readonly SettingsService settingsService;
public LanguageService(IEnumerable<Language> languages, IEnumerable<IResourceFileHandler> resourceFileHandlers, SettingsService settingsService)
{
this.settingsService = settingsService;
languageSettings = settingsService.SessionSettings.LanguageSettings;
var sortedLanguages = languages.ToList();
sortedLanguages.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
#if DEBUG
sortedLanguages.AddRange(ILAstLanguage.GetDebugLanguages());
sortedLanguages.AddRange(CSharpLanguage.GetDebugLanguages(resourceFileHandlers.ToArray()));
#endif
AllLanguages = sortedLanguages.AsReadOnly();
this.language = GetLanguage(languageSettings.LanguageId);
this.languageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == languageSettings.LanguageVersionId) ?? Language.LanguageVersions.LastOrDefault();
}
/// <summary>
/// A list of all languages.
/// </summary>
public ReadOnlyCollection<Language> AllLanguages { get; }
/// <summary>
/// Gets a language using its name.
/// If the language is not found, C# is returned instead.
/// </summary>
public Language GetLanguage(string? name)
{
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
}
ILLanguage? ilLanguage;
public ILLanguage ILLanguage => ilLanguage ??= (ILLanguage)GetLanguage("IL");
/// <summary>
/// This dictionary is necessary to remember language versions across language changes. For example,
/// the user first select C# 10, then switches to IL, then switches back to C#. After that we must be
/// able to restore the original selection (i.e., C# 10).
/// </summary>
private readonly Dictionary<Language, LanguageVersion?> languageVersionHistory = new();
Language language;
/// <summary>
/// Gets/Sets the current language.
/// </summary>
/// <remarks>
/// 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 => language;
set {
if (language == value)
return;
if (language is { HasLanguageVersions: true })
{
languageVersionHistory[language] = languageVersion;
}
language = value;
OnPropertyChanged();
languageSettings.LanguageId = language.Name;
if (language.HasLanguageVersions)
{
LanguageVersion = languageVersionHistory.TryGetValue(value, out var version) ? version : Language.LanguageVersions.Last();
}
else
{
LanguageVersion = default;
}
}
}
LanguageVersion? languageVersion;
/// <summary>
/// Gets/Sets the current language version.
/// </summary>
/// <remarks>
/// 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)
return;
languageVersion = value;
OnPropertyChanged();
if (Language.HasLanguageVersions)
{
languageVersionHistory[Language] = languageVersion;
}
languageSettings.LanguageVersionId = languageVersion?.Version;
}
}
public DecompilationOptions CreateDecompilationOptions(TabPageModel tabPage)
{
return new(LanguageVersion, settingsService.DecompilerSettings, settingsService.DisplaySettings) { Progress = tabPage.Content as IProgress<DecompilationProgress> };
}
}
}

69
ILSpy/Languages/Languages.cs

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
// Copyright (c) 2011 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
using System;
using System.Collections.ObjectModel;
using System.Linq;
using TomsToolbox.Composition;
namespace ICSharpCode.ILSpy
{
public static class Languages
{
/// <summary>
/// A list of all languages.
/// </summary>
public static ReadOnlyCollection<Language> AllLanguages { get; } = Initialize(App.ExportProvider);
static ReadOnlyCollection<Language> Initialize(IExportProvider exportProvider)
{
var languages = exportProvider.GetExportedValues<Language>().ToList();
languages.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
#if DEBUG
languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif
return languages.AsReadOnly();
}
/// <summary>
/// Gets a language using its name.
/// If the language is not found, C# is returned instead.
/// </summary>
public static Language GetLanguage(string name)
{
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
}
static ILLanguage? ilLanguage;
public static ILLanguage ILLanguage {
get {
if (ilLanguage == null)
{
ilLanguage = (ILLanguage)GetLanguage("IL");
}
return ilLanguage;
}
}
}
}

6
ILSpy/MainWindow.xaml

@ -149,9 +149,9 @@ @@ -149,9 +149,9 @@
<ItemsControl ItemsSource="{x:Static local:Languages.AllLanguages}" DisplayMemberPath="Name" Height="0" Margin="15,0" />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" MaxDropDownHeight="Auto"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}"
ItemsSource="{Binding LanguageService.AllLanguages}"
ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
SelectedItem="{Binding LanguageService.Language}" />
</Grid>
<Grid Margin="2,0">
<ItemsControl ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="DisplayName" Height="0" Margin="15,0" />
@ -160,7 +160,7 @@ @@ -160,7 +160,7 @@
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
SelectedItem="{Binding LanguageService.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</ToolBar>
<!-- Update panel -->

1
ILSpy/MainWindowViewModel.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.ILSpy @@ -27,6 +27,7 @@ namespace ICSharpCode.ILSpy
{
public DockWorkspace Workspace => DockWorkspace.Instance;
public SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
public LanguageService LanguageService => LanguageService.Instance;
public AssemblyListManager AssemblyListManager => SettingsService.Instance.AssemblyListManager;
}
}

2
ILSpy/SolutionWriter.cs

@ -213,7 +213,7 @@ namespace ICSharpCode.ILSpy @@ -213,7 +213,7 @@ namespace ICSharpCode.ILSpy
using (var projectFileWriter = new StreamWriter(projectFileName))
{
var projectFileOutput = new PlainTextOutput(projectFileWriter);
var options = SettingsService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
options.FullDecompilation = true;
options.CancellationToken = ct;
options.SaveAsProjectDirectory = targetDirectory;

6
ILSpy/TextView/DecompilerTextView.cs

@ -403,7 +403,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -403,7 +403,7 @@ namespace ICSharpCode.ILSpy.TextView
if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code)
{
XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation;
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), SettingsService.Instance.SessionSettings.LanguageSettings.Language.SyntaxHighlighting);
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), LanguageService.Instance.Language.SyntaxHighlighting);
renderer.AddSignatureBlock($"{code.Name} (0x{code.Code:x})");
if (docProvider != null)
{
@ -453,7 +453,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -453,7 +453,7 @@ namespace ICSharpCode.ILSpy.TextView
static FlowDocument? CreateTooltipForEntity(IEntity resolved)
{
Language currentLanguage = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
Language currentLanguage = LanguageService.Instance.Language;
DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), currentLanguage.SyntaxHighlighting);
RichText richText = currentLanguage.GetRichTextTooltip(resolved);
if (richText == null)
@ -544,7 +544,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -544,7 +544,7 @@ namespace ICSharpCode.ILSpy.TextView
{
if (SettingsService.Instance.DisplaySettings.HighlightMatchingBraces)
{
var result = SettingsService.Instance.SessionSettings.LanguageSettings.Language.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset);
var result = LanguageService.Instance.Language.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset);
bracketHighlightRenderer.SetHighlight(result);
}
else

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -547,7 +547,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -547,7 +547,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
dlg.Filter = language.Name + " project|*" + language.ProjectFileExtension + "|" + language.Name + " single file|*" + language.FileExtension + "|All files|*.*";
if (dlg.ShowDialog() == true)
{
var options = SettingsService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
var options = LanguageService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
options.FullDecompilation = true;
if (dlg.FilterIndex == 1)
{

3
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler;
@ -56,7 +55,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -56,7 +55,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
if (settings.SearchTermMatches(type.Name))
{
if (type.DeclaringType != null && (settings.ShowApiLevel != ApiVisibility.All || !settings.Language.ShowMember(type)))
if (type.DeclaringType != null && (settings.ShowApiLevel != ApiVisibility.All || !LanguageService.Instance.Language.ShowMember(type)))
return FilterResult.Hidden;
else
return FilterResult.Match;

2
ILSpy/TreeNodes/EventTreeNode.cs

@ -72,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -72,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(EventDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(EventDefinition)))
if (settings.SearchTermMatches(EventDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || LanguageService.Instance.Language.ShowMember(EventDefinition)))
return FilterResult.Match;
else
return FilterResult.Hidden;

2
ILSpy/TreeNodes/FieldTreeNode.cs

@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(FieldDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(FieldDefinition)))
if (settings.SearchTermMatches(FieldDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || LanguageService.Instance.Language.ShowMember(FieldDefinition)))
return FilterResult.Match;
else
return FilterResult.Hidden;

4
ILSpy/TreeNodes/ILSpyTreeNode.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
LanguageSettings LanguageSettings => SettingsService.Instance.SessionSettings.LanguageSettings;
public Language Language => LanguageSettings.Language;
public Language Language => LanguageService.Instance.Language;
public virtual FilterResult Filter(LanguageSettings settings)
{
@ -131,7 +131,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -131,7 +131,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (sender is not ILSpy.LanguageSettings)
return;
if (e.PropertyName is not (nameof(LanguageSettings.Language) or nameof(LanguageSettings.LanguageVersion)))
if (e.PropertyName is not (nameof(LanguageSettings.LanguageId) or nameof(LanguageSettings.LanguageVersionId)))
return;
RaisePropertyChanged(nameof(Text));

4
ILSpy/TreeNodes/MethodTreeNode.cs

@ -103,7 +103,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -103,7 +103,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(MethodDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(MethodDefinition)))
if (settings.SearchTermMatches(MethodDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || LanguageService.Instance.Language.ShowMember(MethodDefinition)))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -127,7 +127,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -127,7 +127,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override string ToString()
{
return Languages.ILLanguage.MethodToString(MethodDefinition, false, false, false);
return LanguageService.Instance.ILLanguage.MethodToString(MethodDefinition, false, false, false);
}
}
}

4
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(PropertyDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(PropertyDefinition)))
if (settings.SearchTermMatches(PropertyDefinition.Name) && (settings.ShowApiLevel == ApiVisibility.All || LanguageService.Instance.Language.ShowMember(PropertyDefinition)))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override string ToString()
{
return Languages.ILLanguage.PropertyToString(PropertyDefinition, false, false, false);
return LanguageService.Instance.ILLanguage.PropertyToString(PropertyDefinition, false, false, false);
}
}
}

2
ILSpy/TreeNodes/TypeTreeNode.cs

@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return FilterResult.Hidden;
if (settings.SearchTermMatches(TypeDefinition.Name))
{
if (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(TypeDefinition))
if (settings.ShowApiLevel == ApiVisibility.All || LanguageService.Instance.Language.ShowMember(TypeDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;

5
ILSpy/Util/SettingsService.cs

@ -132,11 +132,6 @@ namespace ICSharpCode.ILSpy.Util @@ -132,11 +132,6 @@ namespace ICSharpCode.ILSpy.Util
UseDebugSymbols = DecompilerSettings.UseDebugSymbols
};
public DecompilationOptions CreateDecompilationOptions(TabPageModel tabPage)
{
return new(SessionSettings.LanguageSettings.LanguageVersion, DecompilerSettings, DisplaySettings) { Progress = tabPage.Content as IProgress<DecompilationProgress> };
}
public AssemblyList LoadInitialAssemblyList()
{
var loadPreviousAssemblies = MiscSettings.LoadPreviousAssemblies;

6
ILSpy/Views/DebugSteps.xaml.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy
writingOptions.PropertyChanged += WritingOptions_PropertyChanged;
if (SettingsService.Instance.SessionSettings.LanguageSettings.Language is ILAstLanguage l)
if (LanguageService.Instance.Language is ILAstLanguage l)
{
l.StepperUpdated += ILAstStepperUpdated;
language = l;
@ -66,13 +66,13 @@ namespace ICSharpCode.ILSpy @@ -66,13 +66,13 @@ namespace ICSharpCode.ILSpy
if (sender is not LanguageSettings)
return;
if (e.PropertyName == nameof(LanguageSettings.Language))
if (e.PropertyName == nameof(LanguageSettings.LanguageId))
{
if (language != null)
{
language.StepperUpdated -= ILAstStepperUpdated;
}
if (SettingsService.Instance.SessionSettings.LanguageSettings.Language is ILAstLanguage l)
if (LanguageService.Instance.Language is ILAstLanguage l)
{
l.StepperUpdated += ILAstStepperUpdated;
language = l;

Loading…
Cancel
Save