@@ -449,22 +449,216 @@ public void UsePrivates()
449449 CheckFieldsPropertiesMethods ( myType , expectedFieldNames , expectedPropertyNames , expectedMethodNames ) ;
450450 }
451451
452+ [ Fact ]
453+ public void Record ( )
454+ {
455+ // Compile the referenced assembly first.
456+ Compilation referencedCompilation = CompilationHelper . CreateReferencedLibRecordCompilation ( ) ;
457+
458+ // Emit the image of the referenced assembly.
459+ byte [ ] referencedImage = CompilationHelper . CreateAssemblyImage ( referencedCompilation ) ;
460+
461+ string source = @"
462+ using System.Text.Json.Serialization;
463+
464+ namespace HelloWorld
465+ {
466+ [JsonSerializable(typeof(AppRecord))]
467+ internal partial class JsonContext : JsonSerializerContext
468+ {
469+ }
470+
471+ public record AppRecord(int Id)
472+ {
473+ public string Address1 { get; set; }
474+ public string Address2 { get; set; }
475+ public string City { get; set; }
476+ public string State { get; set; }
477+ public string PostalCode { get; set; }
478+ public string Name { get; set; }
479+ [JsonInclude]
480+ public string PhoneNumber;
481+ [JsonInclude]
482+ public string Country;
483+ }
484+ }" ;
485+
486+ MetadataReference [ ] additionalReferences = { MetadataReference . CreateFromImage ( referencedImage ) } ;
487+
488+ Compilation compilation = CompilationHelper . CreateCompilation ( source ) ;
489+
490+ JsonSourceGenerator generator = new JsonSourceGenerator ( ) ;
491+
492+ Compilation newCompilation = CompilationHelper . RunGenerators ( compilation , out ImmutableArray < Diagnostic > generatorDiags , generator ) ;
493+
494+ // Make sure compilation was successful.
495+ CheckCompilationDiagnosticsErrors ( generatorDiags ) ;
496+ CheckCompilationDiagnosticsErrors ( newCompilation . GetDiagnostics ( ) ) ;
497+
498+ Dictionary < string , Type > types = generator . GetSerializableTypes ( ) ;
499+
500+ // Check base functionality of found types.
501+ Assert . Equal ( 1 , types . Count ) ;
502+ Type recordType = types [ "HelloWorld.AppRecord" ] ;
503+ Assert . Equal ( "HelloWorld.AppRecord" , recordType . FullName ) ;
504+
505+ // Check for received fields, properties and methods for NotMyType.
506+ string [ ] expectedFieldsNames = { "Country" , "PhoneNumber" } ;
507+ string [ ] expectedPropertyNames = { "Address1" , "Address2" , "City" , "Id" , "Name" , "PostalCode" , "State" } ;
508+ CheckFieldsPropertiesMethods ( recordType , expectedFieldsNames , expectedPropertyNames ) ;
509+
510+ Assert . Equal ( 1 , recordType . GetConstructors ( ) . Length ) ;
511+ }
512+
513+ [ Fact ]
514+ public void RecordInExternalAssembly ( )
515+ {
516+ // Compile the referenced assembly first.
517+ Compilation referencedCompilation = CompilationHelper . CreateReferencedLibRecordCompilation ( ) ;
518+
519+ // Emit the image of the referenced assembly.
520+ byte [ ] referencedImage = CompilationHelper . CreateAssemblyImage ( referencedCompilation ) ;
521+
522+ string source = @"
523+ using System.Text.Json.Serialization;
524+ using ReferencedAssembly;
525+
526+ namespace HelloWorld
527+ {
528+ [JsonSerializable(typeof(LibRecord))]
529+ internal partial class JsonContext : JsonSerializerContext
530+ {
531+ }
532+ }" ;
533+
534+ MetadataReference [ ] additionalReferences = { MetadataReference . CreateFromImage ( referencedImage ) } ;
535+
536+ Compilation compilation = CompilationHelper . CreateCompilation ( source , additionalReferences ) ;
537+
538+ JsonSourceGenerator generator = new JsonSourceGenerator ( ) ;
539+
540+ Compilation newCompilation = CompilationHelper . RunGenerators ( compilation , out ImmutableArray < Diagnostic > generatorDiags , generator ) ;
541+
542+ // Make sure compilation was successful.
543+ CheckCompilationDiagnosticsErrors ( generatorDiags ) ;
544+ CheckCompilationDiagnosticsErrors ( newCompilation . GetDiagnostics ( ) ) ;
545+
546+ Dictionary < string , Type > types = generator . GetSerializableTypes ( ) ;
547+
548+ Assert . Equal ( 1 , types . Count ) ;
549+ Type recordType = types [ "ReferencedAssembly.LibRecord" ] ;
550+ Assert . Equal ( "ReferencedAssembly.LibRecord" , recordType . FullName ) ;
551+
552+ string [ ] expectedFieldsNames = { "Country" , "PhoneNumber" } ;
553+ string [ ] expectedPropertyNames = { "Address1" , "Address2" , "City" , "Id" , "Name" , "PostalCode" , "State" } ;
554+ CheckFieldsPropertiesMethods ( recordType , expectedFieldsNames , expectedPropertyNames ) ;
555+
556+ Assert . Equal ( 1 , recordType . GetConstructors ( ) . Length ) ;
557+ }
558+
559+ [ Fact ]
560+ public void RecordDerivedFromRecordInExternalAssembly ( )
561+ {
562+ // Compile the referenced assembly first.
563+ Compilation referencedCompilation = CompilationHelper . CreateReferencedSimpleLibRecordCompilation ( ) ;
564+
565+ // Emit the image of the referenced assembly.
566+ byte [ ] referencedImage = CompilationHelper . CreateAssemblyImage ( referencedCompilation ) ;
567+
568+ string source = @"
569+ using System.Text.Json.Serialization;
570+ using ReferencedAssembly;
571+
572+ namespace HelloWorld
573+ {
574+ [JsonSerializable(typeof(AppRecord))]
575+ internal partial class JsonContext : JsonSerializerContext
576+ {
577+ }
578+
579+ internal record AppRecord : LibRecord
580+ {
581+ public string ExtraData { get; set; }
582+ }
583+ }" ;
584+
585+ MetadataReference [ ] additionalReferences = { MetadataReference . CreateFromImage ( referencedImage ) } ;
586+
587+ Compilation compilation = CompilationHelper . CreateCompilation ( source , additionalReferences ) ;
588+
589+ JsonSourceGenerator generator = new JsonSourceGenerator ( ) ;
590+
591+ Compilation newCompilation = CompilationHelper . RunGenerators ( compilation , out ImmutableArray < Diagnostic > generatorDiags , generator ) ;
592+
593+ // Make sure compilation was successful.
594+ CheckCompilationDiagnosticsErrors ( generatorDiags ) ;
595+ CheckCompilationDiagnosticsErrors ( newCompilation . GetDiagnostics ( ) ) ;
596+
597+ Dictionary < string , Type > types = generator . GetSerializableTypes ( ) ;
598+
599+ Assert . Equal ( 1 , types . Count ) ;
600+ Type recordType = types [ "HelloWorld.AppRecord" ] ;
601+ Assert . Equal ( "HelloWorld.AppRecord" , recordType . FullName ) ;
602+
603+ string [ ] expectedFieldsNames = { "Country" , "PhoneNumber" } ;
604+ string [ ] expectedPropertyNames = { "Address1" , "Address2" , "City" , "ExtraData" , "Id" , "Name" , "PostalCode" , "State" } ;
605+ CheckFieldsPropertiesMethods ( recordType , expectedFieldsNames , expectedPropertyNames , inspectBaseTypes : true ) ;
606+
607+ Assert . Equal ( 1 , recordType . GetConstructors ( ) . Length ) ;
608+ }
609+
452610 private void CheckCompilationDiagnosticsErrors ( ImmutableArray < Diagnostic > diagnostics )
453611 {
454612 Assert . Empty ( diagnostics . Where ( diagnostic => diagnostic . Severity == DiagnosticSeverity . Error ) ) ;
455613 }
456614
457- private void CheckFieldsPropertiesMethods ( Type type , string [ ] expectedFields , string [ ] expectedProperties , string [ ] expectedMethods )
615+ private void CheckFieldsPropertiesMethods (
616+ Type type ,
617+ string [ ] expectedFields ,
618+ string [ ] expectedProperties ,
619+ string [ ] expectedMethods = null ,
620+ bool inspectBaseTypes = false )
458621 {
459622 BindingFlags bindingFlags = BindingFlags . Public | BindingFlags . Instance ;
460623
461- string [ ] receivedFields = type . GetFields ( bindingFlags ) . Select ( field => field . Name ) . OrderBy ( s => s ) . ToArray ( ) ;
462- string [ ] receivedProperties = type . GetProperties ( bindingFlags ) . Select ( property => property . Name ) . OrderBy ( s => s ) . ToArray ( ) ;
624+ string [ ] receivedFields ;
625+ string [ ] receivedProperties ;
626+
627+ if ( ! inspectBaseTypes )
628+ {
629+ receivedFields = type . GetFields ( bindingFlags ) . Select ( field => field . Name ) . OrderBy ( s => s ) . ToArray ( ) ;
630+ receivedProperties = type . GetProperties ( bindingFlags ) . Select ( property => property . Name ) . OrderBy ( s => s ) . ToArray ( ) ;
631+ }
632+ else
633+ {
634+ List < string > fields = new List < string > ( ) ;
635+ List < string > props = new List < string > ( ) ;
636+
637+ Type currentType = type ;
638+ while ( currentType != null )
639+ {
640+ fields . AddRange ( currentType . GetFields ( bindingFlags ) . Select ( property => property . Name ) . OrderBy ( s => s ) . ToArray ( ) ) ;
641+ props . AddRange ( currentType . GetProperties ( bindingFlags ) . Select ( property => property . Name ) . OrderBy ( s => s ) . ToArray ( ) ) ;
642+ currentType = currentType . BaseType ;
643+ }
644+
645+ receivedFields = fields . ToArray ( ) ;
646+ receivedProperties = props . ToArray ( ) ;
647+ }
648+
463649 string [ ] receivedMethods = type . GetMethods ( ) . Select ( method => method . Name ) . OrderBy ( s => s ) . ToArray ( ) ;
464650
651+ Array . Sort ( receivedFields ) ;
652+ Array . Sort ( receivedProperties ) ;
653+ Array . Sort ( receivedMethods ) ;
654+
465655 Assert . Equal ( expectedFields , receivedFields ) ;
466656 Assert . Equal ( expectedProperties , receivedProperties ) ;
467- Assert . Equal ( expectedMethods , receivedMethods ) ;
657+
658+ if ( expectedMethods != null )
659+ {
660+ Assert . Equal ( expectedMethods , receivedMethods ) ;
661+ }
468662 }
469663
470664 // TODO: add test guarding against (de)serializing static classes.
0 commit comments