Skip to content

Commit

Permalink
Fix recursive type support when consuming source generated code from …
Browse files Browse the repository at this point in the history
…the .NET 6 sdk. (#86821)
  • Loading branch information
eiriktsarpalis committed May 31, 2023
1 parent 4ac21d7 commit 1af3c9e
Show file tree
Hide file tree
Showing 19 changed files with 544 additions and 123 deletions.
Expand Up @@ -569,9 +569,9 @@ private void GeneratePropMetadataInitFunc(SourceWriter writer, string propInitMe
string getterValue = property switch
{
{ DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null",
{ CanUseGetter: true } => $"static (obj) => (({declaringTypeFQN})obj).{propertyName}",
{ CanUseGetter: true } => $"static obj => (({declaringTypeFQN})obj).{propertyName}",
{ CanUseGetter: false, HasJsonInclude: true }
=> $"""static (obj) => throw new {InvalidOperationExceptionTypeRef}("{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.TypeRef.Name, propertyName)}")""",
=> $"""static _ => throw new {InvalidOperationExceptionTypeRef}("{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.TypeRef.Name, propertyName)}")""",
_ => "null"
};

Expand Down Expand Up @@ -838,7 +838,7 @@ private static string GetParameterizedCtorInvocationFunc(TypeGenerationSpec type

const string ArgsVarName = "args";

StringBuilder sb = new($"static ({ArgsVarName}) => new {typeGenerationSpec.TypeRef.FullyQualifiedName}(");
StringBuilder sb = new($"static {ArgsVarName} => new {typeGenerationSpec.TypeRef.FullyQualifiedName}(");

if (parameters.Count > 0)
{
Expand Down
Expand Up @@ -102,7 +102,7 @@ private static void PopulateProperties(JsonTypeInfo typeInfo)

if (state.IsPropertyOrderSpecified)
{
typeInfo.SortProperties();
typeInfo.PropertyList.SortProperties();
}
}

Expand Down Expand Up @@ -210,7 +210,7 @@ private static void PopulateProperties(JsonTypeInfo typeInfo)
}

Debug.Assert(jsonPropertyInfo.Name != null);
typeInfo.AddProperty(jsonPropertyInfo, ref state);
typeInfo.PropertyList.AddPropertyWithConflictResolution(jsonPropertyInfo, ref state);
}

[RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
Expand Down
Expand Up @@ -14,7 +14,7 @@ public static partial class JsonMetadataServices
/// </summary>
private static JsonTypeInfo<T> CreateCore<T>(JsonConverter converter, JsonSerializerOptions options)
{
JsonTypeInfo<T> typeInfo = new JsonTypeInfo<T>(converter, options);
var typeInfo = new JsonTypeInfo<T>(converter, options);
typeInfo.PopulatePolymorphismMetadata();
typeInfo.MapInterfaceTypesToCallbacks();

Expand All @@ -29,7 +29,7 @@ private static JsonTypeInfo<T> CreateCore<T>(JsonConverter converter, JsonSerial
private static JsonTypeInfo<T> CreateCore<T>(JsonSerializerOptions options, JsonObjectInfoValues<T> objectInfo)
{
JsonConverter<T> converter = GetConverter(objectInfo);
JsonTypeInfo<T> typeInfo = new JsonTypeInfo<T>(converter, options);
var typeInfo = new JsonTypeInfo<T>(converter, options);
if (objectInfo.ObjectWithParameterizedConstructorCreator != null)
{
typeInfo.CreateObjectWithArgs = objectInfo.ObjectWithParameterizedConstructorCreator;
Expand All @@ -41,7 +41,15 @@ private static JsonTypeInfo<T> CreateCore<T>(JsonSerializerOptions options, Json
typeInfo.CreateObjectForExtensionDataProperty = ((JsonTypeInfo)typeInfo).CreateObject;
}

PopulateProperties(typeInfo, objectInfo.PropertyMetadataInitializer);
if (objectInfo.PropertyMetadataInitializer != null)
{
typeInfo.SourceGenDelayedPropertyInitializer = objectInfo.PropertyMetadataInitializer;
}
else
{
typeInfo.PropertyMetadataSerializationNotSupported = true;
}

typeInfo.SerializeHandler = objectInfo.SerializeHandler;
typeInfo.NumberHandling = objectInfo.NumberHandling;
typeInfo.PopulatePolymorphismMetadata();
Expand All @@ -62,15 +70,16 @@ private static JsonTypeInfo<T> CreateCore<T>(JsonSerializerOptions options, Json
object? createObjectWithArgs = null,
object? addFunc = null)
{
if (collectionInfo is null)
{
ThrowHelper.ThrowArgumentNullException(nameof(collectionInfo));
}

converter = collectionInfo.SerializeHandler != null
? new JsonMetadataServicesConverter<T>(converter)
: converter;

JsonTypeInfo<T> typeInfo = new JsonTypeInfo<T>(converter, options);
if (collectionInfo is null)
{
ThrowHelper.ThrowArgumentNullException(nameof(collectionInfo));
}

typeInfo.KeyTypeInfo = collectionInfo.KeyInfo;
typeInfo.ElementTypeInfo = collectionInfo.ElementInfo;
Expand Down Expand Up @@ -116,28 +125,15 @@ private static void PopulateParameterInfoValues(JsonTypeInfo typeInfo, Func<Json
}
}

private static void PopulateProperties(JsonTypeInfo typeInfo, Func<JsonSerializerContext, JsonPropertyInfo[]?>? propInitFunc)
internal static void PopulateProperties(JsonTypeInfo typeInfo, JsonTypeInfo.JsonPropertyInfoList propertyList, Func<JsonSerializerContext, JsonPropertyInfo[]> propInitFunc)
{
Debug.Assert(typeInfo.Kind is JsonTypeInfoKind.Object);
Debug.Assert(!typeInfo.IsReadOnly);

JsonSerializerContext? context = (typeInfo.OriginatingResolver ?? typeInfo.Options.TypeInfoResolver) as JsonSerializerContext;
if (propInitFunc?.Invoke(context!) is not JsonPropertyInfo[] properties)
{
if (typeInfo.Type == JsonTypeInfo.ObjectType)
{
return;
}
Debug.Assert(!typeInfo.IsConfigured);
Debug.Assert(typeInfo.Type != JsonTypeInfo.ObjectType);
Debug.Assert(typeInfo.Converter.ElementType is null);

if (typeInfo.Converter.ElementType != null)
{
// Nullable<> or F# optional converter strategy is set to element strategy
return;
}

typeInfo.PropertyMetadataSerializationNotSupported = true;
return;
}
JsonSerializerContext? context = typeInfo.Options.TypeInfoResolver as JsonSerializerContext;
JsonPropertyInfo[] properties = propInitFunc(context!);

// TODO update the source generator so that all property
// hierarchy resolution is happening at compile time.
Expand All @@ -161,7 +157,7 @@ private static void PopulateProperties(JsonTypeInfo typeInfo, Func<JsonSerialize
continue;
}

typeInfo.AddProperty(jsonPropertyInfo, ref state);
propertyList.AddPropertyWithConflictResolution(jsonPropertyInfo, ref state);
}

// NB we don't need to sort source gen properties here since they were already sorted at compile time.
Expand Down
Expand Up @@ -5,7 +5,6 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json.Reflection;

namespace System.Text.Json.Serialization.Metadata
{
Expand Down

0 comments on commit 1af3c9e

Please sign in to comment.