Skip to content

Commit

Permalink
fix record PrintMembers() handling of positional properties of refere…
Browse files Browse the repository at this point in the history
…nce types

Only positional properties typed as string, primitive types or type parameters were being handled.
Positional properties of all other reference types would simply be ignored in by PrintMembers()
  • Loading branch information
adrianoc committed Jun 18, 2024
1 parent 7728c23 commit 254402a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
13 changes: 13 additions & 0 deletions Cecilifier.Core.Tests/Tests/OutputBased/RecordTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ public void RecordPropertyAccess()
record Record(int Value);
""",
"42");
}

[Test]
public void CyclicReferences()
{
AssertOutput(
"""
var ri = new Record("Child", new Record("Parent", null));
System.Console.WriteLine($"{ri.Name},{ri.Other.Equals(ri.Other)},{ri}");

record Record(string Name, Record Other);
""",
"Child,True,Record { Name = Child, Other = Record { Name = Parent, Other = } }");
}
}

Expand Down
23 changes: 16 additions & 7 deletions Cecilifier.Core/CodeGeneration/Record.Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,14 +569,23 @@ string PrintMembersMethodToCall()

static IMethodSymbol StringBuilderAppendMethodFor(IVisitorContext context, ITypeSymbol type, ITypeSymbol stringBuilderSymbol)
{
// if type is a generic type parameter we should use the `object` overload instead and box.
var targetType = type.TypeKind == TypeKind.TypeParameter ? context.RoslynTypeSystem.SystemObject : type;
var stringBuilderAppendMethod = stringBuilderSymbol
.GetMembers("Append")
.OfType<IMethodSymbol>()
.SingleOrDefault(m => m.Parameters.Length == 1 && SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, targetType));
var stringBuilderAppendMethod = AppendMethodFor(stringBuilderSymbol, type);
if (stringBuilderAppendMethod != null)
return stringBuilderAppendMethod;

// if type is a generic type parameter or a class use the `object` overload instead.
return type.TypeKind == TypeKind.TypeParameter || !type.IsValueType
? AppendMethodFor(stringBuilderSymbol, context.RoslynTypeSystem.SystemObject)
:null;

return stringBuilderAppendMethod;
static IMethodSymbol AppendMethodFor(ITypeSymbol typeSymbol, ITypeSymbol type)
{
var stringBuilderAppendMethod = typeSymbol
.GetMembers("Append")
.OfType<IMethodSymbol>()
.SingleOrDefault(m => m.Parameters.Length == 1 && SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, type));
return stringBuilderAppendMethod;
}
}
}

Expand Down

0 comments on commit 254402a

Please sign in to comment.