Skip to content

Commit

Permalink
Member resolving fix for derived attributes (#62937) (#63837)
Browse files Browse the repository at this point in the history
* Member resolving fix for derived attributes (#62937)

* Added property with simple [Required] attribute
  • Loading branch information
Kloizdena authored Feb 2, 2022
1 parent e696cba commit ce019b9
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public CustomAttributeDataWrapper(AttributeData a, MetadataLoadContextInternal m
var namedArguments = new List<CustomAttributeNamedArgument>();
foreach (KeyValuePair<string, TypedConstant> na in a.NamedArguments)
{
var member = a.AttributeClass!.GetMembers(na.Key).First();
var member = a.AttributeClass.BaseTypes().SelectMany(t => t.GetMembers(na.Key)).First();

MemberInfo memberInfo = member is IPropertySymbol
? new PropertyInfoWrapper((IPropertySymbol)member, metadataLoadContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public interface ITestContext
public JsonTypeInfo<ClassWithBadCustomConverter> ClassWithBadCustomConverter { get; }
public JsonTypeInfo<StructWithBadCustomConverter> StructWithBadCustomConverter { get; }
public JsonTypeInfo<PersonStruct?> NullablePersonStruct { get; }
public JsonTypeInfo<TypeWithValidationAttributes> TypeWithValidationAttributes { get; }
public JsonTypeInfo<TypeWithDerivedAttribute> TypeWithDerivedAttribute { get; }
}

internal partial class JsonContext : JsonSerializerContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ namespace System.Text.Json.SourceGeneration.Tests
[JsonSerializable(typeof(ClassWithBadCustomConverter))]
[JsonSerializable(typeof(StructWithBadCustomConverter))]
[JsonSerializable(typeof(PersonStruct?))]
[JsonSerializable(typeof(TypeWithValidationAttributes))]
[JsonSerializable(typeof(TypeWithDerivedAttribute))]
internal partial class MetadataAndSerializationContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Default;
Expand Down Expand Up @@ -88,6 +90,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => MetadataAndSerializationContext.Default.StructWithBadCustomConverter);
Assert.Null(MetadataAndSerializationContext.Default.NullablePersonStruct.SerializeHandler);
Assert.NotNull(MetadataAndSerializationContext.Default.PersonStruct.SerializeHandler);
Assert.NotNull(MetadataAndSerializationContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.NotNull(MetadataAndSerializationContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ namespace System.Text.Json.SourceGeneration.Tests
[JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(TypeWithValidationAttributes), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(TypeWithDerivedAttribute), GenerationMode = JsonSourceGenerationMode.Metadata)]
internal partial class MetadataWithPerTypeAttributeContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata;
Expand Down Expand Up @@ -86,6 +88,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => MetadataWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.NullablePersonStruct.SerializeHandler);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.PersonStruct.SerializeHandler);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.Null(MetadataWithPerTypeAttributeContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}
}

Expand Down Expand Up @@ -124,6 +128,8 @@ public override void EnsureFastPathGeneratedAsExpected()
[JsonSerializable(typeof(ClassWithBadCustomConverter))]
[JsonSerializable(typeof(StructWithBadCustomConverter))]
[JsonSerializable(typeof(PersonStruct?))]
[JsonSerializable(typeof(TypeWithValidationAttributes))]
[JsonSerializable(typeof(TypeWithDerivedAttribute))]
internal partial class MetadataContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata;
Expand Down Expand Up @@ -193,6 +199,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => MetadataContext.Default.StructWithBadCustomConverter.SerializeHandler);
Assert.Null(MetadataContext.Default.NullablePersonStruct.SerializeHandler);
Assert.Null(MetadataContext.Default.PersonStruct.SerializeHandler);
Assert.Null(MetadataContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.Null(MetadataContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ namespace System.Text.Json.SourceGeneration.Tests
[JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithValidationAttributes), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithDerivedAttribute), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
internal partial class MixedModeContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization;
Expand Down Expand Up @@ -88,6 +90,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => MixedModeContext.Default.StructWithBadCustomConverter.SerializeHandler);
Assert.Null(MixedModeContext.Default.NullablePersonStruct.SerializeHandler);
Assert.NotNull(MixedModeContext.Default.PersonStruct.SerializeHandler);
Assert.NotNull(MixedModeContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.NotNull(MixedModeContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -882,5 +882,44 @@ public virtual void NullableStruct()
Assert.Equal("Jane", person.Value.FirstName);
Assert.Equal("Doe", person.Value.LastName);
}

[Fact]
public void TypeWithValidationAttributes()
{
var instance = new TypeWithValidationAttributes { Name = "Test Name", Email = "email@test.com" };

string json = JsonSerializer.Serialize(instance, DefaultContext.TypeWithValidationAttributes);
JsonTestHelper.AssertJsonEqual(@"{""Name"":""Test Name"",""Email"":""email@test.com""}", json);
if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization)
{
// Deserialization not supported in fast path serialization only mode
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize(json, DefaultContext.TypeWithValidationAttributes));
}
else
{
instance = JsonSerializer.Deserialize(json, DefaultContext.TypeWithValidationAttributes);
Assert.Equal("Test Name", instance.Name);
Assert.Equal("email@test.com", instance.Email);
}
}

