Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not use FQNs when referencing core STJ types. #94428

Closed

Conversation

eiriktsarpalis
Copy link
Member

Inspired by #94267, this PR updates the STJ source generator so that fully qualified names are not used for core STJ types employed by the source generator (while still using them for all types that the generator targets). This should serve to improve readability of generated code, while not impacting type disambiguation.

Before

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70
{
    public partial class Net70GeneratedContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? _WeatherForecastWithPOCOs;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> WeatherForecastWithPOCOs
        {
            get => _WeatherForecastWithPOCOs ??= Create_WeatherForecastWithPOCOs(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> Create_WeatherForecastWithPOCOs(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, customConverter);
            }
            else
            {
                global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>()
                {
                    ObjectCreator = static () => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastWithPOCOsPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    NumberHandling = default,
                    SerializeHandler = WeatherForecastWithPOCOsSerializeHandler
                };
        
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, objectInfo);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
        private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] WeatherForecastWithPOCOsPropInit(global::System.Text.Json.JsonSerializerOptions options)
        {
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[7];
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTimeOffset> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTimeOffset>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Date",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.DateTimeOffset>(options, info0);
            properties[0] = propertyInfo0;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32> info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo1 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Int32>(options, info1);
            properties[1] = propertyInfo1;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info2 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo2 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info2);
            properties[2] = propertyInfo2;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>> info3 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "DatesAvailable",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo3 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.List<global::System.DateTimeOffset>>(options, info3);
            properties[3] = propertyInfo3;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>> info4 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureRanges",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo4 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>(options, info4);
            properties[4] = propertyInfo4;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String[]> info5 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String[]>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "SummaryWords",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo5 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String[]>(options, info5);
            properties[5] = propertyInfo5;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info6 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = false,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "SummaryField",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo6 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info6);
            properties[6] = propertyInfo6;
        
            return properties;
        }
        
        // Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
        // methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
        private void WeatherForecastWithPOCOsSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
        
            writer.WriteStartObject();
            writer.WriteString(PropName_Date, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Date);
            writer.WriteNumber(PropName_TemperatureCelsius, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureCelsius);
            writer.WriteString(PropName_Summary, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Summary);
            writer.WritePropertyName(PropName_DatesAvailable);
            ListDateTimeOffsetSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).DatesAvailable!);
            writer.WritePropertyName(PropName_TemperatureRanges);
            DictionaryStringHighLowTempsSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureRanges!);
            writer.WritePropertyName(PropName_SummaryWords);
            StringArraySerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).SummaryWords!);
        
            writer.WriteEndObject();
        }
    }
}

After

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0612, CS0618

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70
{
    public partial class Net70GeneratedContext
    {
        private JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? _WeatherForecastWithPOCOs;
        
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> WeatherForecastWithPOCOs
        {
            get => _WeatherForecastWithPOCOs ??= (JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>)Options.GetTypeInfo(typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs));
        }
        
        private JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> Create_WeatherForecastWithPOCOs(JsonSerializerOptions options)
        {
            if (!TryGetTypeInfoForRuntimeCustomConverter<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, out JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> jsonTypeInfo))
            {
                var objectInfo = new JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>
                {
                    ObjectCreator = () => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastWithPOCOsPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    SerializeHandler = WeatherForecastWithPOCOsSerializeHandler
                };
                
                jsonTypeInfo = JsonMetadataServices.CreateObjectInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, objectInfo);
                jsonTypeInfo.NumberHandling = null;
            }
        
            jsonTypeInfo.OriginatingResolver = this;
            return jsonTypeInfo;
        }

        private static JsonPropertyInfo[] WeatherForecastWithPOCOsPropInit(JsonSerializerOptions options)
        {
            var properties = new JsonPropertyInfo[7];

            var info0 = new JsonPropertyInfoValues<global::System.DateTimeOffset>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "Date",
                JsonPropertyName = null
            };
            
            properties[0] = JsonMetadataServices.CreatePropertyInfo<global::System.DateTimeOffset>(options, info0);

            var info1 = new JsonPropertyInfoValues<int>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
            
            properties[1] = JsonMetadataServices.CreatePropertyInfo<int>(options, info1);

            var info2 = new JsonPropertyInfoValues<string>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
            
            properties[2] = JsonMetadataServices.CreatePropertyInfo<string>(options, info2);

            var info3 = new JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "DatesAvailable",
                JsonPropertyName = null
            };
            
            properties[3] = JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.List<global::System.DateTimeOffset>>(options, info3);

            var info4 = new JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<string, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "TemperatureRanges",
                JsonPropertyName = null
            };
            
            properties[4] = JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.Dictionary<string, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>(options, info4);

            var info5 = new JsonPropertyInfoValues<string[]>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "SummaryWords",
                JsonPropertyName = null
            };
            
            properties[5] = JsonMetadataServices.CreatePropertyInfo<string[]>(options, info5);

            var info6 = new JsonPropertyInfoValues<string>
            {
                IsProperty = false,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "SummaryField",
                JsonPropertyName = null
            };
            
            properties[6] = JsonMetadataServices.CreatePropertyInfo<string>(options, info6);

            return properties;
        }

        private void WeatherForecastWithPOCOsSerializeHandler(Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
            
            writer.WriteStartObject();

            writer.WriteString(PropName_Date, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Date);
            writer.WriteNumber(PropName_TemperatureCelsius, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureCelsius);
            writer.WriteString(PropName_Summary, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Summary);
            writer.WritePropertyName(PropName_DatesAvailable);
            ListDateTimeOffsetSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).DatesAvailable);
            writer.WritePropertyName(PropName_TemperatureRanges);
            DictionaryStringHighLowTempsSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureRanges);
            writer.WritePropertyName(PropName_SummaryWords);
            StringArraySerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).SummaryWords);

            writer.WriteEndObject();
        }
    }
}

