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. 16
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

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

@ -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 record Properties
{ {
public int A { public int A {

16
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1179,24 +1179,28 @@ namespace ICSharpCode.Decompiler.CSharp
typeDecl.Members.Add(nestedType); 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 (fieldOrProperty.MetadataToken.IsNil || MemberIsHidden(module.PEFile, fieldOrProperty.MetadataToken, settings))
{ {
if (!field.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, field.MetadataToken, settings)) continue;
}
if (fieldOrProperty is IField field)
{ {
if (typeDef.Kind == TypeKind.Enum && !field.IsConst) if (typeDef.Kind == TypeKind.Enum && !field.IsConst)
continue; continue;
var memberDecl = DoDecompile(field, decompileRun, decompilationContext.WithCurrentMember(field)); var memberDecl = DoDecompile(field, decompileRun, decompilationContext.WithCurrentMember(field));
typeDecl.Members.Add(memberDecl); typeDecl.Members.Add(memberDecl);
} }
} else if (fieldOrProperty is IProperty property)
foreach (var property in typeDef.Properties)
{ {
if (recordDecompiler?.PropertyIsGenerated(property) == true) if (recordDecompiler?.PropertyIsGenerated(property) == true)
{ {
continue; continue;
} }
if (!property.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, property.MetadataToken, settings))
{
var propDecl = DoDecompile(property, decompileRun, decompilationContext.WithCurrentMember(property)); var propDecl = DoDecompile(property, decompileRun, decompilationContext.WithCurrentMember(property));
typeDecl.Members.Add(propDecl); typeDecl.Members.Add(propDecl);
} }

21
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -152,13 +152,17 @@ namespace ICSharpCode.Decompiler.CSharp
// need to detect the correct interleaving. // need to detect the correct interleaving.
// We could try to detect this from the PrintMembers body, but let's initially // 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. // restrict ourselves to the common case where the record only uses properties.
if (recordTypeDef.Fields.All(backingFieldToAutoProperty.ContainsKey)) return recordTypeDef.Properties.Concat<IMember>(
{ recordTypeDef.Fields.Where(f => !backingFieldToAutoProperty.ContainsKey(f))
return recordTypeDef.Properties.ToList<IMember>(); ).ToList();
}
return null;
} }
/// <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) bool IsRecordType(IType type)
{ {
return type.GetDefinition() == recordTypeDef return type.GetDefinition() == recordTypeDef
@ -422,6 +426,13 @@ namespace ICSharpCode.Decompiler.CSharp
if (!getterCall.Arguments[0].MatchLdThis()) if (!getterCall.Arguments[0].MatchLdThis())
return false; 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 else
{ {
return false; return false;

Loading…
Cancel
Save