Skip to content

Commit

Permalink
wip: handle generic records (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianoc committed Jun 7, 2024
1 parent 57f44bb commit 4065bf2
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 34 deletions.
19 changes: 18 additions & 1 deletion Cecilifier.Core.Tests/Tests/OutputBased/RecordTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,24 @@ record Derived2(int Value, string Name, bool IsCool) : Derived(Value, Name);
"42,Foo,True");
}
}


[TestFixture]
public class Generics : OutputBasedTestBase
{
[Test]
public void X()
{
AssertOutput(
"""
var ri = new Record<int>(42);
System.Console.WriteLine($"{ri}");
record Record<T>(T Value);
""",
"Record { Value = 42 }");
}
}

[Test]
public void Constructor_WhenInheritFromRecordWithProperties_CorrectArgumentsArePassed()
{
Expand Down
20 changes: 14 additions & 6 deletions Cecilifier.Core/CodeGeneration/PrimaryConstructor.Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ internal static void AddPropertiesFrom(IVisitorContext context, string typeDefin
if (type.ParameterList is null)
return;

var declaringTypeIsGeneric = type.TypeParameterList?.Parameters.Count > 0;
foreach (var parameter in type.GetUniqueParameters(context))
{
AddPropertyFor(context, parameter, typeDefinitionVariable);
AddPropertyFor(context, parameter, typeDefinitionVariable, declaringTypeIsGeneric);
context.WriteNewLine();
}
}

private static void AddPropertyFor(IVisitorContext context, ParameterSyntax parameter, string typeDefinitionVariable)
private static void AddPropertyFor(IVisitorContext context, ParameterSyntax parameter, string typeDefinitionVariable, bool declaringTypeIsGeneric)
{
using var _ = LineInformationTracker.Track(context, parameter);

Expand All @@ -55,7 +56,7 @@ private static void AddPropertyFor(IVisitorContext context, ParameterSyntax para
var propertyData = new PropertyGenerationData(
declaringTypeVariable.MemberName,
declaringTypeVariable.VariableName,
false, // TODO
declaringTypeIsGeneric,
propDefVar,
parameter.Identifier.Text,
new Dictionary<string, string>
Expand All @@ -74,7 +75,6 @@ private static void AddPropertyFor(IVisitorContext context, ParameterSyntax para
PropertyGenerator propertyGenerator = new (context);

AddGetter();
context.WriteNewLine();
AddInit();

void AddGetter()
Expand All @@ -89,6 +89,7 @@ void AddGetter()

propertyGenerator.AddAutoGetterMethodImplementation(in propertyData, ilVar, getMethodVar);
}
context.WriteNewLine();
}

void AddInit()
Expand All @@ -103,12 +104,13 @@ void AddInit()
propertyGenerator.AddAutoSetterMethodImplementation(in propertyData, ilVar, setMethodVar);
context.EmitCilInstruction(ilVar, OpCodes.Ret);
}
context.WriteNewLine();
}
}

internal static void AddPrimaryConstructor(IVisitorContext context, string recordTypeDefinitionVariable, TypeDeclarationSyntax typeDeclaration)
{
context.WriteComment($"Constructor: {typeDeclaration.Identifier.ValueText()}{typeDeclaration.ParameterList}");
context.WriteComment($"Constructor: {typeDeclaration.Identifier.ValueText}{typeDeclaration.ParameterList}");
var ctorVar = context.Naming.Constructor(typeDeclaration, false);
var ctorExp = CecilDefinitionsFactory.Constructor(
context,
Expand All @@ -131,6 +133,12 @@ internal static void AddPrimaryConstructor(IVisitorContext context, string recor
var ctorExps = CecilDefinitionsFactory.MethodBody(context.Naming, $"ctor_{typeDeclaration.Identifier.ValueText}", ctorVar, ctorIlVar, [], []);
context.WriteCecilExpressions(ctorExps);

var typeSymbol = context.SemanticModel.GetDeclaredSymbol(typeDeclaration).EnsureNotNull<ISymbol, ITypeSymbol>();
var resolvedType = context.TypeResolver.Resolve(typeSymbol);
Func<string, string> fieldRefResolver = backingFieldVar => typeDeclaration.TypeParameterList.Parameters.Count > 0
? $"new FieldReference({backingFieldVar}.Name, {backingFieldVar}.FieldType, {resolvedType})"
: backingFieldVar;

var uniqueParameters = typeDeclaration.GetUniqueParameters(context).ToHashSet();
foreach (var parameter in typeDeclaration.ParameterList.Parameters)
{
Expand All @@ -150,7 +158,7 @@ internal static void AddPrimaryConstructor(IVisitorContext context, string recor
if (!backingFieldVar.IsValid)
throw new InvalidOperationException($"Backing field variable for property '{parameter.Identifier.ValueText}' could not be found.");

context.EmitCilInstruction(ctorIlVar, OpCodes.Stfld, backingFieldVar.VariableName);
context.EmitCilInstruction(ctorIlVar, OpCodes.Stfld, fieldRefResolver(backingFieldVar.VariableName));
}

InvokeBaseConstructor(context, ctorIlVar, typeDeclaration);
Expand Down
Loading

0 comments on commit 4065bf2

Please sign in to comment.