From b2877e35fb8697e85ec8ec18b78482902e547fcd Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Mon, 16 Nov 2020 16:54:08 +0100 Subject: [PATCH] Fixed name convention interference with the introspection types. (#2588) --- .../Contracts/IObjectFieldDescriptor.cs | 2 +- .../Types/Types/Introspection/__Directive.cs | 66 ++++-- .../Introspection/__DirectiveLocation.cs | 116 +++++++---- .../Types/Types/Introspection/__EnumValue.cs | 45 +++-- .../src/Types/Types/Introspection/__Field.cs | 58 ++++-- .../Types/Types/Introspection/__InputValue.cs | 54 +++-- .../src/Types/Types/Introspection/__Schema.cs | 45 ++++- .../src/Types/Types/Introspection/__Type.cs | 189 +++++++++--------- .../Types/Types/Introspection/__TypeKind.cs | 63 ++++-- ...ectionTests.DefaultValueIsInputObject.snap | 18 +- ...sts.ExecuteGraphiQLIntrospectionQuery.snap | 18 +- ...cuteGraphiQLIntrospectionQuery_ToJson.snap | 18 +- .../Core/test/Types.Tests/SchemaFirstTests.cs | 6 +- ...rstTests.DescriptionsAreCorrectlyRead.snap | 18 +- ...rrectly_Exposed_Through_Introspection.snap | 18 +- .../Language.SyntaxTree/DirectiveLocation.cs | 2 + 16 files changed, 438 insertions(+), 298 deletions(-) diff --git a/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IObjectFieldDescriptor.cs b/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IObjectFieldDescriptor.cs index bbdf820747d..9c6fbffbc77 100644 --- a/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IObjectFieldDescriptor.cs +++ b/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IObjectFieldDescriptor.cs @@ -66,7 +66,7 @@ IObjectFieldDescriptor Type() Type resultType); IObjectFieldDescriptor ResolveWith( - Expression> propertyOrMethod); + Expression> propertyOrMethod); IObjectFieldDescriptor ResolveWith(MemberInfo propertyOrMethod); diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs index 5288809d1bb..8460cdcd569 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs @@ -1,53 +1,63 @@ +#pragma warning disable IDE1006 // Naming Styles using System.Collections.Generic; using HotChocolate.Properties; using HotChocolate.Resolvers; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] - internal sealed class __Directive - : ObjectType + internal sealed class __Directive : ObjectType { protected override void Configure( IObjectTypeDescriptor descriptor) { - descriptor.Name("__Directive"); - - descriptor.Description(TypeResources.Directive_Description); + descriptor + .Name(Names.__Directive) + .Description(TypeResources.Directive_Description); - descriptor.Field("name") + descriptor + .Field(Names.Name) .Type>() - .Resolver(c => c.Parent().Name); + .Resolve(c => c.Parent().Name); - descriptor.Field("description") + descriptor + .Field(Names.Description) .Type() - .Resolver(c => c.Parent().Description); + .Resolve(c => c.Parent().Description); - descriptor.Field("isRepeatable") + descriptor + .Field(Names.IsRepeatable) .Type() - .Resolver(c => c.Parent().IsRepeatable); + .Resolve(c => c.Parent().IsRepeatable); - descriptor.Field("locations") + descriptor + .Field(Names.Locations) .Type>>>() - .Resolver(c => c.Parent().Locations); + .Resolve(c => c.Parent().Locations); - descriptor.Field("args") + descriptor + .Field(Names.Args) .Type>>>() - .Resolver(c => c.Parent().Arguments); + .Resolve(c => c.Parent().Arguments); - descriptor.Field("onOperation") + descriptor + .Field(Names.OnOperation) .Type>() - .Resolver(c => GetOnOperation(c)) + .Resolve(c => GetOnOperation(c)) .Deprecated(TypeResources.Directive_UseLocation); - descriptor.Field("onFragment") + descriptor + .Field(Names.OnFragment) .Type>() - .Resolver(c => GetOnFragment(c)) + .Resolve(c => GetOnFragment(c)) .Deprecated(TypeResources.Directive_UseLocation); - descriptor.Field("onField") + descriptor + .Field(Names.OnField) .Type>() - .Resolver(c => GetOnField(c)) + .Resolve(c => GetOnField(c)) .Deprecated(TypeResources.Directive_UseLocation); } @@ -78,5 +88,19 @@ private static bool GetOnField(IResolverContext context) return locations.Contains(DirectiveLocation.Field); } + + public static class Names + { + public const string __Directive = "__Directive"; + public const string Name = "name"; + public const string Description = "description"; + public const string IsRepeatable = "isRepeatable"; + public const string Locations = "locations"; + public const string Args = "args"; + public const string OnOperation = "onOperation"; + public const string OnFragment = "onFragment"; + public const string OnField = "onField"; + } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveLocation.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveLocation.cs index 35d907eb54c..feca828e0f2 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveLocation.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveLocation.cs @@ -1,86 +1,122 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Properties; +using Lang = HotChocolate.Language.DirectiveLocation; +#nullable enable namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __DirectiveLocation -#pragma warning restore IDE1006 // Naming Styles - : EnumType + internal sealed class __DirectiveLocation : EnumType { protected override void Configure(IEnumTypeDescriptor descriptor) { - descriptor.Name("__DirectiveLocation"); - - descriptor.Description( - TypeResources.DirectiveLocation_Description); - - descriptor.Item(DirectiveLocation.Query) + descriptor + .Name(Names.__DirectiveLocation) + .Description(TypeResources.DirectiveLocation_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindItems(BindingBehavior.Explicit); + + descriptor + .Item(DirectiveLocation.Query) + .Name(Lang.Query.Value) .Description(TypeResources.DirectiveLocation_Query); - descriptor.Item(DirectiveLocation.Mutation) + descriptor + .Item(DirectiveLocation.Mutation) + .Name(Lang.Mutation.Value) .Description(TypeResources.DirectiveLocation_Mutation); - descriptor.Item(DirectiveLocation.Subscription) + descriptor + .Item(DirectiveLocation.Subscription) + .Name(Lang.Subscription.Value) .Description(TypeResources.DirectiveLocation_Subscription); - descriptor.Item(DirectiveLocation.Field) + descriptor + .Item(DirectiveLocation.Field) + .Name(Lang.Field.Value) .Description(TypeResources.DirectiveLocation_Field); - // TODO : Resources - descriptor.Item(DirectiveLocation.VariableDefinition) - .Name("VARIABLE_DEFINITION") - .Description("Location adjacent to a variable definition."); - - descriptor.Item(DirectiveLocation.FragmentDefinition) - .Name("FRAGMENT_DEFINITION") + descriptor + .Item(DirectiveLocation.FragmentDefinition) + .Name(Lang.FragmentDefinition.Value) .Description(TypeResources.DirectiveLocation_FragmentDefinition); - descriptor.Item(DirectiveLocation.FragmentSpread) - .Name("FRAGMENT_SPREAD") + descriptor + .Item(DirectiveLocation.FragmentSpread) + .Name(Lang.FragmentSpread.Value) .Description(TypeResources.DirectiveLocation_FragmentSpread); - descriptor.Item(DirectiveLocation.InlineFragment) - .Name("INLINE_FRAGMENT") + descriptor + .Item(DirectiveLocation.InlineFragment) + .Name(Lang.InlineFragment.Value) .Description(TypeResources.DirectiveLocation_InlineFragment); - descriptor.Item(DirectiveLocation.Schema) + descriptor + .Item(DirectiveLocation.VariableDefinition) + .Name(Lang.VariableDefinition.Value) + .Description("Location adjacent to a variable definition."); + + descriptor + .Item(DirectiveLocation.Schema) + .Name(Lang.Schema.Value) .Description(TypeResources.DirectiveLocation_Schema); - descriptor.Item(DirectiveLocation.Scalar) + descriptor + .Item(DirectiveLocation.Scalar) + .Name(Lang.Scalar.Value) .Description(TypeResources.DirectiveLocation_Scalar); - descriptor.Item(DirectiveLocation.Object) + descriptor + .Item(DirectiveLocation.Object) + .Name(Lang.Object.Value) .Description(TypeResources.DirectiveLocation_Object); - descriptor.Item(DirectiveLocation.FieldDefinition) - .Name("FIELD_DEFINITION") + descriptor + .Item(DirectiveLocation.FieldDefinition) + .Name(Lang.FieldDefinition.Value) .Description(TypeResources.DirectiveLocation_FieldDefinition); - descriptor.Item(DirectiveLocation.ArgumentDefinition) - .Name("ARGUMENT_DEFINITION") + descriptor + .Item(DirectiveLocation.ArgumentDefinition) + .Name(Lang.ArgumentDefinition.Value) .Description(TypeResources.DirectiveLocation_ArgumentDefinition); - descriptor.Item(DirectiveLocation.Interface) + descriptor + .Item(DirectiveLocation.Interface) + .Name(Lang.Interface.Value) .Description(TypeResources.DirectiveLocation_Interface); - descriptor.Item(DirectiveLocation.Union) + descriptor + .Item(DirectiveLocation.Union) + .Name(Lang.Union.Value) .Description(TypeResources.DirectiveLocation_Union); - descriptor.Item(DirectiveLocation.Enum) + descriptor + .Item(DirectiveLocation.Enum) + .Name(Lang.Enum.Value) .Description(TypeResources.DirectiveLocation_Enum); - descriptor.Item(DirectiveLocation.EnumValue) - .Name("ENUM_VALUE") + descriptor + .Item(DirectiveLocation.EnumValue) + .Name(Lang.EnumValue.Value) .Description(TypeResources.DirectiveLocation_EnumValue); - descriptor.Item(DirectiveLocation.InputObject) - .Name("INPUT_OBJECT") + descriptor + .Item(DirectiveLocation.InputObject) + .Name(Lang.InputObject.Value) .Description(TypeResources.DirectiveLocation_InputObject); - descriptor.Item(DirectiveLocation.InputFieldDefinition) - .Name("INPUT_FIELD_DEFINITION") + descriptor + .Item(DirectiveLocation.InputFieldDefinition) + .Name(Lang.InputFieldDefinition.Value) .Description(TypeResources.DirectiveLocation_InputFieldDefinition); } + + public static class Names + { + public const string __DirectiveLocation = "__DirectiveLocation"; + } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs index 21f2267fe03..c3c509798a4 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs @@ -1,32 +1,49 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Properties; +#nullable enable namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __EnumValue -#pragma warning restore IDE1006 // Naming Styles - : ObjectType + internal sealed class __EnumValue : ObjectType { protected override void Configure( IObjectTypeDescriptor descriptor) { - descriptor.Name("__EnumValue"); - - descriptor.Description( - TypeResources.EnumValue_Description); - - descriptor.BindFields(BindingBehavior.Explicit); + descriptor + .Name(Names.__EnumValue) + .Description(TypeResources.EnumValue_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindFields(BindingBehavior.Explicit); - descriptor.Field(c => c.Name) + descriptor + .Field(c => c.Name) + .Name(Names.Name) .Type>(); - descriptor.Field(c => c.Description); + descriptor + .Field(c => c.Description) + .Name(Names.Description); - descriptor.Field(c => c.IsDeprecated) + descriptor + .Field(c => c.IsDeprecated) + .Name(Names.IsDeprecated) .Type>(); - descriptor.Field(c => c.DeprecationReason); + descriptor + .Field(c => c.DeprecationReason) + .Name(Names.DeprecationReason); + } + + public static class Names + { + public const string __EnumValue = "__EnumValue"; + public const string Name = "name"; + public const string Description = "description"; + public const string IsDeprecated = "isDeprecated"; + public const string DeprecationReason = "deprecationReason"; } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs index 0484d3f6d4a..7172a066737 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs @@ -1,39 +1,63 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Properties; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __Field -#pragma warning restore IDE1006 // Naming Styles - : ObjectType + internal sealed class __Field : ObjectType { protected override void Configure( IObjectTypeDescriptor descriptor) { - descriptor.Name("__Field"); - - descriptor.Description(TypeResources.Field_Description); - - descriptor.BindFields(BindingBehavior.Explicit); - - descriptor.Field(t => t.Name) + descriptor + .Name(Names.__Field) + .Description(TypeResources.Field_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindFields(BindingBehavior.Explicit); + + descriptor + .Field(t => t.Name) + .Name(Names.Name) .Type>(); - descriptor.Field(t => t.Description); + descriptor + .Field(t => t.Description) + .Name(Names.Description); - descriptor.Field(t => t.Arguments) - .Name("args") + descriptor + .Field(t => t.Arguments) + .Name(Names.Args) .Type>>>() .Resolver(c => c.Parent().Arguments); - descriptor.Field(t => t.Type) + descriptor + .Field(t => t.Type) + .Name(Names.Type) .Type>(); - descriptor.Field(t => t.IsDeprecated) + descriptor + .Field(t => t.IsDeprecated) + .Name(Names.IsDeprecated) .Type>(); - descriptor.Field(t => t.DeprecationReason); + descriptor + .Field(t => t.DeprecationReason) + .Name(Names.DeprecationReason); + } + + public static class Names + { + public const string __Field = "__Field"; + public const string Name = "name"; + public const string Description = "description"; + public const string Args = "args"; + public const string Type = "type"; + public const string IsDeprecated = "isDeprecated"; + public const string DeprecationReason = "deprecationReason"; } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs index 49406129880..837bff16d31 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs @@ -1,33 +1,40 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Language; using HotChocolate.Properties; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __InputValue -#pragma warning restore IDE1006 // Naming Styles - : ObjectType + internal sealed class __InputValue : ObjectType { - protected override void Configure( - IObjectTypeDescriptor descriptor) + protected override void Configure(IObjectTypeDescriptor descriptor) { - descriptor.Name("__InputValue"); - - descriptor.Description( - TypeResources.InputValue_Description); + descriptor + .Name(Names.__InputValue) + .Description(TypeResources.InputValue_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindFields(BindingBehavior.Explicit); - descriptor.BindFields(BindingBehavior.Explicit); - - descriptor.Field(t => t.Name) + descriptor + .Field(t => t.Name) + .Name(Names.Name) .Type>(); - descriptor.Field(t => t.Description); + descriptor + .Field(t => t.Description) + .Name(Names.Description); - descriptor.Field(t => t.Type) + descriptor + .Field(t => t.Type) + .Name(Names.Type) .Type>(); - descriptor.Field(t => t.DefaultValue) + descriptor + .Field(t => t.DefaultValue) + .Name(Names.DefaultValue) .Description(TypeResources.InputValue_DefaultValue) .Type() .Resolver(c => @@ -38,14 +45,23 @@ internal sealed class __InputValue return null; } - if (field.DefaultValue != null) + if (field.DefaultValue is not null) { - return QuerySyntaxSerializer - .Serialize(field.DefaultValue); + return QuerySyntaxSerializer.Serialize(field.DefaultValue); } return null; }); } + + public static class Names + { + public const string __InputValue = "__InputValue"; + public const string Name = "name"; + public const string Description = "description"; + public const string DefaultValue = "defaultValue"; + public const string Type = "type"; + } } } +#pragma warning restore IDE1006 // Naming Styles \ No newline at end of file diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs index 45bd9370280..979aa3d0a2f 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs @@ -1,45 +1,68 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Properties; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __Schema -#pragma warning restore IDE1006 // Naming Styles - : ObjectType + internal sealed class __Schema : ObjectType { protected override void Configure(IObjectTypeDescriptor descriptor) { descriptor - .Name("__Schema") + .Name(Names.__Schema) .Description(TypeResources.Schema_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. .BindFields(BindingBehavior.Explicit); - descriptor.Field("description") + descriptor + .Field(Names.Description) .Type() .Resolver(c => c.Schema.Description); - descriptor.Field("types") + descriptor + .Field(Names.Types) .Description(TypeResources.Schema_Types) .Type>>>() .Resolver(c => c.Schema.Types); - descriptor.Field(t => t.QueryType) + descriptor + .Field(t => t.QueryType) + .Name(Names.QueryType) .Description(TypeResources.Schema_QueryType) .Type>(); - descriptor.Field(t => t.MutationType) + descriptor + .Field(t => t.MutationType) + .Name(Names.MutationType) .Description(TypeResources.Schema_MutationType) .Type<__Type>(); - descriptor.Field(t => t.SubscriptionType) + descriptor + .Field(t => t.SubscriptionType) + .Name(Names.SubscriptionType) .Description(TypeResources.Schema_SubscriptionType) .Type<__Type>(); - descriptor.Field("directives") + descriptor + .Field(Names.Directives) .Description(TypeResources.Schema_Directives) .Type>>>() .Resolver(c => c.Schema.DirectiveTypes); } + + public static class Names + { + public const string __Schema = "__Schema"; + public const string Description = "description"; + public const string Types = "types"; + public const string QueryType = "queryType"; + public const string MutationType = "mutationType"; + public const string SubscriptionType = "subscriptionType"; + public const string Directives = "directives"; + } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs index 90a1655ebc2..2813c5e0e3a 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs @@ -1,147 +1,138 @@ +#pragma warning disable IDE1006 // Naming Styles using System.Collections.Generic; using System.Linq; using HotChocolate.Properties; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] -#pragma warning disable IDE1006 // Naming Styles - internal sealed class __Type -#pragma warning restore IDE1006 // Naming Styles - : ObjectType + internal sealed class __Type : ObjectType { protected override void Configure(IObjectTypeDescriptor descriptor) { - descriptor.Name("__Type"); - - descriptor.Description(TypeResources.Type_Description); - - descriptor.BindFields(BindingBehavior.Explicit); - - descriptor.Field("kind") - .Type>() - .Resolver(c => c.Parent().Kind); - - descriptor.Field("name") + descriptor + .Name(Names.__Type) + .Description(TypeResources.Type_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindFields(BindingBehavior.Explicit); + + descriptor + .Field(t => t.Kind) + .Name(Names.Kind) + .Type>(); + + descriptor + .Field(Names.Name) .Type() - .Resolver(c => GetName(c.Parent())); + .ResolveWith(t => t.GetName(default!)); - descriptor.Field("description") + descriptor + .Field(Names.Description) .Type() - .Resolver(c => GetDescription(c.Parent())); + .ResolveWith(t => t.GetDescription(default!)); - descriptor.Field("fields") + descriptor + .Field(Names.Fields) + .Argument(Names.IncludeDeprecated, a => a.Type().DefaultValue(false)) .Type>>() - .Argument("includeDeprecated", - a => a.Type().DefaultValue(false)) - .Resolver(c => GetFields(c.Parent(), - c.ArgumentValue("includeDeprecated"))); + .ResolveWith(t => t.GetFields(default!, default)); - descriptor.Field("interfaces") + descriptor + .Field(Names.Interfaces) .Type>>() - .Resolver(c => GetInterfaces(c.Parent())); + .ResolveWith(t => t.GetInterfaces(default!)); - descriptor.Field("possibleTypes") + descriptor + .Field(Names.PossibleTypes) .Type>>() - .Resolver(c => GetPossibleTypes(c.Schema, c.Parent())); + .ResolveWith(t => t.GetPossibleTypes(default!, default!)); - descriptor.Field("enumValues") + descriptor + .Field(Names.EnumValues) + .Argument(Names.IncludeDeprecated, a => a.Type().DefaultValue(false)) .Type>>() - .Argument("includeDeprecated", - a => a.Type().DefaultValue(false)) - .Resolver(c => GetEnumValues(c.Parent(), - c.ArgumentValue("includeDeprecated"))); + .ResolveWith(t => t.GetEnumValues(default!, default!)); - descriptor.Field("inputFields") + descriptor + .Field(Names.InputFields) .Type>>() - .Resolver(c => GetInputFields(c.Parent())); + .ResolveWith(t => t.GetInputFields(default!)); - descriptor.Field("ofType") + descriptor + .Field(Names.OfType) .Type<__Type>() - .Resolver(c => GetOfType(c.Parent())); + .ResolveWith(t => t.GetOfType(default!)); } - private string GetName(IType type) + private class Resolvers { - if (type is INamedType n) - { - return n.Name; - } - return null; - } + public string? GetName([Parent] IType type) => + type is INamedType n ? n.Name.Value : null; - private string GetDescription(IType type) - { - if (type is INamedType n) - { - return n.Description; - } - return null; - } + public string? GetDescription([Parent] IType type) => + type is INamedType n ? n.Description : null; - private IEnumerable GetFields(IType type, bool includeDeprecated) - { - if (type is IComplexOutputType complexType) + public IEnumerable? GetFields([Parent] IType type, bool includeDeprecated) { - if (!includeDeprecated) + if (type is IComplexOutputType complexType) { - return complexType.Fields - .Where(t => !t.IsIntrospectionField && !t.IsDeprecated); + if (!includeDeprecated) + { + return complexType.Fields + .Where(t => !t.IsIntrospectionField && !t.IsDeprecated); + } + return complexType.Fields.Where(t => !t.IsIntrospectionField); } - return complexType.Fields.Where(t => !t.IsIntrospectionField); + return null; } - return null; - } - private IEnumerable GetInterfaces(IType type) - { - if (type is IComplexOutputType complexType) - { - return complexType.Interfaces; - } - return null; - } + public IEnumerable? GetInterfaces([Parent] IType type) => + type is IComplexOutputType complexType ? complexType.Interfaces : null; - private IEnumerable GetPossibleTypes(ISchema schema, INamedType type) - { - if (type.IsAbstractType()) - { - return schema.GetPossibleTypes(type); - } - return null; - } + public IEnumerable? GetPossibleTypes(ISchema schema, [Parent]INamedType type) => + type.IsAbstractType() ? schema.GetPossibleTypes(type) : null; - private IEnumerable GetEnumValues(IType type, bool includeDeprecated) - { - if (type is EnumType et) + public IEnumerable? GetEnumValues( + [Parent] IType type, + bool includeDeprecated) { - IReadOnlyCollection values = et.Values; - if (!includeDeprecated) + if (type is EnumType et) { - return values.Where(t => !t.IsDeprecated); + IReadOnlyCollection values = et.Values; + return includeDeprecated ? values : values.Where(t => !t.IsDeprecated); } - return values; + return null; } - return null; - } - private IEnumerable GetInputFields(IType type) - { - if (type is InputObjectType iot) - { - return iot.Fields; - } - return null; + public IEnumerable? GetInputFields([Parent] IType type) => + type is InputObjectType iot ? iot.Fields : null; + + public IType? GetOfType([Parent] IType type) => + type switch + { + ListType lt => lt.ElementType, + NonNullType nnt => nnt.Type, + _ => null + }; } - private IType GetOfType(IType type) + public static class Names { - return type switch - { - ListType lt => lt.ElementType, - NonNullType nnt => nnt.Type, - _ => null - }; + public const string __Type = "__Type"; + public const string Kind = "kind"; + public const string Name = "name"; + public const string Description = "description"; + public const string Fields = "fields"; + public const string Interfaces = "interfaces"; + public const string PossibleTypes = "possibleTypes"; + public const string EnumValues = "enumValues"; + public const string InputFields = "inputFields"; + public const string OfType = "ofType"; + public const string IncludeDeprecated = "includeDeprecated"; } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__TypeKind.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__TypeKind.cs index b4a15421025..9a8303a4d82 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__TypeKind.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__TypeKind.cs @@ -1,42 +1,75 @@ +#pragma warning disable IDE1006 // Naming Styles using HotChocolate.Properties; +#nullable enable + namespace HotChocolate.Types.Introspection { [Introspection] - internal sealed class __TypeKind - : EnumType + internal sealed class __TypeKind : EnumType { protected override void Configure(IEnumTypeDescriptor descriptor) { - descriptor.Name("__TypeKind"); - - descriptor.Description(TypeResources.TypeKind_Description); + descriptor + .Name(Names.__TypeKind) + .Description(TypeResources.TypeKind_Description) + // Introspection types must always be bound explicitly so that we + // do not get any interference with conventions. + .BindItems(BindingBehavior.Explicit); - descriptor.Item(TypeKind.Scalar) + descriptor + .Item(TypeKind.Scalar) + .Name(Names.Scalar) .Description(TypeResources.TypeKind_Scalar); - descriptor.Item(TypeKind.Object) + descriptor + .Item(TypeKind.Object) + .Name(Names.Object) .Description(TypeResources.TypeKind_Object); - descriptor.Item(TypeKind.Interface) + descriptor + .Item(TypeKind.Interface) + .Name(Names.Interface) .Description(TypeResources.TypeKind_Interface); - descriptor.Item(TypeKind.Union) + descriptor + .Item(TypeKind.Union) + .Name(Names.Union) .Description(TypeResources.TypeKind_Union); - descriptor.Item(TypeKind.Enum) + descriptor + .Item(TypeKind.Enum) + .Name(Names.Enum) .Description(TypeResources.TypeKind_Enum); - descriptor.Item(TypeKind.InputObject) - .Name("INPUT_OBJECT") + descriptor + .Item(TypeKind.InputObject) + .Name(Names.InputObject) .Description(TypeResources.TypeKind_InputObject); - descriptor.Item(TypeKind.List) + descriptor + .Item(TypeKind.List) + .Name(Names.List) .Description(TypeResources.TypeKind_List); - descriptor.Item(TypeKind.NonNull) - .Name("NON_NULL") + descriptor + .Item(TypeKind.NonNull) + .Name(Names.NonNull) .Description(TypeResources.TypeKind_NonNull); } + + public static class Names + { + public const string __TypeKind = "__TypeKind"; + public const string Scalar = "SCALAR"; + public const string Object = "OBJECT"; + public const string Interface = "INTERFACE"; + public const string Union = "UNION"; + public const string Enum = "ENUM"; + public const string InputObject = "INPUT_OBJECT"; + public const string List = "LIST"; + public const string NonNull = "NON_NULL"; + } } } +#pragma warning restore IDE1006 // Naming Styles diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.DefaultValueIsInputObject.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.DefaultValueIsInputObject.snap index 9af7207d7a7..c44227330b5 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.DefaultValueIsInputObject.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.DefaultValueIsInputObject.snap @@ -184,12 +184,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "VARIABLE_DEFINITION", - "description": "Location adjacent to a variable definition.", - "isDeprecated": false, - "deprecationReason": null - }, { "name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", @@ -208,6 +202,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "VARIABLE_DEFINITION", + "description": "Location adjacent to a variable definition.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "SCHEMA", "description": "Location adjacent to a schema definition.", @@ -866,12 +866,6 @@ "description": "Indicates this type is a non-null. \u0060ofType\u0060 is a valid field.", "isDeprecated": false, "deprecationReason": null - }, - { - "name": "DIRECTIVE", - "description": null, - "isDeprecated": false, - "deprecationReason": null } ], "possibleTypes": null diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery.snap index ad17f1798ad..3e4e4494903 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery.snap @@ -184,12 +184,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "VARIABLE_DEFINITION", - "description": "Location adjacent to a variable definition.", - "isDeprecated": false, - "deprecationReason": null - }, { "name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", @@ -208,6 +202,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "VARIABLE_DEFINITION", + "description": "Location adjacent to a variable definition.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "SCHEMA", "description": "Location adjacent to a schema definition.", @@ -866,12 +866,6 @@ "description": "Indicates this type is a non-null. \u0060ofType\u0060 is a valid field.", "isDeprecated": false, "deprecationReason": null - }, - { - "name": "DIRECTIVE", - "description": null, - "isDeprecated": false, - "deprecationReason": null } ], "possibleTypes": null diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery_ToJson.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery_ToJson.snap index ad17f1798ad..3e4e4494903 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery_ToJson.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/IntrospectionTests.ExecuteGraphiQLIntrospectionQuery_ToJson.snap @@ -184,12 +184,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "VARIABLE_DEFINITION", - "description": "Location adjacent to a variable definition.", - "isDeprecated": false, - "deprecationReason": null - }, { "name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", @@ -208,6 +202,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "VARIABLE_DEFINITION", + "description": "Location adjacent to a variable definition.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "SCHEMA", "description": "Location adjacent to a schema definition.", @@ -866,12 +866,6 @@ "description": "Indicates this type is a non-null. \u0060ofType\u0060 is a valid field.", "isDeprecated": false, "deprecationReason": null - }, - { - "name": "DIRECTIVE", - "description": null, - "isDeprecated": false, - "deprecationReason": null } ], "possibleTypes": null diff --git a/src/HotChocolate/Core/test/Types.Tests/SchemaFirstTests.cs b/src/HotChocolate/Core/test/Types.Tests/SchemaFirstTests.cs index 1bd7f24b3d2..f077bfd3e92 100644 --- a/src/HotChocolate/Core/test/Types.Tests/SchemaFirstTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/SchemaFirstTests.cs @@ -2,6 +2,8 @@ using System.Threading.Tasks; using ChilliCream.Testing; using HotChocolate.Execution; +using HotChocolate.Types.Introspection; +using Microsoft.VisualBasic.CompilerServices; using Snapshooter.Xunit; using Xunit; @@ -25,6 +27,8 @@ public async Task DescriptionsAreCorrectlyRead() c.Use(next => context => next(context)); }); + var foo = schema.GetType<__Type>("__Type"); + // assert IRequestExecutor executor = schema.MakeExecutable(); IExecutionResult result = await executor.ExecuteAsync(query); @@ -111,7 +115,7 @@ public async Task SchemaBuilder_BindType() await executor.ExecuteAsync("{ hello }"); result.ToJson().MatchSnapshot(); } - + [Fact] public async Task SchemaBuilder_AddResolver() { diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.DescriptionsAreCorrectlyRead.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.DescriptionsAreCorrectlyRead.snap index 505bb0ef7a5..974df8b27a4 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.DescriptionsAreCorrectlyRead.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.DescriptionsAreCorrectlyRead.snap @@ -409,12 +409,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "VARIABLE_DEFINITION", - "description": "Location adjacent to a variable definition.", - "isDeprecated": false, - "deprecationReason": null - }, { "name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", @@ -433,6 +427,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "VARIABLE_DEFINITION", + "description": "Location adjacent to a variable definition.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "SCHEMA", "description": "Location adjacent to a schema definition.", @@ -1091,12 +1091,6 @@ "description": "Indicates this type is a non-null. \u0060ofType\u0060 is a valid field.", "isDeprecated": false, "deprecationReason": null - }, - { - "name": "DIRECTIVE", - "description": null, - "isDeprecated": false, - "deprecationReason": null } ], "possibleTypes": null diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.Interfaces_Impl_Interfaces_Are_Correctly_Exposed_Through_Introspection.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.Interfaces_Impl_Interfaces_Are_Correctly_Exposed_Through_Introspection.snap index 49db7e42675..aa85e9508db 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.Interfaces_Impl_Interfaces_Are_Correctly_Exposed_Through_Introspection.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaFirstTests.Interfaces_Impl_Interfaces_Are_Correctly_Exposed_Through_Introspection.snap @@ -305,12 +305,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "VARIABLE_DEFINITION", - "description": "Location adjacent to a variable definition.", - "isDeprecated": false, - "deprecationReason": null - }, { "name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", @@ -329,6 +323,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "VARIABLE_DEFINITION", + "description": "Location adjacent to a variable definition.", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "SCHEMA", "description": "Location adjacent to a schema definition.", @@ -987,12 +987,6 @@ "description": "Indicates this type is a non-null. \u0060ofType\u0060 is a valid field.", "isDeprecated": false, "deprecationReason": null - }, - { - "name": "DIRECTIVE", - "description": null, - "isDeprecated": false, - "deprecationReason": null } ], "possibleTypes": null diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/DirectiveLocation.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/DirectiveLocation.cs index 6117216e4b0..b63ab718169 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/DirectiveLocation.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/DirectiveLocation.cs @@ -28,6 +28,8 @@ private DirectiveLocation(string value) _value = value; } + public string Value => _value; + public bool Equals(DirectiveLocation? other) { if (ReferenceEquals(null, other))