[Fact]
public void TypeWithDerivedAttribute()
{
var instance = new TypeWithDerivedAttribute();

string json = JsonSerializer.Serialize(instance, DefaultContext.TypeWithDerivedAttribute);
JsonTestHelper.AssertJsonEqual(@"{}", json);
if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization)
{
// Deserialization not supported in fast path serialization only mode
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize(json, DefaultContext.TypeWithDerivedAttribute));
}
else
{
instance = JsonSerializer.Deserialize(json, DefaultContext.TypeWithDerivedAttribute);
Assert.NotNull(instance);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ namespace System.Text.Json.SourceGeneration.Tests
[JsonSerializable(typeof(ClassWithBadCustomConverter))]
[JsonSerializable(typeof(StructWithBadCustomConverter))]
[JsonSerializable(typeof(PersonStruct?))]
[JsonSerializable(typeof(TypeWithValidationAttributes))]
[JsonSerializable(typeof(TypeWithDerivedAttribute))]
internal partial class SerializationContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization;
Expand Down Expand Up @@ -80,6 +82,8 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex
[JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithValidationAttributes), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithDerivedAttribute), GenerationMode = JsonSourceGenerationMode.Serialization)]
internal partial class SerializationWithPerTypeAttributeContext : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization;
Expand Down Expand Up @@ -120,6 +124,8 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer
[JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithValidationAttributes), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(TypeWithDerivedAttribute), GenerationMode = JsonSourceGenerationMode.Serialization)]
internal partial class SerializationContextWithCamelCase : JsonSerializerContext, ITestContext
{
public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization;
Expand Down Expand Up @@ -169,6 +175,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => SerializationContext.Default.StructWithBadCustomConverter.SerializeHandler);
Assert.Null(SerializationContext.Default.NullablePersonStruct.SerializeHandler);
Assert.NotNull(SerializationContext.Default.PersonStruct.SerializeHandler);
Assert.NotNull(SerializationContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.NotNull(SerializationContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}

[Fact]
Expand Down Expand Up @@ -492,6 +500,8 @@ public override void EnsureFastPathGeneratedAsExpected()
Assert.Throws<InvalidOperationException>(() => SerializationWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler);
Assert.Null(SerializationWithPerTypeAttributeContext.Default.NullablePersonStruct.SerializeHandler);
Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.PersonStruct.SerializeHandler);
Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.TypeWithValidationAttributes.SerializeHandler);
Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.TypeWithDerivedAttribute.SerializeHandler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,26 @@ public struct PersonStruct
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class TypeWithValidationAttributes
{
[ComponentModel.DataAnnotations.Required(ErrorMessage = "Name is required")]
[ComponentModel.DataAnnotations.StringLength(100, ErrorMessage = "Name must not be longer than 100 characters")]
public string Name { get; set; }

[ComponentModel.DataAnnotations.Required]
public string Email { get; set; }
}

public class BaseAttribute : Attribute
{
public string TestProperty { get; set; }
}

public class DerivedAttribute : BaseAttribute
{ }

[Derived(TestProperty = "Test")]
public class TypeWithDerivedAttribute
{ }
}

0 comments on commit ce019b9

Please sign in to comment.