@ghost
Copy link

ghost commented Nov 6, 2023

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

Issue Details

Inspired by #94267, this PR updates the STJ source generator so that fully qualified names are not used for core STJ types employed by the source generator (while still using them for all types that the generator targets). This should serve to improve readability of generated code, while not impacting type disambiguation.

Before

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618

namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70
{
    public partial class Net70GeneratedContext
    {
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? _WeatherForecastWithPOCOs;
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> WeatherForecastWithPOCOs
        {
            get => _WeatherForecastWithPOCOs ??= Create_WeatherForecastWithPOCOs(Options, makeReadOnly: true);
        }
        
        private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> Create_WeatherForecastWithPOCOs(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
        {
            global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? jsonTypeInfo = null;
            global::System.Text.Json.Serialization.JsonConverter? customConverter;
            if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs))) != null)
            {
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, customConverter);
            }
            else
            {
                global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>()
                {
                    ObjectCreator = static () => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastWithPOCOsPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    NumberHandling = default,
                    SerializeHandler = WeatherForecastWithPOCOsSerializeHandler
                };
        
                jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, objectInfo);
            }
        
            if (makeReadOnly)
            {
                jsonTypeInfo.MakeReadOnly();
            }
        
            return jsonTypeInfo;
        }
        
        private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] WeatherForecastWithPOCOsPropInit(global::System.Text.Json.JsonSerializerOptions options)
        {
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[7];
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTimeOffset> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.DateTimeOffset>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Date",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.DateTimeOffset>(options, info0);
            properties[0] = propertyInfo0;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32> info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Int32>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo1 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Int32>(options, info1);
            properties[1] = propertyInfo1;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info2 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo2 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info2);
            properties[2] = propertyInfo2;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>> info3 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "DatesAvailable",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo3 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.List<global::System.DateTimeOffset>>(options, info3);
            properties[3] = propertyInfo3;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>> info4 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "TemperatureRanges",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo4 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.Dictionary<global::System.String, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>(options, info4);
            properties[4] = propertyInfo4;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String[]> info5 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String[]>()
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "SummaryWords",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo5 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String[]>(options, info5);
            properties[5] = propertyInfo5;
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info6 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
            {
                IsProperty = false,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField!,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = default,
                PropertyName = "SummaryField",
                JsonPropertyName = null
            };
        
            global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo6 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info6);
            properties[6] = propertyInfo6;
        
            return properties;
        }
        
        // Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
        // methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
        private void WeatherForecastWithPOCOsSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
        
            writer.WriteStartObject();
            writer.WriteString(PropName_Date, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Date);
            writer.WriteNumber(PropName_TemperatureCelsius, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureCelsius);
            writer.WriteString(PropName_Summary, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Summary);
            writer.WritePropertyName(PropName_DatesAvailable);
            ListDateTimeOffsetSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).DatesAvailable!);
            writer.WritePropertyName(PropName_TemperatureRanges);
            DictionaryStringHighLowTempsSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureRanges!);
            writer.WritePropertyName(PropName_SummaryWords);
            StringArraySerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).SummaryWords!);
        
            writer.WriteEndObject();
        }
    }
}

After

// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0612, CS0618

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70
{
    public partial class Net70GeneratedContext
    {
        private JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>? _WeatherForecastWithPOCOs;
        
        /// <summary>
        /// Defines the source generated JSON serialization contract metadata for a given type.
        /// </summary>
        public JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> WeatherForecastWithPOCOs
        {
            get => _WeatherForecastWithPOCOs ??= (JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>)Options.GetTypeInfo(typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs));
        }
        
        private JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> Create_WeatherForecastWithPOCOs(JsonSerializerOptions options)
        {
            if (!TryGetTypeInfoForRuntimeCustomConverter<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, out JsonTypeInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs> jsonTypeInfo))
            {
                var objectInfo = new JsonObjectInfoValues<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>
                {
                    ObjectCreator = () => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs(),
                    ObjectWithParameterizedConstructorCreator = null,
                    PropertyMetadataInitializer = _ => WeatherForecastWithPOCOsPropInit(options),
                    ConstructorParameterMetadataInitializer = null,
                    SerializeHandler = WeatherForecastWithPOCOsSerializeHandler
                };
                
                jsonTypeInfo = JsonMetadataServices.CreateObjectInfo<global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs>(options, objectInfo);
                jsonTypeInfo.NumberHandling = null;
            }
        
            jsonTypeInfo.OriginatingResolver = this;
            return jsonTypeInfo;
        }

        private static JsonPropertyInfo[] WeatherForecastWithPOCOsPropInit(JsonSerializerOptions options)
        {
            var properties = new JsonPropertyInfo[7];

            var info0 = new JsonPropertyInfoValues<global::System.DateTimeOffset>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Date = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "Date",
                JsonPropertyName = null
            };
            
            properties[0] = JsonMetadataServices.CreatePropertyInfo<global::System.DateTimeOffset>(options, info0);

            var info1 = new JsonPropertyInfoValues<int>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureCelsius = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "TemperatureCelsius",
                JsonPropertyName = null
            };
            
            properties[1] = JsonMetadataServices.CreatePropertyInfo<int>(options, info1);

            var info2 = new JsonPropertyInfoValues<string>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).Summary = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "Summary",
                JsonPropertyName = null
            };
            
            properties[2] = JsonMetadataServices.CreatePropertyInfo<string>(options, info2);

            var info3 = new JsonPropertyInfoValues<global::System.Collections.Generic.List<global::System.DateTimeOffset>>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).DatesAvailable = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "DatesAvailable",
                JsonPropertyName = null
            };
            
            properties[3] = JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.List<global::System.DateTimeOffset>>(options, info3);

            var info4 = new JsonPropertyInfoValues<global::System.Collections.Generic.Dictionary<string, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).TemperatureRanges = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "TemperatureRanges",
                JsonPropertyName = null
            };
            
            properties[4] = JsonMetadataServices.CreatePropertyInfo<global::System.Collections.Generic.Dictionary<string, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.HighLowTemps>>(options, info4);

            var info5 = new JsonPropertyInfoValues<string[]>
            {
                IsProperty = true,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryWords = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "SummaryWords",
                JsonPropertyName = null
            };
            
            properties[5] = JsonMetadataServices.CreatePropertyInfo<string[]>(options, info5);

            var info6 = new JsonPropertyInfoValues<string>
            {
                IsProperty = false,
                IsPublic = true,
                IsVirtual = false,
                DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs),
                Converter = null,
                Getter = static obj => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField,
                Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)obj).SummaryField = value!,
                IgnoreCondition = null,
                HasJsonInclude = false,
                IsExtensionData = false,
                NumberHandling = null,
                PropertyName = "SummaryField",
                JsonPropertyName = null
            };
            
            properties[6] = JsonMetadataServices.CreatePropertyInfo<string>(options, info6);

            return properties;
        }

        private void WeatherForecastWithPOCOsSerializeHandler(Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs? value)
        {
            if (value == null)
            {
                writer.WriteNullValue();
                return;
            }
            
            writer.WriteStartObject();

            writer.WriteString(PropName_Date, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Date);
            writer.WriteNumber(PropName_TemperatureCelsius, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureCelsius);
            writer.WriteString(PropName_Summary, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).Summary);
            writer.WritePropertyName(PropName_DatesAvailable);
            ListDateTimeOffsetSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).DatesAvailable);
            writer.WritePropertyName(PropName_TemperatureRanges);
            DictionaryStringHighLowTempsSerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).TemperatureRanges);
            writer.WritePropertyName(PropName_SummaryWords);
            StringArraySerializeHandler(writer, ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.WeatherForecastWithPOCOs)value).SummaryWords);

            writer.WriteEndObject();
        }
    }
}
Author: eiriktsarpalis
Assignees: eiriktsarpalis
Labels:

