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