Browse Source

Add support for attributes of field/property in primary ctor of records

pull/2476/head
SilverFox 4 years ago
parent
commit
11b44e53b7
  1. 13
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  2. 26
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 14
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  4. 2
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

13
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs

@ -1,4 +1,6 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public record Base(string A); public record Base(string A);
@ -37,6 +39,7 @@
public record PairWithPrimaryCtor<A, B>(A First, B Second); public record PairWithPrimaryCtor<A, B>(A First, B Second);
public record PrimaryCtor(int A, string B); public record PrimaryCtor(int A, string B);
public record PrimaryCtorWithAttribute([RecordTest("param")] [property: RecordTest("property")][field: RecordTest("field")] int a);
public record PrimaryCtorWithField(int A, string B) public record PrimaryCtorWithField(int A, string B)
{ {
public double C = 1.0; public double C = 1.0;
@ -63,6 +66,14 @@
} }
} }
[AttributeUsage(AttributeTargets.All)]
public class RecordTestAttribute : Attribute
{
public RecordTestAttribute(string name)
{
}
}
public sealed record Sealed(string A); public sealed record Sealed(string A);
public sealed record SealedDerived(int B) : Base(B.ToString()); public sealed record SealedDerived(int B) : Base(B.ToString());

26
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1225,7 +1225,31 @@ namespace ICSharpCode.Decompiler.CSharp
if (recordDecompiler?.PrimaryConstructor != null) if (recordDecompiler?.PrimaryConstructor != null)
{ {
foreach (var p in recordDecompiler.PrimaryConstructor.Parameters) foreach (var p in recordDecompiler.PrimaryConstructor.Parameters)
typeDecl.PrimaryConstructorParameters.Add(typeSystemAstBuilder.ConvertParameter(p)); {
ParameterDeclaration pd = typeSystemAstBuilder.ConvertParameter(p);
(IProperty prop, IField field) = recordDecompiler.GetPropertyInfoByPrimaryConstructorParameter(p);
Syntax.Attribute[] attributes = prop.GetAttributes().Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes.Length > 0)
{
var section = new AttributeSection {
AttributeTarget = "property"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
}
attributes = field.GetAttributes()
.Where(a => !PatternStatementTransform.attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName))
.Select(attr => typeSystemAstBuilder.ConvertAttribute(attr)).ToArray();
if (attributes.Length > 0)
{
var section = new AttributeSection {
AttributeTarget = "field"
};
section.Attributes.AddRange(attributes);
pd.Attributes.Add(section);
}
typeDecl.PrimaryConstructorParameters.Add(pd);
}
} }
foreach (var type in typeDef.NestedTypes) foreach (var type in typeDef.NestedTypes)

14
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (method.IsStatic || !method.IsConstructor) if (method.IsStatic || !method.IsConstructor)
continue; continue;
var m = method.Specialize(subst); var m = method.Specialize(subst);
if (IsPrimaryConstructor(m)) if (IsPrimaryConstructor(m, method))
return method; return method;
primaryCtorParameterToAutoProperty.Clear(); primaryCtorParameterToAutoProperty.Clear();
autoPropertyToPrimaryCtorParameter.Clear(); autoPropertyToPrimaryCtorParameter.Clear();
@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.CSharp
return null; return null;
bool IsPrimaryConstructor(IMethod method) bool IsPrimaryConstructor(IMethod method, IMethod unspecializedMethod)
{ {
Debug.Assert(method.IsConstructor); Debug.Assert(method.IsConstructor);
var body = DecompileBody(method); var body = DecompileBody(method);
@ -202,8 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp
return false; return false;
if (!backingFieldToAutoProperty.TryGetValue(field, out var property)) if (!backingFieldToAutoProperty.TryGetValue(field, out var property))
return false; return false;
primaryCtorParameterToAutoProperty.Add(method.Parameters[i], property); primaryCtorParameterToAutoProperty.Add(unspecializedMethod.Parameters[i], property);
autoPropertyToPrimaryCtorParameter.Add(property, method.Parameters[i]); autoPropertyToPrimaryCtorParameter.Add(property, unspecializedMethod.Parameters[i]);
} }
if (!isStruct) if (!isStruct)
@ -331,6 +331,12 @@ namespace ICSharpCode.Decompiler.CSharp
&& autoPropertyToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst)); && autoPropertyToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst));
} }
internal (IProperty prop, IField field) GetPropertyInfoByPrimaryConstructorParameter(IParameter parameter)
{
var prop = primaryCtorParameterToAutoProperty[parameter];
return (prop, autoPropertyToBackingField[prop]);
}
public bool IsCopyConstructor(IMethod method) public bool IsCopyConstructor(IMethod method)
{ {
if (method == null) if (method == null)

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

@ -936,7 +936,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
"System.Runtime.CompilerServices.MethodImplAttribute" "System.Runtime.CompilerServices.MethodImplAttribute"
}; };
static readonly string[] attributeTypesToRemoveFromAutoProperties = new[] { internal static readonly string[] attributeTypesToRemoveFromAutoProperties = new[] {
"System.Runtime.CompilerServices.CompilerGeneratedAttribute", "System.Runtime.CompilerServices.CompilerGeneratedAttribute",
"System.Diagnostics.DebuggerBrowsableAttribute" "System.Diagnostics.DebuggerBrowsableAttribute"
}; };

Loading…
Cancel
Save