diff --git a/src/HotChocolate/Core/src/Abstractions/GraphQLIgnoreXmlDocumentationAttribute.cs b/src/HotChocolate/Core/src/Abstractions/GraphQLIgnoreXmlDocumentationAttribute.cs new file mode 100644 index 00000000000..9da72a68091 --- /dev/null +++ b/src/HotChocolate/Core/src/Abstractions/GraphQLIgnoreXmlDocumentationAttribute.cs @@ -0,0 +1,33 @@ +namespace HotChocolate; + +/// +/// Controls whether XML documentation comments are considered when inferring GraphQL descriptions. +/// +/// +/// By default, Hot Chocolate infers GraphQL descriptions from XML documentation comments. +/// Applying this attribute allows explicitly opting out of that behavior. +/// When applied at the assembly or type level, the setting applies to all contained members +/// unless overridden by a more specific declaration. +/// This attribute can also be used to explicitly opt back in by setting to false. +/// +[AttributeUsage( + AttributeTargets.Class + | AttributeTargets.Struct + | AttributeTargets.Interface + | AttributeTargets.Method + | AttributeTargets.Property + | AttributeTargets.Parameter + | AttributeTargets.Field + | AttributeTargets.Assembly)] +public sealed class GraphQLIgnoreXmlDocumentationAttribute : Attribute +{ + /// + /// Gets or sets whether the XML documentation should be ignored for the annotated symbol. + /// + /// + /// The default value is true, which disables XML documentation inference. + /// Set this value to false to explicitly enable XML documentation inference + /// when it has been disabled within the outer scope. + /// + public bool Ignore { get; init; } = true; +} diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Errors.cs b/src/HotChocolate/Core/src/Types.Analyzers/Errors.cs index d322a938226..f57266f07c6 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Errors.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Errors.cs @@ -256,4 +256,17 @@ public static class Errors category: "TypeSystem", DiagnosticSeverity.Error, isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor MissingXmlDocumentation = + new( + id: "HC0106", + title: "XML documentation is not enabled", + messageFormat: + "XML documentation inference is enabled, but no XML documentation file was generated. " + + "Enable XML documentation generation within the current project" + + "or add [assembly: GraphQLIgnoreXmlDocumentation] to disable XML documentation inference.", + category: "Documentation", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true, + customTags: WellKnownDiagnosticTags.CompilationEnd); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs index 803e0afccac..e2a775cb593 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs @@ -383,6 +383,11 @@ static string GetReturnsElementText(XDocument doc) return null; } + if (IsXmlDocInferenceDisabledByAttribute(symbol)) + { + return null; + } + var trivia = syntax.GetLeadingTrivia(); StringBuilder? builder = null; foreach (var comment in trivia) @@ -639,6 +644,47 @@ static string GetReturnsElementText(XDocument doc) } } + private static bool IsXmlDocInferenceDisabledByAttribute(ISymbol symbol) + { + var currentSymbol = symbol; + while (currentSymbol != null) + { + var ignoreValue = GetIgnoreValue(currentSymbol); + if (ignoreValue.HasValue) + { + return ignoreValue.Value; + } + + currentSymbol = currentSymbol.ContainingSymbol; + } + + var assemblyScopeIgnore = GetIgnoreValue(symbol.ContainingAssembly); + return assemblyScopeIgnore.HasValue && assemblyScopeIgnore.Value; + + static bool? GetIgnoreValue(ISymbol s) + { + const string attributeName = "GraphQLIgnoreXmlDocumentationAttribute"; + foreach (var attr in s.GetAttributes()) + { + if (attr.AttributeClass?.Name == attributeName) + { + foreach (var arg in attr.NamedArguments) + { + if (arg is { Key: "Ignore", Value.Value: bool ignore }) + { + return ignore; + } + } + + // Default: Ignore = true + return true; + } + } + + return null; + } + } + public static bool IsNullableType(this ITypeSymbol typeSymbol) => typeSymbol.IsNullableRefType() || typeSymbol.IsNullableValueType(); diff --git a/src/HotChocolate/Core/src/Types.Analyzers/XmlDocumentationEnabledAnalyzer.cs b/src/HotChocolate/Core/src/Types.Analyzers/XmlDocumentationEnabledAnalyzer.cs new file mode 100644 index 00000000000..5517a071efe --- /dev/null +++ b/src/HotChocolate/Core/src/Types.Analyzers/XmlDocumentationEnabledAnalyzer.cs @@ -0,0 +1,63 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace HotChocolate.Types.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class XmlDocumentationEnabledAnalyzer: DiagnosticAnalyzer +{ + public override ImmutableArray SupportedDiagnostics { get; } = + [Errors.MissingXmlDocumentation]; + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + context.RegisterCompilationAction(AnalyzeCompilation); + } + + private static void AnalyzeCompilation(CompilationAnalysisContext context) + { + var compilation = context.Compilation; + + if (IsXmlDocumentationEnabled(compilation)) + { + return; + } + + if (HasAssemblyIgnoreAttribute(compilation.Assembly)) + { + return; + } + + context.ReportDiagnostic(Diagnostic.Create(Errors.MissingXmlDocumentation, Location.None)); + } + + private static bool HasAssemblyIgnoreAttribute(IAssemblySymbol assembly) + { + const string attributeName = "GraphQLIgnoreXmlDocumentationAttribute"; + return assembly.GetAttributes().Any(attr => + attr.AttributeClass?.Name == attributeName + && (attr.NamedArguments.Length == 0 + || (attr.NamedArguments[0].Key == "Ignore" && attr.NamedArguments[0].Value.Value is true))); + } + + private static bool IsXmlDocumentationEnabled(Compilation compilation) + { + foreach (var tree in compilation.SyntaxTrees) + { + if (tree.Options is CSharpParseOptions csharpOptions) + { + if (csharpOptions.DocumentationMode != DocumentationMode.None) + { + return true; + } + } + } + + return false; + } +} diff --git a/src/HotChocolate/Core/test/Directory.Build.props b/src/HotChocolate/Core/test/Directory.Build.props index 6ae29fd74ba..dbbd8565287 100644 --- a/src/HotChocolate/Core/test/Directory.Build.props +++ b/src/HotChocolate/Core/test/Directory.Build.props @@ -6,6 +6,10 @@ false + + $(NoWarn);HC0106; + + diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/ObjectTypeTests.XmlDocInference.cs b/src/HotChocolate/Core/test/Types.Analyzers.Tests/ObjectTypeTests.XmlDocInference.cs index 60474f8691b..6662114454a 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/ObjectTypeTests.XmlDocInference.cs +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/ObjectTypeTests.XmlDocInference.cs @@ -238,4 +238,225 @@ public static partial class Query var emitted = s_description.Matches(content).Single().Groups; Assert.Equal("This type is similar useless to 'The Bar type.'.", emitted[1].Value); } + + [Fact] + public void XmlDocumentation_Is_Used_When_No_Attributes_Are_Present() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + internal static partial class Query + { + /// + /// This is XML + /// + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + var emitted = s_description.Matches(content).Single().Groups; + Assert.Equal("This is XML", emitted[1].Value); + } + + [Fact] + public void XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Member() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + internal static partial class Query + { + /// + /// This is XML + /// + [GraphQLIgnoreXmlDocumentation] + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + Assert.DoesNotMatch(s_description, content); + } + + [Fact] + public void XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Type() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + [GraphQLIgnoreXmlDocumentation] + internal static partial class Query + { + /// + /// This is XML + /// + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + Assert.DoesNotMatch(s_description, content); + } + + [Fact] + public void XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Assembly() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + internal static partial class Query + { + /// + /// This is XML + /// + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + Assert.DoesNotMatch(s_description, content); + } + + [Fact] + public void XmlDocumentation_OptIn_OnType_Overrides_Assembly_Level_Ignore() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + [GraphQLIgnoreXmlDocumentation(Ignore = false)] + internal static partial class Query + { + /// + /// This is XML + /// + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + var emitted = s_description.Matches(content).Single().Groups; + Assert.Equal("This is XML", emitted[1].Value); + } + + [Fact] + public void XmlDocumentation_OptIn_OnMember_Overrides_Assembly_Level_Ignore() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + internal static partial class Query + { + /// + /// This is XML + /// + [GraphQLIgnoreXmlDocumentation(Ignore = false)] + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + var emitted = s_description.Matches(content).Single().Groups; + Assert.Equal("This is XML", emitted[1].Value); + } + + [Fact] + public void XmlDocumentation_OptIn_OnMember_Overrides_Type_Level_Ignore() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + [GraphQLIgnoreXmlDocumentation] + internal static partial class Query + { + /// + /// This is XML + /// + [GraphQLIgnoreXmlDocumentation(Ignore = false)] + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + var emitted = s_description.Matches(content).Single().Groups; + Assert.Equal("This is XML", emitted[1].Value); + } + + [Fact] + public void DescriptionAttribute_Overrides_Xml_Even_When_XmlIgnored() + { + var snapshot = + TestHelper.GetGeneratedSourceSnapshot( + """ + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + internal static partial class Query + { + /// + /// This is XML + /// + [GraphQLIgnoreXmlDocumentation(Ignore = false)] + [GraphQLDescription("Explicit")] + public static string GetUser() => "User"; + } + """); + + var content = snapshot.Match(); + var emitted = s_description.Matches(content).Single().Groups; + Assert.Equal("Explicit", emitted[1].Value); + } } diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/TestHelper.cs b/src/HotChocolate/Core/test/Types.Analyzers.Tests/TestHelper.cs index c37a7671d79..0c3db374de1 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/TestHelper.cs +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/TestHelper.cs @@ -36,7 +36,8 @@ public static Snapshot GetGeneratedSourceSnapshot( string[] sourceTexts, string? assemblyName = "Tests", bool enableInterceptors = false, - bool enableAnalyzers = false) + bool enableAnalyzers = false, + DocumentationMode documentationMode = DocumentationMode.Parse) { IEnumerable references = [ @@ -121,6 +122,8 @@ public static Snapshot GetGeneratedSourceSnapshot( ["InterceptorsNamespaces"] = "HotChocolate.Execution.Generated" }); + parseOptions = parseOptions.WithDocumentationMode(documentationMode); + var compilation = CSharpCompilation.Create( assemblyName: assemblyName, syntaxTrees: sourceTexts.Select(s => CSharpSyntaxTree.ParseText(s, parseOptions)), @@ -213,7 +216,8 @@ private static Snapshot CreateSnapshot(CSharpCompilation compilation, GeneratorD new ShareableScopedOnMemberAnalyzer(), new DataAttributeOrderAnalyzer(), new IdAttributeOnRecordParameterAnalyzer(), - new WrongAuthorizationAttributeAnalyzer()); + new WrongAuthorizationAttributeAnalyzer(), + new XmlDocumentationEnabledAnalyzer()); var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers); var analyzerDiagnostics = compilationWithAnalyzers.GetAllDiagnosticsAsync().Result; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/XmlDocumentationEnabledAnalyzerTests.cs b/src/HotChocolate/Core/test/Types.Analyzers.Tests/XmlDocumentationEnabledAnalyzerTests.cs new file mode 100644 index 00000000000..8653ecd4c32 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/XmlDocumentationEnabledAnalyzerTests.cs @@ -0,0 +1,94 @@ +using Microsoft.CodeAnalysis; + +namespace HotChocolate.Types; + +public class XmlDocumentationEnabledAnalyzerTests +{ + [Fact] + public async Task XmlDocumentationEnabled_NoDocs_NoIgnoreAttribute_ProducesWarning() + { + await TestHelper.GetGeneratedSourceSnapshot( + [""" + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + public static partial class Query + { + public static string GetUser() => "User"; + } + """], + enableAnalyzers: true, + documentationMode: DocumentationMode.None) + .MatchMarkdownAsync(); + } + + [Fact] + public async Task XmlDocumentationEnabled_Docs_NoIgnoreAttribute_ProducesNoWarning() + { + await TestHelper.GetGeneratedSourceSnapshot( + [""" + using HotChocolate; + using HotChocolate.Types; + + namespace TestNamespace; + + [QueryType] + public static partial class Query + { + public static string GetUser() => "User"; + } + """], + enableAnalyzers: true, + documentationMode: DocumentationMode.Parse) + .MatchMarkdownAsync(); + } + + [Fact] + public async Task XmlDocumentationEnabled_Docs_IgnoreAttribute_ProducesNoWarning() + { + await TestHelper.GetGeneratedSourceSnapshot( + [""" + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + public static partial class Query + { + public static string GetUser() => "User"; + } + """], + enableAnalyzers: true, + documentationMode: DocumentationMode.Parse) + .MatchMarkdownAsync(); + } + + [Fact] + public async Task XmlDocumentationEnabled_NoDocs_IgnoreAttribute_ProducesNoWarning() + { + await TestHelper.GetGeneratedSourceSnapshot( + [""" + using HotChocolate; + using HotChocolate.Types; + + [assembly: GraphQLIgnoreXmlDocumentation] + + namespace TestNamespace; + + [QueryType] + public static partial class Query + { + public static string GetUser() => "User"; + } + """], + enableAnalyzers: true, + documentationMode: DocumentationMode.None) + .MatchMarkdownAsync(); + } +} diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.DescriptionAttribute_Overrides_Xml_Even_When_XmlIgnored.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.DescriptionAttribute_Overrides_Xml_Even_When_XmlIgnored.snap new file mode 100644 index 00000000000..bef59b1fa5a --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.DescriptionAttribute_Overrides_Xml_Even_When_XmlIgnored.snap @@ -0,0 +1,115 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Description = "Explicit"; + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Assembly.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Assembly.snap new file mode 100644 index 00000000000..b7d13058f6f --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Assembly.snap @@ -0,0 +1,114 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Member.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Member.snap new file mode 100644 index 00000000000..b7d13058f6f --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Member.snap @@ -0,0 +1,114 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Type.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Type.snap new file mode 100644 index 00000000000..b7d13058f6f --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Ignored_When_IgnoreAttribute_Is_On_Type.snap @@ -0,0 +1,114 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Used_When_No_Attributes_Are_Present.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Used_When_No_Attributes_Are_Present.snap new file mode 100644 index 00000000000..d40f99a4c72 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_Is_Used_When_No_Attributes_Are_Present.snap @@ -0,0 +1,115 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Description = "This is XML"; + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Assembly_Level_Ignore.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Assembly_Level_Ignore.snap new file mode 100644 index 00000000000..d40f99a4c72 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Assembly_Level_Ignore.snap @@ -0,0 +1,115 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Description = "This is XML"; + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Type_Level_Ignore.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Type_Level_Ignore.snap new file mode 100644 index 00000000000..d40f99a4c72 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnMember_Overrides_Type_Level_Ignore.snap @@ -0,0 +1,115 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Description = "This is XML"; + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnType_Overrides_Assembly_Level_Ignore.snap b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnType_Overrides_Assembly_Level_Ignore.snap new file mode 100644 index 00000000000..d40f99a4c72 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ObjectTypeXmlDocInferenceTests.XmlDocumentation_OptIn_OnType_Overrides_Assembly_Level_Ignore.snap @@ -0,0 +1,115 @@ +HotChocolateTypeModule.735550c.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +--------------- + +Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs +--------------- +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + internal static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Description = "This is XML"; + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +--------------- diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_IgnoreAttribute_ProducesNoWarning.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_IgnoreAttribute_ProducesNoWarning.md new file mode 100644 index 00000000000..dfb00553df1 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_IgnoreAttribute_ProducesNoWarning.md @@ -0,0 +1,119 @@ +# XmlDocumentationEnabled_Docs_IgnoreAttribute_ProducesNoWarning + +## HotChocolateTypeModule.735550c.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +``` + +## Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + public static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +``` + diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_NoIgnoreAttribute_ProducesNoWarning.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_NoIgnoreAttribute_ProducesNoWarning.md new file mode 100644 index 00000000000..f94c4ce700f --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_Docs_NoIgnoreAttribute_ProducesNoWarning.md @@ -0,0 +1,119 @@ +# XmlDocumentationEnabled_Docs_NoIgnoreAttribute_ProducesNoWarning + +## HotChocolateTypeModule.735550c.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +``` + +## Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + public static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +``` + diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_IgnoreAttribute_ProducesNoWarning.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_IgnoreAttribute_ProducesNoWarning.md new file mode 100644 index 00000000000..0ed03e3dcc4 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_IgnoreAttribute_ProducesNoWarning.md @@ -0,0 +1,119 @@ +# XmlDocumentationEnabled_NoDocs_IgnoreAttribute_ProducesNoWarning + +## HotChocolateTypeModule.735550c.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +``` + +## Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + public static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +``` + diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_NoIgnoreAttribute_ProducesWarning.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_NoIgnoreAttribute_ProducesWarning.md new file mode 100644 index 00000000000..4473672af07 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/XmlDocumentationEnabledAnalyzerTests.XmlDocumentationEnabled_NoDocs_NoIgnoreAttribute_ProducesWarning.md @@ -0,0 +1,139 @@ +# XmlDocumentationEnabled_NoDocs_NoIgnoreAttribute_ProducesWarning + +## HotChocolateTypeModule.735550c.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static partial class TestsTypesRequestExecutorBuilderExtensions + { + public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder) + { + builder.ConfigureDescriptorContext(ctx => ctx.TypeConfiguration.TryAdd( + "Tests::TestNamespace.Query", + global::HotChocolate.Types.OperationTypeNames.Query, + () => global::TestNamespace.Query.Initialize)); + builder.ConfigureSchema( + b => b.TryAddRootType( + () => new global::HotChocolate.Types.ObjectType( + d => d.Name(global::HotChocolate.Types.OperationTypeNames.Query)), + HotChocolate.Language.OperationType.Query)); + return builder; + } + } +} + +``` + +## Query.WaAdMHmlGJHjtEI4nqY7WA.hc.g.cs + +```csharp +// + +#nullable enable +#pragma warning disable + +using System; +using System.Runtime.CompilerServices; +using HotChocolate; +using HotChocolate.Types; +using HotChocolate.Execution.Configuration; +using Microsoft.Extensions.DependencyInjection; +using HotChocolate.Internal; + +namespace TestNamespace +{ + public static partial class Query + { + internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor) + { + var extension = descriptor.Extend(); + var configuration = extension.Configuration; + var thisType = typeof(global::TestNamespace.Query); + var bindingResolver = extension.Context.ParameterBindingResolver; + var resolvers = new __Resolvers(); + + HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration( + extension.Context, + descriptor, + null, + new global::HotChocolate.Types.QueryTypeAttribute()); + configuration.ConfigurationsAreApplied = true; + + var naming = descriptor.Extend().Context.Naming; + + descriptor + .Field(naming.GetMemberName("User", global::HotChocolate.Types.MemberKind.ObjectField)) + .ExtendWith(static (field, context) => + { + var configuration = field.Configuration; + var typeInspector = field.Context.TypeInspector; + var bindingResolver = field.Context.ParameterBindingResolver; + var naming = field.Context.Naming; + + configuration.Type = global::HotChocolate.Types.Descriptors.TypeReference.Create( + typeInspector.GetTypeRef(typeof(string), HotChocolate.Types.TypeContext.Output), + new global::HotChocolate.Language.NonNullTypeNode(new global::HotChocolate.Language.NamedTypeNode("string"))); + configuration.ResultType = typeof(string); + + configuration.SetSourceGeneratorFlags(); + + configuration.Resolvers = context.Resolvers.GetUser(); + }, + (Resolvers: resolvers, ThisType: thisType)); + + Configure(descriptor); + } + + static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor); + + private sealed class __Resolvers + { + public HotChocolate.Resolvers.FieldResolverDelegates GetUser() + { + return new global::HotChocolate.Resolvers.FieldResolverDelegates(pureResolver: GetUser); + } + + private global::System.Object? GetUser(global::HotChocolate.Resolvers.IResolverContext context) + { + var result = global::TestNamespace.Query.GetUser(); + return result; + } + } + } +} + + +``` + +## Analyzer Diagnostics + +```json +[ + { + "Id": "HC0106", + "Title": "XML documentation is not enabled", + "Severity": "Warning", + "WarningLevel": 1, + "Location": ": (0,0)-(0,0)", + "MessageFormat": "XML documentation inference is enabled, but no XML documentation file was generated. Enable XML documentation generation within the current projector add [assembly: GraphQLIgnoreXmlDocumentation] to disable XML documentation inference.", + "Message": "XML documentation inference is enabled, but no XML documentation file was generated. Enable XML documentation generation within the current projector add [assembly: GraphQLIgnoreXmlDocumentation] to disable XML documentation inference.", + "Category": "Documentation", + "CustomTags": [ + "CompilationEnd" + ] + } +] +``` + diff --git a/src/HotChocolate/Data/test/Directory.Build.props b/src/HotChocolate/Data/test/Directory.Build.props index 4516f1b3c88..e679daa3bc8 100644 --- a/src/HotChocolate/Data/test/Directory.Build.props +++ b/src/HotChocolate/Data/test/Directory.Build.props @@ -6,6 +6,10 @@ false + + $(NoWarn);HC0106; + +