diff --git a/src/CarpaNet.SourceGen/Generation/CborContextGenerator.cs b/src/CarpaNet.SourceGen/Generation/CborContextGenerator.cs index d35c3ef..71a0894 100644 --- a/src/CarpaNet.SourceGen/Generation/CborContextGenerator.cs +++ b/src/CarpaNet.SourceGen/Generation/CborContextGenerator.cs @@ -604,6 +604,12 @@ private static string GetArrayConverterExpression( return ListConverterRef(refType, CborTypeInfoRef(refType)); } + if (refKind == LexiconTypeKind.Array) + { + var innerConverter = GetConverterExpressionForArrayRef(items.Ref!, currentNsid, registry); + return ListConverterRef(refType, innerConverter); + } + var converter = GetPrimitiveConverterForRef(items.Ref!, currentNsid, registry); return ListConverterRef(refType, converter); } diff --git a/tests/CarpaNet.UnitTests/Generation/CborContextGeneratorTests.cs b/tests/CarpaNet.UnitTests/Generation/CborContextGeneratorTests.cs new file mode 100644 index 0000000..fa8f01a --- /dev/null +++ b/tests/CarpaNet.UnitTests/Generation/CborContextGeneratorTests.cs @@ -0,0 +1,67 @@ +using CarpaNet.Generation; +using CarpaNet.Models; +using CarpaNet.Utilities; + +using Xunit; + +namespace CarpaNet.UnitTests.Generation; + +public class CborContextGeneratorTests +{ + [Fact] + public void ArrayOfArrayRef_UsesListConverterNotStringConverter() + { + // Arrange: reproduce the MebiByte pattern where "transform" is an array + // of "transformRow" refs, and "transformRow" is itself an array of strings. + // Without the fix, the inner List element gets a StringCborConverter + // instead of a CborListTypeInfo. + var registry = new TypeRegistry(); + var doc = new LexiconDocument + { + Id = "test.nested.array", + Defs = new Dictionary + { + ["transformRow"] = new LexiconDefinition + { + Type = "array", + Items = new LexiconDefinition { Type = "string" }, + }, + ["main"] = new LexiconDefinition + { + Type = "object", + Properties = new Dictionary + { + ["transform"] = new LexiconDefinition + { + Type = "array", + Items = new LexiconDefinition + { + Type = "ref", + Ref = "#transformRow", + }, + }, + }, + }, + }, + }; + registry.RegisterDocument(doc); + + var sb = new SourceBuilder(); + var options = new GeneratorOptions(); + var mainDef = doc.Defs["main"]; + + // Act + CborContextGenerator.GenerateCborTypeInfo( + sb, "TestNested.Array.DefsMain", "TestNested_Array_DefsMain", + mainDef, "test.nested.array", registry, options); + + var result = sb.ToString(); + + // Assert: the transform property should wrap the inner List in a + // CborListTypeInfo, not pass a StringCborConverter directly as the element + // converter for List>. + // Correct: CborListTypeInfo>( CborListTypeInfo( StringCborConverter ) ) + // Wrong: CborListTypeInfo>( StringCborConverter ) + Assert.Contains("new CarpaNet.Cbor.CborListTypeInfo>(new CarpaNet.Cbor.CborListTypeInfo(new CarpaNet.Cbor.Converters.StringCborConverter()))", result); + } +}