@@ -79,22 +79,24 @@ private string Generate(TypeMeta typeMeta, ConstructorMeta constructorMeta)
7979#pragma warning disable CS8602 // Dereference of a possibly null reference.
8080#pragma warning disable CS8603 // Possible null reference return.
8181#pragma warning disable CS8604 // Possible null reference argument for parameter.
82- #pragma warning disable CS8619 // Possible null reference assignment fix
82+ #pragma warning disable CS8619 // Possible null reference assignment fix.
83+ #pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
8384
8485using CsToml;
86+ using CsToml.Error;
8587using CsToml.Formatter;
8688using CsToml.Formatter.Resolver;
8789
8890{{ namespaceTag }}
8991
90- partial {{ typeMeta . TypeKeyword }} {{ typeMeta . TypeName }} : ITomlSerializedObject<{{ typeMeta . TypeName }} >
92+ partial {{ typeMeta . TypeKeyword }} {{ typeMeta . TypeName }} : ITomlSerializedObject<{{ typeMeta . GenericTypeParameterName }} >
9193{
9294
93- static {{ typeMeta . TypeName }} ITomlSerializedObject<{{ typeMeta . TypeName }} >.Deserialize(ref TomlDocumentNode rootNode, CsTomlSerializerOptions options)
95+ static {{ typeMeta . GenericTypeParameterName }} ITomlSerializedObject<{{ typeMeta . GenericTypeParameterName }} >.Deserialize(ref TomlDocumentNode rootNode, CsTomlSerializerOptions options)
9496 {
9597{{ GenerateDeserializePart ( typeMeta , constructorMeta ) }} }
9698
97- static void ITomlSerializedObject<{{ typeMeta . TypeName }} >.Serialize<TBufferWriter>(ref Utf8TomlDocumentWriter<TBufferWriter> writer, {{ typeMeta . TypeName }} target, CsTomlSerializerOptions options)
99+ static void ITomlSerializedObject<{{ typeMeta . GenericTypeParameterName }} >.Serialize<TBufferWriter>(ref Utf8TomlDocumentWriter<TBufferWriter> writer, {{ typeMeta . GenericTypeParameterName }} target, CsTomlSerializerOptions options)
98100 {
99101{{ GenerateSerializePart ( typeMeta ) }} }
100102
@@ -112,6 +114,14 @@ private string GenerateDeserializePart(TypeMeta typeMeta, ConstructorMeta constr
112114 {
113115 var builder = new StringBuilder ( ) ;
114116
117+ if ( typeMeta . IsReferenceType )
118+ {
119+ builder . AppendLine ( $$ """
120+ if (!(rootNode.HasValue || rootNode.IsTableHeader)) return default;
121+
122+ """ ) ;
123+ }
124+
115125 foreach ( var member in typeMeta . Members )
116126 {
117127 var propertyName = member . DefinedName ;
@@ -178,6 +188,14 @@ private string GenerateSerializePart(TypeMeta typeMeta)
178188 {
179189 var builder = new StringBuilder ( ) ;
180190
191+ if ( typeMeta . IsReferenceType )
192+ {
193+ builder . AppendLine ( $$ """
194+ if (target == null) ThrowIfNull(nameof(target));
195+
196+ """ ) ;
197+ }
198+
181199 var members = typeMeta . Members ;
182200 var onlyTomlSerializedObject = members . Length == 1 && members [ 0 ] . SerializationKind == TomlSerializationKind . TomlSerializedObject ;
183201 if ( ! onlyTomlSerializedObject )
@@ -355,6 +373,17 @@ private string GenerateSerializePart(TypeMeta typeMeta)
355373 {
356374 builder . AppendLine ( " writer.EndScope();" ) ;
357375 }
376+
377+ if ( typeMeta . IsReferenceType )
378+ {
379+ builder . AppendLine ( $$ """
380+
381+ static void ThrowIfNull(string args)
382+ {
383+ throw new CsTomlException($@"Serialization failed because the argument '{args}' is null.");
384+ }
385+ """ ) ;
386+ }
358387 return builder . ToString ( ) ;
359388 }
360389
@@ -397,19 +426,52 @@ private string GenerateRegisterPart(TypeMeta typeMeta)
397426""" ) ;
398427 break ;
399428 case TomlSerializationKind . CollectionOfITomlSerializedObject :
400- if ( FormatterTypeMetaData . TryGetGenericFormatterType ( type , out var formatter ) != GenericFormatterType . None )
429+ if ( type is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol . IsGenericType )
401430 {
402- var collectionNamedType = ( INamedTypeSymbol ) type ;
403- var typeParameters = string . Join ( "," , collectionNamedType . TypeArguments . Select ( x => x . ToFullFormatString ( ) ) ) ;
404- formatter = formatter ! . Replace ( "TYPEPARAMETER" , typeParameters ) ;
431+ // Nullable<T> is a special case.
432+ var typeSymbol = namedTypeSymbol . ConstructUnboundGenericType ( ) ;
433+ if ( typeSymbol . ToDisplayString ( ) == "T?" )
434+ {
435+ builder . AppendLine ( $$ """
436+ if (!TomlValueFormatterResolver.IsRegistered<{{ fullTypeName }} >())
437+ {
438+ TomlValueFormatterResolver.Register(new NullableFormatter<{{ namedTypeSymbol . TypeArguments [ 0 ] . ToFullFormatString ( ) }} >());
439+ }
440+ """ ) ;
441+ break ;
442+ }
405443
406- builder . AppendLine ( $$ """
444+ if ( FormatterTypeMetaData . TryGetGenericFormatterType ( typeSymbol . ToFullFormatString ( ) , out var typeFormatter ) != GenericFormatterType . None )
445+ {
446+ var typeParameters = string . Join ( "," , namedTypeSymbol . TypeArguments . Select ( x => x . ToFullFormatString ( ) ) ) ;
447+ typeFormatter = typeFormatter . Replace ( "TYPEPARAMETER" , typeParameters ) ;
448+
449+ builder . AppendLine ( $$ """
450+ if (!TomlValueFormatterResolver.IsRegistered<{{ fullTypeName }} >())
451+ {
452+ TomlValueFormatterResolver.Register(new {{ typeFormatter }} ());
453+ }
454+ """ ) ;
455+ break ;
456+ }
457+ }
458+ else
459+ {
460+ if ( FormatterTypeMetaData . TryGetGenericFormatterType ( type , out var formatter ) != GenericFormatterType . None )
461+ {
462+ var collectionNamedType = ( INamedTypeSymbol ) type ;
463+ var typeParameters = string . Join ( "," , collectionNamedType . TypeArguments . Select ( x => x . ToFullFormatString ( ) ) ) ;
464+ formatter = formatter ! . Replace ( "TYPEPARAMETER" , typeParameters ) ;
465+
466+ builder . AppendLine ( $$ """
407467 if (!TomlValueFormatterResolver.IsRegistered<{{ fullTypeName }} >())
408468 {
409469 TomlValueFormatterResolver.Register(new {{ formatter }} ());
410470 }
411471""" ) ;
472+ }
412473 }
474+
413475 break ;
414476 case TomlSerializationKind . Dictionary :
415477 if ( FormatterTypeMetaData . TryGetGenericFormatterType ( type , out var dictFormatter ) != GenericFormatterType . None )
@@ -442,24 +504,24 @@ private string GenerateRegisterPart(TypeMeta typeMeta)
442504 if ( FormatterTypeMetaData . ContainsBuiltInFormatterType ( type ) )
443505 break ;
444506
445- if ( type is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol . IsGenericType )
507+ if ( type is INamedTypeSymbol namedTypeSymbol2 && namedTypeSymbol2 . IsGenericType )
446508 {
447509 // Nullable<T> is a special case.
448- var typeSymbol = namedTypeSymbol . ConstructUnboundGenericType ( ) ;
510+ var typeSymbol = namedTypeSymbol2 . ConstructUnboundGenericType ( ) ;
449511 if ( typeSymbol . ToDisplayString ( ) == "T?" )
450512 {
451513 builder . AppendLine ( $$ """
452514 if (!TomlValueFormatterResolver.IsRegistered<{{ fullTypeName }} >())
453515 {
454- TomlValueFormatterResolver.Register(new NullableFormatter<{{ namedTypeSymbol . TypeArguments [ 0 ] . ToFullFormatString ( ) }} >());
516+ TomlValueFormatterResolver.Register(new NullableFormatter<{{ namedTypeSymbol2 . TypeArguments [ 0 ] . ToFullFormatString ( ) }} >());
455517 }
456518""" ) ;
457519 break ;
458520 }
459521
460522 if ( FormatterTypeMetaData . TryGetGenericFormatterType ( typeSymbol . ToFullFormatString ( ) , out var typeFormatter ) != GenericFormatterType . None )
461523 {
462- var typeParameters = string . Join ( "," , namedTypeSymbol . TypeArguments . Select ( x => x . ToFullFormatString ( ) ) ) ;
524+ var typeParameters = string . Join ( "," , namedTypeSymbol2 . TypeArguments . Select ( x => x . ToFullFormatString ( ) ) ) ;
463525 typeFormatter = typeFormatter . Replace ( "TYPEPARAMETER" , typeParameters ) ;
464526
465527 builder . AppendLine ( $$ """
@@ -475,7 +537,9 @@ private string GenerateRegisterPart(TypeMeta typeMeta)
475537 }
476538 }
477539
478- var code = $$ """
540+ if ( typeMeta . IsReferenceType )
541+ {
542+ var code = $$ """
479543 if (!TomlValueFormatterResolver.IsRegistered<{{ typeMeta . TypeName }} >())
480544 {
481545 TomlValueFormatterResolver.Register(new TomlSerializedObjectFormatter<{{ typeMeta . TypeName }} >());
@@ -484,7 +548,21 @@ private string GenerateRegisterPart(TypeMeta typeMeta)
484548 // Register Formatter in advance.
485549{{ builder }}
486550""" ;
487- return code ;
551+ return code ;
552+ }
553+ else
554+ {
555+ var code = $$ """
556+ if (!TomlValueFormatterResolver.IsRegistered<{{ typeMeta . TypeName }} >())
557+ {
558+ TomlValueFormatterResolver.Register(new StructTomlSerializedObjectFormatter<{{ typeMeta . TypeName }} >());
559+ }
560+
561+ // Register Formatter in advance.
562+ {{ builder }}
563+ """ ;
564+ return code ;
565+ }
488566 }
489567}
490568
0 commit comments