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

26
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1225,7 +1225,31 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1225,7 +1225,31 @@ namespace ICSharpCode.Decompiler.CSharp
if (recordDecompiler?.PrimaryConstructor != null)
{
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)

14
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (method.IsStatic || !method.IsConstructor)
continue;
var m = method.Specialize(subst);
if (IsPrimaryConstructor(m))
if (IsPrimaryConstructor(m, method))
return method;
primaryCtorParameterToAutoProperty.Clear();
autoPropertyToPrimaryCtorParameter.Clear();
@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.CSharp
return null;
bool IsPrimaryConstructor(IMethod method)
bool IsPrimaryConstructor(IMethod method, IMethod unspecializedMethod)
{
Debug.Assert(method.IsConstructor);
var body = DecompileBody(method);
@ -202,8 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -202,8 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (!backingFieldToAutoProperty.TryGetValue(field, out var property))
return false;
primaryCtorParameterToAutoProperty.Add(method.Parameters[i], property);
autoPropertyToPrimaryCtorParameter.Add(property, method.Parameters[i]);
primaryCtorParameterToAutoProperty.Add(unspecializedMethod.Parameters[i], property);
autoPropertyToPrimaryCtorParameter.Add(property, unspecializedMethod.Parameters[i]);
}
if (!isStruct)
@ -331,6 +331,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -331,6 +331,12 @@ namespace ICSharpCode.Decompiler.CSharp
&& 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)
{
if (method == null)

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

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

Loading…
Cancel
Save