Browse Source

Fix #2297: Add an option to disable decompilation of getter-only auto properties.

pull/2308/head
Siegfried Pammer 4 years ago
parent
commit
afa4db00b6
  1. 38
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 3
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  4. 22
      ICSharpCode.Decompiler/DecompilerSettings.cs
  5. 9
      ILSpy/Properties/Resources.Designer.cs
  6. 3
      ILSpy/Properties/Resources.resx

38
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -23,6 +23,7 @@ using System.IO; @@ -23,6 +23,7 @@ using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
using System.Threading;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
@ -329,8 +330,29 @@ namespace ICSharpCode.Decompiler.CSharp @@ -329,8 +330,29 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field, metadata))
return true;
if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field, metadata))
if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field, metadata, out var propertyName))
{
if (!settings.GetterOnlyAutomaticProperties && IsGetterOnlyProperty(propertyName))
return false;
bool IsGetterOnlyProperty(string propertyName)
{
var properties = metadata.GetTypeDefinition(field.GetDeclaringType()).GetProperties();
foreach (var p in properties)
{
var pd = metadata.GetPropertyDefinition(p);
string name = metadata.GetString(pd.Name);
if (!metadata.StringComparer.Equals(pd.Name, propertyName))
continue;
PropertyAccessors accessors = pd.GetAccessors();
return !accessors.Getter.IsNil && accessors.Setter.IsNil;
}
return false;
}
return true;
}
if (settings.SwitchStatementOnString && IsSwitchOnStringCache(field, metadata))
return true;
}
@ -359,10 +381,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -359,10 +381,20 @@ namespace ICSharpCode.Decompiler.CSharp
return metadata.GetString(field.Name).StartsWith("<>f__switch", StringComparison.Ordinal);
}
static bool IsAutomaticPropertyBackingField(SRM.FieldDefinition field, MetadataReader metadata)
static readonly Regex automaticPropertyBackingFieldRegex = new Regex(@"^<(.*)>k__BackingField$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
static bool IsAutomaticPropertyBackingField(SRM.FieldDefinition field, MetadataReader metadata, out string propertyName)
{
propertyName = null;
var name = metadata.GetString(field.Name);
return name.StartsWith("<", StringComparison.Ordinal) && name.EndsWith("BackingField", StringComparison.Ordinal);
var m = automaticPropertyBackingFieldRegex.Match(name);
if (m.Success)
{
propertyName = m.Groups[1].Value;
return true;
}
return false;
}
static bool IsAnonymousMethodCacheField(SRM.FieldDefinition field, MetadataReader metadata)

3
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -292,7 +292,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -292,7 +292,8 @@ namespace ICSharpCode.Decompiler.CSharp
// It feels a bit hacky, though.
if (settings.AutomaticProperties
&& PatternStatementTransform.IsBackingFieldOfAutomaticProperty(field, out var property)
&& decompilationContext.CurrentMember != property)
&& decompilationContext.CurrentMember != property
&& (property.CanSet || settings.GetterOnlyAutomaticProperties))
{
requireTarget = RequiresQualifier(property, target);
}

5
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -103,7 +103,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -103,7 +103,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
if (context.Settings.AutomaticProperties)
if (context.Settings.AutomaticProperties
&& (!propertyDeclaration.Setter.IsNull || context.Settings.GetterOnlyAutomaticProperties))
{
AstNode result = TransformAutomaticProperty(propertyDeclaration);
if (result != null)
@ -738,6 +739,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -738,6 +739,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (field != null && IsBackingFieldOfAutomaticProperty(field, out var property)
&& CanTransformToAutomaticProperty(property) && currentMethod.AccessorOwner != property)
{
if (!property.CanSet && !context.Settings.GetterOnlyAutomaticProperties)
return null;
parent.RemoveAnnotations<MemberResolveResult>();
parent.AddAnnotation(new MemberResolveResult(mrr.TargetResult, property));
return Identifier.Create(property.Name);

22
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -93,6 +93,7 @@ namespace ICSharpCode.Decompiler @@ -93,6 +93,7 @@ namespace ICSharpCode.Decompiler
dictionaryInitializers = false;
extensionMethodsInCollectionInitializers = false;
useRefLocalsForAccurateOrderOfEvaluation = false;
getterOnlyAutomaticProperties = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp7)
{
@ -159,7 +160,8 @@ namespace ICSharpCode.Decompiler @@ -159,7 +160,8 @@ namespace ICSharpCode.Decompiler
|| discards || localFunctions)
return CSharp.LanguageVersion.CSharp7;
if (awaitInCatchFinally || useExpressionBodyForCalculatedGetterOnlyProperties || nullPropagation
|| stringInterpolation || dictionaryInitializers || extensionMethodsInCollectionInitializers || useRefLocalsForAccurateOrderOfEvaluation)
|| stringInterpolation || dictionaryInitializers || extensionMethodsInCollectionInitializers
|| useRefLocalsForAccurateOrderOfEvaluation || getterOnlyAutomaticProperties)
return CSharp.LanguageVersion.CSharp6;
if (asyncAwait)
return CSharp.LanguageVersion.CSharp5;
@ -572,6 +574,24 @@ namespace ICSharpCode.Decompiler @@ -572,6 +574,24 @@ namespace ICSharpCode.Decompiler
}
}
bool getterOnlyAutomaticProperties = true;
/// <summary>
/// Decompile getter-only automatic properties
/// </summary>
[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;
/// <summary>

9
ILSpy/Properties/Resources.Designer.cs generated

@ -927,6 +927,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -927,6 +927,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Decompile getter-only automatic properties.
/// </summary>
public static string DecompilerSettings_GetterOnlyAutomaticProperties {
get {
return ResourceManager.GetString("DecompilerSettings.GetterOnlyAutomaticProperties", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Include XML documentation comments in the decompiled code.
/// </summary>

3
ILSpy/Properties/Resources.resx

@ -339,6 +339,9 @@ Are you sure you want to continue?</value> @@ -339,6 +339,9 @@ Are you sure you want to continue?</value>
<data name="DecompilerSettings.FunctionPointers" xml:space="preserve">
<value>Function pointers</value>
</data>
<data name="DecompilerSettings.GetterOnlyAutomaticProperties" xml:space="preserve">
<value>Decompile getter-only automatic properties</value>
</data>
<data name="DecompilerSettings.IncludeXMLDocumentationCommentsInTheDecompiledCode" xml:space="preserve">
<value>Include XML documentation comments in the decompiled code</value>
</data>

Loading…
Cancel
Save