area-System.Text.Json

Milestone: -

@eiriktsarpalis eiriktsarpalis added this to the 9.0.0 milestone Nov 6, 2023
@@ -231,7 +206,7 @@ private static SourceText GenerateForTypeWithBuiltInConverter(ContextGenerationS

GenerateTypeInfoFactoryHeader(writer, typeMetadata);
writer.WriteLine($"""
{JsonTypeInfoLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.{typeInfoPropertyName}Converter);
{JsonTypeInfoLocalVariableName} = JsonMetadataServices.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, JsonMetadataServices.{typeInfoPropertyName}Converter);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm intentionally avoiding DRY here, the idea is that the type names are being repeated everywhere since 1) these will never change in the future and 2) it improves readability of the emitted code.

@Sergio0694
Copy link
Contributor

Isn't this technically "not safe", as there may be some type collisions? What I think the regex generator is doing (and what eg. I'm also doing in ComputeSharp) is to basically use fully qualified type names with this rule depending on where the code is:

  • For any generated code in user provided namespace, always use fully qualified type names
  • For any generated code in "reserved" namespaces (eg. ComputeSharp.Generated), emit nested using directives inside the namespace scope for that reserved generated namespace, and then use simple names for code in that scope

This guarantees that the code in that scope is easy to read while still being fully safe.
Of course, if STJ has to emit all code in user provided namespaces, I suppose that's not that easily done 😅

(just thinking out loud here 🙂)

@eiriktsarpalis eiriktsarpalis added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Nov 6, 2023
@eiriktsarpalis
Copy link
Member Author

That's a good point. Curious what you mean by the "user-provided" vs "reserved" distinction, in practice couldn't a user declare types inside arbitrary namespaces?

@Sergio0694
Copy link
Contributor

Sergio0694 commented Nov 6, 2023

They could, yes, but the assumption is that you can just document that namespace as being reserved for your source generator, and if they were to define things there that would conflict with your code, then all bets are off and that's on them, as they'd be breaking the contract. Whereas with user provided namespaces, defining types that might potentially conflict with those the generator is trying to reference can be perfectly legitimate, and shouldn't result in code failing to build.

Eg. as I mentioned, in ComputeSharp I have the ComputeSharp.Generated and ComputeSharp.D2D1.Generated namespaces, where the generators will emit a bunch of file types to use in the other generated code. The promise is that I will always respect user types and not conflict with them if I'm generating code in their own namespaces, but code in these "Generated" namespaces can instead rely on local using directives and shouldn't expect conflicts from user types deliberately added to that same namespace. In practice, realistically speaking, nobody would really ever try to define types in those namespaces anyway, so that works out pretty well.

@eiriktsarpalis
Copy link
Member Author

Doesn't this mean you're necessarily exposing public or internal APIs in the "generated" namespace that could be invoked by the user?

@eiriktsarpalis
Copy link
Member Author

You've convinced me that it's unlikely it would be possible to avoid conflicts entirely without making substantial changes to how code is generated, so I'm going to close this for now.

@Sergio0694
Copy link
Contributor

"Doesn't this mean you're necessarily exposing public or internal APIs in the "generated" namespace that could be invoked by the user?"

I guess that depends on the use case scenario. Eg. for the regex generator and ComputeSharp, all types generated into those namespaces are file accessible, so the user would just never see the namespace show up at all from other files in their project, because there would be no accessible types defined there for them to possibly reference. The MVVM Toolkit instead generates some internal types there (eg. the cached PropertyChangedEventArgs fields and their containing types), but then again I think it's reasonable to still go by "this namespace is considered reserved for the source generator only, don't use it".

"You've convinced me that it's unlikely it would be possible to avoid conflicts entirely without making substantial changes to how code is generated, so I'm going to close this for now."

That's fair, yeah right now STJ is just filling in members in the user type so I can see how it's not super easy to transition to a different setup. Hope this helped though! Didn't mean to be a party pooper for the PR here ahah 😅

@eiriktsarpalis
Copy link
Member Author

I guess that depends on the use case scenario. Eg. for the regex generator and ComputeSharp, all types generated into those namespaces are file accessible,

I guess file would solve this in a way, although for STJ we're stuck with C# 9.0 for now. It's probably also not worth having multi-namespace source files for the sake of removing FQN's -- it defeats the purpose from a code readability perspective.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants