diff --git a/ICSharpCode.Decompiler.Generators/AnalyzerReleases.Unshipped.md b/ICSharpCode.Decompiler.Generators/AnalyzerReleases.Unshipped.md
index a0353a503..326331a43 100644
--- a/ICSharpCode.Decompiler.Generators/AnalyzerReleases.Unshipped.md
+++ b/ICSharpCode.Decompiler.Generators/AnalyzerReleases.Unshipped.md
@@ -6,3 +6,7 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
DSTG001 | DecompilerSyntaxTreeGenerator | Error | Slot kind must map to a single child type
+DSTG002 | DecompilerSettingsGenerator | Error | [DecompilerSetting] target must be a partial instance bool property
+DSTG003 | DecompilerSettingsGenerator | Error | Version-gated setting must not declare [Category]
+DSTG004 | DecompilerSettingsGenerator | Error | Language version has no display category
+DSTG005 | DecompilerSettingsGenerator | Error | Setting must be declared in a non-nested partial class
diff --git a/ICSharpCode.Decompiler.Generators/DecompilerSettingsGenerator.cs b/ICSharpCode.Decompiler.Generators/DecompilerSettingsGenerator.cs
new file mode 100644
index 000000000..96f6a7258
--- /dev/null
+++ b/ICSharpCode.Decompiler.Generators/DecompilerSettingsGenerator.cs
@@ -0,0 +1,369 @@
+// Copyright (c) 2026 Siegfried Pammer
+//
+// 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.
+
+using System.Collections.Immutable;
+using System.Text;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+namespace ICSharpCode.Decompiler.Generators;
+
+///
+/// Generates the boilerplate behind [DecompilerSetting] partial properties: the backing field,
+/// the accessors with change notification, and - from the per-setting language version - the
+/// [Category] attribute plus the SetLanguageVersion and GetMinimumRequiredVersion methods,
+/// so that a setting's version is declared in exactly one place.
+///
+[Generator]
+internal class DecompilerSettingsGenerator : IIncrementalGenerator
+{
+ static readonly DiagnosticDescriptor InvalidSettingProperty = new(
+ id: "DSTG002",
+ title: "[DecompilerSetting] target must be a partial instance bool property",
+ messageFormat: "Setting property '{0}' must be a partial instance bool property with get and set accessors and an uppercase-start name (the generated backing field uses the camelCase form)",
+ category: "DecompilerSettingsGenerator",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ // The generated [Category] would join a handwritten one on the merged partial property, and
+ // GetCustomAttribute() (used by the settings UI) throws on duplicates.
+ static readonly DiagnosticDescriptor CategoryOnVersionedSetting = new(
+ id: "DSTG003",
+ title: "Version-gated setting must not declare [Category]",
+ messageFormat: "Setting '{0}' derives its [Category] from the language version; remove the handwritten [Category] attribute",
+ category: "DecompilerSettingsGenerator",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ static readonly DiagnosticDescriptor UnsupportedLanguageVersion = new(
+ id: "DSTG004",
+ title: "Language version has no display category",
+ messageFormat: "Language version '{0}' has no display category; gate settings on a released C# version, or add the new version to DecompilerSettingsGenerator.CategoryByVersion",
+ category: "DecompilerSettingsGenerator",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ // The generated implementation is emitted as a top-level partial class; a nested or
+ // non-partial containing type would make it merge nowhere (or into a stray new type).
+ static readonly DiagnosticDescriptor InvalidContainingType = new(
+ id: "DSTG005",
+ title: "Setting must be declared in a non-nested partial class",
+ messageFormat: "Setting '{0}' must be declared in a partial, non-nested class so the generated implementation merges into it",
+ category: "DecompilerSettingsGenerator",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
+
+ static readonly Dictionary DescriptorsById =
+ new DiagnosticDescriptor[] { InvalidSettingProperty, CategoryOnVersionedSetting, UnsupportedLanguageVersion, InvalidContainingType }
+ .ToDictionary(d => d.Id);
+
+ // Display category per released C# version; the settings UI groups options by these strings.
+ static readonly Dictionary CategoryByVersion = new() {
+ ["CSharp1"] = "C# 1.0 / VS .NET",
+ ["CSharp2"] = "C# 2.0 / VS 2005",
+ ["CSharp3"] = "C# 3.0 / VS 2008",
+ ["CSharp4"] = "C# 4.0 / VS 2010",
+ ["CSharp5"] = "C# 5.0 / VS 2012",
+ ["CSharp6"] = "C# 6.0 / VS 2015",
+ ["CSharp7"] = "C# 7.0 / VS 2017",
+ ["CSharp7_1"] = "C# 7.1 / VS 2017.3",
+ ["CSharp7_2"] = "C# 7.2 / VS 2017.4",
+ ["CSharp7_3"] = "C# 7.3 / VS 2017.7",
+ ["CSharp8_0"] = "C# 8.0 / VS 2019",
+ ["CSharp9_0"] = "C# 9.0 / VS 2019.8",
+ ["CSharp10_0"] = "C# 10.0 / VS 2022",
+ ["CSharp11_0"] = "C# 11.0 / VS 2022.4",
+ ["CSharp12_0"] = "C# 12.0 / VS 2022.8",
+ ["CSharp13_0"] = "C# 13.0 / VS 2022.12",
+ ["CSharp14_0"] = "C# 14.0 / VS 2026",
+ };
+
+ readonly record struct SettingInfo(
+ string Namespace, string ClassName, string Accessibility, string PropertyName, string FieldName,
+ bool DefaultValue, int VersionValue, string? VersionName, string? Category,
+ string FilePath, int SpanStart);
+
+ // A diagnostic captured during the transform; kept as plain values so the pipeline stays cacheable.
+ readonly record struct DiagInfo(string Id, string MessageArg, string FilePath, int SpanStart, int SpanLength,
+ int StartLine, int StartChar, int EndLine, int EndChar);
+
+ readonly record struct SettingResult(SettingInfo? Setting, EquatableArray? Diagnostics);
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ context.RegisterPostInitializationOutput(i => i.AddSource("DecompilerSettingsGeneratorAttributes.g.cs", RoslynHelpers.EmbeddedAttributeSource + @"
+namespace ICSharpCode.Decompiler
+{
+ [global::Microsoft.CodeAnalysis.EmbeddedAttribute]
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property)]
+ sealed class DecompilerSettingAttribute : global::System.Attribute
+ {
+ public DecompilerSettingAttribute() { }
+
+ public DecompilerSettingAttribute(global::ICSharpCode.Decompiler.CSharp.LanguageVersion introducedIn) { }
+
+ /// Initial value of the setting. Defaults to true.
+ public bool DefaultValue { get; set; } = true;
+ }
+}
+
+"));
+
+ var settings = context.SyntaxProvider.ForAttributeWithMetadataName(
+ "ICSharpCode.Decompiler.DecompilerSettingAttribute",
+ (n, ct) => n is PropertyDeclarationSyntax,
+ GetSetting);
+
+ context.RegisterSourceOutput(settings.Collect(), WriteSettingsClasses);
+ }
+
+ static SettingResult GetSetting(GeneratorAttributeSyntaxContext context, CancellationToken cancellationToken)
+ {
+ var property = (IPropertySymbol)context.TargetSymbol;
+ var node = (PropertyDeclarationSyntax)context.TargetNode;
+ var diagnostics = new List();
+
+ if (property.Type.SpecialType != SpecialType.System_Boolean || property.IsStatic
+ || property.GetMethod == null || property.SetMethod == null || property.SetMethod.IsInitOnly
+ || !char.IsUpper(property.Name[0])
+ || !node.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
+ {
+ diagnostics.Add(MakeDiagInfo(InvalidSettingProperty.Id, property.Name, node));
+ return new SettingResult(null, diagnostics.ToEquatableArray());
+ }
+
+ if (property.ContainingType.ContainingType != null
+ || node.Parent is not ClassDeclarationSyntax containingClass
+ || !containingClass.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
+ {
+ diagnostics.Add(MakeDiagInfo(InvalidContainingType.Id, property.Name, node));
+ return new SettingResult(null, diagnostics.ToEquatableArray());
+ }
+
+ var attribute = context.Attributes[0];
+ int versionValue = 0;
+ string? versionName = null;
+ string? category = null;
+ if (attribute.ConstructorArguments.Length == 1)
+ {
+ var versionArgument = attribute.ConstructorArguments[0];
+ if (versionArgument.Kind == TypedConstantKind.Error || versionArgument.Value is not int boundVersion || versionArgument.Type is null)
+ {
+ // The argument did not bind (e.g. a typo'd enum member); the compiler already
+ // reports that error at the argument, so just skip the setting instead of
+ // crashing the whole generator.
+ return new SettingResult(null, null);
+ }
+ versionValue = boundVersion;
+ versionName = VersionNameFromSyntax(attribute)
+ ?? versionArgument.Type.GetMembers()
+ .OfType()
+ .FirstOrDefault(f => f.HasConstantValue && Equals(f.ConstantValue, versionValue))?.Name
+ ?? versionValue.ToString();
+ if (!CategoryByVersion.TryGetValue(versionName, out category))
+ {
+ diagnostics.Add(MakeDiagInfo(UnsupportedLanguageVersion.Id, versionName, node));
+ return new SettingResult(null, diagnostics.ToEquatableArray());
+ }
+ if (property.GetAttributes().Any(a => a.AttributeClass?.ToDisplayString() == "System.ComponentModel.CategoryAttribute"))
+ {
+ diagnostics.Add(MakeDiagInfo(CategoryOnVersionedSetting.Id, property.Name, node));
+ // The compiler would otherwise also flag the generated [Category] as a duplicate;
+ // suppress it so the mistake surfaces as the single DSTG003.
+ category = null;
+ }
+ }
+
+ bool defaultValue = true;
+ foreach (var named in attribute.NamedArguments)
+ {
+ // A named argument that failed to bind is already a compiler error; ignore it here.
+ if (named.Value.Value is not bool namedValue)
+ continue;
+ if (named.Key == "DefaultValue")
+ defaultValue = namedValue;
+ }
+
+ string fieldName = char.ToLowerInvariant(property.Name[0]) + property.Name.Substring(1);
+ if (SyntaxFacts.GetKeywordKind(fieldName) != SyntaxKind.None)
+ fieldName = "@" + fieldName;
+
+ var setting = new SettingInfo(
+ property.ContainingNamespace.IsGlobalNamespace ? "" : property.ContainingNamespace.ToDisplayString(),
+ property.ContainingType.Name,
+ SyntaxFacts.GetText(property.DeclaredAccessibility),
+ property.Name,
+ fieldName,
+ defaultValue,
+ versionValue,
+ versionName,
+ category,
+ node.SyntaxTree.FilePath,
+ node.SpanStart);
+ return new SettingResult(setting, diagnostics.Count == 0 ? null : diagnostics.ToEquatableArray());
+ }
+
+ // Prefer the enum member name as spelled at the use site: constant values are not unique in
+ // LanguageVersion (CSharp15_0 and Preview share a value), so a value-based reverse lookup can
+ // name an alias the user never wrote.
+ static string? VersionNameFromSyntax(AttributeData attribute)
+ {
+ if (attribute.ApplicationSyntaxReference?.GetSyntax() is not AttributeSyntax { ArgumentList.Arguments: { Count: >= 1 } arguments })
+ return null;
+ if (arguments[0].NameEquals != null)
+ return null;
+ return arguments[0].Expression switch {
+ MemberAccessExpressionSyntax memberAccess => memberAccess.Name.Identifier.Text,
+ IdentifierNameSyntax identifier => identifier.Identifier.Text,
+ _ => null,
+ };
+ }
+
+ static DiagInfo MakeDiagInfo(string id, string messageArg, SyntaxNode node)
+ {
+ var lineSpan = node.GetLocation().GetLineSpan();
+ return new DiagInfo(id, messageArg, node.SyntaxTree.FilePath, node.Span.Start, node.Span.Length,
+ lineSpan.StartLinePosition.Line, lineSpan.StartLinePosition.Character,
+ lineSpan.EndLinePosition.Line, lineSpan.EndLinePosition.Character);
+ }
+
+ static void WriteSettingsClasses(SourceProductionContext context, ImmutableArray results)
+ {
+ foreach (var result in results)
+ {
+ if (result.Diagnostics is not { } resultDiagnostics)
+ continue;
+ foreach (var diag in resultDiagnostics)
+ {
+ // Indexer lookup so a diagnostic id missing from the map fails loudly instead of
+ // being reported under an unrelated descriptor.
+ var descriptor = DescriptorsById[diag.Id];
+ var location = Location.Create(diag.FilePath, new TextSpan(diag.SpanStart, diag.SpanLength),
+ new LinePositionSpan(new LinePosition(diag.StartLine, diag.StartChar), new LinePosition(diag.EndLine, diag.EndChar)));
+ context.ReportDiagnostic(Diagnostic.Create(descriptor, location, diag.MessageArg));
+ }
+ }
+
+ var settings = results
+ .Where(r => r.Setting != null)
+ .Select(r => r.Setting!.Value)
+ .OrderBy(s => s.FilePath, StringComparer.Ordinal)
+ .ThenBy(s => s.SpanStart);
+
+ foreach (var settingsClass in settings.GroupBy(s => (s.Namespace, s.ClassName)))
+ {
+ WriteSettingsClass(context, settingsClass.Key.Namespace, settingsClass.Key.ClassName, settingsClass.ToArray());
+ }
+ }
+
+ static void WriteSettingsClass(SourceProductionContext context, string ns, string className, SettingInfo[] settings)
+ {
+ var builder = new StringBuilder();
+ builder.AppendLine("// ");
+ builder.AppendLine("#nullable enable");
+ builder.AppendLine();
+ if (ns.Length > 0)
+ {
+ builder.AppendLine($"namespace {ns}");
+ builder.AppendLine("{");
+ }
+ builder.AppendLine($"\tpartial class {className}");
+ builder.AppendLine("\t{");
+
+ foreach (var setting in settings)
+ {
+ builder.AppendLine($"\t\tbool {setting.FieldName} = {(setting.DefaultValue ? "true" : "false")};");
+ builder.AppendLine();
+ if (setting.Category != null)
+ {
+ builder.AppendLine($"\t\t[global::System.ComponentModel.Category(\"{setting.Category}\")]");
+ }
+ builder.AppendLine($"\t\t{setting.Accessibility} partial bool {setting.PropertyName} {{");
+ builder.AppendLine($"\t\t\tget {{ return {setting.FieldName}; }}");
+ builder.AppendLine("\t\t\tset {");
+ builder.AppendLine($"\t\t\t\tif ({setting.FieldName} != value)");
+ builder.AppendLine("\t\t\t\t{");
+ builder.AppendLine($"\t\t\t\t\t{setting.FieldName} = value;");
+ builder.AppendLine("\t\t\t\t\tOnPropertyChanged();");
+ builder.AppendLine("\t\t\t\t}");
+ builder.AppendLine("\t\t\t}");
+ builder.AppendLine("\t\t}");
+ builder.AppendLine();
+ }
+
+ var versionBuckets = settings
+ .Where(s => s.VersionName != null)
+ .GroupBy(s => s.VersionValue)
+ .OrderBy(g => g.Key)
+ .ToArray();
+ if (versionBuckets.Length > 0)
+ {
+ WriteSetLanguageVersion(builder, versionBuckets);
+ builder.AppendLine();
+ WriteGetMinimumRequiredVersion(builder, versionBuckets);
+ }
+
+ builder.AppendLine("\t}");
+ if (ns.Length > 0)
+ {
+ builder.AppendLine("}");
+ }
+ // The hint name must carry the full grouping key: two same-named settings classes in
+ // different namespaces would otherwise collide in AddSource and kill the generator.
+ string hintName = ns.Length == 0 ? $"{className}.Settings.g.cs" : $"{ns}.{className}.Settings.g.cs";
+ context.AddSource(hintName, SourceText.From(builder.ToString().Replace("\r\n", "\n"), Encoding.UTF8));
+ }
+
+ // Emitted as partial implementing declarations: the containing class supplies the defining
+ // stubs, which is where the XML documentation lives (the docs on a partial method's defining
+ // declaration apply as long as the implementation carries none).
+ static void WriteSetLanguageVersion(StringBuilder builder, IGrouping[] versionBuckets)
+ {
+ builder.AppendLine("\t\tpublic partial void SetLanguageVersion(global::ICSharpCode.Decompiler.CSharp.LanguageVersion languageVersion)");
+ builder.AppendLine("\t\t{");
+ builder.AppendLine("\t\t\t// By default, all decompiler features are enabled.");
+ builder.AppendLine("\t\t\t// Disable some of them based on language version:");
+ foreach (var bucket in versionBuckets)
+ {
+ builder.AppendLine($"\t\t\tif (languageVersion < global::ICSharpCode.Decompiler.CSharp.LanguageVersion.{bucket.First().VersionName})");
+ builder.AppendLine("\t\t\t{");
+ foreach (var setting in bucket)
+ {
+ builder.AppendLine($"\t\t\t\t{setting.FieldName} = false;");
+ }
+ builder.AppendLine("\t\t\t}");
+ }
+ builder.AppendLine("\t\t}");
+ }
+
+ static void WriteGetMinimumRequiredVersion(StringBuilder builder, IGrouping[] versionBuckets)
+ {
+ builder.AppendLine("\t\tpublic partial global::ICSharpCode.Decompiler.CSharp.LanguageVersion GetMinimumRequiredVersion()");
+ builder.AppendLine("\t\t{");
+ foreach (var bucket in versionBuckets.Reverse())
+ {
+ builder.AppendLine($"\t\t\tif ({string.Join(" || ", bucket.Select(s => s.FieldName))})");
+ builder.AppendLine($"\t\t\t\treturn global::ICSharpCode.Decompiler.CSharp.LanguageVersion.{bucket.First().VersionName};");
+ }
+ builder.AppendLine("\t\t\treturn global::ICSharpCode.Decompiler.CSharp.LanguageVersion.CSharp1;");
+ builder.AppendLine("\t\t}");
+ }
+}
diff --git a/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs b/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs
index c5ea313e1..44044d019 100644
--- a/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs
+++ b/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs
@@ -843,17 +843,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
var visitorMembers = astNodeAdditions.Collect();
context
- .RegisterPostInitializationOutput(i => i.AddSource("DecompilerSyntaxTreeGeneratorAttributes.g.cs", @"
-
-using System;
-
-namespace Microsoft.CodeAnalysis
-{
- internal sealed partial class EmbeddedAttribute : global::System.Attribute
- {
- }
-}
-
+ .RegisterPostInitializationOutput(i => i.AddSource("DecompilerSyntaxTreeGeneratorAttributes.g.cs", RoslynHelpers.EmbeddedAttributeSource + @"
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
diff --git a/ICSharpCode.Decompiler.Generators/RoslynHelpers.cs b/ICSharpCode.Decompiler.Generators/RoslynHelpers.cs
index c0350704e..60e2ce2ef 100644
--- a/ICSharpCode.Decompiler.Generators/RoslynHelpers.cs
+++ b/ICSharpCode.Decompiler.Generators/RoslynHelpers.cs
@@ -22,6 +22,21 @@ namespace ICSharpCode.Decompiler.Generators;
public static class RoslynHelpers
{
+ ///
+ /// Post-init source declaring Microsoft.CodeAnalysis.EmbeddedAttribute. Every generator that
+ /// emits embedded attribute types has to ship its own copy in its own post-init output; the
+ /// declarations merge only while they stay partial and textually compatible, so all generators
+ /// must build their copy from this single constant.
+ ///
+ public const string EmbeddedAttributeSource = @"
+namespace Microsoft.CodeAnalysis
+{
+ internal sealed partial class EmbeddedAttribute : global::System.Attribute
+ {
+ }
+}
+";
+
public static bool IsDerivedFrom(this INamedTypeSymbol type, INamedTypeSymbol baseType)
{
INamedTypeSymbol? t = type;
diff --git a/ICSharpCode.Decompiler.Tests/DecompilerSettingsTests.cs b/ICSharpCode.Decompiler.Tests/DecompilerSettingsTests.cs
new file mode 100644
index 000000000..2645e6f93
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/DecompilerSettingsTests.cs
@@ -0,0 +1,53 @@
+// Copyright (c) 2026 Siegfried Pammer
+//
+// 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.
+
+using ICSharpCode.Decompiler.CSharp;
+
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ class DecompilerSettingsTests
+ {
+ [Test]
+ public void GetMinimumRequiredVersionReturnsTheHighestEnabledFeatureVersion()
+ {
+ var settings = new DecompilerSettings(LanguageVersion.CSharp1);
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp1));
+
+ settings.AnonymousMethods = true;
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp2));
+
+ // Syntax-preference settings participate too: enabled, they emit syntax of their version.
+ settings.UseEnhancedUsing = true;
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp8_0));
+
+ settings.SwitchOnReadOnlySpanChar = true;
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp11_0));
+
+ // The scan must pick the highest enabled feature, not the first match bottom-up.
+ settings.ParamsCollections = true;
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp13_0));
+
+ settings.AnonymousMethods = false;
+ settings.ParamsCollections = false;
+ Assert.That(settings.GetMinimumRequiredVersion(), Is.EqualTo(LanguageVersion.CSharp11_0));
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
index c6ce3eada..84f85968e 100644
--- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
@@ -60,17 +60,31 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
LanguageVersion? languageVersion;
+ ///
+ /// The C# language version written into the exported project file as LangVersion.
+ /// This is an export parameter, not decompiler state: when not set explicitly, it defaults
+ /// to of the current settings,
+ /// and an explicit value below that minimum is rejected (here and again when the export
+ /// starts) because the emitted code could not compile under it.
+ ///
public LanguageVersion LanguageVersion {
get { return languageVersion ?? Settings.GetMinimumRequiredVersion(); }
set {
- var minVersion = Settings.GetMinimumRequiredVersion();
- if (value < minVersion)
- throw new InvalidOperationException($"The chosen settings require at least {minVersion}." +
- $" Please change the DecompilerSettings accordingly.");
+ ValidateLanguageVersion(value);
languageVersion = value;
}
}
+ void ValidateLanguageVersion(LanguageVersion version)
+ {
+ var minVersion = Settings.GetMinimumRequiredVersion();
+ if (version < minVersion)
+ {
+ throw new InvalidOperationException($"The chosen settings require at least {minVersion}." +
+ " Please change the DecompilerSettings accordingly.");
+ }
+ }
+
bool IProjectInfoProvider.CheckForOverflowUnderflow => Settings.CheckForOverflowUnderflow;
public IAssemblyResolver AssemblyResolver { get; }
@@ -154,6 +168,14 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
throw new InvalidOperationException("Must set TargetDirectory");
}
+ // The LanguageVersion setter already rejects a version below what the settings require,
+ // but Settings is mutable and shared, so re-validate against the settings actually in
+ // effect now - otherwise the exported project would carry a LangVersion under which the
+ // emitted code cannot compile.
+ if (languageVersion is { } explicitVersion)
+ {
+ ValidateLanguageVersion(explicitVersion);
+ }
DecompilerEventSource.Log.ProjectDecompilationStart(file.Name);
int codeFileCount = 0, resourceFileCount = 0;
try
diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
index 955003893..31082c624 100644
--- a/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ b/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler
///
/// Settings for the decompiler.
///
- public class DecompilerSettings : INotifyPropertyChanged
+ public partial class DecompilerSettings : INotifyPropertyChanged
{
///
/// Equivalent to new DecompilerSettings(LanguageVersion.Latest)
@@ -44,6 +44,8 @@ namespace ICSharpCode.Decompiler
/// This does not imply that the resulting code strictly uses only language features from
/// that version. Language constructs like generics or ref locals cannot be removed from
/// the compiled code.
+ /// The language version is a construction shortcut, not state: it initializes the feature
+ /// flags once (see ) and is not stored afterwards.
///
public DecompilerSettings(CSharp.LanguageVersion languageVersion)
{
@@ -51,377 +53,99 @@ namespace ICSharpCode.Decompiler
}
///
- /// Deactivates all language features from versions newer than .
+ /// One-shot profile initializer: deactivates all language features from versions newer than
+ /// . The version itself is not stored - the feature flags
+ /// are the only state - so the call is not reversible and a later call with a higher version
+ /// does not re-enable features. Use to derive a
+ /// version back from the flags.
///
- public void SetLanguageVersion(CSharp.LanguageVersion languageVersion)
- {
- // By default, all decompiler features are enabled.
- // Disable some of them based on language version:
- if (languageVersion < CSharp.LanguageVersion.CSharp2)
- {
- anonymousMethods = false;
- liftNullables = false;
- yieldReturn = false;
- useImplicitMethodGroupConversion = false;
- useObjectCreationOfGenericTypeParameter = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp3)
- {
- anonymousTypes = false;
- useLambdaSyntax = false;
- objectCollectionInitializers = false;
- automaticProperties = false;
- extensionMethods = false;
- queryExpressions = false;
- expressionTrees = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp4)
- {
- dynamic = false;
- namedArguments = false;
- optionalArguments = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp5)
- {
- asyncAwait = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp6)
- {
- awaitInCatchFinally = false;
- useExpressionBodyForCalculatedGetterOnlyProperties = false;
- nullPropagation = false;
- stringInterpolation = false;
- dictionaryInitializers = false;
- extensionMethodsInCollectionInitializers = false;
- getterOnlyAutomaticProperties = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp7)
- {
- outVariables = false;
- throwExpressions = false;
- tupleTypes = false;
- tupleConversions = false;
- discards = false;
- localFunctions = false;
- deconstruction = false;
- patternMatching = false;
- useRefLocalsForAccurateOrderOfEvaluation = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp7_2)
- {
- introduceReadonlyAndInModifiers = false;
- introduceRefModifiersOnStructs = false;
- nonTrailingNamedArguments = false;
- refExtensionMethods = false;
- introducePrivateProtectedAccessibilty = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp7_3)
- {
- introduceUnmanagedConstraint = false;
- stackAllocInitializers = false;
- tupleComparisons = false;
- patternBasedFixedStatement = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp8_0)
- {
- nullableReferenceTypes = false;
- readOnlyMethods = false;
- asyncUsingAndForEachStatement = false;
- asyncEnumerator = false;
- useEnhancedUsing = false;
- staticLocalFunctions = false;
- ranges = false;
- switchExpressions = false;
- recursivePatternMatching = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp9_0)
- {
- nativeIntegers = false;
- initAccessors = false;
- functionPointers = false;
- forEachWithGetEnumeratorExtension = false;
- recordClasses = false;
- withExpressions = false;
- usePrimaryConstructorSyntax = false;
- covariantReturns = false;
- relationalPatterns = false;
- patternCombinators = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp10_0)
- {
- fileScopedNamespaces = false;
- recordStructs = false;
- structDefaultConstructorsAndFieldInitializers = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp11_0)
- {
- scopedRef = false;
- requiredMembers = false;
- numericIntPtr = false;
- utf8StringLiterals = false;
- unsignedRightShift = false;
- checkedOperators = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp12_0)
- {
- refReadOnlyParameters = false;
- usePrimaryConstructorSyntaxForNonRecordTypes = false;
- inlineArrays = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp13_0)
- {
- paramsCollections = false;
- }
- if (languageVersion < CSharp.LanguageVersion.CSharp14_0)
- {
- extensionMembers = false;
- firstClassSpanTypes = false;
- }
- }
-
- public CSharp.LanguageVersion GetMinimumRequiredVersion()
- {
- if (extensionMembers || firstClassSpanTypes)
- return CSharp.LanguageVersion.CSharp14_0;
- if (paramsCollections)
- return CSharp.LanguageVersion.CSharp13_0;
- if (refReadOnlyParameters || usePrimaryConstructorSyntaxForNonRecordTypes || inlineArrays)
- return CSharp.LanguageVersion.CSharp12_0;
- if (scopedRef || requiredMembers || numericIntPtr || utf8StringLiterals || unsignedRightShift || checkedOperators)
- return CSharp.LanguageVersion.CSharp11_0;
- if (fileScopedNamespaces || recordStructs || structDefaultConstructorsAndFieldInitializers)
- return CSharp.LanguageVersion.CSharp10_0;
- if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension
- || recordClasses || withExpressions || usePrimaryConstructorSyntax || covariantReturns
- || relationalPatterns || patternCombinators)
- return CSharp.LanguageVersion.CSharp9_0;
- if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement
- || staticLocalFunctions || ranges || switchExpressions || recursivePatternMatching)
- return CSharp.LanguageVersion.CSharp8_0;
- if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers
- || patternBasedFixedStatement)
- return CSharp.LanguageVersion.CSharp7_3;
- if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers
- || nonTrailingNamedArguments || refExtensionMethods || introducePrivateProtectedAccessibilty)
- return CSharp.LanguageVersion.CSharp7_2;
- // C# 7.1 missing
- if (outVariables || throwExpressions || tupleTypes || tupleConversions
- || discards || localFunctions || deconstruction || patternMatching || useRefLocalsForAccurateOrderOfEvaluation)
- return CSharp.LanguageVersion.CSharp7;
- if (awaitInCatchFinally || useExpressionBodyForCalculatedGetterOnlyProperties || nullPropagation
- || stringInterpolation || dictionaryInitializers || extensionMethodsInCollectionInitializers
- || getterOnlyAutomaticProperties)
- return CSharp.LanguageVersion.CSharp6;
- if (asyncAwait)
- return CSharp.LanguageVersion.CSharp5;
- if (dynamic || namedArguments || optionalArguments)
- return CSharp.LanguageVersion.CSharp4;
- if (anonymousTypes || objectCollectionInitializers || automaticProperties
- || queryExpressions || expressionTrees)
- return CSharp.LanguageVersion.CSharp3;
- if (anonymousMethods || liftNullables || yieldReturn || useImplicitMethodGroupConversion || useObjectCreationOfGenericTypeParameter)
- return CSharp.LanguageVersion.CSharp2;
- return CSharp.LanguageVersion.CSharp1;
- }
+ public partial void SetLanguageVersion(CSharp.LanguageVersion languageVersion);
- bool nativeIntegers = true;
+ ///
+ /// Derives the lowest language version that includes all currently enabled language
+ /// features. The settings do not store a language version, so this derivation is how a
+ /// version is recovered from the flags; project export uses it as the default (and lower
+ /// bound) for the LangVersion written into the project file.
+ ///
+ public partial CSharp.LanguageVersion GetMinimumRequiredVersion();
///
/// Use C# 9 nint/nuint types.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.NativeIntegers")]
- public bool NativeIntegers {
- get { return nativeIntegers; }
- set {
- if (nativeIntegers != value)
- {
- nativeIntegers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool numericIntPtr = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool NativeIntegers { get; set; }
///
/// Treat IntPtr/UIntPtr as nint/nuint.
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.NumericIntPtr")]
- public bool NumericIntPtr {
- get { return numericIntPtr; }
- set {
- if (numericIntPtr != value)
- {
- numericIntPtr = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool covariantReturns = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool NumericIntPtr { get; set; }
///
/// Decompile C# 9 covariant return types.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.CovariantReturns")]
- public bool CovariantReturns {
- get { return covariantReturns; }
- set {
- if (covariantReturns != value)
- {
- covariantReturns = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool initAccessors = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool CovariantReturns { get; set; }
///
/// Use C# 9 init; property accessors.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.InitAccessors")]
- public bool InitAccessors {
- get { return initAccessors; }
- set {
- if (initAccessors != value)
- {
- initAccessors = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool recordClasses = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool InitAccessors { get; set; }
///
/// Use C# 9 record classes.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.RecordClasses")]
- public bool RecordClasses {
- get { return recordClasses; }
- set {
- if (recordClasses != value)
- {
- recordClasses = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool recordStructs = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool RecordClasses { get; set; }
///
/// Use C# 10 record structs.
///
- [Category("C# 10.0 / VS 2022")]
[Description("DecompilerSettings.RecordStructs")]
- public bool RecordStructs {
- get { return recordStructs; }
- set {
- if (recordStructs != value)
- {
- recordStructs = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool structDefaultConstructorsAndFieldInitializers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp10_0)]
+ public partial bool RecordStructs { get; set; }
///
/// Use field initializers in structs.
///
- [Category("C# 10.0 / VS 2022")]
[Description("DecompilerSettings.StructDefaultConstructorsAndFieldInitializers")]
- public bool StructDefaultConstructorsAndFieldInitializers {
- get { return structDefaultConstructorsAndFieldInitializers; }
- set {
- if (structDefaultConstructorsAndFieldInitializers != value)
- {
- structDefaultConstructorsAndFieldInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool withExpressions = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp10_0)]
+ public partial bool StructDefaultConstructorsAndFieldInitializers { get; set; }
///
/// Use C# 9 with initializer expressions.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.WithExpressions")]
- public bool WithExpressions {
- get { return withExpressions; }
- set {
- if (withExpressions != value)
- {
- withExpressions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool usePrimaryConstructorSyntax = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool WithExpressions { get; set; }
///
/// Use primary constructor syntax with records.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.UsePrimaryConstructorSyntax")]
- public bool UsePrimaryConstructorSyntax {
- get { return usePrimaryConstructorSyntax; }
- set {
- if (usePrimaryConstructorSyntax != value)
- {
- usePrimaryConstructorSyntax = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool functionPointers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool UsePrimaryConstructorSyntax { get; set; }
///
/// Use C# 9 delegate* unmanaged types.
/// If this option is disabled, function pointers will instead be decompiled with type `IntPtr`.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.FunctionPointers")]
- public bool FunctionPointers {
- get { return functionPointers; }
- set {
- if (functionPointers != value)
- {
- functionPointers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool scopedRef = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool FunctionPointers { get; set; }
///
/// Use C# 11 scoped modifier.
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.ScopedRef")]
- public bool ScopedRef {
- get { return scopedRef; }
- set {
- if (scopedRef != value)
- {
- scopedRef = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool ScopedRef { get; set; }
[Obsolete("Renamed to ScopedRef. This property will be removed in a future version of the decompiler.")]
[Browsable(false)]
@@ -430,610 +154,235 @@ namespace ICSharpCode.Decompiler
set { ScopedRef = value; }
}
- bool requiredMembers = true;
-
///
/// Use C# 11 required modifier.
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.RequiredMembers")]
- public bool RequiredMembers {
- get { return requiredMembers; }
- set {
- if (requiredMembers != value)
- {
- requiredMembers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool switchExpressions = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool RequiredMembers { get; set; }
///
/// Use C# 8 switch expressions.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.SwitchExpressions")]
- public bool SwitchExpressions {
- get { return switchExpressions; }
- set {
- if (switchExpressions != value)
- {
- switchExpressions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool fileScopedNamespaces = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool SwitchExpressions { get; set; }
///
/// Use C# 10 file-scoped namespaces.
///
- [Category("C# 10.0 / VS 2022")]
[Description("DecompilerSettings.FileScopedNamespaces")]
- public bool FileScopedNamespaces {
- get { return fileScopedNamespaces; }
- set {
- if (fileScopedNamespaces != value)
- {
- fileScopedNamespaces = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool anonymousMethods = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp10_0)]
+ public partial bool FileScopedNamespaces { get; set; }
///
/// Decompile anonymous methods/lambdas.
///
- [Category("C# 2.0 / VS 2005")]
[Description("DecompilerSettings.DecompileAnonymousMethodsLambdas")]
- public bool AnonymousMethods {
- get { return anonymousMethods; }
- set {
- if (anonymousMethods != value)
- {
- anonymousMethods = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool anonymousTypes = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp2)]
+ public partial bool AnonymousMethods { get; set; }
///
/// Decompile anonymous types.
///
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.DecompileAnonymousTypes")]
- public bool AnonymousTypes {
- get { return anonymousTypes; }
- set {
- if (anonymousTypes != value)
- {
- anonymousTypes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useLambdaSyntax = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool AnonymousTypes { get; set; }
///
/// Use C# 3 lambda syntax if possible.
///
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.UseLambdaSyntaxIfPossible")]
- public bool UseLambdaSyntax {
- get { return useLambdaSyntax; }
- set {
- if (useLambdaSyntax != value)
- {
- useLambdaSyntax = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool expressionTrees = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool UseLambdaSyntax { get; set; }
///
/// Decompile expression trees.
///
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.DecompileExpressionTrees")]
- public bool ExpressionTrees {
- get { return expressionTrees; }
- set {
- if (expressionTrees != value)
- {
- expressionTrees = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool yieldReturn = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool ExpressionTrees { get; set; }
///
/// Decompile enumerators.
///
- [Category("C# 2.0 / VS 2005")]
[Description("DecompilerSettings.DecompileEnumeratorsYieldReturn")]
- public bool YieldReturn {
- get { return yieldReturn; }
- set {
- if (yieldReturn != value)
- {
- yieldReturn = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool dynamic = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp2)]
+ public partial bool YieldReturn { get; set; }
///
/// Decompile use of the 'dynamic' type.
///
- [Category("C# 4.0 / VS 2010")]
[Description("DecompilerSettings.DecompileUseOfTheDynamicType")]
- public bool Dynamic {
- get { return dynamic; }
- set {
- if (dynamic != value)
- {
- dynamic = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool asyncAwait = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp4)]
+ public partial bool Dynamic { get; set; }
///
/// Decompile async methods.
///
- [Category("C# 5.0 / VS 2012")]
[Description("DecompilerSettings.DecompileAsyncMethods")]
- public bool AsyncAwait {
- get { return asyncAwait; }
- set {
- if (asyncAwait != value)
- {
- asyncAwait = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool awaitInCatchFinally = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp5)]
+ public partial bool AsyncAwait { get; set; }
///
/// Decompile await in catch/finally blocks.
/// Only has an effect if is enabled.
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.DecompileAwaitInCatchFinallyBlocks")]
- public bool AwaitInCatchFinally {
- get { return awaitInCatchFinally; }
- set {
- if (awaitInCatchFinally != value)
- {
- awaitInCatchFinally = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool asyncEnumerator = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool AwaitInCatchFinally { get; set; }
///
/// Decompile IAsyncEnumerator/IAsyncEnumerable.
/// Only has an effect if is enabled.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.AsyncEnumerator")]
- public bool AsyncEnumerator {
- get { return asyncEnumerator; }
- set {
- if (asyncEnumerator != value)
- {
- asyncEnumerator = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool decimalConstants = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool AsyncEnumerator { get; set; }
///
/// Decompile [DecimalConstant(...)] as simple literal values.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DecompileDecimalConstantAsSimpleLiteralValues")]
- public bool DecimalConstants {
- get { return decimalConstants; }
- set {
- if (decimalConstants != value)
- {
- decimalConstants = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool fixedBuffers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool DecimalConstants { get; set; }
///
/// Decompile C# 1.0 'public unsafe fixed int arr[10];' members.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DecompileC10PublicUnsafeFixedIntArr10Members")]
- public bool FixedBuffers {
- get { return fixedBuffers; }
- set {
- if (fixedBuffers != value)
- {
- fixedBuffers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool stringConcat = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool FixedBuffers { get; set; }
///
/// Decompile 'string.Concat(a, b)' calls into 'a + b'.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.StringConcat")]
- public bool StringConcat {
- get { return stringConcat; }
- set {
- if (stringConcat != value)
- {
- stringConcat = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool liftNullables = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool StringConcat { get; set; }
///
/// Use lifted operators for nullables.
///
- [Category("C# 2.0 / VS 2005")]
[Description("DecompilerSettings.UseLiftedOperatorsForNullables")]
- public bool LiftNullables {
- get { return liftNullables; }
- set {
- if (liftNullables != value)
- {
- liftNullables = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool nullPropagation = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp2)]
+ public partial bool LiftNullables { get; set; }
///
/// Decompile C# 6 ?. and ?[] operators.
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.NullPropagation")]
- public bool NullPropagation {
- get { return nullPropagation; }
- set {
- if (nullPropagation != value)
- {
- nullPropagation = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool automaticProperties = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool NullPropagation { get; set; }
///
/// Decompile automatic properties
///
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.DecompileAutomaticProperties")]
- public bool AutomaticProperties {
- get { return automaticProperties; }
- set {
- if (automaticProperties != value)
- {
- automaticProperties = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool getterOnlyAutomaticProperties = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool AutomaticProperties { get; set; }
///
/// Decompile getter-only automatic properties
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.GetterOnlyAutomaticProperties")]
- public bool GetterOnlyAutomaticProperties {
- get { return getterOnlyAutomaticProperties; }
- set {
- if (getterOnlyAutomaticProperties != value)
- {
- getterOnlyAutomaticProperties = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool automaticEvents = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool GetterOnlyAutomaticProperties { get; set; }
///
/// Decompile automatic events
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DecompileAutomaticEvents")]
- public bool AutomaticEvents {
- get { return automaticEvents; }
- set {
- if (automaticEvents != value)
- {
- automaticEvents = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool usingStatement = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool AutomaticEvents { get; set; }
///
/// Decompile using statements.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DetectUsingStatements")]
- public bool UsingStatement {
- get { return usingStatement; }
- set {
- if (usingStatement != value)
- {
- usingStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useEnhancedUsing = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool UsingStatement { get; set; }
///
/// Use enhanced using statements.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.UseEnhancedUsing")]
- public bool UseEnhancedUsing {
- get { return useEnhancedUsing; }
- set {
- if (useEnhancedUsing != value)
- {
- useEnhancedUsing = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysUseBraces = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool UseEnhancedUsing { get; set; }
///
/// Gets/Sets whether to use braces for single-statement-blocks.
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysUseBraces")]
- public bool AlwaysUseBraces {
- get { return alwaysUseBraces; }
- set {
- if (alwaysUseBraces != value)
- {
- alwaysUseBraces = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool forEachStatement = true;
+ [DecompilerSetting]
+ public partial bool AlwaysUseBraces { get; set; }
///
/// Decompile foreach statements.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DetectForeachStatements")]
- public bool ForEachStatement {
- get { return forEachStatement; }
- set {
- if (forEachStatement != value)
- {
- forEachStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool forEachWithGetEnumeratorExtension = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool ForEachStatement { get; set; }
///
/// Support GetEnumerator extension methods in foreach.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.DecompileForEachWithGetEnumeratorExtension")]
- public bool ForEachWithGetEnumeratorExtension {
- get { return forEachWithGetEnumeratorExtension; }
- set {
- if (forEachWithGetEnumeratorExtension != value)
- {
- forEachWithGetEnumeratorExtension = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool paramsCollections = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool ForEachWithGetEnumeratorExtension { get; set; }
///
/// Support params collections.
///
- [Category("C# 13.0 / VS 2022.12")]
[Description("DecompilerSettings.DecompileParamsCollections")]
- public bool ParamsCollections {
- get { return paramsCollections; }
- set {
- if (paramsCollections != value)
- {
- paramsCollections = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool lockStatement = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp13_0)]
+ public partial bool ParamsCollections { get; set; }
///
/// Decompile lock statements.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DetectLockStatements")]
- public bool LockStatement {
- get { return lockStatement; }
- set {
- if (lockStatement != value)
- {
- lockStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool switchStatementOnString = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool LockStatement { get; set; }
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DetectSwitchOnString")]
- public bool SwitchStatementOnString {
- get { return switchStatementOnString; }
- set {
- if (switchStatementOnString != value)
- {
- switchStatementOnString = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool SwitchStatementOnString { get; set; }
- bool sparseIntegerSwitch = true;
-
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.SparseIntegerSwitch")]
- public bool SparseIntegerSwitch {
- get { return sparseIntegerSwitch; }
- set {
- if (sparseIntegerSwitch != value)
- {
- sparseIntegerSwitch = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool usingDeclarations = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool SparseIntegerSwitch { get; set; }
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.InsertUsingDeclarations")]
- public bool UsingDeclarations {
- get { return usingDeclarations; }
- set {
- if (usingDeclarations != value)
- {
- usingDeclarations = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool extensionMethods = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool UsingDeclarations { get; set; }
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.UseExtensionMethodSyntax")]
- public bool ExtensionMethods {
- get { return extensionMethods; }
- set {
- if (extensionMethods != value)
- {
- extensionMethods = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool ExtensionMethods { get; set; }
- bool queryExpressions = true;
-
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.UseLINQExpressionSyntax")]
- public bool QueryExpressions {
- get { return queryExpressions; }
- set {
- if (queryExpressions != value)
- {
- queryExpressions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useImplicitMethodGroupConversion = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool QueryExpressions { get; set; }
///
/// Gets/Sets whether to use C# 2.0 method group conversions.
/// true: EventHandler h = this.OnClick;
/// false: EventHandler h = new EventHandler(this.OnClick);
///
- [Category("C# 2.0 / VS 2005")]
[Description("DecompilerSettings.UseImplicitMethodGroupConversions")]
- public bool UseImplicitMethodGroupConversion {
- get { return useImplicitMethodGroupConversion; }
- set {
- if (useImplicitMethodGroupConversion != value)
- {
- useImplicitMethodGroupConversion = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useObjectCreationOfGenericTypeParameter = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp2)]
+ public partial bool UseImplicitMethodGroupConversion { get; set; }
///
/// Gets/Sets whether to use object creation expressions for generic types with new() constraint.
/// true: T t = new T();
/// false: T t = Activator.CreateInstance<T>()
///
- [Category("C# 2.0 / VS 2005")]
[Description("DecompilerSettings.UseObjectCreationOfGenericTypeParameter")]
- public bool UseObjectCreationOfGenericTypeParameter {
- get { return useObjectCreationOfGenericTypeParameter; }
- set {
- if (useObjectCreationOfGenericTypeParameter != value)
- {
- useObjectCreationOfGenericTypeParameter = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysCastTargetsOfExplicitInterfaceImplementationCalls = false;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp2)]
+ public partial bool UseObjectCreationOfGenericTypeParameter { get; set; }
///
/// Gets/Sets whether to always cast targets to explicitly implemented methods.
@@ -1041,20 +390,10 @@ namespace ICSharpCode.Decompiler
/// false: pictureBox1.BeginInit();
/// default: false
///
- [Category("Other")]
+ [Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls")]
- public bool AlwaysCastTargetsOfExplicitInterfaceImplementationCalls {
- get { return alwaysCastTargetsOfExplicitInterfaceImplementationCalls; }
- set {
- if (alwaysCastTargetsOfExplicitInterfaceImplementationCalls != value)
- {
- alwaysCastTargetsOfExplicitInterfaceImplementationCalls = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysQualifyMemberReferences = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { get; set; }
///
/// Gets/Sets whether to always qualify member references.
@@ -1062,20 +401,10 @@ namespace ICSharpCode.Decompiler
/// false: DoSomething();
/// default: false
///
- [Category("Other")]
+ [Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysQualifyMemberReferences")]
- public bool AlwaysQualifyMemberReferences {
- get { return alwaysQualifyMemberReferences; }
- set {
- if (alwaysQualifyMemberReferences != value)
- {
- alwaysQualifyMemberReferences = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysShowEnumMemberValues = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AlwaysQualifyMemberReferences { get; set; }
///
/// Gets/Sets whether to always show enum member values.
@@ -1083,113 +412,49 @@ namespace ICSharpCode.Decompiler
/// false: enum Kind { A, B, C = 5 }
/// default: false
///
- [Category("Other")]
+ [Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysShowEnumMemberValues")]
- public bool AlwaysShowEnumMemberValues {
- get { return alwaysShowEnumMemberValues; }
- set {
- if (alwaysShowEnumMemberValues != value)
- {
- alwaysShowEnumMemberValues = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useDebugSymbols = true;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AlwaysShowEnumMemberValues { get; set; }
///
/// Gets/Sets whether to use variable names from debug symbols, if available.
///
- [Category("Other")]
- [Description("DecompilerSettings.UseVariableNamesFromDebugSymbolsIfAvailable")]
- public bool UseDebugSymbols {
- get { return useDebugSymbols; }
- set {
- if (useDebugSymbols != value)
- {
- useDebugSymbols = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool arrayInitializers = true;
+ [Category("DecompilerSettings.Other")]
+ [Description("DecompilerSettings.UseVariableNamesFromDebugSymbolsIfAvailable")]
+ [DecompilerSetting]
+ public partial bool UseDebugSymbols { get; set; }
///
/// Gets/Sets whether to use array initializers.
/// If set to false, might produce non-compilable code.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.ArrayInitializerExpressions")]
- public bool ArrayInitializers {
- get { return arrayInitializers; }
- set {
- if (arrayInitializers != value)
- {
- arrayInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool objectCollectionInitializers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool ArrayInitializers { get; set; }
///
/// Gets/Sets whether to use C# 3.0 object/collection initializers.
///
- [Category("C# 3.0 / VS 2008")]
[Description("DecompilerSettings.ObjectCollectionInitializerExpressions")]
- public bool ObjectOrCollectionInitializers {
- get { return objectCollectionInitializers; }
- set {
- if (objectCollectionInitializers != value)
- {
- objectCollectionInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool dictionaryInitializers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp3)]
+ public partial bool ObjectOrCollectionInitializers { get; set; }
///
/// Gets/Sets whether to use C# 6.0 dictionary initializers.
/// Only has an effect if ObjectOrCollectionInitializers is enabled.
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.DictionaryInitializerExpressions")]
- public bool DictionaryInitializers {
- get { return dictionaryInitializers; }
- set {
- if (dictionaryInitializers != value)
- {
- dictionaryInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool extensionMethodsInCollectionInitializers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool DictionaryInitializers { get; set; }
///
/// Gets/Sets whether to use C# 6.0 Extension Add methods in collection initializers.
/// Only has an effect if ObjectOrCollectionInitializers is enabled.
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.AllowExtensionAddMethodsInCollectionInitializerExpressions")]
- public bool ExtensionMethodsInCollectionInitializers {
- get { return extensionMethodsInCollectionInitializers; }
- set {
- if (extensionMethodsInCollectionInitializers != value)
- {
- extensionMethodsInCollectionInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useRefLocalsForAccurateOrderOfEvaluation = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool ExtensionMethodsInCollectionInitializers { get; set; }
///
/// Gets/Sets whether to use local ref variables in cases where this is necessary
@@ -1198,744 +463,289 @@ namespace ICSharpCode.Decompiler
/// order of evaluation.
/// See https://github.com/icsharpcode/ILSpy/issues/2050
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseRefLocalsForAccurateOrderOfEvaluation")]
- public bool UseRefLocalsForAccurateOrderOfEvaluation {
- get { return useRefLocalsForAccurateOrderOfEvaluation; }
- set {
- if (useRefLocalsForAccurateOrderOfEvaluation != value)
- {
- useRefLocalsForAccurateOrderOfEvaluation = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool refExtensionMethods = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool UseRefLocalsForAccurateOrderOfEvaluation { get; set; }
///
/// Gets/Sets whether to use C# 7.2 'ref' extension methods.
///
- [Category("C# 7.2 / VS 2017.4")]
[Description("DecompilerSettings.AllowExtensionMethodSyntaxOnRef")]
- public bool RefExtensionMethods {
- get { return refExtensionMethods; }
- set {
- if (refExtensionMethods != value)
- {
- refExtensionMethods = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool stringInterpolation = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_2)]
+ public partial bool RefExtensionMethods { get; set; }
///
/// Gets/Sets whether to use C# 6.0 string interpolation
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.UseStringInterpolation")]
- public bool StringInterpolation {
- get { return stringInterpolation; }
- set {
- if (stringInterpolation != value)
- {
- stringInterpolation = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool utf8StringLiterals = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool StringInterpolation { get; set; }
///
/// Gets/Sets whether to use C# 11.0 UTF-8 string literals
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.Utf8StringLiterals")]
- public bool Utf8StringLiterals {
- get { return utf8StringLiterals; }
- set {
- if (utf8StringLiterals != value)
- {
- utf8StringLiterals = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool switchOnReadOnlySpanChar = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool Utf8StringLiterals { get; set; }
///
/// Gets/Sets whether to use C# 11.0 switch on (ReadOnly)Span<char>
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.SwitchOnReadOnlySpanChar")]
- public bool SwitchOnReadOnlySpanChar {
- get { return switchOnReadOnlySpanChar; }
- set {
- if (switchOnReadOnlySpanChar != value)
- {
- switchOnReadOnlySpanChar = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool unsignedRightShift = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool SwitchOnReadOnlySpanChar { get; set; }
///
/// Gets/Sets whether to use C# 11.0 unsigned right shift operator.
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.UnsignedRightShift")]
- public bool UnsignedRightShift {
- get { return unsignedRightShift; }
- set {
- if (unsignedRightShift != value)
- {
- unsignedRightShift = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool checkedOperators = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool UnsignedRightShift { get; set; }
///
/// Gets/Sets whether to use C# 11.0 user-defined checked operators.
///
- [Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.CheckedOperators")]
- public bool CheckedOperators {
- get { return checkedOperators; }
- set {
- if (checkedOperators != value)
- {
- checkedOperators = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool showXmlDocumentation = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp11_0)]
+ public partial bool CheckedOperators { get; set; }
///
/// Gets/Sets whether to include XML documentation comments in the decompiled code.
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.IncludeXMLDocumentationCommentsInTheDecompiledCode")]
- public bool ShowXmlDocumentation {
- get { return showXmlDocumentation; }
- set {
- if (showXmlDocumentation != value)
- {
- showXmlDocumentation = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool foldBraces = false;
+ [DecompilerSetting]
+ public partial bool ShowXmlDocumentation { get; set; }
[Browsable(false)]
- public bool FoldBraces {
- get { return foldBraces; }
- set {
- if (foldBraces != value)
- {
- foldBraces = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool expandXmlDocumentationComments = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool FoldBraces { get; set; }
[Browsable(false)]
- public bool ExpandXmlDocumentationComments {
- get { return expandXmlDocumentationComments; }
- set {
- if (expandXmlDocumentationComments != value)
- {
- expandXmlDocumentationComments = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool expandMemberDefinitions = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool ExpandXmlDocumentationComments { get; set; }
[Browsable(false)]
- public bool ExpandMemberDefinitions {
- get { return expandMemberDefinitions; }
- set {
- if (expandMemberDefinitions != value)
- {
- expandMemberDefinitions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool expandUsingDeclarations = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool ExpandMemberDefinitions { get; set; }
[Browsable(false)]
- public bool ExpandUsingDeclarations {
- get { return expandUsingDeclarations; }
- set {
- if (expandUsingDeclarations != value)
- {
- expandUsingDeclarations = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool decompileMemberBodies = true;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool ExpandUsingDeclarations { get; set; }
///
/// Gets/Sets whether member bodies should be decompiled.
///
[Category("DecompilerSettings.Other")]
[Browsable(false)]
- public bool DecompileMemberBodies {
- get { return decompileMemberBodies; }
- set {
- if (decompileMemberBodies != value)
- {
- decompileMemberBodies = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useExpressionBodyForCalculatedGetterOnlyProperties = true;
+ [DecompilerSetting]
+ public partial bool DecompileMemberBodies { get; set; }
///
/// Gets/Sets whether simple calculated getter-only property declarations
/// should use expression body syntax.
///
- [Category("C# 6.0 / VS 2015")]
[Description("DecompilerSettings.UseExpressionBodiedMemberSyntaxForGetOnlyProperties")]
- public bool UseExpressionBodyForCalculatedGetterOnlyProperties {
- get { return useExpressionBodyForCalculatedGetterOnlyProperties; }
- set {
- if (useExpressionBodyForCalculatedGetterOnlyProperties != value)
- {
- useExpressionBodyForCalculatedGetterOnlyProperties = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool outVariables = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp6)]
+ public partial bool UseExpressionBodyForCalculatedGetterOnlyProperties { get; set; }
///
/// Gets/Sets whether out variable declarations should be used when possible.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseOutVariableDeclarations")]
- public bool OutVariables {
- get { return outVariables; }
- set {
- if (outVariables != value)
- {
- outVariables = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool discards = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool OutVariables { get; set; }
///
/// Gets/Sets whether discards should be used when possible.
/// Only has an effect if is enabled.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseDiscards")]
- public bool Discards {
- get { return discards; }
- set {
- if (discards != value)
- {
- discards = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool introduceRefModifiersOnStructs = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool Discards { get; set; }
///
/// Gets/Sets whether IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs.
///
- [Category("C# 7.2 / VS 2017.4")]
[Description("DecompilerSettings.IsByRefLikeAttributeShouldBeReplacedWithRefModifiersOnStructs")]
- public bool IntroduceRefModifiersOnStructs {
- get { return introduceRefModifiersOnStructs; }
- set {
- if (introduceRefModifiersOnStructs != value)
- {
- introduceRefModifiersOnStructs = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool introduceReadonlyAndInModifiers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_2)]
+ public partial bool IntroduceRefModifiersOnStructs { get; set; }
///
/// Gets/Sets whether IsReadOnlyAttribute should be replaced with 'readonly' modifiers on structs
/// and with the 'in' modifier on parameters.
///
- [Category("C# 7.2 / VS 2017.4")]
[Description("DecompilerSettings." +
"IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters")]
- public bool IntroduceReadonlyAndInModifiers {
- get { return introduceReadonlyAndInModifiers; }
- set {
- if (introduceReadonlyAndInModifiers != value)
- {
- introduceReadonlyAndInModifiers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool introducePrivateProtectedAccessibilty = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_2)]
+ public partial bool IntroduceReadonlyAndInModifiers { get; set; }
///
/// Gets/Sets whether "private protected" should be used.
///
- [Category("C# 7.2 / VS 2017.4")]
[Description("DecompilerSettings.IntroducePrivateProtectedAccessibility")]
- public bool IntroducePrivateProtectedAccessibility {
- get { return introducePrivateProtectedAccessibilty; }
- set {
- if (introducePrivateProtectedAccessibilty != value)
- {
- introducePrivateProtectedAccessibilty = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_2)]
+ public partial bool IntroducePrivateProtectedAccessibility { get; set; }
- bool readOnlyMethods = true;
-
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.ReadOnlyMethods")]
- public bool ReadOnlyMethods {
- get { return readOnlyMethods; }
- set {
- if (readOnlyMethods != value)
- {
- readOnlyMethods = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool asyncUsingAndForEachStatement = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool ReadOnlyMethods { get; set; }
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.DetectAsyncUsingAndForeachStatements")]
- public bool AsyncUsingAndForEachStatement {
- get { return asyncUsingAndForEachStatement; }
- set {
- if (asyncUsingAndForEachStatement != value)
- {
- asyncUsingAndForEachStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool introduceUnmanagedConstraint = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool AsyncUsingAndForEachStatement { get; set; }
///
/// If this option is active, [IsUnmanagedAttribute] on type parameters
/// is replaced with "T : unmanaged" constraints.
///
- [Category("C# 7.3 / VS 2017.7")]
[Description("DecompilerSettings." +
"IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints")]
- public bool IntroduceUnmanagedConstraint {
- get { return introduceUnmanagedConstraint; }
- set {
- if (introduceUnmanagedConstraint != value)
- {
- introduceUnmanagedConstraint = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool stackAllocInitializers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_3)]
+ public partial bool IntroduceUnmanagedConstraint { get; set; }
///
/// Gets/Sets whether C# 7.3 stackalloc initializers should be used.
///
- [Category("C# 7.3 / VS 2017.7")]
[Description("DecompilerSettings.UseStackallocInitializerSyntax")]
- public bool StackAllocInitializers {
- get { return stackAllocInitializers; }
- set {
- if (stackAllocInitializers != value)
- {
- stackAllocInitializers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool patternBasedFixedStatement = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_3)]
+ public partial bool StackAllocInitializers { get; set; }
///
/// Gets/Sets whether C# 7.3 pattern based fixed statement should be used.
///
- [Category("C# 7.3 / VS 2017.7")]
[Description("DecompilerSettings.UsePatternBasedFixedStatement")]
- public bool PatternBasedFixedStatement {
- get { return patternBasedFixedStatement; }
- set {
- if (patternBasedFixedStatement != value)
- {
- patternBasedFixedStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool tupleTypes = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_3)]
+ public partial bool PatternBasedFixedStatement { get; set; }
///
/// Gets/Sets whether tuple type syntax (int, string)
/// should be used for System.ValueTuple.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseTupleTypeSyntax")]
- public bool TupleTypes {
- get { return tupleTypes; }
- set {
- if (tupleTypes != value)
- {
- tupleTypes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool throwExpressions = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool TupleTypes { get; set; }
///
/// Gets/Sets whether throw expressions should be used.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseThrowExpressions")]
- public bool ThrowExpressions {
- get { return throwExpressions; }
- set {
- if (throwExpressions != value)
- {
- throwExpressions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool tupleConversions = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool ThrowExpressions { get; set; }
///
/// Gets/Sets whether implicit conversions between tuples
/// should be used in the decompiled output.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.UseImplicitConversionsBetweenTupleTypes")]
- public bool TupleConversions {
- get { return tupleConversions; }
- set {
- if (tupleConversions != value)
- {
- tupleConversions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool tupleComparisons = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool TupleConversions { get; set; }
///
/// Gets/Sets whether tuple comparisons should be detected.
///
- [Category("C# 7.3 / VS 2017.7")]
[Description("DecompilerSettings.DetectTupleComparisons")]
- public bool TupleComparisons {
- get { return tupleComparisons; }
- set {
- if (tupleComparisons != value)
- {
- tupleComparisons = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool namedArguments = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_3)]
+ public partial bool TupleComparisons { get; set; }
///
/// Gets/Sets whether named arguments should be used.
///
- [Category("C# 4.0 / VS 2010")]
[Description("DecompilerSettings.UseNamedArguments")]
- public bool NamedArguments {
- get { return namedArguments; }
- set {
- if (namedArguments != value)
- {
- namedArguments = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool nonTrailingNamedArguments = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp4)]
+ public partial bool NamedArguments { get; set; }
///
/// Gets/Sets whether C# 7.2 non-trailing named arguments should be used.
///
- [Category("C# 7.2 / VS 2017.4")]
[Description("DecompilerSettings.UseNonTrailingNamedArguments")]
- public bool NonTrailingNamedArguments {
- get { return nonTrailingNamedArguments; }
- set {
- if (nonTrailingNamedArguments != value)
- {
- nonTrailingNamedArguments = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool optionalArguments = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7_2)]
+ public partial bool NonTrailingNamedArguments { get; set; }
///
/// Gets/Sets whether optional arguments should be removed, if possible.
///
- [Category("C# 4.0 / VS 2010")]
[Description("DecompilerSettings.RemoveOptionalArgumentsIfPossible")]
- public bool OptionalArguments {
- get { return optionalArguments; }
- set {
- if (optionalArguments != value)
- {
- optionalArguments = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool expandParamsArguments = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp4)]
+ public partial bool OptionalArguments { get; set; }
///
/// Gets/Sets whether to expand params arguments by replacing explicit array creation
/// with individual values in method calls.
- ///
- [Category("C# 1.0 / VS .NET")]
- [Description("DecompilerSettings.ExpandParamsArguments")]
- public bool ExpandParamsArguments {
- get { return expandParamsArguments; }
- set {
- if (expandParamsArguments != value)
- {
- expandParamsArguments = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool localFunctions = true;
+ ///
+ [Description("DecompilerSettings.ExpandParamsArguments")]
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool ExpandParamsArguments { get; set; }
///
/// Gets/Sets whether C# 7.0 local functions should be transformed.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.IntroduceLocalFunctions")]
- public bool LocalFunctions {
- get { return localFunctions; }
- set {
- if (localFunctions != value)
- {
- localFunctions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool deconstruction = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool LocalFunctions { get; set; }
///
/// Gets/Sets whether C# 7.0 deconstruction should be detected.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.Deconstruction")]
- public bool Deconstruction {
- get { return deconstruction; }
- set {
- if (deconstruction != value)
- {
- deconstruction = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool patternMatching = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool Deconstruction { get; set; }
///
/// Gets/Sets whether C# 7.0 pattern matching should be detected.
///
- [Category("C# 7.0 / VS 2017")]
[Description("DecompilerSettings.PatternMatching")]
- public bool PatternMatching {
- get { return patternMatching; }
- set {
- if (patternMatching != value)
- {
- patternMatching = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool recursivePatternMatching = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp7)]
+ public partial bool PatternMatching { get; set; }
///
/// Gets/Sets whether C# 8.0 recursive patterns should be detected.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.RecursivePatternMatching")]
- public bool RecursivePatternMatching {
- get { return recursivePatternMatching; }
- set {
- if (recursivePatternMatching != value)
- {
- recursivePatternMatching = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool patternCombinators = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool RecursivePatternMatching { get; set; }
///
/// Gets/Sets whether C# 9.0 and, or, not patterns should be detected.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.PatternCombinators")]
- public bool PatternCombinators {
- get { return patternCombinators; }
- set {
- if (patternCombinators != value)
- {
- patternCombinators = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool relationalPatterns = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool PatternCombinators { get; set; }
///
/// Gets/Sets whether C# 9.0 relational patterns should be detected.
///
- [Category("C# 9.0 / VS 2019.8")]
[Description("DecompilerSettings.RelationalPatterns")]
- public bool RelationalPatterns {
- get { return relationalPatterns; }
- set {
- if (relationalPatterns != value)
- {
- relationalPatterns = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool staticLocalFunctions = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp9_0)]
+ public partial bool RelationalPatterns { get; set; }
///
/// Gets/Sets whether C# 8.0 static local functions should be transformed.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.IntroduceStaticLocalFunctions")]
- public bool StaticLocalFunctions {
- get { return staticLocalFunctions; }
- set {
- if (staticLocalFunctions != value)
- {
- staticLocalFunctions = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool ranges = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool StaticLocalFunctions { get; set; }
///
/// Gets/Sets whether C# 8.0 index and range syntax should be used.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.Ranges")]
- public bool Ranges {
- get { return ranges; }
- set {
- if (ranges != value)
- {
- ranges = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool nullableReferenceTypes = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool Ranges { get; set; }
///
/// Gets/Sets whether C# 8.0 nullable reference types are enabled.
///
- [Category("C# 8.0 / VS 2019")]
[Description("DecompilerSettings.NullableReferenceTypes")]
- public bool NullableReferenceTypes {
- get { return nullableReferenceTypes; }
- set {
- if (nullableReferenceTypes != value)
- {
- nullableReferenceTypes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool showDebugInfo;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp8_0)]
+ public partial bool NullableReferenceTypes { get; set; }
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.ShowInfoFromDebugSymbolsIfAvailable")]
[Browsable(false)]
- public bool ShowDebugInfo {
- get { return showDebugInfo; }
- set {
- if (showDebugInfo != value)
- {
- showDebugInfo = value;
- OnPropertyChanged();
- }
- }
- }
-
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool ShowDebugInfo { get; set; }
#region Options to aid VB decompilation
- bool assumeArrayLengthFitsIntoInt32 = true;
///
/// Gets/Sets whether the decompiler can assume that 'ldlen; conv.i4.ovf'
@@ -1943,276 +753,106 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.VBSpecificOptions")]
[Browsable(false)]
- public bool AssumeArrayLengthFitsIntoInt32 {
- get { return assumeArrayLengthFitsIntoInt32; }
- set {
- if (assumeArrayLengthFitsIntoInt32 != value)
- {
- assumeArrayLengthFitsIntoInt32 = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool introduceIncrementAndDecrement = true;
+ [DecompilerSetting]
+ public partial bool AssumeArrayLengthFitsIntoInt32 { get; set; }
///
/// Gets/Sets whether to use increment and decrement operators
///
[Category("DecompilerSettings.VBSpecificOptions")]
[Browsable(false)]
- public bool IntroduceIncrementAndDecrement {
- get { return introduceIncrementAndDecrement; }
- set {
- if (introduceIncrementAndDecrement != value)
- {
- introduceIncrementAndDecrement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool makeAssignmentExpressions = true;
+ [DecompilerSetting]
+ public partial bool IntroduceIncrementAndDecrement { get; set; }
///
/// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
///
[Category("DecompilerSettings.VBSpecificOptions")]
[Browsable(false)]
- public bool MakeAssignmentExpressions {
- get { return makeAssignmentExpressions; }
- set {
- if (makeAssignmentExpressions != value)
- {
- makeAssignmentExpressions = value;
- OnPropertyChanged();
- }
- }
- }
-
+ [DecompilerSetting]
+ public partial bool MakeAssignmentExpressions { get; set; }
#endregion
-
#region Options to aid F# decompilation
- bool removeDeadCode = false;
[Category("DecompilerSettings.FSpecificOptions")]
[Description("DecompilerSettings.RemoveDeadAndSideEffectFreeCodeUseWithCaution")]
- public bool RemoveDeadCode {
- get { return removeDeadCode; }
- set {
- if (removeDeadCode != value)
- {
- removeDeadCode = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool removeDeadStores = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool RemoveDeadCode { get; set; }
[Category("DecompilerSettings.FSpecificOptions")]
[Description("DecompilerSettings.RemoveDeadStores")]
- public bool RemoveDeadStores {
- get { return removeDeadStores; }
- set {
- if (removeDeadStores != value)
- {
- removeDeadStores = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool RemoveDeadStores { get; set; }
#endregion
-
#region Assembly Load and Resolve options
- bool loadInMemory = false;
-
[Browsable(false)]
- public bool LoadInMemory {
- get { return loadInMemory; }
- set {
- if (loadInMemory != value)
- {
- loadInMemory = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool throwOnAssemblyResolveErrors = true;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool LoadInMemory { get; set; }
[Browsable(false)]
- public bool ThrowOnAssemblyResolveErrors {
- get { return throwOnAssemblyResolveErrors; }
- set {
- if (throwOnAssemblyResolveErrors != value)
- {
- throwOnAssemblyResolveErrors = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool applyWindowsRuntimeProjections = true;
+ [DecompilerSetting]
+ public partial bool ThrowOnAssemblyResolveErrors { get; set; }
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.ApplyWindowsRuntimeProjectionsOnLoadedAssemblies")]
- public bool ApplyWindowsRuntimeProjections {
- get { return applyWindowsRuntimeProjections; }
- set {
- if (applyWindowsRuntimeProjections != value)
- {
- applyWindowsRuntimeProjections = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool autoLoadAssemblyReferences = true;
+ [DecompilerSetting]
+ public partial bool ApplyWindowsRuntimeProjections { get; set; }
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AutoLoadAssemblyReferences")]
- public bool AutoLoadAssemblyReferences {
- get { return autoLoadAssemblyReferences; }
- set {
- if (autoLoadAssemblyReferences != value)
- {
- autoLoadAssemblyReferences = value;
- OnPropertyChanged();
- }
- }
- }
-
+ [DecompilerSetting]
+ public partial bool AutoLoadAssemblyReferences { get; set; }
#endregion
- bool forStatement = true;
-
///
/// Gets/sets whether the decompiler should produce for loops.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.ForStatement")]
- public bool ForStatement {
- get { return forStatement; }
- set {
- if (forStatement != value)
- {
- forStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool doWhileStatement = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool ForStatement { get; set; }
///
/// Gets/sets whether the decompiler should produce do-while loops.
///
- [Category("C# 1.0 / VS .NET")]
[Description("DecompilerSettings.DoWhileStatement")]
- public bool DoWhileStatement {
- get { return doWhileStatement; }
- set {
- if (doWhileStatement != value)
- {
- doWhileStatement = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool refReadOnlyParameters = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp1)]
+ public partial bool DoWhileStatement { get; set; }
///
/// Gets/sets whether RequiresLocationAttribute on parameters should be replaced with 'ref readonly' modifiers.
///
- [Category("C# 12.0 / VS 2022.8")]
[Description("DecompilerSettings.RefReadOnlyParameters")]
- public bool RefReadOnlyParameters {
- get { return refReadOnlyParameters; }
- set {
- if (refReadOnlyParameters != value)
- {
- refReadOnlyParameters = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool usePrimaryConstructorSyntaxForNonRecordTypes = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp12_0)]
+ public partial bool RefReadOnlyParameters { get; set; }
///
/// Use primary constructor syntax with classes and structs.
///
- [Category("C# 12.0 / VS 2022.8")]
[Description("DecompilerSettings.UsePrimaryConstructorSyntaxForNonRecordTypes")]
- public bool UsePrimaryConstructorSyntaxForNonRecordTypes {
- get { return usePrimaryConstructorSyntaxForNonRecordTypes; }
- set {
- if (usePrimaryConstructorSyntaxForNonRecordTypes != value)
- {
- usePrimaryConstructorSyntaxForNonRecordTypes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool inlineArrays = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp12_0)]
+ public partial bool UsePrimaryConstructorSyntaxForNonRecordTypes { get; set; }
///
/// Gets/Sets whether C# 12.0 inline array uses should be transformed.
///
- [Category("C# 12.0 / VS 2022.8")]
[Description("DecompilerSettings.InlineArrays")]
- public bool InlineArrays {
- get { return inlineArrays; }
- set {
- if (inlineArrays != value)
- {
- inlineArrays = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool extensionMembers = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp12_0)]
+ public partial bool InlineArrays { get; set; }
///
/// Gets/Sets whether C# 14.0 extension members should be transformed.
///
- [Category("C# 14.0 / VS 2026")]
[Description("DecompilerSettings.ExtensionMembers")]
- public bool ExtensionMembers {
- get { return extensionMembers; }
- set {
- if (extensionMembers != value)
- {
- extensionMembers = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool firstClassSpanTypes = true;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp14_0)]
+ public partial bool ExtensionMembers { get; set; }
///
/// Gets/Sets whether (ReadOnly)Span<T> should be treated like built-in types.
///
- [Category("C# 14.0 / VS 2026")]
[Description("DecompilerSettings.FirstClassSpanTypes")]
- public bool FirstClassSpanTypes {
- get { return firstClassSpanTypes; }
- set {
- if (firstClassSpanTypes != value)
- {
- firstClassSpanTypes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool separateLocalVariableDeclarations = false;
+ [DecompilerSetting(CSharp.LanguageVersion.CSharp14_0)]
+ public partial bool FirstClassSpanTypes { get; set; }
///
/// Gets/sets whether the decompiler should separate local variable declarations
@@ -2220,18 +860,8 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.SeparateLocalVariableDeclarations")]
- public bool SeparateLocalVariableDeclarations {
- get { return separateLocalVariableDeclarations; }
- set {
- if (separateLocalVariableDeclarations != value)
- {
- separateLocalVariableDeclarations = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useSdkStyleProjectFormat = true;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool SeparateLocalVariableDeclarations { get; set; }
///
/// Gets or sets a value indicating whether the new SDK style format
@@ -2239,18 +869,8 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.ProjectExport")]
[Description("DecompilerSettings.UseSdkStyleProjectFormat")]
- public bool UseSdkStyleProjectFormat {
- get { return useSdkStyleProjectFormat; }
- set {
- if (useSdkStyleProjectFormat != value)
- {
- useSdkStyleProjectFormat = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool useNestedDirectoriesForNamespaces;
+ [DecompilerSetting]
+ public partial bool UseSdkStyleProjectFormat { get; set; }
///
/// Gets/sets whether namespaces and namespace-like identifiers should be split at '.'
@@ -2258,18 +878,8 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.ProjectExport")]
[Description("DecompilerSettings.UseNestedDirectoriesForNamespaces")]
- public bool UseNestedDirectoriesForNamespaces {
- get { return useNestedDirectoriesForNamespaces; }
- set {
- if (useNestedDirectoriesForNamespaces != value)
- {
- useNestedDirectoriesForNamespaces = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool aggressiveScalarReplacementOfAggregates = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool UseNestedDirectoriesForNamespaces { get; set; }
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AggressiveScalarReplacementOfAggregates")]
@@ -2277,18 +887,8 @@ namespace ICSharpCode.Decompiler
#if !DEBUG
[Browsable(false)]
#endif
- public bool AggressiveScalarReplacementOfAggregates {
- get { return aggressiveScalarReplacementOfAggregates; }
- set {
- if (aggressiveScalarReplacementOfAggregates != value)
- {
- aggressiveScalarReplacementOfAggregates = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool aggressiveInlining = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AggressiveScalarReplacementOfAggregates { get; set; }
///
/// If set to false (the default), the decompiler will inline local variables only when they occur
@@ -2297,36 +897,16 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AggressiveInlining")]
- public bool AggressiveInlining {
- get { return aggressiveInlining; }
- set {
- if (aggressiveInlining != value)
- {
- aggressiveInlining = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysUseGlobal = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AggressiveInlining { get; set; }
///
/// Always fully qualify namespaces using the "global::" prefix.
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysUseGlobal")]
- public bool AlwaysUseGlobal {
- get { return alwaysUseGlobal; }
- set {
- if (alwaysUseGlobal != value)
- {
- alwaysUseGlobal = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool alwaysMoveInitializer = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AlwaysUseGlobal { get; set; }
///
/// If set to false (the default), the decompiler will move field initializers at the start of constructors
@@ -2336,36 +916,16 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.AlwaysMoveInitializer")]
- public bool AlwaysMoveInitializer {
- get { return alwaysMoveInitializer; }
- set {
- if (alwaysMoveInitializer != value)
- {
- alwaysMoveInitializer = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool sortCustomAttributes = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool AlwaysMoveInitializer { get; set; }
///
/// Sort custom attributes.
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.SortCustomAttributes")]
- public bool SortCustomAttributes {
- get { return sortCustomAttributes; }
- set {
- if (sortCustomAttributes != value)
- {
- sortCustomAttributes = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool sortSwitchSections = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool SortCustomAttributes { get; set; }
///
/// Sort switch sections by their label value instead of by IL offset.
@@ -2374,34 +934,16 @@ namespace ICSharpCode.Decompiler
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.SortSwitchSections")]
- public bool SortSwitchSections {
- get { return sortSwitchSections; }
- set {
- if (sortSwitchSections != value)
- {
- sortSwitchSections = value;
- OnPropertyChanged();
- }
- }
- }
-
- bool checkForOverflowUnderflow = false;
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool SortSwitchSections { get; set; }
///
/// Check for overflow and underflow in operators.
///
[Category("DecompilerSettings.Other")]
[Description("DecompilerSettings.CheckForOverflowUnderflow")]
- public bool CheckForOverflowUnderflow {
- get { return checkForOverflowUnderflow; }
- set {
- if (checkForOverflowUnderflow != value)
- {
- checkForOverflowUnderflow = value;
- OnPropertyChanged();
- }
- }
- }
+ [DecompilerSetting(DefaultValue = false)]
+ public partial bool CheckForOverflowUnderflow { get; set; }
CSharpFormattingOptions csharpFormattingOptions;