private const string JsonNamingPolicyTypeRef = "global::System.Text.Json.JsonNamingPolicy";
private const string JsonSerializerTypeRef = "global::System.Text.Json.JsonSerializer";
private const string JsonSerializerOptionsTypeRef = "global::System.Text.Json.JsonSerializerOptions";
+ private const string JsonSerializerContextTypeRef = "global::System.Text.Json.Serialization.JsonSerializerContext";
private const string Utf8JsonWriterTypeRef = "global::System.Text.Json.Utf8JsonWriter";
private const string JsonConverterTypeRef = "global::System.Text.Json.Serialization.JsonConverter";
private const string JsonConverterFactoryTypeRef = "global::System.Text.Json.Serialization.JsonConverterFactory";
string typeInfoPropertyTypeRef = $"{JsonTypeInfoTypeRef}<{typeCompilableName}>";
return @$"private {typeInfoPropertyTypeRef}? _{typeFriendlyName};
+/// <summary>
+/// Defines the source generated JSON serialization contract metadata for a given type.
+/// </summary>
public {typeInfoPropertyTypeRef} {typeFriendlyName}
{{
get => _{typeFriendlyName} ??= {typeMetadata.CreateTypeInfoMethodName}({OptionsInstanceVariableName});
{
string contextTypeRef = _currentContext.ContextTypeRef;
string contextTypeName = _currentContext.ContextType.Name;
+
int backTickIndex = contextTypeName.IndexOf('`');
if (backTickIndex != -1)
{
sb.Append(@$"{GetLogicForDefaultSerializerOptionsInit()}
private static {contextTypeRef}? {DefaultContextBackingStaticVarName};
+
+/// <summary>
+/// The default <see cref=""{JsonSerializerContextTypeRef}""/> associated with a default <see cref=""{JsonSerializerOptionsTypeRef}""/> instance.
+/// </summary>
public static {contextTypeRef} Default => {DefaultContextBackingStaticVarName} ??= new {contextTypeRef}(new {JsonSerializerOptionsTypeRef}({DefaultOptionsStaticVarName}));
+/// <summary>
+/// The source-generated options associated with this context.
+/// </summary>
protected override {JsonSerializerOptionsTypeRef}? GeneratedSerializerOptions {{ get; }} = {DefaultOptionsStaticVarName};
+/// <inheritdoc/>
public {contextTypeName}() : base(null)
{{
}}
+/// <inheritdoc/>
public {contextTypeName}({JsonSerializerOptionsTypeRef} {OptionsLocalVariableName}) : base({OptionsLocalVariableName})
{{
}}
{
StringBuilder sb = new();
- sb.Append(@$"public override {JsonTypeInfoTypeRef} GetTypeInfo({TypeTypeRef} type)
+ sb.Append(
+@$"/// <inheritdoc/>
+public override {JsonTypeInfoTypeRef} GetTypeInfo({TypeTypeRef} type)
{{");
HashSet<TypeGenerationSpec> types = new(_currentContext.TypesWithMetadataGenerated);
string source,
MetadataReference[] additionalReferences = null,
string assemblyName = "TestAssembly",
- bool includeSTJ = true)
+ bool includeSTJ = true,
+ Func<CSharpParseOptions, CSharpParseOptions> configureParseOptions = null)
{
List<MetadataReference> references = new List<MetadataReference> {
}
}
+ configureParseOptions ??= (options) => options;
+ var parseOptions = configureParseOptions(s_parseOptions);
return CSharpCompilation.Create(
assemblyName,
- syntaxTrees: new[] { CSharpSyntaxTree.ParseText(source, s_parseOptions) },
+ syntaxTrees: new[] { CSharpSyntaxTree.ParseText(source, parseOptions) },
references: references.ToArray(),
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
return CreateCompilation(source);
}
-
+
public static Compilation CreateCompilationWithInitOnlyProperties()
{
string source = @"
return CreateCompilation(source);
}
-
+
public static Compilation CreateCompilationWithMixedInitOnlyProperties()
{
string source = @"
return CreateCompilation(source);
}
-
+
public static Compilation CreateCompilationWithRecordPositionalParameters()
{
string source = @"
return CreateCompilation(source);
}
-
+
public static Compilation CreateCompilationWithInaccessibleJsonIncludeProperties()
{
string source = @"
return CreateCompilation(source);
}
- public static Compilation CreateReferencedSimpleLibRecordCompilation()
- {
- string source = @"
+ public static Compilation CreateReferencedSimpleLibRecordCompilation()
+ {
+ string source = @"
using System.Text.Json.Serialization;
namespace ReferencedAssembly
}
";
- return CreateCompilation(source);
+ return CreateCompilation(source);
+ }
+
+ public static Compilation CreateReferencedModelWithFullyDocumentedProperties()
+ {
+ string source = @"
+ namespace ReferencedAssembly
+ {
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public class Model
+ {
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public int Property1 { get; set; }
+
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public int Property2 { get; set; }
+ }
+ }";
+
+ return CreateCompilation(source);
}
internal static void CheckDiagnosticMessages(
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using Xunit;
{
public class JsonSourceGeneratorDiagnosticsTests
{
+ /// <summary>
+ /// https://github.com/dotnet/runtime/issues/61379
+ /// </summary>
+ [Fact]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/58226", TestPlatforms.Browser)]
+ public void EmitsDocumentationOnPublicMembersAndDoesNotCauseCS1591()
+ {
+ // Compile the referenced assembly first.
+ Compilation documentedCompilation = CompilationHelper.CreateReferencedModelWithFullyDocumentedProperties();
+
+ // Emit the image of the referenced assembly.
+ byte[] documentedImage = CompilationHelper.CreateAssemblyImage(documentedCompilation);
+
+ // Main source for current compilation.
+ string source = @"
+ using System.Collections.Generic;
+ using System.Text.Json.Serialization;
+ using ReferencedAssembly;
+
+ namespace JsonSourceGenerator
+ {
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ [JsonSerializable(typeof(DocumentedModel))]
+ [JsonSerializable(typeof(DocumentedModel2<string>))]
+ public partial class JsonContext : JsonSerializerContext
+ {
+ }
+
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public class DocumentedModel2<T>
+ {
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public List<Model> Models { get; set; }
+ /// documentation
+ public T Prop { get; set; }
+ }
+
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public class DocumentedModel
+ {
+ /// <summary>
+ /// Documentation
+ /// </summary>
+ public List<Model> Models { get; set; }
+ }
+ }";
+
+ MetadataReference[] additionalReferences = {
+ MetadataReference.CreateFromImage(documentedImage),
+ };
+
+ Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences, configureParseOptions: options => options.WithDocumentationMode(DocumentationMode.Diagnose));
+
+ JsonSourceGenerator generator = new JsonSourceGenerator();
+
+ compilation = CompilationHelper.RunGenerators(compilation, out var _, generator);
+
+ using var emitStream = new MemoryStream();
+ using var xmlStream = new MemoryStream();
+ var result = compilation.Emit(emitStream, xmlDocumentationStream: xmlStream);
+ var diagnostics = result.Diagnostics;
+
+ CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, diagnostics, Array.Empty<(Location, string)>());
+ CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, diagnostics, Array.Empty<(Location, string)>());
+ CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, diagnostics, Array.Empty<(Location, string)>());
+ }
+
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/58226", TestPlatforms.Browser)]
public void SuccessfulSourceGeneration()