Browse Source

Merge pull request #1471 from icsharpcode/decompiler-options-rework

Rework C# decompiler options dialog.
pull/1505/head
Siegfried Pammer 6 years ago committed by GitHub
parent
commit
b31d922a82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 137
      ICSharpCode.Decompiler/DecompilerSettings.cs
  2. 1
      ICSharpCode.Decompiler/Output/ITextOutput.cs
  3. 15
      ICSharpCode.Decompiler/Output/PlainTextOutput.cs
  4. 13
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  5. 33
      ILSpy/DecompilationOptions.cs
  6. 8
      ILSpy/ILSpy.csproj
  7. 2
      ILSpy/Languages/CSharpILMixedLanguage.cs
  8. 3
      ILSpy/Languages/CSharpLanguage.cs
  9. 1
      ILSpy/Languages/ILLanguage.cs
  10. 67
      ILSpy/Options/DecompilerSettingsPanel.xaml
  11. 232
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs
  12. 65
      ILSpy/Options/DisplaySettings.cs
  13. 18
      ILSpy/Options/DisplaySettingsPanel.xaml
  14. 35
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  15. 2
      ILSpy/Options/MiscSettingsPanel.xaml.cs
  16. 2
      ILSpy/Options/OptionsDialog.xaml

137
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -40,9 +40,18 @@ namespace ICSharpCode.Decompiler @@ -40,9 +40,18 @@ namespace ICSharpCode.Decompiler
/// appropriate for the specified language version.
/// </summary>
/// <remarks>
/// This does not imply that the resulting
/// 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.
/// </remarks>
public DecompilerSettings(CSharp.LanguageVersion languageVersion)
{
SetLanguageVersion(languageVersion);
}
/// <summary>
/// Deactivates all language features from versions newer than <paramref name="languageVersion"/>.
/// </summary>
public void SetLanguageVersion(CSharp.LanguageVersion languageVersion)
{
// By default, all decompiler features are enabled.
// Disable some of them based on language version:
@ -129,6 +138,8 @@ namespace ICSharpCode.Decompiler @@ -129,6 +138,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile anonymous methods/lambdas.
/// </summary>
[Category("C# 2.0 / VS 2005")]
[Description("Decompile anonymous methods/lambdas")]
public bool AnonymousMethods {
get { return anonymousMethods; }
set {
@ -144,6 +155,8 @@ namespace ICSharpCode.Decompiler @@ -144,6 +155,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile anonymous types.
/// </summary>
[Category("C# 3.0 / VS 2008")]
[Description("Decompile anonymous types")]
public bool AnonymousTypes {
get { return anonymousTypes; }
set {
@ -159,6 +172,8 @@ namespace ICSharpCode.Decompiler @@ -159,6 +172,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Use C# 3 lambda syntax if possible.
/// </summary>
[Category("C# 3.0 / VS 2008")]
[Description("Use lambda syntax, if possible")]
public bool UseLambdaSyntax {
get { return useLambdaSyntax; }
set {
@ -174,6 +189,8 @@ namespace ICSharpCode.Decompiler @@ -174,6 +189,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile expression trees.
/// </summary>
[Category("C# 3.0 / VS 2008")]
[Description("Decompile expression trees")]
public bool ExpressionTrees {
get { return expressionTrees; }
set {
@ -189,6 +206,8 @@ namespace ICSharpCode.Decompiler @@ -189,6 +206,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile enumerators.
/// </summary>
[Category("C# 2.0 / VS 2005")]
[Description("Decompile enumerators (yield return)")]
public bool YieldReturn {
get { return yieldReturn; }
set {
@ -204,6 +223,8 @@ namespace ICSharpCode.Decompiler @@ -204,6 +223,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile use of the 'dynamic' type.
/// </summary>
[Category("C# 4.0 / VS 2010")]
[Description("Decompile use of the 'dynamic' type")]
public bool Dynamic {
get { return dynamic; }
set {
@ -219,6 +240,8 @@ namespace ICSharpCode.Decompiler @@ -219,6 +240,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile async methods.
/// </summary>
[Category("C# 5.0 / VS 2012")]
[Description("Decompile async methods")]
public bool AsyncAwait {
get { return asyncAwait; }
set {
@ -235,6 +258,8 @@ namespace ICSharpCode.Decompiler @@ -235,6 +258,8 @@ namespace ICSharpCode.Decompiler
/// Decompile await in catch/finally blocks.
/// Only has an effect if <see cref="AsyncAwait"/> is enabled.
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Decompile await in catch/finally blocks")]
public bool AwaitInCatchFinally {
get { return awaitInCatchFinally; }
set {
@ -250,6 +275,8 @@ namespace ICSharpCode.Decompiler @@ -250,6 +275,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile [DecimalConstant(...)] as simple literal values.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Decompile [DecimalConstant(...)] as simple literal values")]
public bool DecimalConstants {
get { return decimalConstants; }
set {
@ -265,6 +292,8 @@ namespace ICSharpCode.Decompiler @@ -265,6 +292,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile C# 1.0 'public unsafe fixed int arr[10];' members.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Decompile C# 1.0 'public unsafe fixed int arr[10];' members")]
public bool FixedBuffers {
get { return fixedBuffers; }
set {
@ -280,6 +309,8 @@ namespace ICSharpCode.Decompiler @@ -280,6 +309,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Use lifted operators for nullables.
/// </summary>
[Category("C# 2.0 / VS 2005")]
[Description("Use lifted operators for nullables")]
public bool LiftNullables {
get { return liftNullables; }
set {
@ -295,6 +326,8 @@ namespace ICSharpCode.Decompiler @@ -295,6 +326,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile C# 6 ?. and ?[] operators.
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Decompile ?. and ?[] operators")]
public bool NullPropagation {
get { return nullPropagation; }
set {
@ -310,6 +343,8 @@ namespace ICSharpCode.Decompiler @@ -310,6 +343,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile automatic properties
/// </summary>
[Category("C# 3.0 / VS 2008")]
[Description("Decompile automatic properties")]
public bool AutomaticProperties {
get { return automaticProperties; }
set {
@ -325,6 +360,8 @@ namespace ICSharpCode.Decompiler @@ -325,6 +360,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile automatic events
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Decompile automatic events")]
public bool AutomaticEvents {
get { return automaticEvents; }
set {
@ -340,6 +377,8 @@ namespace ICSharpCode.Decompiler @@ -340,6 +377,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile using statements.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Detect using statements")]
public bool UsingStatement {
get { return usingStatement; }
set {
@ -355,6 +394,8 @@ namespace ICSharpCode.Decompiler @@ -355,6 +394,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use braces for single-statement-blocks.
/// </summary>
[Category("Other")]
[Description("Always use braces")]
public bool AlwaysUseBraces {
get { return alwaysUseBraces; }
set {
@ -370,6 +411,8 @@ namespace ICSharpCode.Decompiler @@ -370,6 +411,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile foreach statements.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Detect foreach statements")]
public bool ForEachStatement {
get { return forEachStatement; }
set {
@ -385,6 +428,8 @@ namespace ICSharpCode.Decompiler @@ -385,6 +428,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Decompile lock statements.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Detect lock statements")]
public bool LockStatement {
get { return lockStatement; }
set {
@ -397,6 +442,8 @@ namespace ICSharpCode.Decompiler @@ -397,6 +442,8 @@ namespace ICSharpCode.Decompiler
bool switchStatementOnString = true;
[Category("C# 1.0 / VS .NET")]
[Description("Detect switch on string")]
public bool SwitchStatementOnString {
get { return switchStatementOnString; }
set {
@ -409,6 +456,8 @@ namespace ICSharpCode.Decompiler @@ -409,6 +456,8 @@ namespace ICSharpCode.Decompiler
bool usingDeclarations = true;
[Category("C# 1.0 / VS .NET")]
[Description("Insert using declarations")]
public bool UsingDeclarations {
get { return usingDeclarations; }
set {
@ -421,6 +470,8 @@ namespace ICSharpCode.Decompiler @@ -421,6 +470,8 @@ namespace ICSharpCode.Decompiler
bool extensionMethods = true;
[Category("C# 3.0 / VS 2008")]
[Description("Use extension method syntax")]
public bool ExtensionMethods {
get { return extensionMethods; }
set {
@ -433,6 +484,8 @@ namespace ICSharpCode.Decompiler @@ -433,6 +484,8 @@ namespace ICSharpCode.Decompiler
bool queryExpressions = true;
[Category("C# 3.0 / VS 2008")]
[Description("Use LINQ expression syntax")]
public bool QueryExpressions {
get { return queryExpressions; }
set {
@ -450,6 +503,8 @@ namespace ICSharpCode.Decompiler @@ -450,6 +503,8 @@ namespace ICSharpCode.Decompiler
/// true: <c>EventHandler h = this.OnClick;</c>
/// false: <c>EventHandler h = new EventHandler(this.OnClick);</c>
/// </summary>
[Category("C# 2.0 / VS 2005")]
[Description("Use implicit method group conversions")]
public bool UseImplicitMethodGroupConversion {
get { return useImplicitMethodGroupConversion; }
set {
@ -468,6 +523,8 @@ namespace ICSharpCode.Decompiler @@ -468,6 +523,8 @@ namespace ICSharpCode.Decompiler
/// false: <c>pictureBox1.BeginInit();</c>
/// default: false
/// </summary>
[Category("Other")]
[Description("Always cast targets of explicit interface implementation calls")]
public bool AlwaysCastTargetsOfExplicitInterfaceImplementationCalls {
get { return alwaysCastTargetsOfExplicitInterfaceImplementationCalls; }
set {
@ -483,6 +540,8 @@ namespace ICSharpCode.Decompiler @@ -483,6 +540,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use variable names from debug symbols, if available.
/// </summary>
[Category("Other")]
[Description("Use variable names from debug symbols, if available")]
public bool UseDebugSymbols {
get { return useDebugSymbols; }
set {
@ -499,6 +558,8 @@ namespace ICSharpCode.Decompiler @@ -499,6 +558,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether to use array initializers.
/// If set to false, might produce non-compilable code.
/// </summary>
[Category("C# 1.0 / VS .NET")]
[Description("Array initializer expressions")]
public bool ArrayInitializers
{
get { return arrayInitializers; }
@ -517,6 +578,8 @@ namespace ICSharpCode.Decompiler @@ -517,6 +578,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use C# 3.0 object/collection initializers.
/// </summary>
[Category("C# 3.0 / VS 2008")]
[Description("Object/collection initializer expressions")]
public bool ObjectOrCollectionInitializers {
get { return objectCollectionInitializers; }
set {
@ -533,6 +596,8 @@ namespace ICSharpCode.Decompiler @@ -533,6 +596,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether to use C# 6.0 dictionary initializers.
/// Only has an effect if ObjectOrCollectionInitializers is enabled.
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Dictionary initializer expressions")]
public bool DictionaryInitializers {
get { return dictionaryInitializers; }
set {
@ -549,6 +614,8 @@ namespace ICSharpCode.Decompiler @@ -549,6 +614,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether to use C# 6.0 Extension Add methods in collection initializers.
/// Only has an effect if ObjectOrCollectionInitializers is enabled.
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Allow extension 'Add' methods in collection initializer expressions")]
public bool ExtensionMethodsInCollectionInitializers {
get { return extensionMethodsInCollectionInitializers; }
set {
@ -564,6 +631,8 @@ namespace ICSharpCode.Decompiler @@ -564,6 +631,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use C# 6.0 string interpolation
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Use string interpolation")]
public bool StringInterpolation {
get { return stringInterpolation; }
set {
@ -579,6 +648,8 @@ namespace ICSharpCode.Decompiler @@ -579,6 +648,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to include XML documentation comments in the decompiled code.
/// </summary>
[Category("Other")]
[Description("Include XML documentation comments in the decompiled code")]
public bool ShowXmlDocumentation {
get { return showXmlDocumentation; }
set {
@ -591,6 +662,7 @@ namespace ICSharpCode.Decompiler @@ -591,6 +662,7 @@ namespace ICSharpCode.Decompiler
bool foldBraces = false;
[Browsable(false)]
public bool FoldBraces {
get { return foldBraces; }
set {
@ -603,6 +675,7 @@ namespace ICSharpCode.Decompiler @@ -603,6 +675,7 @@ namespace ICSharpCode.Decompiler
bool expandMemberDefinitions = false;
[Browsable(false)]
public bool ExpandMemberDefinitions {
get { return expandMemberDefinitions; }
set {
@ -613,11 +686,26 @@ namespace ICSharpCode.Decompiler @@ -613,11 +686,26 @@ namespace ICSharpCode.Decompiler
}
}
bool expandUsingDeclarations = false;
[Browsable(false)]
public bool ExpandUsingDeclarations {
get { return expandUsingDeclarations; }
set {
if (expandUsingDeclarations != value) {
expandUsingDeclarations = value;
OnPropertyChanged();
}
}
}
bool decompileMemberBodies = true;
/// <summary>
/// Gets/Sets whether member bodies should be decompiled.
/// </summary>
[Category("Other")]
[Browsable(false)]
public bool DecompileMemberBodies {
get { return decompileMemberBodies; }
set {
@ -633,6 +721,8 @@ namespace ICSharpCode.Decompiler @@ -633,6 +721,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether simple calculated getter-only property declarations should use expression body syntax.
/// </summary>
[Category("C# 6.0 / VS 2015")]
[Description("Use expression-bodied member syntax for get-only properties")]
public bool UseExpressionBodyForCalculatedGetterOnlyProperties {
get { return useExpressionBodyForCalculatedGetterOnlyProperties; }
set {
@ -648,6 +738,8 @@ namespace ICSharpCode.Decompiler @@ -648,6 +738,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether out variable declarations should be used when possible.
/// </summary>
[Category("C# 7.0 / VS 2017")]
[Description("Use out variable declarations")]
public bool OutVariables {
get { return outVariables; }
set {
@ -664,6 +756,8 @@ namespace ICSharpCode.Decompiler @@ -664,6 +756,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether discards should be used when possible.
/// Only has an effect if <see cref="OutVariables"/> is enabled.
/// </summary>
[Category("C# 7.0 / VS 2017")]
[Description("Use discards")]
public bool Discards {
get { return discards; }
set {
@ -679,6 +773,8 @@ namespace ICSharpCode.Decompiler @@ -679,6 +773,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs.
/// </summary>
[Category("C# 7.2 / VS 2017.4")]
[Description("IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs")]
public bool IntroduceRefModifiersOnStructs {
get { return introduceRefModifiersOnStructs; }
set {
@ -695,6 +791,8 @@ namespace ICSharpCode.Decompiler @@ -695,6 +791,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether IsReadOnlyAttribute should be replaced with 'readonly' modifiers on structs
/// and with the 'in' modifier on parameters.
/// </summary>
[Category("C# 7.2 / VS 2017.4")]
[Description("IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters")]
public bool IntroduceReadonlyAndInModifiers {
get { return introduceReadonlyAndInModifiers; }
set {
@ -711,6 +809,8 @@ namespace ICSharpCode.Decompiler @@ -711,6 +809,8 @@ namespace ICSharpCode.Decompiler
/// If this option is active, [IsUnmanagedAttribute] on type parameters
/// is replaced with "T : unmanaged" constraints.
/// </summary>
[Category("C# 7.3 / VS 2017.7")]
[Description("IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints")]
public bool IntroduceUnmanagedConstraint {
get { return introduceUnmanagedConstraint; }
set {
@ -726,6 +826,8 @@ namespace ICSharpCode.Decompiler @@ -726,6 +826,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether C# 7.3 stackalloc initializers should be used.
/// </summary>
[Category("C# 7.3 / VS 2017.7")]
[Description("Use stackalloc initializer syntax")]
public bool StackAllocInitializers {
get { return stackAllocInitializers; }
set {
@ -742,6 +844,8 @@ namespace ICSharpCode.Decompiler @@ -742,6 +844,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether tuple type syntax <c>(int, string)</c>
/// should be used for <c>System.ValueTuple</c>.
/// </summary>
[Category("C# 7.0 / VS 2017")]
[Description("Use tuple type syntax")]
public bool TupleTypes {
get { return tupleTypes; }
set {
@ -758,6 +862,8 @@ namespace ICSharpCode.Decompiler @@ -758,6 +862,8 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether implicit conversions between tuples
/// should be used in the decompiled output.
/// </summary>
[Category("C# 7.0 / VS 2017")]
[Description("Use implicit conversions between tuple types")]
public bool TupleConversions {
get { return tupleConversions; }
set {
@ -773,6 +879,8 @@ namespace ICSharpCode.Decompiler @@ -773,6 +879,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether tuple comparisons should be detected.
/// </summary>
[Category("C# 7.3 / VS 2017.7")]
[Description("Detect tuple comparisons")]
public bool TupleComparisons {
get { return tupleComparisons; }
set {
@ -788,6 +896,8 @@ namespace ICSharpCode.Decompiler @@ -788,6 +896,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether named arguments should be used.
/// </summary>
[Category("C# 4.0 / VS 2010")]
[Description("Use named arguments")]
public bool NamedArguments {
get { return namedArguments; }
set {
@ -803,6 +913,8 @@ namespace ICSharpCode.Decompiler @@ -803,6 +913,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether C# 7.2 non-trailing named arguments should be used.
/// </summary>
[Category("C# 7.2 / VS 2017.4")]
[Description("Use non-trailing named arguments")]
public bool NonTrailingNamedArguments {
get { return nonTrailingNamedArguments; }
set {
@ -818,6 +930,8 @@ namespace ICSharpCode.Decompiler @@ -818,6 +930,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether optional arguments should be removed, if possible.
/// </summary>
[Category("C# 4.0 / VS 2010")]
[Description("Remove optional arguments, if possible")]
public bool OptionalArguments {
get { return optionalArguments; }
set {
@ -834,6 +948,9 @@ namespace ICSharpCode.Decompiler @@ -834,6 +948,9 @@ namespace ICSharpCode.Decompiler
/// Gets/Sets whether C# 7.0 local functions should be used.
/// Note: this language feature is currently not implemented and this setting is always false.
/// </summary>
[Category("C# 7.0 / VS 2017")]
[Description("Introduce local functions (NOT IMPLEMENTED!)")]
[Browsable(false)]
public bool LocalFunctions {
get { return localFunctions; }
set {
@ -850,6 +967,8 @@ namespace ICSharpCode.Decompiler @@ -850,6 +967,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether C# 8.0 nullable reference types are enabled.
/// </summary>
[Category("C# 8.0 / VS 2019")]
[Description("Nullable reference types")]
public bool NullableReferenceTypes {
get { return nullableReferenceTypes; }
set {
@ -862,6 +981,9 @@ namespace ICSharpCode.Decompiler @@ -862,6 +981,9 @@ namespace ICSharpCode.Decompiler
bool showDebugInfo;
[Category("Other")]
[Description("Show info from debug symbols, if available")]
[Browsable(false)]
public bool ShowDebugInfo {
get { return showDebugInfo; }
set {
@ -878,6 +1000,8 @@ namespace ICSharpCode.Decompiler @@ -878,6 +1000,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether the decompiler can assume that 'ldlen; conv.i4.ovf' does not throw an overflow exception.
/// </summary>
[Category("VB-specific options")]
[Browsable(false)]
public bool AssumeArrayLengthFitsIntoInt32 {
get { return assumeArrayLengthFitsIntoInt32; }
set {
@ -893,6 +1017,8 @@ namespace ICSharpCode.Decompiler @@ -893,6 +1017,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use increment and decrement operators
/// </summary>
[Category("VB-specific options")]
[Browsable(false)]
public bool IntroduceIncrementAndDecrement {
get { return introduceIncrementAndDecrement; }
set {
@ -908,6 +1034,8 @@ namespace ICSharpCode.Decompiler @@ -908,6 +1034,8 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
/// </summary>
[Category("VB-specific options")]
[Browsable(false)]
public bool MakeAssignmentExpressions {
get { return makeAssignmentExpressions; }
set {
@ -923,6 +1051,8 @@ namespace ICSharpCode.Decompiler @@ -923,6 +1051,8 @@ namespace ICSharpCode.Decompiler
#region Options to aid F# decompilation
bool removeDeadCode = false;
[Category("F#-specific options")]
[Description("Remove dead and side effect free code (use with caution!)")]
public bool RemoveDeadCode {
get { return removeDeadCode; }
set {
@ -938,6 +1068,7 @@ namespace ICSharpCode.Decompiler @@ -938,6 +1068,7 @@ namespace ICSharpCode.Decompiler
bool loadInMemory = false;
[Browsable(false)]
public bool LoadInMemory {
get { return loadInMemory; }
set {
@ -950,6 +1081,7 @@ namespace ICSharpCode.Decompiler @@ -950,6 +1081,7 @@ namespace ICSharpCode.Decompiler
bool throwOnAssemblyResolveErrors = true;
[Browsable(false)]
public bool ThrowOnAssemblyResolveErrors {
get { return throwOnAssemblyResolveErrors; }
set {
@ -962,6 +1094,8 @@ namespace ICSharpCode.Decompiler @@ -962,6 +1094,8 @@ namespace ICSharpCode.Decompiler
bool applyWindowsRuntimeProjections = true;
[Category("Other")]
[Description("Apply Windows Runtime projections on loaded assemblies")]
public bool ApplyWindowsRuntimeProjections {
get { return applyWindowsRuntimeProjections; }
set {
@ -976,6 +1110,7 @@ namespace ICSharpCode.Decompiler @@ -976,6 +1110,7 @@ namespace ICSharpCode.Decompiler
CSharpFormattingOptions csharpFormattingOptions;
[Browsable(false)]
public CSharpFormattingOptions CSharpFormattingOptions {
get {
if (csharpFormattingOptions == null) {

1
ICSharpCode.Decompiler/Output/ITextOutput.cs

@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler @@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler
{
public interface ITextOutput
{
string IndentationString { get; set; }
void Indent();
void Unindent();
void Write(char ch);

15
ICSharpCode.Decompiler/Output/PlainTextOutput.cs

@ -35,7 +35,9 @@ namespace ICSharpCode.Decompiler @@ -35,7 +35,9 @@ namespace ICSharpCode.Decompiler
int line = 1;
int column = 1;
public string IndentationString { get; set; } = "\t";
public PlainTextOutput(TextWriter writer)
{
if (writer == null)
@ -74,7 +76,7 @@ namespace ICSharpCode.Decompiler @@ -74,7 +76,7 @@ namespace ICSharpCode.Decompiler
if (needsIndent) {
needsIndent = false;
for (int i = 0; i < indent; i++) {
writer.Write('\t');
writer.Write(IndentationString);
}
column += indent;
}
@ -154,6 +156,15 @@ namespace ICSharpCode.Decompiler @@ -154,6 +156,15 @@ namespace ICSharpCode.Decompiler
this.actions = new List<Action<ITextOutput>>();
}
string ITextOutput.IndentationString {
get {
return target.IndentationString;
}
set {
target.IndentationString = value;
}
}
public void Commit()
{
foreach (var action in actions) {

13
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -23,9 +23,7 @@ using ICSharpCode.Decompiler.CSharp; @@ -23,9 +23,7 @@ using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler
{
@ -40,9 +38,6 @@ namespace ICSharpCode.Decompiler @@ -40,9 +38,6 @@ namespace ICSharpCode.Decompiler
bool firstUsingDeclaration;
bool lastUsingDeclaration;
public bool FoldBraces = false;
public bool ExpandMemberDefinitions = false;
public TextTokenWriter(ITextOutput output, DecompilerSettings settings, IDecompilerTypeSystem typeSystem)
{
if (output == null)
@ -96,7 +91,7 @@ namespace ICSharpCode.Decompiler @@ -96,7 +91,7 @@ namespace ICSharpCode.Decompiler
}
if (firstUsingDeclaration) {
output.MarkFoldStart(defaultCollapsed: true);
output.MarkFoldStart(defaultCollapsed: !settings.ExpandUsingDeclarations);
firstUsingDeclaration = false;
}
@ -220,15 +215,15 @@ namespace ICSharpCode.Decompiler @@ -220,15 +215,15 @@ namespace ICSharpCode.Decompiler
}
if (braceLevelWithinType >= 0 || nodeStack.Peek() is TypeDeclaration)
braceLevelWithinType++;
if (nodeStack.OfType<BlockStatement>().Count() <= 1 || FoldBraces) {
output.MarkFoldStart(defaultCollapsed: !ExpandMemberDefinitions && braceLevelWithinType == 1);
if (nodeStack.OfType<BlockStatement>().Count() <= 1 || settings.FoldBraces) {
output.MarkFoldStart(defaultCollapsed: !settings.ExpandMemberDefinitions && braceLevelWithinType == 1);
}
output.Write("{");
break;
case "}":
output.Write('}');
if (role != Roles.RBrace) break;
if (nodeStack.OfType<BlockStatement>().Count() <= 1 || FoldBraces)
if (nodeStack.OfType<BlockStatement>().Count() <= 1 || settings.FoldBraces)
output.MarkFoldEnd();
if (braceLevelWithinType >= 0)
braceLevelWithinType--;

33
ILSpy/DecompilationOptions.cs

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
using System;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Options;
namespace ICSharpCode.ILSpy
@ -77,21 +76,27 @@ namespace ICSharpCode.ILSpy @@ -77,21 +76,27 @@ namespace ICSharpCode.ILSpy
{
}
public DecompilationOptions(LanguageVersion version, Options.DecompilerSettings settings, Options.DisplaySettings displaySettings)
public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, Options.DisplaySettings displaySettings)
{
if (!Enum.TryParse(version.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
if (!Enum.TryParse(version.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
languageVersion = Decompiler.CSharp.LanguageVersion.Latest;
this.DecompilerSettings = new Decompiler.DecompilerSettings(languageVersion) {
AlwaysUseBraces = settings.AlwaysUseBraces,
ExpandMemberDefinitions = displaySettings.ExpandMemberDefinitions,
FoldBraces = displaySettings.FoldBraces,
RemoveDeadCode = settings.RemoveDeadCode,
ShowDebugInfo = settings.ShowDebugInfo,
ShowXmlDocumentation = settings.ShowXmlDocumentation,
UseDebugSymbols = settings.UseDebugSymbols,
UsingDeclarations = settings.UsingDeclarations,
ApplyWindowsRuntimeProjections = settings.ApplyWindowsRuntimeProjections,
};
var newSettings = this.DecompilerSettings = settings.Clone();
newSettings.SetLanguageVersion(languageVersion);
newSettings.ExpandMemberDefinitions = displaySettings.ExpandMemberDefinitions;
newSettings.ExpandUsingDeclarations = displaySettings.ExpandUsingDeclarations;
newSettings.FoldBraces = displaySettings.FoldBraces;
newSettings.ShowDebugInfo = displaySettings.ShowDebugInfo;
newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings);
}
private string GetIndentationString(DisplaySettings displaySettings)
{
if (displaySettings.IndentationUseTabs) {
int numberOfTabs = displaySettings.IndentationSize / displaySettings.IndentationTabSize;
int numberOfSpaces = displaySettings.IndentationSize % displaySettings.IndentationTabSize;
return new string('\t', numberOfTabs) + new string(' ', numberOfSpaces);
}
return new string(' ', displaySettings.IndentationSize);
}
}
}

8
ILSpy/ILSpy.csproj

@ -158,6 +158,7 @@ @@ -158,6 +158,7 @@
<Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" />
<Compile Include="Options\DecompilerSettingsPanel.xaml.cs" />
<Compile Include="Search\LiteralSearchStrategy.cs" />
<Compile Include="LoadedAssembly.cs" />
<Compile Include="LoadedAssemblyExtensions.cs" />
@ -184,10 +185,6 @@ @@ -184,10 +185,6 @@
<Compile Include="OpenListDialog.xaml.cs">
<DependentUpon>OpenListDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Options\DecompilerSettingsPanel.xaml.cs">
<DependentUpon>DecompilerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Options\DisplaySettings.cs" />
<Compile Include="Options\DisplaySettingsPanel.xaml.cs">
<DependentUpon>DisplaySettingsPanel.xaml</DependentUpon>
@ -389,6 +386,9 @@ @@ -389,6 +386,9 @@
<ItemGroup>
<Page Update="@(Page)" SubType="Designer" Generator="MSBuild:Compile" />
<Page Update="Options\DecompilerSettingsPanel.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>

2
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -65,7 +65,7 @@ namespace ICSharpCode.ILSpy @@ -65,7 +65,7 @@ namespace ICSharpCode.ILSpy
static void WriteCode(TextWriter output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
TokenWriter tokenWriter = new TextWriterTokenWriter(output);
TokenWriter tokenWriter = new TextWriterTokenWriter(output) { IndentationString = settings.CSharpFormattingOptions.IndentationString };
tokenWriter = TokenWriter.WrapInWriterThatSetsLocationsInAST(tokenWriter);
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, settings.CSharpFormattingOptions));
}

3
ILSpy/Languages/CSharpLanguage.cs

@ -121,7 +121,8 @@ namespace ICSharpCode.ILSpy @@ -121,7 +121,8 @@ namespace ICSharpCode.ILSpy
void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
TokenWriter tokenWriter = new TextTokenWriter(output, settings, typeSystem) { FoldBraces = settings.FoldBraces, ExpandMemberDefinitions = settings.ExpandMemberDefinitions };
output.IndentationString = settings.CSharpFormattingOptions.IndentationString;
TokenWriter tokenWriter = new TextTokenWriter(output, settings, typeSystem);
if (output is ISmartTextOutput highlightingOutput) {
tokenWriter = new CSharpHighlightingTokenWriter(tokenWriter, highlightingOutput);
}

1
ILSpy/Languages/ILLanguage.cs

@ -52,6 +52,7 @@ namespace ICSharpCode.ILSpy @@ -52,6 +52,7 @@ namespace ICSharpCode.ILSpy
protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options)
{
output.IndentationString = options.DecompilerSettings.CSharpFormattingOptions.IndentationString;
return new ReflectionDisassembler(output, options.CancellationToken) {
DetectControlStructure = detectControlStructure,
ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo,

67
ILSpy/Options/DecompilerSettingsPanel.xaml

@ -2,18 +2,61 @@ @@ -2,18 +2,61 @@
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls">
xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options">
<UserControl.Resources>
<controls:BoolToVisibilityConverter x:Key="boolConv" />
<CollectionViewSource x:Key="SettingsCollection" Source="{Binding Settings}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
<StackPanel Margin="10">
<CheckBox IsChecked="{Binding UseDebugSymbols}">Use variable names from debug symbols, if available</CheckBox>
<CheckBox IsChecked="{Binding ShowDebugInfo}">Show info from debug symbols, if available</CheckBox>
<CheckBox IsChecked="{Binding ShowXmlDocumentation}">Show XML documentation in decompiled code</CheckBox>
<CheckBox IsChecked="{Binding RemoveDeadCode}">Remove dead and side effect free code</CheckBox>
<CheckBox IsChecked="{Binding UsingDeclarations}">Insert using declarations</CheckBox>
<CheckBox IsChecked="{Binding AlwaysUseBraces}">Always use braces</CheckBox>
<CheckBox IsChecked="{Binding ApplyWindowsRuntimeProjections}">Apply Windows Runtime projections on loaded assemblies</CheckBox>
</StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Margin="3" Grid.ColumnSpan="3" TextWrapping="Wrap" Text="The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls." />
<ListBox Grid.Row="1" ItemsSource="{Binding Source={StaticResource SettingsCollection}}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Padding="0" BorderThickness="0" IsExpanded="True">
<Expander.Header>
<CheckBox Checked="OnGroupChecked" Unchecked="OnGroupUnchecked" Loaded="OnGroupLoaded" VerticalContentAlignment="Center"
FontSize="16" FontWeight="Bold" Content="{Binding Name}" />
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Margin="19,0,0,0" IsChecked="{Binding IsEnabled}" Content="{Binding Description}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>

232
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -17,8 +17,12 @@ @@ -17,8 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Xml.Linq;
namespace ICSharpCode.ILSpy.Options
@ -26,182 +30,166 @@ namespace ICSharpCode.ILSpy.Options @@ -26,182 +30,166 @@ namespace ICSharpCode.ILSpy.Options
/// <summary>
/// Interaction logic for DecompilerSettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = "Decompiler", Order = 0)]
partial class DecompilerSettingsPanel : UserControl, IOptionPage
[ExportOptionPage(Title = "Decompiler", Order = 10)]
internal partial class DecompilerSettingsPanel : UserControl, IOptionPage
{
public DecompilerSettingsPanel()
{
InitializeComponent();
}
public void Load(ILSpySettings settings)
{
this.DataContext = currentDecompilerSettings ?? LoadDecompilerSettings(settings);
}
static DecompilerSettings currentDecompilerSettings;
public static DecompilerSettings CurrentDecompilerSettings {
static Decompiler.DecompilerSettings currentDecompilerSettings;
public static Decompiler.DecompilerSettings CurrentDecompilerSettings {
get {
return currentDecompilerSettings ?? (currentDecompilerSettings = LoadDecompilerSettings(ILSpySettings.Load()));
}
}
public static DecompilerSettings LoadDecompilerSettings(ILSpySettings settings)
public static Decompiler.DecompilerSettings LoadDecompilerSettings(ILSpySettings settings)
{
XElement e = settings["DecompilerSettings"];
DecompilerSettings s = new DecompilerSettings();
s.ShowDebugInfo = (bool?)e.Attribute("showDebugInfo") ?? s.ShowDebugInfo;
s.ShowXmlDocumentation = (bool?)e.Attribute("xmlDoc") ?? s.ShowXmlDocumentation;
s.RemoveDeadCode = (bool?)e.Attribute("removeDeadCode") ?? s.RemoveDeadCode;
s.UsingDeclarations = (bool?)e.Attribute("usingDeclarations") ?? s.UsingDeclarations;
s.AlwaysUseBraces = (bool?)e.Attribute("alwaysUseBraces") ?? s.AlwaysUseBraces;
s.ApplyWindowsRuntimeProjections = (bool?)e.Attribute("applyWindowsRuntimeProjections") ?? s.ApplyWindowsRuntimeProjections;
return s;
}
var newSettings = new Decompiler.DecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties) {
p.SetValue(newSettings, (bool?)e.Attribute(p.Name) ?? true);
}
return newSettings;
}
public void Load(ILSpySettings settings)
{
this.DataContext = new DecompilerSettings(LoadDecompilerSettings(settings));
}
public void Save(XElement root)
{
DecompilerSettings s = (DecompilerSettings)this.DataContext;
XElement section = new XElement("DecompilerSettings");
section.SetAttributeValue("useDebugSymbols", s.UseDebugSymbols);
section.SetAttributeValue("showDebugInfo", s.ShowDebugInfo);
section.SetAttributeValue("xmlDoc", s.ShowXmlDocumentation);
section.SetAttributeValue("removeDeadCode", s.RemoveDeadCode);
section.SetAttributeValue("usingDeclarations", s.UsingDeclarations);
section.SetAttributeValue("alwaysUseBraces", s.AlwaysUseBraces);
section.SetAttributeValue("applyWindowsRuntimeProjections", s.ApplyWindowsRuntimeProjections);
var newSettings = ((DecompilerSettings)this.DataContext).ToDecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties) {
section.SetAttributeValue(p.Name, p.GetValue(newSettings));
}
XElement existingElement = root.Element("DecompilerSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
currentDecompilerSettings = s; // update cached settings
currentDecompilerSettings = newSettings;
}
}
public class DecompilerSettings : INotifyPropertyChanged
{
bool showXmlDocumentation = true;
private void OnGroupChecked(object sender, RoutedEventArgs e)
{
CheckGroup((CollectionViewGroup)((CheckBox)sender).DataContext, true);
}
private void OnGroupUnchecked(object sender, RoutedEventArgs e)
{
CheckGroup((CollectionViewGroup)((CheckBox)sender).DataContext, false);
}
/// <summary>
/// Gets/Sets whether to include XML documentation comments in the decompiled code.
/// </summary>
public bool ShowXmlDocumentation {
get { return showXmlDocumentation; }
set {
if (showXmlDocumentation != value) {
showXmlDocumentation = value;
OnPropertyChanged();
void CheckGroup(CollectionViewGroup group, bool value)
{
foreach (var item in group.Items) {
switch (item) {
case CollectionViewGroup subGroup:
CheckGroup(subGroup, value);
break;
case CSharpDecompilerSetting setting:
setting.IsEnabled = value;
break;
}
}
}
bool decompileMemberBodies = true;
/// <summary>
/// Gets/Sets whether member bodies should be decompiled.
/// </summary>
public bool DecompileMemberBodies {
get { return decompileMemberBodies; }
set {
if (decompileMemberBodies != value) {
decompileMemberBodies = value;
OnPropertyChanged();
bool IsGroupChecked(CollectionViewGroup group)
{
bool value = true;
foreach (var item in group.Items) {
switch (item) {
case CollectionViewGroup subGroup:
value = value && IsGroupChecked(subGroup);
break;
case CSharpDecompilerSetting setting:
value = value && setting.IsEnabled;
break;
}
}
return value;
}
bool useDebugSymbols = true;
/// <summary>
/// Gets/Sets whether to use variable names from debug symbols, if available.
/// </summary>
public bool UseDebugSymbols {
get { return useDebugSymbols; }
set {
if (useDebugSymbols != value) {
useDebugSymbols = value;
OnPropertyChanged();
}
}
private void OnGroupLoaded(object sender, RoutedEventArgs e)
{
CheckBox checkBox = (CheckBox)sender;
checkBox.IsChecked = IsGroupChecked((CollectionViewGroup)checkBox.DataContext);
}
}
bool usingDeclarations = true;
public class DecompilerSettings : INotifyPropertyChanged
{
public CSharpDecompilerSetting[] Settings { get; set; }
public bool UsingDeclarations {
get { return usingDeclarations; }
set {
if (usingDeclarations != value) {
usingDeclarations = value;
OnPropertyChanged();
}
}
public DecompilerSettings(Decompiler.DecompilerSettings settings)
{
Settings = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false)
.Select(p => new CSharpDecompilerSetting(p) { IsEnabled = (bool)p.GetValue(settings) })
.OrderBy(item => item.Category)
.ThenBy(item => item.Description)
.ToArray();
}
bool showDebugInfo;
public event PropertyChangedEventHandler PropertyChanged;
public bool ShowDebugInfo {
get { return showDebugInfo; }
set {
if (showDebugInfo != value) {
showDebugInfo = value;
OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
bool removeDeadCode = false;
public bool RemoveDeadCode {
get { return removeDeadCode; }
set {
if (removeDeadCode != value) {
removeDeadCode = value;
OnPropertyChanged();
}
public Decompiler.DecompilerSettings ToDecompilerSettings()
{
var settings = new Decompiler.DecompilerSettings();
foreach (var item in Settings) {
item.Property.SetValue(settings, item.IsEnabled);
}
return settings;
}
}
bool alwaysUseBraces = true;
public class CSharpDecompilerSetting : INotifyPropertyChanged
{
bool isEnabled;
/// <summary>
/// Gets/Sets whether to use braces for single-statement-blocks.
/// </summary>
public bool AlwaysUseBraces {
get { return alwaysUseBraces; }
set {
if (alwaysUseBraces != value) {
alwaysUseBraces = value;
OnPropertyChanged();
}
}
public CSharpDecompilerSetting(PropertyInfo p)
{
this.Property = p;
this.Category = p.GetCustomAttribute<CategoryAttribute>()?.Category ?? "Other";
this.Description = p.GetCustomAttribute<DescriptionAttribute>()?.Description ?? p.Name;
}
bool applyWindowsRuntimeProjections = true;
public PropertyInfo Property { get; }
/// <summary>
/// Gets/Sets whether to Windows Runtime projections to all loaded assemblies.
/// </summary>
public bool ApplyWindowsRuntimeProjections {
get { return applyWindowsRuntimeProjections; }
public bool IsEnabled {
get => isEnabled;
set {
if (applyWindowsRuntimeProjections != value) {
applyWindowsRuntimeProjections = value;
if (value != isEnabled) {
isEnabled = value;
OnPropertyChanged();
}
}
}
public string Description { get; set; }
public string Category { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

65
ILSpy/Options/DisplaySettings.cs

@ -155,6 +155,66 @@ namespace ICSharpCode.ILSpy.Options @@ -155,6 +155,66 @@ namespace ICSharpCode.ILSpy.Options
}
}
bool expandUsingDeclarations = false;
public bool ExpandUsingDeclarations {
get { return expandUsingDeclarations; }
set {
if (expandUsingDeclarations != value) {
expandUsingDeclarations = value;
OnPropertyChanged();
}
}
}
bool showDebugInfo;
public bool ShowDebugInfo {
get { return showDebugInfo; }
set {
if (showDebugInfo != value) {
showDebugInfo = value;
OnPropertyChanged();
}
}
}
bool indentationUseTabs = true;
public bool IndentationUseTabs {
get { return indentationUseTabs; }
set {
if (indentationUseTabs != value) {
indentationUseTabs = value;
OnPropertyChanged();
}
}
}
int indentationTabSize = 4;
public int IndentationTabSize {
get { return indentationTabSize; }
set {
if (indentationTabSize != value) {
indentationTabSize = value;
OnPropertyChanged();
}
}
}
int indentationSize = 4;
public int IndentationSize {
get { return indentationSize; }
set {
if (indentationSize != value) {
indentationSize = value;
OnPropertyChanged();
}
}
}
public void CopyValues(DisplaySettings s)
{
this.SelectedFont = s.selectedFont;
@ -162,10 +222,15 @@ namespace ICSharpCode.ILSpy.Options @@ -162,10 +222,15 @@ namespace ICSharpCode.ILSpy.Options
this.ShowLineNumbers = s.showLineNumbers;
this.ShowMetadataTokens = s.showMetadataTokens;
this.ShowMetadataTokensInBase10 = s.showMetadataTokensInBase10;
this.ShowDebugInfo = s.showDebugInfo;
this.EnableWordWrap = s.enableWordWrap;
this.SortResults = s.sortResults;
this.FoldBraces = s.foldBraces;
this.ExpandMemberDefinitions = s.expandMemberDefinitions;
this.ExpandUsingDeclarations = s.expandUsingDeclarations;
this.IndentationUseTabs = s.indentationUseTabs;
this.IndentationTabSize = s.indentationTabSize;
this.IndentationSize = s.indentationSize;
}
}
}

18
ILSpy/Options/DisplaySettingsPanel.xaml

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
@ -57,15 +58,30 @@ @@ -57,15 +58,30 @@
</Border>
</Grid>
</GroupBox>
<GroupBox Header="Other options" Grid.Row="1">
<GroupBox Header="Indentation" Grid.Row="1">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding IndentationUseTabs}">Use tabs instead of spaces</CheckBox>
<StackPanel Orientation="Horizontal">
<Label>Tab size:</Label>
<TextBox x:Name="tabSizeTextBox" Width="50" Margin="3" Text="{Binding IndentationTabSize}" PreviewTextInput="TextBox_PreviewTextInput" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Indent size:</Label>
<TextBox x:Name="indentSizeTextBox" Width="50" Margin="3" Text="{Binding IndentationSize}" PreviewTextInput="TextBox_PreviewTextInput" />
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="Other options" Grid.Row="2">
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding ShowLineNumbers}">Show line numbers</CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokens}">Show metadata tokens</CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokensInBase10}">Show metadata tokens in base 10</CheckBox>
<CheckBox IsChecked="{Binding ShowDebugInfo}">Show info from debug symbols, if available</CheckBox>
<CheckBox IsChecked="{Binding EnableWordWrap}">Enable word wrap</CheckBox>
<CheckBox IsChecked="{Binding FoldBraces}">Enable folding on all blocks in braces</CheckBox>
<CheckBox IsChecked="{Binding SortResults}">Sort results by fitness</CheckBox>
<CheckBox IsChecked="{Binding ExpandMemberDefinitions}">Expand member definitions after decompilation</CheckBox>
<CheckBox IsChecked="{Binding ExpandUsingDeclarations}">Expand using declarations after decompilation</CheckBox>
</StackPanel>
</GroupBox>
</Grid>

35
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -31,13 +31,16 @@ namespace ICSharpCode.ILSpy.Options @@ -31,13 +31,16 @@ namespace ICSharpCode.ILSpy.Options
/// <summary>
/// Interaction logic for DisplaySettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = "Display", Order = 1)]
[ExportOptionPage(Title = "Display", Order = 20)]
public partial class DisplaySettingsPanel : UserControl, IOptionPage
{
public DisplaySettingsPanel()
{
InitializeComponent();
DataObject.AddPastingHandler(tabSizeTextBox, OnPaste);
DataObject.AddPastingHandler(indentSizeTextBox, OnPaste);
Task<FontFamily[]> task = new Task<FontFamily[]>(FontLoader);
task.Start();
task.ContinueWith(
@ -57,7 +60,7 @@ namespace ICSharpCode.ILSpy.Options @@ -57,7 +60,7 @@ namespace ICSharpCode.ILSpy.Options
}
);
}
public void Load(ILSpySettings settings)
{
this.DataContext = LoadDisplaySettings(settings);
@ -102,10 +105,15 @@ namespace ICSharpCode.ILSpy.Options @@ -102,10 +105,15 @@ namespace ICSharpCode.ILSpy.Options
s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
s.ShowMetadataTokens = (bool?)e.Attribute("ShowMetadataTokens") ?? false;
s.ShowMetadataTokensInBase10 = (bool?)e.Attribute("ShowMetadataTokensInBase10") ?? false;
s.ShowDebugInfo = (bool?)e.Attribute("ShowDebugInfo") ?? false;
s.EnableWordWrap = (bool?)e.Attribute("EnableWordWrap") ?? false;
s.SortResults = (bool?)e.Attribute("SortResults") ?? true;
s.FoldBraces = (bool?)e.Attribute("FoldBraces") ?? false;
s.ExpandMemberDefinitions = (bool?)e.Attribute("ExpandMemberDefinitions") ?? false;
s.ExpandUsingDeclarations = (bool?)e.Attribute("ExpandUsingDeclarations") ?? false;
s.IndentationUseTabs = (bool?)e.Attribute("IndentationUseTabs") ?? true;
s.IndentationSize = (int?)e.Attribute("IndentationSize") ?? 4;
s.IndentationTabSize = (int?)e.Attribute("IndentationTabSize") ?? 4;
return s;
}
@ -120,10 +128,14 @@ namespace ICSharpCode.ILSpy.Options @@ -120,10 +128,14 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("ShowLineNumbers", s.ShowLineNumbers);
section.SetAttributeValue("ShowMetadataTokens", s.ShowMetadataTokens);
section.SetAttributeValue("ShowMetadataTokensInBase10", s.ShowMetadataTokensInBase10);
section.SetAttributeValue("ShowDebugInfo", s.ShowDebugInfo);
section.SetAttributeValue("EnableWordWrap", s.EnableWordWrap);
section.SetAttributeValue("SortResults", s.SortResults);
section.SetAttributeValue("FoldBraces", s.FoldBraces);
section.SetAttributeValue("ExpandMemberDefinitions", s.ExpandMemberDefinitions);
section.SetAttributeValue("IndentationUseTabs", s.IndentationUseTabs);
section.SetAttributeValue("IndentationSize", s.IndentationSize);
section.SetAttributeValue("IndentationTabSize", s.IndentationTabSize);
XElement existingElement = root.Element("DisplaySettings");
if (existingElement != null)
@ -134,8 +146,23 @@ namespace ICSharpCode.ILSpy.Options @@ -134,8 +146,23 @@ namespace ICSharpCode.ILSpy.Options
if (currentDisplaySettings != null)
currentDisplaySettings.CopyValues(s);
}
private void TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
if (!e.Text.All(char.IsDigit))
e.Handled = true;
}
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
if (!e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true))
return;
var text = (string)e.SourceDataObject.GetData(DataFormats.UnicodeText, true) ?? string.Empty;
if (!text.All(char.IsDigit))
e.CancelCommand();
}
}
public class FontSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

2
ILSpy/Options/MiscSettingsPanel.xaml.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.ILSpy.Options @@ -24,7 +24,7 @@ namespace ICSharpCode.ILSpy.Options
/// <summary>
/// Interaction logic for MiscSettingsPanel.xaml
/// </summary>
[ExportOptionPage(Title = "Misc", Order = 2)]
[ExportOptionPage(Title = "Misc", Order = 30)]
public partial class MiscSettingsPanel : UserControl, IOptionPage
{
public MiscSettingsPanel()

2
ILSpy/Options/OptionsDialog.xaml

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
Style="{DynamicResource DialogWindow}"
WindowStartupLocation="CenterOwner"
ResizeMode="CanResizeWithGrip"
Title="Options" Height="400" Width="500">
Title="Options" Height="500" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition

Loading…
Cancel
Save