Browse Source

Records: support for fields.

pull/2251/head
Daniel Grunwald 4 years ago
parent
commit
0bf6d552e0
  1. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  2. 24
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

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

@ -4,6 +4,15 @@ @@ -4,6 +4,15 @@
{
}
public record Fields
{
public int A;
public double B = 1.0;
public object C;
public dynamic D;
public string S = "abc";
}
public record Properties
{
public int A {

24
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1179,24 +1179,28 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1179,24 +1179,28 @@ namespace ICSharpCode.Decompiler.CSharp
typeDecl.Members.Add(nestedType);
}
}
foreach (var field in typeDef.Fields)
// With C# 9 records, the relative order of fields and properties matters:
IEnumerable<IMember> fieldsAndProperties = recordDecompiler?.FieldsAndProperties
?? typeDef.Fields.Concat<IMember>(typeDef.Properties);
foreach (var fieldOrProperty in fieldsAndProperties)
{
if (!field.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, field.MetadataToken, settings))
if (fieldOrProperty.MetadataToken.IsNil || MemberIsHidden(module.PEFile, fieldOrProperty.MetadataToken, settings))
{
continue;
}
if (fieldOrProperty is IField field)
{
if (typeDef.Kind == TypeKind.Enum && !field.IsConst)
continue;
var memberDecl = DoDecompile(field, decompileRun, decompilationContext.WithCurrentMember(field));
typeDecl.Members.Add(memberDecl);
}
}
foreach (var property in typeDef.Properties)
{
if (recordDecompiler?.PropertyIsGenerated(property) == true)
{
continue;
}
if (!property.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, property.MetadataToken, settings))
else if (fieldOrProperty is IProperty property)
{
if (recordDecompiler?.PropertyIsGenerated(property) == true)
{
continue;
}
var propDecl = DoDecompile(property, decompileRun, decompilationContext.WithCurrentMember(property));
typeDecl.Members.Add(propDecl);
}

21
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -152,13 +152,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -152,13 +152,17 @@ namespace ICSharpCode.Decompiler.CSharp
// need to detect the correct interleaving.
// We could try to detect this from the PrintMembers body, but let's initially
// restrict ourselves to the common case where the record only uses properties.
if (recordTypeDef.Fields.All(backingFieldToAutoProperty.ContainsKey))
{
return recordTypeDef.Properties.ToList<IMember>();
}
return null;
return recordTypeDef.Properties.Concat<IMember>(
recordTypeDef.Fields.Where(f => !backingFieldToAutoProperty.ContainsKey(f))
).ToList();
}
/// <summary>
/// Gets the fields and properties of the record type, interleaved as necessary to
/// maintain Equals/ToString/etc. semantics.
/// </summary>
public IEnumerable<IMember> FieldsAndProperties => orderedMembers;
bool IsRecordType(IType type)
{
return type.GetDefinition() == recordTypeDef
@ -422,6 +426,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -422,6 +426,13 @@ namespace ICSharpCode.Decompiler.CSharp
if (!getterCall.Arguments[0].MatchLdThis())
return false;
}
else if (val.MatchLdFld(out var target, out var field) || val.MatchLdFlda(out target, out field))
{
if (!target.MatchLdThis())
return false;
if (!field.MemberDefinition.Equals(member))
return false;
}
else
{
return false;

Loading…
Cancel
Save