From 0465de07ea1d9550e08a29559f6fadf75faca850 Mon Sep 17 00:00:00 2001 From: Glen Date: Fri, 23 Jan 2026 14:31:18 +0200 Subject: [PATCH 1/2] Removed Symbol references from `IOutputTypeInfo` and implementations --- .../FileBuilders/ConnectionTypeFileBuilder.cs | 11 +++-- .../FileBuilders/EdgeTypeFileBuilder.cs | 12 +++-- .../FileBuilders/InterfaceTypeFileBuilder.cs | 6 +-- .../FileBuilders/ObjectTypeFileBuilder.cs | 6 +-- .../FileBuilders/RootTypeFileBuilder.cs | 3 +- .../FileBuilders/TypeFileBuilderBase.cs | 13 +++--- .../Generators/TypeModuleSyntaxGenerator.cs | 27 +++++------- .../Helpers/SymbolExtensions.cs | 7 +++ .../Inspectors/ConnectionTypeTransformer.cs | 4 +- .../Models/ConnectionTypeInfo.cs | 28 ++++++------ .../Types.Analyzers/Models/EdgeTypeInfo.cs | 28 ++++++------ .../Types.Analyzers/Models/IOutputTypeInfo.cs | 44 +++++++------------ .../Models/InterfaceTypeInfo.cs | 43 +++++++++--------- .../Types.Analyzers/Models/ObjectTypeInfo.cs | 39 ++++++++-------- .../src/Types.Analyzers/Models/Resolver.cs | 12 +++-- .../Types.Analyzers/Models/RootTypeInfo.cs | 38 ++++++++-------- .../Types.Analyzers/Models/TypeNameInfo.cs | 22 ++++++++++ .../Core/src/Types.Analyzers/Polyfills.cs | 22 ++++++++++ 18 files changed, 192 insertions(+), 173 deletions(-) create mode 100644 src/HotChocolate/Core/src/Types.Analyzers/Models/TypeNameInfo.cs create mode 100644 src/HotChocolate/Core/src/Types.Analyzers/Polyfills.cs diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ConnectionTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ConnectionTypeFileBuilder.cs index cbbe7a716cb..07af7c3d88a 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ConnectionTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ConnectionTypeFileBuilder.cs @@ -16,7 +16,7 @@ public override void WriteBeginClass(IOutputTypeInfo type) "{0} partial class {1} : ObjectType", type.IsPublic ? "public" : "internal", type.Name, - type.RuntimeTypeFullName); + type.RuntimeTypeName?.FullName); Writer.WriteIndentedLine("{"); Writer.IncreaseIndent(); } @@ -32,7 +32,7 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku Writer.WriteIndentedLine( "protected override void Configure(global::{0} descriptor)", WellKnownTypes.IObjectTypeDescriptor, - connectionType.RuntimeTypeFullName); + connectionType.RuntimeTypeName.FullName); Writer.WriteIndentedLine("{"); @@ -48,7 +48,7 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku { Writer.WriteIndentedLine( "var thisType = typeof(global::{0});", - connectionType.RuntimeTypeFullName); + connectionType.RuntimeTypeName.FullName); Writer.WriteIndentedLine( "var bindingResolver = extension.Context.ParameterBindingResolver;"); Writer.WriteIndentedLine( @@ -106,15 +106,14 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku } } - if (connectionType.RuntimeType.IsGenericType + if (connectionType.NodeFullyQualifiedName is not null && !string.IsNullOrEmpty(connectionType.NameFormat) && connectionType.NameFormat!.Contains("{0}")) { - var nodeTypeName = connectionType.RuntimeType.TypeArguments[0].ToFullyQualified(); Writer.WriteLine(); Writer.WriteIndentedLine( "var nodeTypeRef = extension.Context.TypeInspector.GetTypeRef(typeof({0}));", - nodeTypeName); + connectionType.NodeFullyQualifiedName); Writer.WriteIndentedLine("descriptor"); using (Writer.IncreaseIndent()) { diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs index 1e362b31274..5c4433446bd 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs @@ -1,6 +1,5 @@ using System.Text; using HotChocolate.Types.Analyzers.Generators; -using HotChocolate.Types.Analyzers.Helpers; using HotChocolate.Types.Analyzers.Models; namespace HotChocolate.Types.Analyzers.FileBuilders; @@ -15,7 +14,7 @@ public override void WriteBeginClass(IOutputTypeInfo type) "{0} partial class {1} : ObjectType", type.IsPublic ? "public" : "internal", type.Name, - type.RuntimeTypeFullName); + type.RuntimeTypeName?.FullName); Writer.WriteIndentedLine("{"); Writer.IncreaseIndent(); } @@ -31,7 +30,7 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku Writer.WriteIndentedLine( "protected override void Configure(global::{0} descriptor)", WellKnownTypes.IObjectTypeDescriptor, - edgeType.RuntimeTypeFullName); + edgeType.RuntimeTypeName.FullName); Writer.WriteIndentedLine("{"); @@ -47,7 +46,7 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku { Writer.WriteIndentedLine( "var thisType = typeof(global::{0});", - edgeType.RuntimeTypeFullName); + edgeType.RuntimeTypeName.FullName); Writer.WriteIndentedLine( "var bindingResolver = extension.Context.ParameterBindingResolver;"); Writer.WriteIndentedLine( @@ -105,15 +104,14 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku } } - if (edgeType.RuntimeType.IsGenericType + if (edgeType.NodeFullyQualifiedName is not null && !string.IsNullOrEmpty(edgeType.NameFormat) && edgeType.NameFormat!.Contains("{0}")) { - var nodeTypeName = edgeType.RuntimeType.TypeArguments[0].ToFullyQualified(); Writer.WriteLine(); Writer.WriteIndentedLine( "var nodeTypeRef = extension.Context.TypeInspector.GetTypeRef(typeof({0}));", - nodeTypeName); + edgeType.NodeFullyQualifiedName); Writer.WriteIndentedLine("descriptor"); using (Writer.IncreaseIndent()) { diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/InterfaceTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/InterfaceTypeFileBuilder.cs index 6cbc4a49feb..d6948e80b35 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/InterfaceTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/InterfaceTypeFileBuilder.cs @@ -19,14 +19,14 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku Writer.WriteIndentedLine( "internal static void Initialize(global::{0} descriptor)", WellKnownTypes.IInterfaceTypeDescriptor, - interfaceType.RuntimeTypeFullName); + interfaceType.RuntimeTypeName.FullName); Writer.WriteIndentedLine("{"); using (Writer.IncreaseIndent()) { WriteInitializationBase( - interfaceType.SchemaTypeFullName, + interfaceType.SchemaTypeName.FullName, interfaceType.Resolvers.Length > 0, interfaceType.Resolvers.Any(t => t.RequiresParameterBindings), interfaceType.DescriptorAttributes, @@ -53,7 +53,7 @@ public override void WriteConfigureMethod(IOutputTypeInfo type) Writer.WriteIndentedLine( "static partial void Configure(global::{0} descriptor);", WellKnownTypes.IInterfaceTypeDescriptor, - interfaceType.RuntimeTypeFullName); + interfaceType.RuntimeTypeName.FullName); Writer.WriteLine(); } } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeFileBuilder.cs index 6eca0786e5e..6c1b68c8ff4 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeFileBuilder.cs @@ -19,14 +19,14 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku Writer.WriteIndentedLine( "internal static void Initialize(global::{0} descriptor)", WellKnownTypes.IObjectTypeDescriptor, - objectType.RuntimeTypeFullName); + objectType.RuntimeTypeName.FullName); Writer.WriteIndentedLine("{"); using (Writer.IncreaseIndent()) { WriteInitializationBase( - objectType.SchemaTypeFullName, + objectType.SchemaTypeName.FullName, objectType.Resolvers.Length > 0 || objectType.NodeResolver is not null, objectType.Resolvers.Any(t => t.RequiresParameterBindings) || (objectType.NodeResolver?.RequiresParameterBindings ?? false), @@ -92,7 +92,7 @@ public override void WriteResolverConstructor(IOutputTypeInfo type, ILocalTypeLo WriteResolverConstructor( objectType, typeLookup, - $"global::{objectType.SchemaTypeFullName}", + $"global::{objectType.SchemaTypeName.FullName}", type.Resolvers.Any(t => t.RequiresParameterBindings) || (objectType.NodeResolver?.RequiresParameterBindings ?? false)); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/RootTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/RootTypeFileBuilder.cs index 89a4e762dbc..6f58521fc6c 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/RootTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/RootTypeFileBuilder.cs @@ -1,6 +1,5 @@ using System.Text; using HotChocolate.Types.Analyzers.Generators; -using HotChocolate.Types.Analyzers.Helpers; using HotChocolate.Types.Analyzers.Models; namespace HotChocolate.Types.Analyzers.FileBuilders; @@ -26,7 +25,7 @@ public override void WriteInitializeMethod(IOutputTypeInfo type, ILocalTypeLooku using (Writer.IncreaseIndent()) { WriteInitializationBase( - rootType.SchemaSchemaType.ToFullyQualified(), + rootType.SchemaTypeName.FullyQualifiedName, rootType.Resolvers.Length > 0, rootType.Resolvers.Any(t => t.RequiresParameterBindings), rootType.DescriptorAttributes, diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs index b116bbde798..998161e6ba4 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs @@ -536,7 +536,7 @@ protected void WriteFieldFlags(Resolver resolver) public virtual void WriteConfigureMethod(IOutputTypeInfo type) { - if (type.RuntimeType is null) + if (type.RuntimeTypeName is null) { Writer.WriteIndentedLine( "static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor);"); @@ -545,7 +545,7 @@ public virtual void WriteConfigureMethod(IOutputTypeInfo type) { Writer.WriteIndentedLine( "static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor<{0}> descriptor);", - type.RuntimeType.ToFullyQualified()); + type.RuntimeTypeName.FullyQualifiedName); } Writer.WriteLine(); @@ -595,14 +595,15 @@ protected void WriteResolverField(Resolver resolver) public virtual void WriteResolverConstructor(IOutputTypeInfo type, ILocalTypeLookup typeLookup) { - var resolverType = - type.SchemaSchemaType ?? - type.RuntimeType ?? throw new InvalidOperationException("Schema type and runtime type are null."); + var resolverTypeName = + type.SchemaTypeName?.FullyQualifiedName + ?? type.RuntimeTypeName?.FullyQualifiedName + ?? throw new InvalidOperationException("Schema type and runtime type are null."); WriteResolverConstructor( type, typeLookup, - resolverType.ToFullyQualified(), + resolverTypeName, type.Resolvers.Any(t => t.RequiresParameterBindings)); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Generators/TypeModuleSyntaxGenerator.cs b/src/HotChocolate/Core/src/Types.Analyzers/Generators/TypeModuleSyntaxGenerator.cs index 64118abb265..7e5f97f0dc1 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Generators/TypeModuleSyntaxGenerator.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Generators/TypeModuleSyntaxGenerator.cs @@ -149,12 +149,12 @@ private static void WriteConfiguration( && objectTypeExtension.Diagnostics.Length == 0) { objectTypeExtensions ??= []; - objectTypeExtensions.Add(objectTypeExtension.RuntimeType.ToFullyQualified()); + objectTypeExtensions.Add(objectTypeExtension.RuntimeTypeName.FullyQualifiedName); generator.WriteRegisterTypeExtension( - GetAssemblyQualifiedName(objectTypeExtension.SchemaSchemaType), - objectTypeExtension.RuntimeType.ToFullyQualified(), - objectTypeExtension.SchemaSchemaType.ToFullyQualified()); + objectTypeExtension.RegistrationKey, + objectTypeExtension.RuntimeTypeName.FullyQualifiedName, + objectTypeExtension.SchemaTypeName.FullyQualifiedName); hasConfigurations = true; } @@ -185,12 +185,12 @@ private static void WriteConfiguration( && interfaceType.Diagnostics.Length == 0) { interfaceTypeExtensions ??= []; - interfaceTypeExtensions.Add(interfaceType.RuntimeType.ToFullyQualified()); + interfaceTypeExtensions.Add(interfaceType.RuntimeTypeName.FullyQualifiedName); generator.WriteRegisterTypeExtension( - GetAssemblyQualifiedName(interfaceType.SchemaSchemaType), - interfaceType.RuntimeType.ToFullyQualified(), - interfaceType.SchemaSchemaType.ToFullyQualified()); + interfaceType.RegistrationKey, + interfaceType.RuntimeTypeName.FullyQualifiedName, + interfaceType.SchemaTypeName.FullyQualifiedName); hasConfigurations = true; } @@ -203,9 +203,9 @@ private static void WriteConfiguration( var operationType = rootType.OperationType; generator.WriteRegisterRootTypeExtension( - GetAssemblyQualifiedName(rootType.SchemaSchemaType), + rootType.RegistrationKey, operationType, - rootType.SchemaSchemaType.ToFullyQualified()); + rootType.SchemaTypeName.FullyQualifiedName); hasConfigurations = true; if (operationType is not OperationType.No && (operations & operationType) != operationType) @@ -311,11 +311,4 @@ private static void WriteOperationTypes( addSource(WellKnownFileNames.RootTypesFile, generator.ToString()); } - - public static string GetAssemblyQualifiedName(ITypeSymbol typeSymbol) - { - var assemblyName = typeSymbol.ContainingAssembly?.Name ?? "UnknownAssembly"; - var typeFullName = typeSymbol.ToDisplayString(); - return $"{assemblyName}::{typeFullName}"; - } } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs index 803e0afccac..b8ef4cdde86 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs @@ -659,6 +659,13 @@ public static bool IsNullableValueType(this ITypeSymbol typeSymbol) public static string PrintNullRefQualifier(this ITypeSymbol typeSymbol) => typeSymbol.IsNullableRefType() ? "?" : string.Empty; + public static string ToAssemblyQualified(this ITypeSymbol typeSymbol) + { + var assemblyName = typeSymbol.ContainingAssembly?.Name ?? "UnknownAssembly"; + var typeFullName = typeSymbol.ToDisplayString(); + return $"{assemblyName}::{typeFullName}"; + } + public static string ToFullyQualified(this ITypeSymbol typeSymbol) => typeSymbol.ToDisplayString(FullyQualifiedFormat); diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ConnectionTypeTransformer.cs b/src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ConnectionTypeTransformer.cs index c922cc4109e..ffa2b144895 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ConnectionTypeTransformer.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Inspectors/ConnectionTypeTransformer.cs @@ -50,9 +50,9 @@ public ImmutableArray Transform( if (syntaxInfo is IOutputTypeInfo { HasRuntimeType: true } typeInfo) { #if NET8_0_OR_GREATER - connectionTypeLookup[typeInfo.RuntimeTypeFullName] = typeInfo; + connectionTypeLookup[typeInfo.RuntimeTypeName.FullName] = typeInfo; #else - connectionTypeLookup[typeInfo.RuntimeTypeFullName!] = typeInfo; + connectionTypeLookup[typeInfo.RuntimeTypeName!.FullName] = typeInfo; #endif } } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/ConnectionTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/ConnectionTypeInfo.cs index 81fc976ad33..33e98d84cdb 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/ConnectionTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/ConnectionTypeInfo.cs @@ -20,14 +20,14 @@ private ConnectionTypeInfo( ImmutableArray attributes) { Name = name; + RuntimeTypeName = TypeNameInfo.Create(runtimeType); + NodeFullyQualifiedName = runtimeType.IsGenericType ? runtimeType.TypeArguments[0].ToFullyQualified() : null; NameFormat = nameFormat; EdgeTypeName = edgeTypeName; - RuntimeTypeFullName = runtimeType.ToDisplayString(); - RuntimeType = runtimeType; Namespace = runtimeType.ContainingNamespace.ToDisplayString(); + IsPublic = runtimeType.DeclaredAccessibility == Accessibility.Public; ClassDeclaration = classDeclaration; Resolvers = resolvers; - Attributes = attributes; Shareable = attributes.GetShareableScope(); Inaccessible = attributes.GetInaccessibleScope(); DescriptorAttributes = attributes.GetUserAttributes(); @@ -35,6 +35,14 @@ private ConnectionTypeInfo( public string Name { get; } + public TypeNameInfo? SchemaTypeName => null; + + public TypeNameInfo RuntimeTypeName { get; } + + public string? NodeFullyQualifiedName { get; } + + public string? RegistrationKey => null; + public string? NameFormat { get; } public string EdgeTypeName { get; } @@ -43,32 +51,22 @@ private ConnectionTypeInfo( public string? Description => null; - public bool IsPublic => RuntimeType.DeclaredAccessibility == Accessibility.Public; - - public INamedTypeSymbol? SchemaSchemaType => null; - - public string? SchemaTypeFullName => null; + public bool IsPublic { get; } public bool HasSchemaType => false; - public INamedTypeSymbol RuntimeType { get; } - - public string RuntimeTypeFullName { get; } - public bool HasRuntimeType => true; public ClassDeclarationSyntax? ClassDeclaration { get; } public ImmutableArray Resolvers { get; private set; } - public override string OrderByKey => RuntimeTypeFullName; + public override string OrderByKey => RuntimeTypeName.FullName; public DirectiveScope Shareable { get; } public DirectiveScope Inaccessible { get; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } public void ReplaceResolver(Resolver current, Resolver replacement) diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/EdgeTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/EdgeTypeInfo.cs index 075d95a8195..2350a608e6b 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/EdgeTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/EdgeTypeInfo.cs @@ -21,14 +21,14 @@ private EdgeTypeInfo( ImmutableArray attributes) { Name = name; + RuntimeTypeName = TypeNameInfo.Create(runtimeType); + NodeFullyQualifiedName = runtimeType.IsGenericType ? runtimeType.TypeArguments[0].ToFullyQualified() : null; NameFormat = nameFormat; - RuntimeTypeFullName = runtimeType.ToDisplayString(); - RuntimeType = runtimeType; Namespace = @namespace; Description = description; + IsPublic = runtimeType.DeclaredAccessibility == Accessibility.Public; ClassDeclaration = classDeclaration; Resolvers = resolvers; - Attributes = attributes; Shareable = attributes.GetShareableScope(); Inaccessible = attributes.GetInaccessibleScope(); DescriptorAttributes = attributes.GetUserAttributes(); @@ -36,23 +36,23 @@ private EdgeTypeInfo( public string Name { get; } - public string? NameFormat { get; } + public TypeNameInfo? SchemaTypeName => null; - public string Namespace { get; } + public TypeNameInfo RuntimeTypeName { get; } - public string? Description { get; } + public string? NodeFullyQualifiedName { get; } - public bool IsPublic => RuntimeType.DeclaredAccessibility == Accessibility.Public; + public string? RegistrationKey => null; - public INamedTypeSymbol? SchemaSchemaType => null; + public string? NameFormat { get; } - public string? SchemaTypeFullName => null; + public string Namespace { get; } - public bool HasSchemaType => false; + public string? Description { get; } - public INamedTypeSymbol RuntimeType { get; } + public bool IsPublic { get; } - public string RuntimeTypeFullName { get; } + public bool HasSchemaType => false; public bool HasRuntimeType => true; @@ -64,11 +64,9 @@ private EdgeTypeInfo( public DirectiveScope Inaccessible { get; private set; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } - public override string OrderByKey => RuntimeTypeFullName; + public override string OrderByKey => RuntimeTypeName.FullName; public void ReplaceResolver(Resolver current, Resolver replacement) => Resolvers = Resolvers.Replace(current, replacement); diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/IOutputTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/IOutputTypeInfo.cs index 773e493253f..c42e5ff6885 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/IOutputTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/IOutputTypeInfo.cs @@ -18,53 +18,48 @@ public interface IOutputTypeInfo : IDiagnosticsProvider string Name { get; } /// - /// Gets the namespace that the generator shall use to generate the output type. + /// Gets the schema type name info. /// - string Namespace { get; } + TypeNameInfo? SchemaTypeName { get; } /// - /// Gets the description of the object type. + /// Gets the runtime type name info. /// - string? Description { get; } + TypeNameInfo? RuntimeTypeName { get; } /// - /// Defines if the type is a public. + /// Gets the registration key of the type. /// - bool IsPublic { get; } + string? RegistrationKey { get; } /// - /// Gets the schema type symbol. + /// Gets the namespace that the generator shall use to generate the output type. + /// + string Namespace { get; } + + /// + /// Gets the description of the object type. /// - INamedTypeSymbol? SchemaSchemaType { get; } + string? Description { get; } /// - /// Gets the full schema type name. + /// Defines if the type is a public. /// - string? SchemaTypeFullName { get; } + bool IsPublic { get; } /// /// Specifies if this type info has a schema type. /// #if NET8_0_OR_GREATER - [MemberNotNull(nameof(RuntimeTypeFullName), nameof(RuntimeType))] + [MemberNotNull(nameof(SchemaTypeName))] #endif bool HasSchemaType { get; } - /// - /// Gets the runtime type symbol. - /// - INamedTypeSymbol? RuntimeType { get; } - - /// - /// Gets the full runtime type name. - /// - string? RuntimeTypeFullName { get; } - /// /// Specifies if this type info has a runtime type. /// #if NET8_0_OR_GREATER - [MemberNotNull(nameof(RuntimeTypeFullName), nameof(RuntimeType))] + [MemberNotNull(nameof(RuntimeTypeName))] #endif bool HasRuntimeType { get; } @@ -88,11 +83,6 @@ public interface IOutputTypeInfo : IDiagnosticsProvider /// DirectiveScope Inaccessible { get; } - /// - /// Gets all attributes on this type. - /// - ImmutableArray Attributes { get; } - /// /// Gets descriptor attributes annotated to this type. /// diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/InterfaceTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/InterfaceTypeInfo.cs index 2ea054d887c..a04940d8622 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/InterfaceTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/InterfaceTypeInfo.cs @@ -5,7 +5,9 @@ namespace HotChocolate.Types.Analyzers.Models; -public sealed class InterfaceTypeInfo : SyntaxInfo, IOutputTypeInfo +public sealed class InterfaceTypeInfo + : SyntaxInfo + , IOutputTypeInfo { public InterfaceTypeInfo( INamedTypeSymbol schemaType, @@ -14,37 +16,36 @@ public InterfaceTypeInfo( ImmutableArray resolvers, ImmutableArray attributes) { - SchemaSchemaType = schemaType; - SchemaTypeFullName = schemaType.ToDisplayString(); - RuntimeType = runtimeType; - RuntimeTypeFullName = runtimeType.ToDisplayString(); + Name = schemaType.Name; + SchemaTypeName = TypeNameInfo.Create(schemaType); + RuntimeTypeName = TypeNameInfo.Create(runtimeType); + RegistrationKey = schemaType.ToAssemblyQualified(); + Namespace = schemaType.ContainingNamespace.ToDisplayString(); + Description = schemaType.GetDescription(); + IsPublic = schemaType.DeclaredAccessibility == Accessibility.Public; ClassDeclaration = classDeclarationSyntax; Resolvers = resolvers; - Description = schemaType.GetDescription(); // sharable directives are only allowed on object types and field definitions Shareable = DirectiveScope.None; - Attributes = attributes; Inaccessible = attributes.GetInaccessibleScope(); DescriptorAttributes = attributes.GetUserAttributes(); } - public string Name => SchemaSchemaType.Name; + public string Name { get; } - public string Namespace => SchemaSchemaType.ContainingNamespace.ToDisplayString(); - - public string? Description { get; } + public TypeNameInfo SchemaTypeName { get; } - public bool IsPublic => SchemaSchemaType.DeclaredAccessibility == Accessibility.Public; + public TypeNameInfo RuntimeTypeName { get; } - public INamedTypeSymbol SchemaSchemaType { get; } + public string RegistrationKey { get; } - public string SchemaTypeFullName { get; } + public string Namespace { get; } - public bool HasSchemaType => true; + public string? Description { get; } - public INamedTypeSymbol RuntimeType { get; } + public bool IsPublic { get; } - public string? RuntimeTypeFullName { get; } + public bool HasSchemaType => true; public bool HasRuntimeType => true; @@ -52,14 +53,12 @@ public InterfaceTypeInfo( public ImmutableArray Resolvers { get; private set; } - public override string OrderByKey => SchemaTypeFullName; + public override string OrderByKey => SchemaTypeName.FullName; public DirectiveScope Shareable { get; } public DirectiveScope Inaccessible { get; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } public void ReplaceResolver(Resolver current, Resolver replacement) @@ -84,10 +83,10 @@ private bool Equals(InterfaceTypeInfo? other) } return OrderByKey.Equals(other.OrderByKey) - && string.Equals(SchemaTypeFullName, other.SchemaTypeFullName, StringComparison.Ordinal) + && string.Equals(SchemaTypeName.FullName, other.SchemaTypeName.FullName, StringComparison.Ordinal) && ClassDeclaration.SyntaxTree.IsEquivalentTo(other.ClassDeclaration.SyntaxTree); } public override int GetHashCode() - => HashCode.Combine(OrderByKey, SchemaTypeFullName, ClassDeclaration); + => HashCode.Combine(OrderByKey, SchemaTypeName.FullName, ClassDeclaration); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/ObjectTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/ObjectTypeInfo.cs index eea8fcea91a..92b46ba3d3b 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/ObjectTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/ObjectTypeInfo.cs @@ -17,37 +17,36 @@ public ObjectTypeInfo( ImmutableArray resolvers, ImmutableArray attributes) { - SchemaSchemaType = schemaType; - SchemaTypeFullName = schemaType.ToDisplayString(); - RuntimeType = runtimeType; - RuntimeTypeFullName = runtimeType.ToDisplayString(); + Name = schemaType.Name; + SchemaTypeName = TypeNameInfo.Create(schemaType); + RuntimeTypeName = TypeNameInfo.Create(runtimeType); + RegistrationKey = schemaType.ToAssemblyQualified(); + Namespace = schemaType.ContainingNamespace.ToDisplayString(); + Description = schemaType.GetDescription(); + IsPublic = schemaType.DeclaredAccessibility == Accessibility.Public; NodeResolver = nodeResolver; ClassDeclaration = classDeclarationSyntax; Resolvers = resolvers; - Description = schemaType.GetDescription(); - Attributes = attributes; Shareable = attributes.GetShareableScope(); Inaccessible = attributes.GetInaccessibleScope(); DescriptorAttributes = attributes.GetUserAttributes(); } - public string Name => SchemaSchemaType.Name; + public string Name { get; } - public string Namespace => SchemaSchemaType.ContainingNamespace.ToDisplayString(); - - public string? Description { get; } + public TypeNameInfo SchemaTypeName { get; } - public bool IsPublic => SchemaSchemaType.DeclaredAccessibility == Accessibility.Public; + public TypeNameInfo RuntimeTypeName { get; } - public INamedTypeSymbol SchemaSchemaType { get; } + public string RegistrationKey { get; } - public string SchemaTypeFullName { get; } + public string Namespace { get; } - public bool HasSchemaType => true; + public string? Description { get; } - public INamedTypeSymbol RuntimeType { get; } + public bool IsPublic { get; } - public string RuntimeTypeFullName { get; } + public bool HasSchemaType => true; public bool HasRuntimeType => true; @@ -57,14 +56,12 @@ public ObjectTypeInfo( public ImmutableArray Resolvers { get; private set; } - public override string OrderByKey => SchemaTypeFullName; + public override string OrderByKey => SchemaTypeName.FullName; public DirectiveScope Shareable { get; } public DirectiveScope Inaccessible { get; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } public void ReplaceResolver(Resolver current, Resolver replacement) @@ -89,10 +86,10 @@ private bool Equals(ObjectTypeInfo? other) } return OrderByKey.Equals(other.OrderByKey) - && string.Equals(SchemaTypeFullName, other.SchemaTypeFullName, StringComparison.Ordinal) + && string.Equals(SchemaTypeName.FullName, other.SchemaTypeName.FullName, StringComparison.Ordinal) && ClassDeclaration.SyntaxTree.IsEquivalentTo(other.ClassDeclaration.SyntaxTree); } public override int GetHashCode() - => HashCode.Combine(OrderByKey, SchemaTypeFullName, ClassDeclaration); + => HashCode.Combine(OrderByKey, SchemaTypeName.FullName, ClassDeclaration); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs index ed917363b6d..3370d2208b0 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/Resolver.cs @@ -40,11 +40,11 @@ public Resolver( } } - Attributes = member.GetAttributes(); - Shareable = Attributes.GetShareableScope(); - Inaccessible = Attributes.GetInaccessibleScope(); - IsNodeResolver = Attributes.IsNodeResolver(); - DescriptorAttributes = Attributes.GetUserAttributes(); + var attributes = member.GetAttributes(); + Shareable = attributes.GetShareableScope(); + Inaccessible = attributes.GetInaccessibleScope(); + IsNodeResolver = attributes.IsNodeResolver(); + DescriptorAttributes = attributes.GetUserAttributes(); } public string FieldName { get; } @@ -88,8 +88,6 @@ public bool IsPure public DirectiveScope Inaccessible { get; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } public Resolver WithSchemaTypeName(SchemaTypeReference schemaTypeRef) diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/RootTypeInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/RootTypeInfo.cs index 8868c81a22b..5a4d20c0ecc 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Models/RootTypeInfo.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/RootTypeInfo.cs @@ -16,37 +16,37 @@ public RootTypeInfo( ImmutableArray resolvers, ImmutableArray attributes) { + Name = schemaType.Name; OperationType = operationType; - SchemaSchemaType = schemaType; - SchemaTypeFullName = schemaType.ToDisplayString(); + SchemaTypeName = TypeNameInfo.Create(schemaType); + RegistrationKey = schemaType.ToAssemblyQualified(); + Namespace = schemaType.ContainingNamespace.ToDisplayString(); + Description = schemaType.GetDescription(); + IsPublic = schemaType.DeclaredAccessibility == Accessibility.Public; ClassDeclaration = classDeclarationSyntax; Resolvers = resolvers; - Description = schemaType.GetDescription(); - Attributes = attributes; Shareable = attributes.GetShareableScope(); Inaccessible = attributes.GetInaccessibleScope(); DescriptorAttributes = attributes.GetUserAttributes(); } - public string Name => SchemaSchemaType.Name; + public string Name { get; } - public string Namespace => SchemaSchemaType.ContainingNamespace.ToDisplayString(); + public TypeNameInfo SchemaTypeName { get; } - public string? Description { get; } + public TypeNameInfo? RuntimeTypeName => null; - public bool IsPublic => SchemaSchemaType.DeclaredAccessibility == Accessibility.Public; - - public OperationType OperationType { get; } + public string RegistrationKey { get; } - public INamedTypeSymbol SchemaSchemaType { get; } + public string Namespace { get; } - public string SchemaTypeFullName { get; } + public string? Description { get; } - public bool HasSchemaType => true; + public bool IsPublic { get; } - public INamedTypeSymbol? RuntimeType => null; + public OperationType OperationType { get; } - public string? RuntimeTypeFullName => null; + public bool HasSchemaType => true; public bool HasRuntimeType => false; @@ -54,14 +54,12 @@ public RootTypeInfo( public ImmutableArray Resolvers { get; private set; } - public override string OrderByKey => SchemaTypeFullName; + public override string OrderByKey => SchemaTypeName.FullName; public DirectiveScope Shareable { get; } public DirectiveScope Inaccessible { get; } - public ImmutableArray Attributes { get; } - public ImmutableArray DescriptorAttributes { get; } public bool SourceSchemaDetected { get; set; } @@ -88,10 +86,10 @@ public bool Equals(RootTypeInfo? other) } return OrderByKey.Equals(other.OrderByKey, StringComparison.Ordinal) - && string.Equals(SchemaTypeFullName, other.SchemaTypeFullName, StringComparison.Ordinal) + && string.Equals(SchemaTypeName.FullName, other.SchemaTypeName.FullName, StringComparison.Ordinal) && ClassDeclaration.SyntaxTree.IsEquivalentTo(other.ClassDeclaration.SyntaxTree); } public override int GetHashCode() - => HashCode.Combine(OrderByKey, SchemaTypeFullName, ClassDeclaration); + => HashCode.Combine(OrderByKey, SchemaTypeName.FullName, ClassDeclaration); } diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Models/TypeNameInfo.cs b/src/HotChocolate/Core/src/Types.Analyzers/Models/TypeNameInfo.cs new file mode 100644 index 00000000000..c46d8e1ddbe --- /dev/null +++ b/src/HotChocolate/Core/src/Types.Analyzers/Models/TypeNameInfo.cs @@ -0,0 +1,22 @@ +using HotChocolate.Types.Analyzers.Helpers; +using Microsoft.CodeAnalysis; + +namespace HotChocolate.Types.Analyzers.Models; + +public sealed record TypeNameInfo +{ + public required string FullName { get; init; } + + public required string FullyQualifiedName { get; init; } + + public static TypeNameInfo Create(INamedTypeSymbol namedTypeSymbol) + { + return new TypeNameInfo + { + FullName = namedTypeSymbol.ToDisplayString(), + FullyQualifiedName = namedTypeSymbol.ToFullyQualified() + }; + } + + private TypeNameInfo() { } +} diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Polyfills.cs b/src/HotChocolate/Core/src/Types.Analyzers/Polyfills.cs new file mode 100644 index 00000000000..2df16611b89 --- /dev/null +++ b/src/HotChocolate/Core/src/Types.Analyzers/Polyfills.cs @@ -0,0 +1,22 @@ +#pragma warning disable IDE0130 // Namespace does not match folder structure + +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute; +} + +namespace System.Runtime.CompilerServices +{ + internal sealed class IsExternalInit; + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute; + + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute(string featureName) : Attribute + { + public string FeatureName { get; } = featureName; + public bool IsOptional { get; init; } + } +} From adf7836ea44d41f0955cdc28ad38f673cbfd1535 Mon Sep 17 00:00:00 2001 From: Glen Date: Fri, 30 Jan 2026 14:44:56 +0200 Subject: [PATCH 2/2] Addressed Copilot feedback --- .../FileBuilders/EdgeTypeFileBuilder.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs index 5c4433446bd..52a535bb3c4 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/EdgeTypeFileBuilder.cs @@ -10,11 +10,17 @@ public sealed class EdgeTypeFileBuilder(StringBuilder sb) : TypeFileBuilderBase( public override void WriteBeginClass(IOutputTypeInfo type) { + if (type is not EdgeTypeInfo edgeType) + { + throw new InvalidOperationException( + "The specified type is not an edge type."); + } + Writer.WriteIndentedLine( "{0} partial class {1} : ObjectType", - type.IsPublic ? "public" : "internal", - type.Name, - type.RuntimeTypeName?.FullName); + edgeType.IsPublic ? "public" : "internal", + edgeType.Name, + edgeType.RuntimeTypeName.FullName); Writer.WriteIndentedLine("{"); Writer.IncreaseIndent(); }