diff --git a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs index 6a11170a157..ccb76ff19e6 100644 --- a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs +++ b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs @@ -206,5 +206,17 @@ internal static string ThrowHelper_TryRewriteNullability_InvalidNullabilityStruc return ResourceManager.GetString("ThrowHelper_TryRewriteNullability_InvalidNullabilityStructure", resourceCulture); } } + + internal static string ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName { + get { + return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName", resourceCulture); + } + } + + internal static string ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate { + get { + return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate", resourceCulture); + } + } } } diff --git a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.resx b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.resx index db623dbceae..68b27859e0a 100644 --- a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.resx +++ b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.resx @@ -198,4 +198,10 @@ The nullability modifier does not match the field type structure. + + A argument name without a member name is only allowed on directive coordinates. + + + A directive cannot contain a member name. + diff --git a/src/HotChocolate/Core/src/Abstractions/SchemaCoordinate.cs b/src/HotChocolate/Core/src/Abstractions/SchemaCoordinate.cs new file mode 100644 index 00000000000..31d4bc07a83 --- /dev/null +++ b/src/HotChocolate/Core/src/Abstractions/SchemaCoordinate.cs @@ -0,0 +1,170 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using HotChocolate.Language; +using static HotChocolate.Properties.AbstractionResources; + +namespace HotChocolate; + +/// +/// A is a human readable string that uniquely identifies a +/// schema element within a GraphQL Schema. +/// A schema element is a specific instance of a named type, field, input field, enum value, +/// field argument, directive, or directive argument. +/// A is always unique. Each schema element may be referenced +/// by exactly one possible schema coordinate. +/// +/// A may refer to either a defined or built-in schema element. +/// For example, `String` and `@deprecated(reason:)` are both valid schema coordinates which refer +/// to built-in schema elements. However it must not refer to a meta-field. +/// For example, `Business.__typename` is not a valid schema coordinate. +/// +/// SchemaCoordinate : +/// - Name +/// - Name . Name +/// - Name . Name ( Name : ) +/// - @ Name +/// - @ Name ( Name : ) +/// +public readonly struct SchemaCoordinate +{ + /// + /// Creates a new instance of + /// + /// + /// The is null or . + /// + /// + /// - A directive cannot contain a . + /// - A . without a is only allowed + /// on directive coordinates. + /// + public SchemaCoordinate( + NameString name, + NameString? memberName = null, + NameString? argumentName = null, + bool ofDirective = false) + { + memberName?.EnsureNotEmpty(nameof(memberName)); + argumentName?.EnsureNotEmpty(nameof(argumentName)); + + if (ofDirective && memberName is not null) + { + throw new ArgumentException( + ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate, + nameof(memberName)); + } + + if (!ofDirective && memberName is null && argumentName is not null) + { + throw new ArgumentException( + ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName, + nameof(argumentName)); + } + + Name = name.EnsureNotEmpty(nameof(name)); + MemberName = memberName; + ArgumentName = argumentName; + OfDirective = ofDirective; + } + + /// + /// Specifies if this is a coordinate of a directive. + /// + public bool OfDirective { get; } + + /// + /// The name of the referenced + /// + public NameString Name { get; } + + /// + /// The optional name of the referenced field or enum value + /// + public NameString? MemberName { get; } + + /// + /// The optional name of the referenced argument + /// + public NameString? ArgumentName { get; } + + /// + /// Gets the syntax representation of this . + /// + public SchemaCoordinateNode ToSyntax() + { + NameNode? memberName = MemberName is null ? null : new(MemberName.Value); + NameNode? argumentName = ArgumentName is null ? null : new(ArgumentName.Value); + + return new(null, OfDirective, new(Name.Value), memberName, argumentName); + } + + /// + /// Gets the string representation of this . + /// + public override string ToString() => ToSyntax().ToString(); + + /// + /// Tries to parse a from a . + /// + /// The string that may represent a . + /// + /// If the string represented a valid schema coordinate string this + /// will be the parsed schema coordinate. + /// + /// + /// true if the string was a valid representation of a schema coordinate. + /// + public static bool TryParse( + string s, + [NotNullWhen(true)] out SchemaCoordinate? coordinate) + { + if (string.IsNullOrEmpty(s)) + { + coordinate = null; + return false; + } + + try + { + coordinate = Parse(s); + return true; + } + catch (SyntaxException) + { + coordinate = null; + return false; + } + } + + /// + /// Parses a schema coordinate string representation. + /// + /// The schema coordinate string representation. + /// + /// Returns the parses schema coordinate. + /// + public static SchemaCoordinate Parse(string s) + => FromSyntax(Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(s)); + + /// + /// Creates a from a . + /// + /// + /// The syntax node. + /// + /// + /// Returns the instance. + /// + public static SchemaCoordinate FromSyntax(SchemaCoordinateNode node) + { + NameString? memberName = node.MemberName is null + ? null + : (NameString?)node.MemberName.Value; + + NameString? argumentName = node.ArgumentName is null + ? null + : (NameString?)node.ArgumentName.Value; + + return new(node.Name.Value, memberName, argumentName, node.OfDirective); + } +} diff --git a/src/HotChocolate/Core/src/Types/Extensions/SchemaExtensions.cs b/src/HotChocolate/Core/src/Types/Extensions/SchemaExtensions.cs index 62db68c8e4f..add10fd232e 100644 --- a/src/HotChocolate/Core/src/Types/Extensions/SchemaExtensions.cs +++ b/src/HotChocolate/Core/src/Types/Extensions/SchemaExtensions.cs @@ -1,9 +1,17 @@ using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; using HotChocolate.Language; using HotChocolate.Types; +using TypeThrowHelper = HotChocolate.Utilities.ThrowHelper; + +#nullable enable namespace HotChocolate; +/// +/// Provides extension methods to . +/// public static class SchemaExtensions { /// @@ -14,7 +22,7 @@ public static class SchemaExtensions /// /// Returns the root operation object type. /// - public static ObjectType GetOperationType(this ISchema schema, OperationType operation) + public static ObjectType? GetOperationType(this ISchema schema, OperationType operation) { switch (operation) { @@ -28,4 +36,279 @@ public static ObjectType GetOperationType(this ISchema schema, OperationType ope throw new NotSupportedException(); } } + + /// + /// Tries to resolve a by its . + /// + /// + /// The schema on which the shall be resolved. + /// + /// + /// A string representing a schema coordinate. + /// + /// + /// The resolved type system member. + /// + /// + /// true if a type system member was found with the given + /// ; otherwise, false. + /// + /// + /// is null. + /// + public static bool TryGetMember( + this ISchema schema, + string coordinateString, + [NotNullWhen(true)] out ITypeSystemMember? member) + { + if (SchemaCoordinate.TryParse(coordinateString, out var coordinate)) + { + return TryGetMember(schema, coordinate.Value, out member); + } + + member = null; + return false; + } + + /// + /// Tries to resolve a by its . + /// + /// + /// The schema on which the shall be resolved. + /// + /// + /// A schema coordinate. + /// + /// + /// The resolved type system member. + /// + /// + /// true if a type system member was found with the given + /// ; otherwise, false. + /// + /// + /// is null. + /// + public static bool TryGetMember( + this ISchema schema, + SchemaCoordinate coordinate, + [NotNullWhen(true)] out ITypeSystemMember? member) + { + if (schema is null) + { + throw new ArgumentNullException(nameof(schema)); + } + + if (coordinate.OfDirective) + { + if (schema.TryGetDirectiveType(coordinate.Name, out var directive)) + { + if (coordinate.ArgumentName is null) + { + member = directive; + return true; + } + + if (directive.Arguments.TryGetField(coordinate.ArgumentName.Value, out var arg)) + { + member = arg; + return true; + } + } + + member = null; + return false; + } + + if (schema.TryGetType(coordinate.Name, out var type)) + { + if (coordinate.MemberName is null) + { + member = type; + return true; + } + + if (coordinate.ArgumentName is null) + { + if (type.Kind is TypeKind.Enum) + { + var enumType = (EnumType)type; + if (enumType.TryGetValue(coordinate.MemberName.Value, out var enumValue)) + { + member = enumValue; + return true; + } + } + + if (type.Kind is TypeKind.InputObject) + { + var inputType = (InputObjectType)type; + if (inputType.Fields.TryGetField(coordinate.MemberName.Value, out var input)) + { + member = input; + return true; + } + } + } + + if (type.Kind is not TypeKind.Object and not TypeKind.Interface) + { + member = null; + return false; + } + + var complexType = (IComplexOutputType)type; + if (complexType.Fields.TryGetField(coordinate.MemberName.Value, out var field)) + { + if (coordinate.ArgumentName is null) + { + member = field; + return true; + } + + if (field.Arguments.TryGetField(coordinate.ArgumentName.Value, out var fieldArg)) + { + member = fieldArg; + return true; + } + } + } + + member = null; + return false; + } + + /// + /// Gets a by its . + /// + /// + /// The schema on which the shall be resolved. + /// + /// + /// A string representing a schema coordinate. + /// + /// + /// Returns the resolved type system member. + /// + /// + /// is null. + /// + /// + /// The has invalid syntax. + /// + /// + /// Unable to resolve a type system member with the + /// specified . + /// + public static ITypeSystemMember GetMember( + this ISchema schema, + string coordinateString) + => GetMember(schema, SchemaCoordinate.Parse(coordinateString)); + + /// + /// Gets a by its . + /// + /// + /// The schema on which the shall be resolved. + /// + /// + /// A schema coordinate. + /// + /// + /// Returns the resolved type system member. + /// + /// + /// is null. + /// + /// + /// Unable to resolve a type system member with the + /// specified . + /// + public static ITypeSystemMember GetMember( + this ISchema schema, + SchemaCoordinate coordinate) + { + if (schema is null) + { + throw new ArgumentNullException(nameof(schema)); + } + + if (coordinate.OfDirective) + { + if (schema.TryGetDirectiveType(coordinate.Name, out var directive)) + { + if (coordinate.ArgumentName is null) + { + return directive; + } + + if (directive.Arguments.TryGetField(coordinate.ArgumentName.Value, out var arg)) + { + return arg; + } + + throw TypeThrowHelper.Schema_GetMember_DirectiveArgumentNotFound(coordinate); + } + + throw TypeThrowHelper.Schema_GetMember_DirectiveNotFound(coordinate); + } + + if (schema.TryGetType(coordinate.Name, out var type)) + { + if (coordinate.MemberName is null) + { + return type; + } + + if (coordinate.ArgumentName is null) + { + if (type.Kind is TypeKind.Enum) + { + var enumType = (EnumType)type; + if (enumType.TryGetValue(coordinate.MemberName.Value, out var enumValue)) + { + return enumValue; + } + + throw TypeThrowHelper.Schema_GetMember_EnumValueNotFound(coordinate); + } + + if (type.Kind is TypeKind.InputObject) + { + var inputType = (InputObjectType)type; + if (inputType.Fields.TryGetField(coordinate.MemberName.Value, out var input)) + { + return input; + } + + throw TypeThrowHelper.Schema_GetMember_InputFieldNotFound(coordinate); + } + } + + if (type.Kind is not TypeKind.Object and not TypeKind.Interface) + { + throw TypeThrowHelper.Schema_GetMember_InvalidCoordinate(coordinate, type); + } + + var complexType = (IComplexOutputType)type; + if (complexType.Fields.TryGetField(coordinate.MemberName.Value, out var field)) + { + if (coordinate.ArgumentName is null) + { + return field; + } + + if (field.Arguments.TryGetField(coordinate.ArgumentName.Value, out var fieldArg)) + { + return fieldArg; + } + + throw TypeThrowHelper.Schema_GetMember_FieldArgNotFound(coordinate); + } + + throw TypeThrowHelper.Schema_GetMember_FieldNotFound(coordinate); + } + + throw TypeThrowHelper.Schema_GetMember_TypeNotFound(coordinate); + } } diff --git a/src/HotChocolate/Core/src/Types/InvalidSchemaCoordinateException.cs b/src/HotChocolate/Core/src/Types/InvalidSchemaCoordinateException.cs new file mode 100644 index 00000000000..9ebf5f6c4e8 --- /dev/null +++ b/src/HotChocolate/Core/src/Types/InvalidSchemaCoordinateException.cs @@ -0,0 +1,51 @@ +using System; +using System.Runtime.Serialization; + +#nullable enable + +namespace HotChocolate; + +/// +/// This exception indicates that the specified +/// +/// could not be resolved. +/// +[Serializable] +public class InvalidSchemaCoordinateException : Exception +{ + /// + /// Creates new instance of . + /// + /// The error message. + /// The invalid schema coordinate. + public InvalidSchemaCoordinateException(string message, SchemaCoordinate coordinate) + : base(message) + { + Coordinate = coordinate; + } + + /// + /// Initializes a new instance of the + /// class with serialized data. + /// + /// The . + /// The . + protected InvalidSchemaCoordinateException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + Coordinate = SchemaCoordinate.Parse(info.GetString(nameof(Coordinate))!); + } + + /// + /// The invalid schema coordinate. + /// + /// + public SchemaCoordinate Coordinate { get; } + + /// + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue(nameof(Coordinate), Coordinate.ToString()); + } +} diff --git a/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumType.cs b/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumType.cs index 67a4c2ccc49..5344ad89218 100644 --- a/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumType.cs +++ b/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumType.cs @@ -21,6 +21,24 @@ public interface IEnumType : ILeafType /// IReadOnlyCollection Values { get; } + /// + /// Tries to get the for + /// the specified . + /// + /// + /// The GraphQL enum value name. + /// + /// + /// The GraphQL enum value. + /// + /// + /// true if the represents a value of this enum type; + /// otherwise, false. + /// + bool TryGetValue( + NameString name, + [NotNullWhen(true)] out IEnumValue? value); + /// /// Tries to get the for /// the specified . diff --git a/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumValue.cs b/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumValue.cs index b74275f199b..744d4b1f0d6 100644 --- a/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumValue.cs +++ b/src/HotChocolate/Core/src/Types/Types/Contracts/IEnumValue.cs @@ -10,6 +10,7 @@ namespace HotChocolate.Types; public interface IEnumValue : IHasDirectives , IHasReadOnlyContextData + , ITypeSystemMember { /// /// The associated syntax node from the GraphQL SDL. diff --git a/src/HotChocolate/Core/src/Types/Types/EnumType.cs b/src/HotChocolate/Core/src/Types/Types/EnumType.cs index da15a33f492..0f0d59bfcab 100644 --- a/src/HotChocolate/Core/src/Types/Types/EnumType.cs +++ b/src/HotChocolate/Core/src/Types/Types/EnumType.cs @@ -54,21 +54,11 @@ public partial class EnumType /// protected IReadOnlyDictionary ValueLookup => _valueLookup; - /// - /// Tries to resolve the runtime value of this enum type by its name. - /// - /// - /// The GraphQL name for the enum value. - /// - /// - /// The runtime enum runtime value. - /// - /// - /// true, if there is a runtime value associated with the provided enum value name. - /// - public bool TryGetRuntimeValue( - NameString name, - [NotNullWhen(true)] out object? runtimeValue) + public bool TryGetValue(NameString name, [NotNullWhen(true)] out IEnumValue? value) + => _enumValues.TryGetValue(name, out value); + + /// + public bool TryGetRuntimeValue(NameString name, [NotNullWhen(true)] out object? runtimeValue) { if (_enumValues.TryGetValue(name, out IEnumValue? value)) { diff --git a/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs b/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs index 54860dd9e0c..dbeffa79c35 100644 --- a/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs +++ b/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using HotChocolate.Language; @@ -405,4 +406,84 @@ public static SerializationException FormatResultLeaf_InvalidSyntaxKind( public static InvalidOperationException RewriteNullability_InvalidNullabilityStructure() => new(AbstractionResources.ThrowHelper_TryRewriteNullability_InvalidNullabilityStructure); + + public static InvalidSchemaCoordinateException Schema_GetMember_DirectiveArgumentNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Argument `{0}` was not found on directive `@{1}`.", + coordinate.ArgumentName!.Value, + coordinate.Name), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_DirectiveNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Directive `@{0}` not found.", + coordinate.Name), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_EnumValueNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Enum value `{0}` was not found on type `{1}`.", + coordinate.MemberName!.Value, + coordinate.Name), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_InputFieldNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Input field `{0}` was not found on type `{1}`.", + coordinate.MemberName!.Value, + coordinate.Name), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_InvalidCoordinate( + SchemaCoordinate coordinate, + INamedType type) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "The coordinate `{0}` is invalid for the type `{1}`.", + coordinate.ToString(), + type.Name.Value), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_FieldArgNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Argument `{0}` was not found on field `{1}.{2}`.", + coordinate.ArgumentName!.Value, + coordinate.Name.Value, + coordinate.MemberName!.Value), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_FieldNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "Field `{0}` was not found on type `{1}`.", + coordinate.MemberName!.Value, + coordinate.Name.Value), + coordinate); + + public static InvalidSchemaCoordinateException Schema_GetMember_TypeNotFound( + SchemaCoordinate coordinate) + => new InvalidSchemaCoordinateException( + string.Format( + CultureInfo.InvariantCulture, + "A type with the name `{0}` was not found.", + coordinate.Name.Value), + coordinate); } diff --git a/src/HotChocolate/Core/test/Abstractions.Tests/SchemaCoordinateTests.cs b/src/HotChocolate/Core/test/Abstractions.Tests/SchemaCoordinateTests.cs new file mode 100644 index 00000000000..f1faabda066 --- /dev/null +++ b/src/HotChocolate/Core/test/Abstractions.Tests/SchemaCoordinateTests.cs @@ -0,0 +1,218 @@ +using System; +using HotChocolate.Language; +using Xunit; + +#nullable enable + +namespace HotChocolate; + +public class SchemaCoordinateTests +{ + [Fact] + public void Create_Type_SchemaCoordinate() + { + // arrange & act + var coordinate = new SchemaCoordinate("Abc"); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("Abc", coordinate.ToString()); + } + + [Fact] + public void Create_Field_SchemaCoordinate() + { + // arrange & act + var coordinate = new SchemaCoordinate("Abc", "def"); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("def", coordinate.MemberName); + Assert.Equal("Abc.def", coordinate.ToString()); + } + + [Fact] + public void Create_Field_Argument_SchemaCoordinate() + { + // arrange & act + var coordinate = new SchemaCoordinate("Abc", "def", "ghi"); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("def", coordinate.MemberName); + Assert.Equal("ghi", coordinate.ArgumentName); + Assert.Equal("Abc.def(ghi:)", coordinate.ToString()); + } + + [Fact] + public void Create_Field_Argument_SchemaCoordinate_Without_MemberName() + { + // arrange & act + void Fail() => new SchemaCoordinate("abc", argumentName: "def"); + + // assert + ArgumentException ex = Assert.Throws(Fail); + Assert.Equal("argumentName", ex.ParamName); + Assert.StartsWith( + "A argument name without a member name is only allowed on directive coordinates", + ex.Message); + } + + [Fact] + public void Create_Directive_SchemaCoordinate() + { + // arrange & act + var coordinate = new SchemaCoordinate("abc", ofDirective: true); + + // assert + Assert.Equal("abc", coordinate.Name); + Assert.Equal("@abc", coordinate.ToString()); + } + + [Fact] + public void Create_Directive_Argument_SchemaCoordinate() + { + // arrange & act + var coordinate = new SchemaCoordinate("abc", argumentName: "def", ofDirective: true); + + // assert + Assert.Equal("abc", coordinate.Name); + Assert.Equal("def", coordinate.ArgumentName); + Assert.Equal("@abc(def:)", coordinate.ToString()); + } + + [Fact] + public void Create_Directive_SchemaCoordinate_With() + { + // arrange & act + void Fail() => new SchemaCoordinate("abc", memberName: "def", ofDirective: true); + + // assert + ArgumentException ex = Assert.Throws(Fail); + Assert.Equal("memberName", ex.ParamName); + Assert.StartsWith("A directive cannot contain a member name.", ex.Message); + } + + [Fact] + public void Parse_SchemaCoordinate() + { + // arrange & act + var coordinate = SchemaCoordinate.Parse("Abc.def"); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("def", coordinate.MemberName); + Assert.Equal("Abc.def", coordinate.ToString()); + } + + [Fact] + public void Parse_Invalid_SchemaCoordinate() + { + // arrange & act + void Fail() => SchemaCoordinate.Parse("..."); + + // assert + Assert.Throws(Fail); + } + + [Fact] + public void TryParse_SchemaCoordinate() + { + // arrange & act + var success = SchemaCoordinate.TryParse("Abc.def", out var coordinate); + + // assert + Assert.True(success); + Assert.Equal("Abc", coordinate?.Name); + Assert.Equal("def", coordinate?.MemberName); + Assert.Equal("Abc.def", coordinate?.ToString()); + } + + [InlineData(null)] + [InlineData("")] + [InlineData("...")] + [Theory] + public void TryParse_Invalid_SchemaCoordinate(string? s) + { + // arrange & act + var success = SchemaCoordinate.TryParse(s, out var coordinate); + + // assert + Assert.False(success); + Assert.Null(coordinate); + } + + [Fact] + public void FromSyntax_Type_SchemaCoordinate() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), null, null); + + // act + var coordinate = SchemaCoordinate.FromSyntax(node); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("Abc", coordinate.ToString()); + } + + [Fact] + public void FromSyntax_Field_SchemaCoordinate() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), new("def"), null); + + // act + var coordinate = SchemaCoordinate.FromSyntax(node); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("def", coordinate.MemberName); + Assert.Equal("Abc.def", coordinate.ToString()); + } + + [Fact] + public void FromSyntax_Field_Argument_SchemaCoordinate() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), new("def"), new("ghi")); + + // act + var coordinate = SchemaCoordinate.FromSyntax(node); + + // assert + Assert.Equal("Abc", coordinate.Name); + Assert.Equal("def", coordinate.MemberName); + Assert.Equal("ghi", coordinate.ArgumentName); + Assert.Equal("Abc.def(ghi:)", coordinate.ToString()); + } + + [Fact] + public void FromSyntax_Directive_SchemaCoordinate() + { + // arrange + var node = new SchemaCoordinateNode(null, true, new("abc"), null, null); + + // act + var coordinate = SchemaCoordinate.FromSyntax(node); + + // assert + Assert.Equal("abc", coordinate.Name); + Assert.Equal("@abc", coordinate.ToString()); + } + + [Fact] + public void FromSyntax_Directive_Argument_SchemaCoordinate() + { + // arrange + var node = new SchemaCoordinateNode(null, true, new("abc"), null, new("def")); + + // act + var coordinate = SchemaCoordinate.FromSyntax(node); + + // assert + Assert.Equal("abc", coordinate.Name); + Assert.Equal("def", coordinate.ArgumentName); + Assert.Equal("@abc(def:)", coordinate.ToString()); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/SchemaCoordinateTests.cs b/src/HotChocolate/Core/test/Types.Tests/SchemaCoordinateTests.cs new file mode 100644 index 00000000000..c96bdc5e84c --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/SchemaCoordinateTests.cs @@ -0,0 +1,717 @@ +using ChilliCream.Testing; +using HotChocolate.Types; +using Snapshooter.Xunit; +using Xunit; + +#nullable enable + +namespace HotChocolate; + +public class SchemaCoordinateTests +{ + [Fact] + public void GetMember_ObjectType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Baz"); + + // assert + Assert.Equal("Baz", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_ObjectType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Baz.name"); + + // assert + ObjectField field = Assert.IsType(member); + Assert.Equal("name", field.Name); + Assert.Equal("Baz", field.DeclaringType.Name); + } + + [Fact] + public void GetMember_ObjectType_FieldArg() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Baz.name(baz:)"); + + // assert + Argument arg = Assert.IsType(member); + Assert.Equal("baz", arg.Name); + Assert.Equal("name", Assert.IsType(arg.DeclaringMember).Name); + Assert.Equal("Baz", arg.DeclaringType.Name); + } + + [Fact] + public void GetMember_Object_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Baz.foo"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_Object_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Baz.name(bar:)"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_InterfaceType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Bar"); + + // assert + Assert.Equal("Bar", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_InterfaceType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Bar.id"); + + // assert + InterfaceField field = Assert.IsType(member); + Assert.Equal("id", field.Name); + Assert.Equal("Bar", field.DeclaringType.Name); + } + + [Fact] + public void GetMember_InterfaceType_FieldArg() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Bar.name(baz:)"); + + // assert + Argument arg = Assert.IsType(member); + Assert.Equal("baz", arg.Name); + Assert.Equal("name", Assert.IsType(arg.DeclaringMember).Name); + Assert.Equal("Bar", arg.DeclaringType.Name); + } + + [Fact] + public void GetMember_Interface_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Bar.xyz"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_Interface_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Bar.name(bar:)"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_UnionType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("FooOrBaz"); + + // assert + Assert.Equal("FooOrBaz", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_UnionType_Invalid_MemberName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("FooOrBaz.Foo"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_InputObjectType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("BazInput"); + + // assert + Assert.Equal("BazInput", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_InputObjectType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("BazInput.name"); + + // assert + InputField argument = Assert.IsType(member); + Assert.Equal("name", argument.Name); + Assert.Equal("BazInput", argument.DeclaringType.Name); + } + + [Fact] + public void GetMember_InputObjectType_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("BazInput.abc"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_InputObjectType_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("BazInput.name(a:)"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_EnumType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Abc"); + + // assert + Assert.Equal("Abc", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_EnumType_Value() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("Abc.DEF"); + + // assert + Assert.Equal("DEF", Assert.IsType(member).Name.Value); + } + + [Fact] + public void GetMember_EnumType_Invalid_Value() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Abc.XYZ"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_ScalarType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("String"); + + // assert + Assert.Equal("String", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_DirectiveType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("@qux"); + + // assert + Assert.Equal("qux", Assert.IsType(member).Name); + } + + [Fact] + public void GetMember_DirectiveType_Argument() + { + // arrange + ISchema schema = CreateSchema(); + + // act + ITypeSystemMember member = schema.GetMember("@qux(a:)"); + + // assert + Argument argument = Assert.IsType(member); + Assert.Equal("a", argument.Name); + Assert.Equal("qux", argument.DeclaringType.Name); + } + + [Fact] + public void GetMember_DirectiveType_Invalid_ArgumentName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("@qux(b:)"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void GetMember_Invalid_TypeName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("Abc123"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + + [Fact] + public void GetMember_Invalid_DirectiveName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + void Fail() => schema.GetMember("@foo123"); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + + [Fact] + public void TryGetMember_ObjectType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz", out var member); + + // assert + Assert.True(success); + Assert.Equal("Baz", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_ObjectType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz.name", out var member); + + // assert + Assert.True(success); + ObjectField field = Assert.IsType(member); + Assert.Equal("name", field.Name); + Assert.Equal("Baz", field.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_ObjectType_FieldArg() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz.name(baz:)", out var member); + + // assert + Assert.True(success); + Argument arg = Assert.IsType(member); + Assert.Equal("baz", arg.Name); + Assert.Equal("name", Assert.IsType(arg.DeclaringMember).Name); + Assert.Equal("Baz", arg.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_Object_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz.foo", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_Object_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz.name(bar:)", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_InterfaceType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Bar", out var member); + + // assert + Assert.True(success); + Assert.Equal("Bar", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_InterfaceType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Bar.id", out var member); + + // assert + Assert.True(success); + InterfaceField field = Assert.IsType(member); + Assert.Equal("id", field.Name); + Assert.Equal("Bar", field.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_InterfaceType_FieldArg() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Bar.name(baz:)", out var member); + + // assert + Assert.True(success); + Argument arg = Assert.IsType(member); + Assert.Equal("baz", arg.Name); + Assert.Equal("name", Assert.IsType(arg.DeclaringMember).Name); + Assert.Equal("Bar", arg.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_Interface_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Baz.xyz", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_Interface_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Bar.name(bar:)", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_UnionType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("FooOrBaz", out var member); + + // assert + Assert.True(success); + } + + [Fact] + public void TryGetMember_UnionType_Invalid_MemberName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("FooOrBaz.Foo", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_InputObjectType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("BazInput", out var member); + + // assert + Assert.True(success); + Assert.Equal("BazInput", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_InputObjectType_Field() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("BazInput.name", out var member); + + // assert + Assert.True(success); + InputField argument = Assert.IsType(member); + Assert.Equal("name", argument.Name); + Assert.Equal("BazInput", argument.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_InputObjectType_Invalid_FieldName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("BazInput.abc", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_InputObjectType_Invalid_FieldArgName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("BazInput.name(a:)", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_EnumType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Abc", out var member); + + // assert + Assert.True(success); + Assert.Equal("Abc", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_EnumType_Value() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Abc.DEF", out var member); + + // assert + Assert.True(success); + Assert.Equal("DEF", Assert.IsType(member).Name.Value); + } + + [Fact] + public void TryGetMember_EnumType_Invalid_Value() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Abc.XYZ", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_ScalarType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("String", out var member); + + // assert + Assert.True(success); + Assert.Equal("String", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_DirectiveType() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("@qux", out var member); + + // assert + Assert.True(success); + Assert.Equal("qux", Assert.IsType(member).Name); + } + + [Fact] + public void TryGetMember_DirectiveType_Argument() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("@qux(a:)", out var member); + + // assert + Assert.True(success); + Argument argument = Assert.IsType(member); + Assert.Equal("a", argument.Name); + Assert.Equal("qux", argument.DeclaringType.Name); + } + + [Fact] + public void TryGetMember_DirectiveType_Invalid_ArgumentName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("@qux(b:)", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_Invalid_TypeName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("Abc123", out var member); + + // assert + Assert.False(success); + } + + [Fact] + public void TryGetMember_Invalid_DirectiveName() + { + // arrange + ISchema schema = CreateSchema(); + + // act + bool success = schema.TryGetMember("@abc", out var member); + + // assert + Assert.False(success); + } + + private ISchema CreateSchema() + { + return SchemaBuilder.New() + .AddDocumentFromString(FileResource.Open("schema_coordinates.graphql")) + .ModifyOptions( + o => + { + o.StrictValidation = false; + o.RemoveUnreachableTypes = false; + }) + .Use(next => context => default) + .Create(); + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__resources__/schema_coordinates.graphql b/src/HotChocolate/Core/test/Types.Tests/__resources__/schema_coordinates.graphql new file mode 100644 index 00000000000..ee2b75a9dd6 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__resources__/schema_coordinates.graphql @@ -0,0 +1,26 @@ +type Baz { + name(baz: BazInput): String +} + +type Foo implements Bar { + id: ID! + name(baz: BazInput): String +} + +interface Bar { + id: ID! + name(baz: BazInput): String +} + +union FooOrBaz = Foo | Baz + +input BazInput { + name: String +} + +enum Abc { + DEF + GHI +} + +directive @qux(a: String) on FIELD_DEFINITION diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_DirectiveType_Invalid_ArgumentName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_DirectiveType_Invalid_ArgumentName.snap new file mode 100644 index 00000000000..9bfd59c74e7 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_DirectiveType_Invalid_ArgumentName.snap @@ -0,0 +1 @@ +Argument `b` was not found on directive `@qux`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_EnumType_Invalid_Value.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_EnumType_Invalid_Value.snap new file mode 100644 index 00000000000..39dd85735f4 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_EnumType_Invalid_Value.snap @@ -0,0 +1 @@ +Enum value `XYZ` was not found on type `Abc`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldArgName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldArgName.snap new file mode 100644 index 00000000000..051e4915d9e --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldArgName.snap @@ -0,0 +1 @@ +The coordinate `BazInput.name(a:)` is invalid for the type `BazInput`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldName.snap new file mode 100644 index 00000000000..762344dc54d --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_InputObjectType_Invalid_FieldName.snap @@ -0,0 +1 @@ +Input field `abc` was not found on type `BazInput`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldArgName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldArgName.snap new file mode 100644 index 00000000000..902af411c7c --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldArgName.snap @@ -0,0 +1 @@ +Argument `bar` was not found on field `Bar.name`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldName.snap new file mode 100644 index 00000000000..99ad327f746 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Interface_Invalid_FieldName.snap @@ -0,0 +1 @@ +Field `xyz` was not found on type `Bar`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_DirectiveName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_DirectiveName.snap new file mode 100644 index 00000000000..76fe1b35fa3 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_DirectiveName.snap @@ -0,0 +1 @@ +Directive `@foo123` not found. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_TypeName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_TypeName.snap new file mode 100644 index 00000000000..c2b500af6e1 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Invalid_TypeName.snap @@ -0,0 +1 @@ +A type with the name `Abc123` was not found. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldArgName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldArgName.snap new file mode 100644 index 00000000000..bdd106051cc --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldArgName.snap @@ -0,0 +1 @@ +Argument `bar` was not found on field `Baz.name`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldName.snap new file mode 100644 index 00000000000..12798961166 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_Object_Invalid_FieldName.snap @@ -0,0 +1 @@ +Field `foo` was not found on type `Baz`. diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_UnionType_Invalid_MemberName.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_UnionType_Invalid_MemberName.snap new file mode 100644 index 00000000000..9f028cd1508 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/SchemaCoordinateTests.GetMember_UnionType_Invalid_MemberName.snap @@ -0,0 +1 @@ +The coordinate `FooOrBaz.Foo` is invalid for the type `FooOrBaz`. diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.Designer.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.Designer.cs index b0d4e918df8..bb9efe8ce21 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.Designer.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.Designer.cs @@ -50,5 +50,17 @@ internal static string DirectiveLocation_Value_CannotBeNullOrEmpty { return ResourceManager.GetString("DirectiveLocation_Value_CannotBeNullOrEmpty", resourceCulture); } } + + internal static string ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName { + get { + return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName", resourceCulture); + } + } + + internal static string ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate { + get { + return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate", resourceCulture); + } + } } } diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.resx b/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.resx index 4e510f1322d..40fcf54d8ea 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.resx +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Properties/Resources.resx @@ -101,4 +101,10 @@ The value mustn't be null or empty. + + A argument name without a member name is only allowed on directive coordinates. + + + A directive cannot contain a member name. + diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/SchemaCoordinateNode.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/SchemaCoordinateNode.cs new file mode 100644 index 00000000000..3ccbf6b8150 --- /dev/null +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/SchemaCoordinateNode.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using HotChocolate.Language.Utilities; +using static HotChocolate.Language.Utilities.ThrowHelper; + +namespace HotChocolate.Language; + +/// +/// A is a human readable string that uniquely identifies a +/// schema element within a GraphQL Schema. +/// A schema element is a specific instance of a named type, field, input field, enum value, +/// field argument, directive, or directive argument. +/// A is always unique. Each schema element may be referenced +/// by exactly one possible schema coordinate. +/// +/// A may refer to either a defined or built-in schema element. +/// For example, `String` and `@deprecated(reason:)` are both valid schema coordinates which refer +/// to built-in schema elements. However it must not refer to a meta-field. +/// For example, `Business.__typename` is not a valid schema coordinate. +/// +/// SchemaCoordinate : +/// - Name +/// - Name . Name +/// - Name . Name ( Name : ) +/// - @ Name +/// - @ Name ( Name : ) +/// +/// +/// Note: A is not a definition within a GraphQL +/// , but a separate standalone grammar, intended to be used by tools +/// to reference types, fields, and other schema elements. For example as references within +/// documentation, or as lookup keys in usage frequency tracking. +/// +/// +public sealed class SchemaCoordinateNode : ISyntaxNode +{ + /// + /// Creates a new instance of + /// + public SchemaCoordinateNode( + Location? location, + bool ofDirective, + NameNode name, + NameNode? memberName, + NameNode? argumentName) + { + if (ofDirective && memberName is not null) + { + throw SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate(nameof(memberName)); + } + + if (!ofDirective && memberName is null && argumentName is not null) + { + throw SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName(nameof(memberName)); + } + + Location = location; + OfDirective = ofDirective; + Name = name ?? throw new ArgumentNullException(nameof(name)); + MemberName = memberName; + ArgumentName = argumentName; + } + + /// + public Location? Location { get; } + + /// + public SyntaxKind Kind => SyntaxKind.SchemaCoordinate; + + /// + /// Specifies if this is a coordinate of a directive. + /// + public bool OfDirective { get; } + + /// + /// The name of the referenced + /// + public NameNode Name { get; } + + /// + /// The optional name of the referenced field or enum value + /// + public NameNode? MemberName { get; } + + /// + /// The optional name of the referenced argument + /// + public NameNode? ArgumentName { get; } + + /// + public IEnumerable GetNodes() + { + yield return Name; + + if (MemberName is not null) + { + yield return MemberName; + } + + if (ArgumentName is not null) + { + yield return ArgumentName; + } + } + + /// + /// Returns the GraphQL syntax representation of this . + /// + /// + /// Returns the GraphQL syntax representation of this . + /// + public override string ToString() => SyntaxPrinter.Print(this, true); + + /// + /// Returns the GraphQL syntax representation of this . + /// + /// + /// A value that indicates whether the GraphQL output should be formatted, + /// which includes indenting nested GraphQL tokens, adding + /// new lines, and adding white space between property names and values. + /// + /// + /// Returns the GraphQL syntax representation of this . + /// + public string ToString(bool indented) => SyntaxPrinter.Print(this, indented); + + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The location that shall be used to replace the current location. + /// + /// + /// Returns the new node with the new . + /// + public SchemaCoordinateNode WithLocation(Location? location) + => new(location, OfDirective, Name, MemberName, ArgumentName); + + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The ofDirective that shall be used to replace the current ofDirective. + /// + /// + /// Returns the new node with the new . + /// + public SchemaCoordinateNode WithOfDirective(bool ofDirective) + => new(Location, ofDirective, Name, MemberName, ArgumentName); + + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The name that shall be used to replace the current name. + /// + /// + /// Returns the new node with the new . + /// + public SchemaCoordinateNode WithName(NameNode name) + => new(Location, OfDirective, name, MemberName, ArgumentName); + + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The memberName that shall be used to replace the current memberName. + /// + /// + /// Returns the new node with the new . + /// + public SchemaCoordinateNode WithMemberName(NameNode? memberName) + => new(Location, OfDirective, Name, memberName, ArgumentName); + + /// + /// Creates a new node from the current instance and replaces the + /// with . + /// + /// + /// The argumentName that shall be used to replace the current argumentName. + /// + /// + /// Returns the new node with the new . + /// + public SchemaCoordinateNode WithArgumentName(NameNode? argumentName) + => new(Location, OfDirective, Name, MemberName, argumentName); +} diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/SyntaxKind.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/SyntaxKind.cs index 841dc03d767..fb0289994e8 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/SyntaxKind.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/SyntaxKind.cs @@ -48,5 +48,6 @@ public enum SyntaxKind PublicKeyword, ListNullability, RequiredDesignator, - OptionalDesignator + OptionalDesignator, + SchemaCoordinate, } diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs index 9e65bbc608c..a60f628b73f 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.SchemaSyntax.cs @@ -220,6 +220,30 @@ private void VisitInputObjectTypeExtension( VisitInputObjectTypeDefinitionBase(node, writer); } + private void VisitSchemaCoordinate( + SchemaCoordinateNode node, + ISyntaxWriter writer) + { + if (node.OfDirective) + { + writer.Write("@"); + } + + writer.WriteName(node.Name); + if (node.MemberName is not null) + { + writer.Write("."); + writer.WriteName(node.MemberName); + } + + if (node.ArgumentName is not null) + { + writer.Write("("); + writer.WriteName(node.ArgumentName); + writer.Write(":)"); + } + } + private void VisitInputObjectTypeDefinitionBase( InputObjectTypeDefinitionNodeBase node, ISyntaxWriter writer) diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.cs index f97dbf133ae..d3a91808a94 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/SyntaxSerializer.cs @@ -132,6 +132,9 @@ public void Serialize(ISyntaxNode node, ISyntaxWriter writer) case SyntaxKind.InputObjectTypeExtension: VisitInputObjectTypeExtension((InputObjectTypeExtensionNode)node, writer); break; + case SyntaxKind.SchemaCoordinate: + VisitSchemaCoordinate((SchemaCoordinateNode)node, writer); + break; default: ThrowHelper.NodeKindIsNotSupported(node.Kind); break; diff --git a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/ThrowHelper.cs b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/ThrowHelper.cs index d546a0b4927..cdc3ff06f01 100644 --- a/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/ThrowHelper.cs +++ b/src/HotChocolate/Language/src/Language.SyntaxTree/Utilities/ThrowHelper.cs @@ -1,4 +1,5 @@ using System; +using HotChocolate.Language.Properties; namespace HotChocolate.Language.Utilities; @@ -7,4 +8,15 @@ internal static class ThrowHelper public static void NodeKindIsNotSupported(SyntaxKind kind) => throw new NotSupportedException($"The node kind {kind} is not supported."); + public static Exception SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate( + string argumentName) => + throw new ArgumentException( + Resources.ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate, + argumentName); + + public static Exception SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName( + string argumentName) => + throw new ArgumentException( + Resources.ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName, + argumentName); } diff --git a/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.Designer.cs b/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.Designer.cs index 4a2ad6c2526..26acb0e0468 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.Designer.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.Designer.cs @@ -9,21 +9,21 @@ namespace HotChocolate.Language.Properties { using System; - - + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class LangUtf8Resources { - + private static System.Resources.ResourceManager resourceMan; - + private static System.Globalization.CultureInfo resourceCulture; - + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal LangUtf8Resources() { } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Resources.ResourceManager ResourceManager { get { @@ -34,7 +34,7 @@ internal static System.Resources.ResourceManager ResourceManager { return resourceMan; } } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Globalization.CultureInfo Culture { get { @@ -44,109 +44,115 @@ internal static System.Globalization.CultureInfo Culture { resourceCulture = value; } } - + internal static string GraphQLData_Empty { get { return ResourceManager.GetString("GraphQLData_Empty", resourceCulture); } } - + internal static string ParseMany_InvalidOpenToken { get { return ResourceManager.GetString("ParseMany_InvalidOpenToken", resourceCulture); } } - + internal static string Parser_InvalidScalarToken { get { return ResourceManager.GetString("Parser_InvalidScalarToken", resourceCulture); } } - + internal static string Parser_InvalidToken { get { return ResourceManager.GetString("Parser_InvalidToken", resourceCulture); } } - + internal static string QuerySyntaxRewriter_NotSupported { get { return ResourceManager.GetString("QuerySyntaxRewriter_NotSupported", resourceCulture); } } - + internal static string Reader_InvalidToken { get { return ResourceManager.GetString("Reader_InvalidToken", resourceCulture); } } - + + internal static string Reader_UnexpectedDigitAfterDot { + get { + return ResourceManager.GetString("Reader_UnexpectedDigitAfterDot", resourceCulture); + } + } + internal static string Reader_UnexpectedPunctuatorToken { get { return ResourceManager.GetString("Reader_UnexpectedPunctuatorToken", resourceCulture); } } - + internal static string SourceText_Empty { get { return ResourceManager.GetString("SourceText_Empty", resourceCulture); } } - + internal static string Utf8Helper_InvalidEscapeChar { get { return ResourceManager.GetString("Utf8Helper_InvalidEscapeChar", resourceCulture); } } - + internal static string Utf8Helper_InvalidQuoteEscapeCount { get { return ResourceManager.GetString("Utf8Helper_InvalidQuoteEscapeCount", resourceCulture); } } - + internal static string NewLineMustBeGreaterOrEqualToOne { get { return ResourceManager.GetString("NewLineMustBeGreaterOrEqualToOne", resourceCulture); } } - + internal static string UnexpectedDigit { get { return ResourceManager.GetString("UnexpectedDigit", resourceCulture); } } - + internal static string InvalidNumber { get { return ResourceManager.GetString("InvalidNumber", resourceCulture); } } - + internal static string UnexpectedCharacter { get { return ResourceManager.GetString("UnexpectedCharacter", resourceCulture); } } - + internal static string InvalidCharacterEscapeSequence { get { return ResourceManager.GetString("InvalidCharacterEscapeSequence", resourceCulture); } } - + internal static string InvalidCharacterWithinString { get { return ResourceManager.GetString("InvalidCharacterWithinString", resourceCulture); } } - + internal static string UnterminatedString { get { return ResourceManager.GetString("UnterminatedString", resourceCulture); } } - + internal static string UnexpectedToken { get { return ResourceManager.GetString("UnexpectedToken", resourceCulture); diff --git a/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.resx b/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.resx index b723f950646..c0c58ef32a9 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.resx +++ b/src/HotChocolate/Language/src/Language.Utf8/Properties/LangUtf8Resources.resx @@ -36,6 +36,9 @@ Expected a `{0}`-token. + + Invalid number, expected digit before ".". + Unexpected punctuator token `{0}`. diff --git a/src/HotChocolate/Language/src/Language.Utf8/TokenKind.cs b/src/HotChocolate/Language/src/Language.Utf8/TokenKind.cs index 7f081905f9f..fab6faacd0f 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/TokenKind.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/TokenKind.cs @@ -118,5 +118,10 @@ public enum TokenKind : byte /// /// A comment token. /// - Comment + Comment, + + /// + /// . + /// + Dot, } diff --git a/src/HotChocolate/Language/src/Language.Utf8/TokenPrinter.cs b/src/HotChocolate/Language/src/Language.Utf8/TokenPrinter.cs index 25e5d50baea..851b1b84c20 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/TokenPrinter.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/TokenPrinter.cs @@ -10,6 +10,7 @@ internal static class TokenPrinter { TokenKind.StartOfFile, "" }, { TokenKind.EndOfFile, "" }, { TokenKind.Bang, "!" }, + { TokenKind.QuestionMark, "?" }, { TokenKind.Dollar, "$" }, { TokenKind.Ampersand, "&" }, { TokenKind.LeftParenthesis, "(" }, @@ -28,7 +29,8 @@ internal static class TokenPrinter { TokenKind.Float, "Float" }, { TokenKind.String, "String" }, { TokenKind.BlockString, "BlockString" }, - { TokenKind.Comment, "Comment" } + { TokenKind.Comment, "Comment" }, + { TokenKind.Dot, "." }, }; public static string Print(in Utf8GraphQLReader reader) diff --git a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.SchemaCoordinate.cs b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.SchemaCoordinate.cs new file mode 100644 index 00000000000..1988c72951a --- /dev/null +++ b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.SchemaCoordinate.cs @@ -0,0 +1,71 @@ +namespace HotChocolate.Language; + +// Implements the parsing rules in the Operations section. +public ref partial struct Utf8GraphQLParser +{ + /// + /// Parses a single schema coordinate. + /// : + /// SchemaCoordinate : + /// - Name + /// - Name . Name + /// - Name . Name ( Name : ) + /// - @ Name + /// - @ Name ( Name : ) + /// + private SchemaCoordinateNode ParseSingleSchemaCoordinate() + { + SchemaCoordinateNode node = ParseSchemaCoordinate(); + Expect(TokenKind.EndOfFile); + return node; + } + + /// + /// Parses a schema coordinate. + /// : + /// SchemaCoordinate : + /// - Name + /// - Name . Name + /// - Name . Name ( Name : ) + /// - @ Name + /// - @ Name ( Name : ) + /// + private SchemaCoordinateNode ParseSchemaCoordinate() + { + TokenInfo start = Start(); + + bool ofDirective = SkipAt(); + NameNode name = ParseName(); + NameNode? memberName = null; + NameNode? argumentName = null; + + if (SkipDot()) + { + if (ofDirective) + { + throw Unexpected(TokenKind.Dot); + } + + memberName = ParseName(); + } + + if (_reader.Kind == TokenKind.LeftParenthesis) + { + MoveNext(); + argumentName = ParseName(); + ExpectColon(); + ExpectRightParenthesis(); + } + + Location? location = CreateLocation(in start); + + return new SchemaCoordinateNode + ( + location, + ofDirective, + name, + memberName, + argumentName + ); + } +} diff --git a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Syntax.cs b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Syntax.cs index 8a25bc0c4aa..43616c26b0c 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Syntax.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Syntax.cs @@ -121,6 +121,31 @@ public static ITypeNode ParseTypeReference( Utf8GraphQLReader reader) => new Utf8GraphQLParser(reader).ParseTypeReference(); + /// + /// Parses a GraphQL schema coordinate e.g. Query.userById(id:) + /// + public static SchemaCoordinateNode ParseSchemaCoordinate( + string sourceText) => + Parse( + sourceText, + parser => parser.ParseSingleSchemaCoordinate()); + + /// + /// Parses a GraphQL schema coordinate e.g. Query.userById(id:) + /// + public static SchemaCoordinateNode ParseSchemaCoordinate( + ReadOnlySpan sourceText) => + Parse( + sourceText, + parser => parser.ParseSingleSchemaCoordinate()); + + /// + /// Parses a GraphQL schema coordinate e.g. Query.userById(id:) + /// + public static SchemaCoordinateNode ParseSchemaCoordinate( + Utf8GraphQLReader reader) => + new Utf8GraphQLParser(reader).ParseSchemaCoordinate(); + private static unsafe T Parse( string sourceText, ParseSyntax parse, diff --git a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Utilities.cs b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Utilities.cs index c4c362d47f2..2e384f11dbf 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Utilities.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLParser.Utilities.cs @@ -136,6 +136,10 @@ private void ExpectKeyword(ReadOnlySpan keyword) private bool SkipAmpersand() => _reader.Skip(TokenKind.Ampersand); + private bool SkipAt() => _reader.Skip(TokenKind.At); + + private bool SkipDot() => _reader.Skip(TokenKind.Dot); + private bool SkipRepeatableKeyword() => SkipKeyword(GraphQLKeywords.Repeatable); diff --git a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLReader.cs b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLReader.cs index 7ab70746485..f2c588180b4 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLReader.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/Utf8GraphQLReader.cs @@ -201,7 +201,7 @@ private void ReadNameToken() /// /// Reads punctuator tokens as specified in /// http://facebook.github.io/graphql/October2016/#sec-Punctuators - /// one of ! $ ( ) ... : = @ [ ] { | } + /// one of ! ? $ ( ) ... . : = @ [ ] { | } /// additionally the reader will tokenize ampersands. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -211,22 +211,30 @@ private void ReadPunctuatorToken(byte code) _end = ++_position; _value = null; - if (code == GraphQLConstants.Dot) + if (code is GraphQLConstants.Dot) { - if (_graphQLData[_position] is GraphQLConstants.Dot - && _graphQLData[_position + 1] is GraphQLConstants.Dot) + if (_graphQLData[_position] is GraphQLConstants.Dot) { - _position += 2; - _end = _position; - _kind = TokenKind.Spread; + if (_graphQLData[_position + 1] is GraphQLConstants.Dot) + { + _position += 2; + _end = _position; + _kind = TokenKind.Spread; + } + else + { + _position--; + throw ThrowHelper.Reader_InvalidToken(this, TokenKind.Spread); + } } - else + else if (_graphQLData[_position].IsDigit()) { _position--; - throw new SyntaxException(this, - string.Format(CultureInfo.InvariantCulture, - Reader_InvalidToken, - TokenKind.Spread)); + throw ThrowHelper.Reader_UnexpectedDigitAfterDot(this); + } + else + { + _kind = TokenKind.Dot; } } else diff --git a/src/HotChocolate/Language/src/Language.Utf8/Utilities/ThrowHelper.cs b/src/HotChocolate/Language/src/Language.Utf8/Utilities/ThrowHelper.cs index be15096c1af..378f39e140d 100644 --- a/src/HotChocolate/Language/src/Language.Utf8/Utilities/ThrowHelper.cs +++ b/src/HotChocolate/Language/src/Language.Utf8/Utilities/ThrowHelper.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using HotChocolate.Language.Properties; namespace HotChocolate.Language; @@ -58,4 +59,17 @@ public static SyntaxException UnexpectedToken(Utf8GraphQLReader reader) => "Unexpected token found `{0}` " + "while expecting a scalar value.", reader.Kind)); + + public static SyntaxException Reader_UnexpectedDigitAfterDot(Utf8GraphQLReader reader) => + new SyntaxException(reader, LangUtf8Resources.Reader_UnexpectedDigitAfterDot); + + public static SyntaxException Reader_InvalidToken( + Utf8GraphQLReader reader, + TokenKind expected) => + new SyntaxException( + reader, + string.Format( + CultureInfo.InvariantCulture, + LangUtf8Resources.Reader_InvalidToken, + expected)); } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitorOptions.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitorOptions.cs index 22d27e46e97..25eef2479fd 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitorOptions.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitorOptions.cs @@ -1,12 +1,27 @@ namespace HotChocolate.Language.Visitors; +/// +/// Represents basic visitor options. +/// public struct SyntaxVisitorOptions { + /// + /// Specifies if the visitor shall traverse name nodes. + /// public bool VisitNames { get; set; } + /// + /// Specifies if the visitor shall traverse description nodes. + /// public bool VisitDescriptions { get; set; } + /// + /// Specifies if the visitor shall traverse directives nodes. + /// public bool VisitDirectives { get; set; } + /// + /// Specifies if the visitor shall traverse argument nodes. + /// public bool VisitArguments { get; set; } } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitor~1.VisitationMap.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitor~1.VisitationMap.cs index 855ae376259..ea9353b5a60 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitor~1.VisitationMap.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxVisitor~1.VisitationMap.cs @@ -90,6 +90,8 @@ protected virtual ISyntaxVisitorAction VisitChildren( return VisitChildren((EnumTypeExtensionNode)node, context); case SyntaxKind.InputObjectTypeExtension: return VisitChildren((InputObjectTypeExtensionNode)node, context); + case SyntaxKind.SchemaCoordinate: + return VisitChildren((SchemaCoordinateNode)node, context); default: throw new NotSupportedException(node.GetType().FullName); @@ -1127,4 +1129,30 @@ protected virtual ISyntaxVisitorAction VisitChildren( return DefaultAction; } + + protected virtual ISyntaxVisitorAction VisitChildren( + SchemaCoordinateNode node, + TContext context) + { + if (_options.VisitNames && Visit(node.Name, node, context).IsBreak()) + { + return Break; + } + + if(_options.VisitNames && + node.MemberName is not null && + Visit(node.MemberName, node, context).IsBreak()) + { + return Break; + } + + if(_options.VisitNames && + node.ArgumentName is not null && + Visit(node.ArgumentName, node, context).IsBreak()) + { + return Break; + } + + return DefaultAction; + } } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Enter.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Enter.cs index 9e85a8b984f..1ac868807a6 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Enter.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Enter.cs @@ -91,6 +91,8 @@ protected override ISyntaxVisitorAction Enter( return Enter((EnumTypeExtensionNode)node, context); case SyntaxKind.InputObjectTypeExtension: return Enter((InputObjectTypeExtensionNode)node, context); + case SyntaxKind.SchemaCoordinate: + return Enter((SchemaCoordinateNode)node, context); default: throw new NotSupportedException(node.GetType().FullName); } @@ -285,4 +287,9 @@ protected virtual ISyntaxVisitorAction Enter( InputObjectTypeExtensionNode node, ISyntaxVisitorContext context) => DefaultAction; + + protected virtual ISyntaxVisitorAction Enter( + SchemaCoordinateNode node, + ISyntaxVisitorContext context) => + DefaultAction; } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Leave.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Leave.cs index 9d7a8a174af..f25342a4a4e 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Leave.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Leave.cs @@ -91,6 +91,8 @@ protected override ISyntaxVisitorAction Leave( return Leave((EnumTypeExtensionNode)node, context); case SyntaxKind.InputObjectTypeExtension: return Leave((InputObjectTypeExtensionNode)node, context); + case SyntaxKind.SchemaCoordinate: + return Leave((SchemaCoordinateNode)node, context); default: throw new NotSupportedException(node.GetType().FullName); } @@ -284,4 +286,9 @@ protected virtual ISyntaxVisitorAction Leave( InputObjectTypeExtensionNode node, ISyntaxVisitorContext context) => DefaultAction; + + protected virtual ISyntaxVisitorAction Leave( + SchemaCoordinateNode node, + ISyntaxVisitorContext context) => + DefaultAction; } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs index fd478ce407d..826fb56c728 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs @@ -91,6 +91,8 @@ protected override ISyntaxVisitorAction Enter( return Enter((EnumTypeExtensionNode)node, context); case SyntaxKind.InputObjectTypeExtension: return Enter((InputObjectTypeExtensionNode)node, context); + case SyntaxKind.SchemaCoordinate: + return Enter((SchemaCoordinateNode)node, context); default: throw new NotSupportedException(node.GetType().FullName); } @@ -285,4 +287,9 @@ protected virtual ISyntaxVisitorAction Enter( InputObjectTypeExtensionNode node, TContext context) => DefaultAction; + + protected virtual ISyntaxVisitorAction Enter( + SchemaCoordinateNode node, + ISyntaxVisitorContext context) => + DefaultAction; } diff --git a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs index 8975affed4b..112c5bd9e68 100644 --- a/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs +++ b/src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs @@ -91,6 +91,8 @@ protected override ISyntaxVisitorAction Leave( return Leave((EnumTypeExtensionNode)node, context); case SyntaxKind.InputObjectTypeExtension: return Leave((InputObjectTypeExtensionNode)node, context); + case SyntaxKind.SchemaCoordinate: + return Leave((SchemaCoordinateNode)node, context); default: throw new NotSupportedException(node.GetType().FullName); } @@ -284,4 +286,9 @@ protected virtual ISyntaxVisitorAction Leave( InputObjectTypeExtensionNode node, TContext context) => DefaultAction; + + protected virtual ISyntaxVisitorAction Leave( + SchemaCoordinateNode node, + ISyntaxVisitorContext context) => + DefaultAction; } diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/SchemaCoordinateTests.cs b/src/HotChocolate/Language/test/Language.Tests/AST/SchemaCoordinateTests.cs new file mode 100644 index 00000000000..002724b53ed --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/SchemaCoordinateTests.cs @@ -0,0 +1,275 @@ +using System; +using Snapshooter.Xunit; +using Xunit; + +namespace HotChocolate.Language; + +public class SchemaCoordinateTests +{ + [Fact] + public void CreateSchemaCoordinateWithLocation() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = false; + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("bar"); + NameNode argumentName = new NameNode("baz"); + + // act + var coordinate = + new SchemaCoordinateNode(location, ofDirective, name, memberName, argumentName); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Equal(location, coordinate.Location); + Assert.False(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Equal(memberName, coordinate.MemberName); + Assert.Equal(argumentName, coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateWithoutLocation() + { + // arrange + bool ofDirective = false; + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("bar"); + NameNode argumentName = new NameNode("baz"); + + // act + var coordinate = + new SchemaCoordinateNode(null, ofDirective, name, memberName, argumentName); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Null(coordinate.Location); + Assert.False(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Equal(memberName, coordinate.MemberName); + Assert.Equal(argumentName, coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateWithoutArgumentName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = false; + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("bar"); + + // act + var coordinate = + new SchemaCoordinateNode(location, ofDirective, name, memberName, null); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Equal(location, coordinate.Location); + Assert.False(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Equal(memberName, coordinate.MemberName); + Assert.Null(coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateWithoutArgumentAndMemberName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = false; + NameNode name = new NameNode("Foo"); + + // act + var coordinate = + new SchemaCoordinateNode(location, ofDirective, name, null, null); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Equal(location, coordinate.Location); + Assert.False(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Null(coordinate.MemberName); + Assert.Null(coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateOfDirectiveWithArgumentName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = true; + NameNode name = new NameNode("Foo"); + NameNode argumentName = new NameNode("baz"); + + // act + var coordinate = + new SchemaCoordinateNode(location, ofDirective, name, null, argumentName); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Equal(location, coordinate.Location); + Assert.True(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Null(coordinate.MemberName); + Assert.Equal(argumentName, coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateOfDirectiveWithoutArgumentName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = true; + NameNode name = new NameNode("Foo"); + + // act + var coordinate = + new SchemaCoordinateNode(location, ofDirective, name, null, null); + + // assert + Assert.Equal(SyntaxKind.SchemaCoordinate, coordinate.Kind); + Assert.Equal(location, coordinate.Location); + Assert.True(coordinate.OfDirective); + Assert.Equal(name, coordinate.Name); + Assert.Null(coordinate.MemberName); + Assert.Null(coordinate.ArgumentName); + coordinate.ToString().MatchSnapshot(); + } + + [Fact] + public void CreateSchemaCoordinateOfDirectiveWithMemberName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = true; + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("Foo"); + + // act + Exception ex = Record.Exception(() => + { + new SchemaCoordinateNode(location, ofDirective, name, memberName, null); + }); + + // assert + Assert.IsType(ex); + } + + [Fact] + public void CreateSchemaCoordinateOfTypeWithArgumentNameButNoMemberName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = false; + NameNode name = new NameNode("Foo"); + NameNode argumentName = new NameNode("baz"); + + // act + Exception ex = Record.Exception(() => + { + new SchemaCoordinateNode(location, ofDirective, name, null, argumentName); + }); + + // assert + Assert.IsType(ex); + } + + [Fact] + public void CreateSchemaCoordinateWithoutName() + { + // arrange + var location = new Location(0, 0, 0, 0); + bool ofDirective = false; + + // act + Exception ex = Record.Exception(() => + { + new SchemaCoordinateNode(location, ofDirective, null!, null, null); + }); + + // assert + Assert.IsType(ex); + } + + [Fact] + public void SchemaCoordinate_With_Location() + { + // arrange + var location = new Location(0, 0, 0, 0); + NameNode name = new NameNode("Foo"); + var node = new SchemaCoordinateNode(null, false, name, null, null); + + // act + SchemaCoordinateNode rewrittenNode = node.WithLocation(location); + + // assert + Assert.Equal(location, rewrittenNode.Location); + } + + [Fact] + public void SchemaCoordinate_With_Name() + { + // arrange + NameNode name = new NameNode("Foo"); + NameNode newName = new NameNode("newName"); + var node = new SchemaCoordinateNode(null, false, name, null, null); + + // act + SchemaCoordinateNode rewrittenNode = node.WithName(newName); + + // assert + Assert.Equal(newName, rewrittenNode.Name); + } + + [Fact] + public void SchemaCoordinate_With_MemberName() + { + // arrange + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("foo"); + var node = new SchemaCoordinateNode(null, false, name, null, null); + + // act + SchemaCoordinateNode rewrittenNode = node.WithMemberName(memberName); + + // assert + Assert.Equal(memberName, rewrittenNode.MemberName); + } + + [Fact] + public void SchemaCoordinate_With_ArgumentName() + { + // arrange + NameNode name = new NameNode("Foo"); + NameNode memberName = new NameNode("foo"); + NameNode argumentName = new NameNode("baz"); + var node = new SchemaCoordinateNode(null, false, name, memberName, null); + + // act + SchemaCoordinateNode rewrittenNode = node.WithArgumentName(argumentName); + + // assert + Assert.Equal(argumentName, rewrittenNode.ArgumentName); + } + + [Fact] + public void SchemaCoordinate_With_OfDirective() + { + // arrange + NameNode name = new NameNode("Foo"); + var node = new SchemaCoordinateNode(null, false, name, null, null); + + // act + SchemaCoordinateNode rewrittenNode = node.WithOfDirective(true); + + // assert + Assert.True(rewrittenNode.OfDirective); + } +} diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithArgumentName.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithArgumentName.snap new file mode 100644 index 00000000000..fe9b1f8e497 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithArgumentName.snap @@ -0,0 +1 @@ +@Foo(baz:) diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithoutArgumentName.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithoutArgumentName.snap new file mode 100644 index 00000000000..85b245d50cf --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateOfDirectiveWithoutArgumentName.snap @@ -0,0 +1 @@ +@Foo diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithLocation.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithLocation.snap new file mode 100644 index 00000000000..ae3a2444b67 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithLocation.snap @@ -0,0 +1 @@ +Foo.bar(baz:) diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentAndMemberName.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentAndMemberName.snap new file mode 100644 index 00000000000..ad32471d9ac --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentAndMemberName.snap @@ -0,0 +1 @@ +Foo diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentName.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentName.snap new file mode 100644 index 00000000000..3d76c813507 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutArgumentName.snap @@ -0,0 +1 @@ +Foo.bar diff --git a/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutLocation.snap b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutLocation.snap new file mode 100644 index 00000000000..ae3a2444b67 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/AST/__snapshots__/SchemaCoordinateTests.CreateSchemaCoordinateWithoutLocation.snap @@ -0,0 +1 @@ +Foo.bar(baz:) diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8BlockStringTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/BlockStringTokenReaderTests.cs similarity index 99% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8BlockStringTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/BlockStringTokenReaderTests.cs index 9e92a621630..5babc2f0d41 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8BlockStringTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/BlockStringTokenReaderTests.cs @@ -5,7 +5,7 @@ namespace HotChocolate.Language; -public class Utf8BlockStringTokenReaderTests +public class BlockStringTokenReaderTests { [Fact] private void ReadToken() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8CommentTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/CommentTokenReaderTests.cs similarity index 96% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8CommentTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/CommentTokenReaderTests.cs index 17d80756497..776ffdc7c6b 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8CommentTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/CommentTokenReaderTests.cs @@ -3,7 +3,7 @@ namespace HotChocolate.Language; -public class Utf8CommentTokenReaderTests +public class CommentTokenReaderTests { [InlineData("# my comment foo bar")] [InlineData("#my comment foo bar")] diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8DirectiveParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/DirectiveParserTests.cs similarity index 98% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8DirectiveParserTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/DirectiveParserTests.cs index 0e54409e1fa..b2fa0e86d22 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8DirectiveParserTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/DirectiveParserTests.cs @@ -5,7 +5,7 @@ namespace HotChocolate.Language; -public class Utf8DirectiveParserTests +public class DirectiveParserTests { [Fact] public void ParseUniqueDirective() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLParserSyntaxTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLParserSyntaxTests.cs similarity index 98% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLParserSyntaxTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLParserSyntaxTests.cs index ac4851de948..d06692d2670 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLParserSyntaxTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLParserSyntaxTests.cs @@ -4,7 +4,7 @@ namespace HotChocolate.Language; -public class Utf8GraphQLParserSyntaxTests +public class GraphQLParserSyntaxTests { [Fact] public void Parse_FieldNode_From_String() => diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLRequestParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLRequestParserTests.cs similarity index 96% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLRequestParserTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLRequestParserTests.cs index 689deca14d4..99ace9a8ce2 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8GraphQLRequestParserTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/GraphQLRequestParserTests.cs @@ -11,7 +11,7 @@ namespace HotChocolate.Language; -public class Utf8GraphQLRequestParserTests +public class GraphQLRequestParserTests { [Fact] public void Utf8GraphQLRequestParser_Parse() @@ -647,9 +647,9 @@ public void Parse_Invalid_Query() Assert.Throws( () => { - // arrange - var source = Encoding.UTF8.GetBytes("{\"query\":\"\"}" - .NormalizeLineBreaks()); + // arrange + var source = Encoding.UTF8.GetBytes("{\"query\":\"\"}" + .NormalizeLineBreaks()); var parserOptions = new ParserOptions(); var requestParser = new Utf8GraphQLRequestParser( source, @@ -657,8 +657,8 @@ public void Parse_Invalid_Query() new DocumentCache(), new Sha256DocumentHashProvider()); - // act - requestParser.Parse(); + // act + requestParser.Parse(); }); } @@ -669,9 +669,9 @@ public void Parse_Empty_Json() Assert.Throws( () => { - // arrange - var source = Encoding.UTF8.GetBytes("{ }" - .NormalizeLineBreaks()); + // arrange + var source = Encoding.UTF8.GetBytes("{ }" + .NormalizeLineBreaks()); var parserOptions = new ParserOptions(); var requestParser = new Utf8GraphQLRequestParser( source, @@ -679,8 +679,8 @@ public void Parse_Empty_Json() new DocumentCache(), new Sha256DocumentHashProvider()); - // act - requestParser.Parse(); + // act + requestParser.Parse(); }); } @@ -691,8 +691,8 @@ public void Parse_Empty_String() Assert.Throws( () => { - // arrange - var source = Encoding.UTF8.GetBytes(string.Empty); + // arrange + var source = Encoding.UTF8.GetBytes(string.Empty); var parserOptions = new ParserOptions(); var requestParser = new Utf8GraphQLRequestParser( source, @@ -700,8 +700,8 @@ public void Parse_Empty_String() new DocumentCache(), new Sha256DocumentHashProvider()); - // act - requestParser.Parse(); + // act + requestParser.Parse(); }); } @@ -712,8 +712,8 @@ public void Parse_Space_String() Assert.Throws( () => { - // arrange - var source = Encoding.UTF8.GetBytes(" "); + // arrange + var source = Encoding.UTF8.GetBytes(" "); var parserOptions = new ParserOptions(); var requestParser = new Utf8GraphQLRequestParser( source, @@ -721,8 +721,8 @@ public void Parse_Space_String() new DocumentCache(), new Sha256DocumentHashProvider()); - // act - requestParser.Parse(); + // act + requestParser.Parse(); }); } diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8KitchenSinkParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/KitchenSinkParserTests.cs similarity index 97% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8KitchenSinkParserTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/KitchenSinkParserTests.cs index 550531397a7..005a1a546e0 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8KitchenSinkParserTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/KitchenSinkParserTests.cs @@ -6,7 +6,7 @@ namespace HotChocolate.Language; -public class Utf8KitchenSinkParserTests +public class KitchenSinkParserTests { [Fact] public void ParseFacebookKitchenSinkSchema() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NameTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/NameTokenReaderTests.cs similarity index 94% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NameTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/NameTokenReaderTests.cs index 742ecb183b1..ec1f37ee6d8 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NameTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/NameTokenReaderTests.cs @@ -3,7 +3,7 @@ namespace HotChocolate.Language; -public class Utf8NameTokenReaderTests +public class NameTokenReaderTests { [InlineData(" \nhelloWorld_123")] [InlineData(" \nhelloWorld_123\n ")] diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NumberTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/NumberTokenReaderTests.cs similarity index 71% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NumberTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/NumberTokenReaderTests.cs index 1495712a156..ae9dc51eb5d 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8NumberTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/NumberTokenReaderTests.cs @@ -1,9 +1,10 @@ using System.Text; +using Snapshooter.Xunit; using Xunit; namespace HotChocolate.Language; -public class Utf8NumberTokenReaderTests +public class NumberTokenReaderTests { [InlineData("1234.123", true)] [InlineData("-1234.123", true)] @@ -31,4 +32,17 @@ private void ReadToken(string sourceBody, bool isFloat) Assert.Equal(0, reader.Start); Assert.Equal(sourceBody.Length, reader.End); } + + [Fact] + public void InvalidNumberToken() + { + // arrange + byte[] source = Encoding.UTF8.GetBytes(".1"); + + // act + void Fail() => new Utf8GraphQLReader(source).Read(); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } } diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8PunctuatorTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/PunctuatorTokenReaderTests.cs similarity index 82% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8PunctuatorTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/PunctuatorTokenReaderTests.cs index 33000fcc042..6ba63863bc6 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8PunctuatorTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/PunctuatorTokenReaderTests.cs @@ -1,9 +1,10 @@ using System.Text; +using Snapshooter.Xunit; using Xunit; namespace HotChocolate.Language; -public class Utf8PunctuatorTokenReaderTests +public class PunctuatorTokenReaderTests { [Fact] public void ReadBangToken() @@ -89,6 +90,23 @@ public void ReadSpreadToken() ReadToken("...", TokenKind.Spread); } + [InlineData("..!")] + [InlineData("..1")] + [InlineData(".._")] + [InlineData("..a")] + [Theory] + public void SpreadExpected(string s) + { + // arrange + byte[] source = Encoding.UTF8.GetBytes(s); + + // act + void Fail() => new Utf8GraphQLReader(source).Read(); + + // assert + Assert.Throws(Fail).Message.MatchSnapshot(); + } + private void ReadToken(char code, TokenKind kind) { ReadToken(code.ToString(), kind); diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8QueryParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/QueryParserTests.cs similarity index 99% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8QueryParserTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/QueryParserTests.cs index e7f2df692f0..ff8973f40f6 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8QueryParserTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/QueryParserTests.cs @@ -7,7 +7,7 @@ namespace HotChocolate.Language; -public class Utf8QueryParserTests +public class QueryParserTests { [Fact] public void ParseSimpleShortHandFormQuery() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8ReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/ReaderTests.cs similarity index 99% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8ReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/ReaderTests.cs index 1b09de4a9d5..4c87f5bd358 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8ReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/ReaderTests.cs @@ -7,7 +7,7 @@ namespace HotChocolate.Language; -public class Utf8ReaderTests +public class ReaderTests { [Fact] public void Read_Two_NameTokens() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/SchemCoordinateParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/SchemCoordinateParserTests.cs new file mode 100644 index 00000000000..0801ccc8925 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/SchemCoordinateParserTests.cs @@ -0,0 +1,124 @@ +using System; +using System.Text; +using Snapshooter.Xunit; +using Xunit; + +namespace HotChocolate.Language; + +public class SchemaCoordinateParserTests +{ + [Fact] + public void ParseName() + { + // arrange + string sourceText = "MyType"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + SchemaCoordinateNode result = Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public void ParseNameAndMemberName() + { + // arrange + string sourceText = "MyType.MemberName"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + SchemaCoordinateNode result = Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public void ParseNameNameName() + { + // arrange + string sourceText = "Name.Name.Name"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + void Fail() => Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + Assert.Throws(Fail); + } + + [Fact] + public void ParseNameAndMemberNameAndArg() + { + // arrange + string sourceText = "MyType.MemberName(arg:)"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + SchemaCoordinateNode result = Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public void ParseDirectiveName() + { + // arrange + string sourceText = "@foo"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + SchemaCoordinateNode result = Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public void ParseDirectiveNameAndArg() + { + // arrange + string sourceText = "@foo(arg:)"; + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + SchemaCoordinateNode result = Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + + // assert + result.MatchSnapshot(); + } + + [Theory] + [InlineData("MyType.field(arg: value)")] + [InlineData("@myDirective.field")] + public void RejectsInvalidPatterns(string sourceText) + { + // arrange + byte[] source = Encoding.UTF8.GetBytes(sourceText); + + // act + Exception ex = Record.Exception(() => + { + Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(source); + }); + + // assert + Assert.IsType(ex); + } + + [InlineData(null)] + [InlineData("")] + [Theory] + public void ParseSourceTextIsEmptyOrNull(string s) + { + // arrange; + // act + void Fail() => Utf8GraphQLParser.Syntax.ParseSchemaCoordinate(s); + + // assert + Assert.Equal("sourceText", Assert.Throws(Fail).ParamName); + } +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8SchemaParserTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/SchemaParserTests.cs similarity index 99% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8SchemaParserTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/SchemaParserTests.cs index 8b87ae5ac51..1481593bb1c 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8SchemaParserTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/SchemaParserTests.cs @@ -5,7 +5,7 @@ namespace HotChocolate.Language; -public class Utf8SchemaParserTests +public class SchemaParserTests { [Fact] public void ParserSimpleObjectType() diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8StringTokenReaderTests.cs b/src/HotChocolate/Language/test/Language.Tests/Parser/StringTokenReaderTests.cs similarity index 97% rename from src/HotChocolate/Language/test/Language.Tests/Parser/Utf8StringTokenReaderTests.cs rename to src/HotChocolate/Language/test/Language.Tests/Parser/StringTokenReaderTests.cs index 64f1517021c..946a01725ea 100644 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/Utf8StringTokenReaderTests.cs +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/StringTokenReaderTests.cs @@ -3,7 +3,7 @@ namespace HotChocolate.Language; -public class Utf8StringTokenReaderTests +public class StringTokenReaderTests { [InlineData(" \n\"üähelloWorld_123\"")] [InlineData("\"üähelloWorld_123\"\n ")] diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.InvalidDigit.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.InvalidDigit.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.InvalidDigit.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.InvalidDigit.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.NoDigitAfterZeroException.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.NoDigitAfterZeroException.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.NoDigitAfterZeroException.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.NoDigitAfterZeroException.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.UnexpectedSyntaxException.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.UnexpectedSyntaxException.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8BlockStringTokenReaderTests.UnexpectedSyntaxException.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/BlockStringTokenReaderTests.UnexpectedSyntaxException.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8DirectiveParserTests.ParseQueryDirective.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/DirectiveParserTests.ParseQueryDirective.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8DirectiveParserTests.ParseQueryDirective.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/DirectiveParserTests.ParseQueryDirective.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_ByteArray.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_ByteArray.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_ByteArray.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_ByteArray.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_Reader.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_Reader.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_Reader.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_Reader.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_String.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_String.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_FieldNode_From_String.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_FieldNode_From_String.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_ByteArray.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_ByteArray.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_ByteArray.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_ByteArray.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_Reader.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_Reader.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_Reader.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_Reader.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_String.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_String.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_String.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ObjectValueNode_From_String.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_ByteArray.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_ByteArray.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_ByteArray.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_ByteArray.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_Reader.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_Reader.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_Reader.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_Reader.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_String.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_String.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_String.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_SelectionSetNode_From_String.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_ByteArray.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_ByteArray.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_ByteArray.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_ByteArray.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_Reader.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_Reader.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_Reader.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_Reader.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_String.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_String.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLParserSyntaxTests.Parse_ValueNode_From_String.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLParserSyntaxTests.Parse_ValueNode_From_String.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Float_Exponent_Format.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Float_Exponent_Format.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Float_Exponent_Format.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Float_Exponent_Format.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Id_As_Name.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Id_As_Name.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Id_As_Name.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Id_As_Name.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Json.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Json.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Json.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Json.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Extensions.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Extensions.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Extensions.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Extensions.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Query.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Query.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Query.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Query.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Variables.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Variables.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Variables.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_AllProps_No_Cache_Variables.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_No_Cache.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_No_Cache.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_No_Cache.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_No_Cache.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Cache.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Cache.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Cache.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Cache.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Characters.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Characters.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Characters.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Characters.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Escaped_Characters.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Escaped_Characters.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Escaped_Characters.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Kitchen_Sink_Query_With_Russian_Escaped_Characters.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Skip_Custom_Property.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Skip_Custom_Property.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Skip_Custom_Property.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Skip_Custom_Property.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Socket_Message.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Socket_Message.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Parse_Socket_Message.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Parse_Socket_Message.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_Parse.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_Parse.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_Parse.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_Parse.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject_FromString.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject_FromString.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject_FromString.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJsonObject_FromString.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson_FromString.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson_FromString.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson_FromString.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/GraphQLRequestParserTests.Utf8GraphQLRequestParser_ParseJson_FromString.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQuery.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQuery.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQuery.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQuery.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability_sdl.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability_sdl.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability_sdl.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQueryNullability_sdl.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQuery_sdl.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQuery_sdl.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkQuery_sdl.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkQuery_sdl.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkSchema.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkSchema.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkSchema.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkSchema.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkSchema_sdl.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkSchema_sdl.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8KitchenSinkParserTests.ParseFacebookKitchenSinkSchema_sdl.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/KitchenSinkParserTests.ParseFacebookKitchenSinkSchema_sdl.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/NumberTokenReaderTests.InvalidNumberToken.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/NumberTokenReaderTests.InvalidNumberToken.snap new file mode 100644 index 00000000000..a6e8c4b4fb1 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/NumberTokenReaderTests.InvalidNumberToken.snap @@ -0,0 +1 @@ +Invalid number, expected digit before ".". diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/PunctuatorTokenReaderTests.SpreadExpected.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/PunctuatorTokenReaderTests.SpreadExpected.snap new file mode 100644 index 00000000000..0abc39cdd18 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/PunctuatorTokenReaderTests.SpreadExpected.snap @@ -0,0 +1 @@ +Expected a `Spread`-token. diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.IntrospectionQuery.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.IntrospectionQuery.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.IntrospectionQuery.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.IntrospectionQuery.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.KitchenSinkQueryQuery.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.KitchenSinkQueryQuery.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.KitchenSinkQueryQuery.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.KitchenSinkQueryQuery.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithComments.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithComments.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithComments.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithComments.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithComments_serialized.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithComments_serialized.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithComments_serialized.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithComments_serialized.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithStringArg.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithStringArg.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.QueryWithStringArg.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.QueryWithStringArg.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.RussianLiterals.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.RussianLiterals.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.RussianLiterals.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/QueryParserTests.RussianLiterals.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_BlockStringValue.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_BlockStringValue.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_BlockStringValue.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_BlockStringValue.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_BlockString_SkipEscapes.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_BlockString_SkipEscapes.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_BlockString_SkipEscapes.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_BlockString_SkipEscapes.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_Comment.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_Comment.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_Comment.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_Comment.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_KitchenSinkQuery.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_KitchenSinkQuery.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_KitchenSinkQuery.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_KitchenSinkQuery.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_NameBraceTokens.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_NameBraceTokens.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_NameBraceTokens.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_NameBraceTokens.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_StringValue.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_StringValue.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_StringValue.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_StringValue.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_String_SkipEscapes.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_String_SkipEscapes.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8ReaderTests.Read_String_SkipEscapes.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/ReaderTests.Read_String_SkipEscapes.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveName.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveName.snap new file mode 100644 index 00000000000..a86d3e7d070 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveName.snap @@ -0,0 +1,22 @@ +{ + "Location": { + "Start": 0, + "End": 4, + "Line": 1, + "Column": 1 + }, + "Kind": "SchemaCoordinate", + "OfDirective": true, + "Name": { + "Kind": "Name", + "Location": { + "Start": 1, + "End": 4, + "Line": 1, + "Column": 2 + }, + "Value": "foo" + }, + "MemberName": null, + "ArgumentName": null +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveNameAndArg.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveNameAndArg.snap new file mode 100644 index 00000000000..365116a45af --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseDirectiveNameAndArg.snap @@ -0,0 +1,31 @@ +{ + "Location": { + "Start": 0, + "End": 10, + "Line": 1, + "Column": 1 + }, + "Kind": "SchemaCoordinate", + "OfDirective": true, + "Name": { + "Kind": "Name", + "Location": { + "Start": 1, + "End": 5, + "Line": 1, + "Column": 2 + }, + "Value": "foo" + }, + "MemberName": null, + "ArgumentName": { + "Kind": "Name", + "Location": { + "Start": 5, + "End": 9, + "Line": 1, + "Column": 6 + }, + "Value": "arg" + } +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseName.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseName.snap new file mode 100644 index 00000000000..a0951d74386 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseName.snap @@ -0,0 +1,22 @@ +{ + "Location": { + "Start": 0, + "End": 6, + "Line": 1, + "Column": 1 + }, + "Kind": "SchemaCoordinate", + "OfDirective": false, + "Name": { + "Kind": "Name", + "Location": { + "Start": 0, + "End": 6, + "Line": 1, + "Column": 1 + }, + "Value": "MyType" + }, + "MemberName": null, + "ArgumentName": null +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberName.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberName.snap new file mode 100644 index 00000000000..426e0074b85 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberName.snap @@ -0,0 +1,31 @@ +{ + "Location": { + "Start": 0, + "End": 17, + "Line": 1, + "Column": 1 + }, + "Kind": "SchemaCoordinate", + "OfDirective": false, + "Name": { + "Kind": "Name", + "Location": { + "Start": 0, + "End": 7, + "Line": 1, + "Column": 1 + }, + "Value": "MyType" + }, + "MemberName": { + "Kind": "Name", + "Location": { + "Start": 7, + "End": 17, + "Line": 1, + "Column": 8 + }, + "Value": "MemberName" + }, + "ArgumentName": null +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberNameAndArg.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberNameAndArg.snap new file mode 100644 index 00000000000..6d4a124afe3 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaCoordinateParserTests.ParseNameAndMemberNameAndArg.snap @@ -0,0 +1,40 @@ +{ + "Location": { + "Start": 0, + "End": 23, + "Line": 1, + "Column": 1 + }, + "Kind": "SchemaCoordinate", + "OfDirective": false, + "Name": { + "Kind": "Name", + "Location": { + "Start": 0, + "End": 7, + "Line": 1, + "Column": 1 + }, + "Value": "MyType" + }, + "MemberName": { + "Kind": "Name", + "Location": { + "Start": 7, + "End": 18, + "Line": 1, + "Column": 8 + }, + "Value": "MemberName" + }, + "ArgumentName": { + "Kind": "Name", + "Location": { + "Start": 18, + "End": 22, + "Line": 1, + "Column": 19 + }, + "Value": "arg" + } +} diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.OneGraph_Schema.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.OneGraph_Schema.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.OneGraph_Schema.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.OneGraph_Schema.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseEnum.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseEnum.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseEnum.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseEnum.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseSchemaDefinition.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseSchemaDefinition.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseSchemaDefinition.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseSchemaDefinition.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseUnion.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseUnion.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseUnion.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseUnion.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseUnion_LeadingPipe.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseUnion_LeadingPipe.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParseUnion_LeadingPipe.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParseUnion_LeadingPipe.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserInputObjectType.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserInputObjectType.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserInputObjectType.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserInputObjectType.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserScalarType.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserScalarType.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserScalarType.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserScalarType.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserSimpleInterfaceType.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserSimpleInterfaceType.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserSimpleInterfaceType.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserSimpleInterfaceType.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserSimpleObjectType.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserSimpleObjectType.snap similarity index 100% rename from src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8SchemaParserTests.ParserSimpleObjectType.snap rename to src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/SchemaParserTests.ParserSimpleObjectType.snap diff --git a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.RussionLiterals.snap b/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.RussionLiterals.snap deleted file mode 100644 index 4cbed770fbf..00000000000 --- a/src/HotChocolate/Language/test/Language.Tests/Parser/__snapshots__/Utf8QueryParserTests.RussionLiterals.snap +++ /dev/null @@ -1,122 +0,0 @@ -{ - "Kind": "Document", - "Location": { - "Start": 0, - "End": 64, - "Line": 1, - "Column": 1 - }, - "Definitions": [ - { - "Kind": "OperationDefinition", - "Location": { - "Start": 0, - "End": 64, - "Line": 1, - "Column": 1 - }, - "Name": null, - "Operation": "Query", - "VariableDefinitions": [], - "Directives": [], - "SelectionSet": { - "Kind": "SelectionSet", - "Location": { - "Start": 6, - "End": 64, - "Line": 1, - "Column": 7 - }, - "Selections": [ - { - "Kind": "Field", - "Alias": null, - "Arguments": [ - { - "Kind": "Argument", - "Location": { - "Start": 16, - "End": 42, - "Line": 2, - "Column": 9 - }, - "Name": { - "Kind": "Name", - "Location": { - "Start": 16, - "End": 26, - "Line": 2, - "Column": 9 - }, - "Value": "parameter" - }, - "Value": { - "Kind": "StringValue", - "Location": { - "Start": 27, - "End": 42, - "Line": 2, - "Column": 20 - }, - "Value": "привет", - "Block": false - } - } - ], - "SelectionSet": { - "Kind": "SelectionSet", - "Location": { - "Start": 43, - "End": 63, - "Line": 2, - "Column": 36 - }, - "Selections": [ - { - "Kind": "Field", - "Alias": null, - "Arguments": [], - "SelectionSet": null, - "Location": { - "Start": 49, - "End": 61, - "Line": 3, - "Column": 5 - }, - "Name": { - "Kind": "Name", - "Location": { - "Start": 49, - "End": 61, - "Line": 3, - "Column": 5 - }, - "Value": "subField" - }, - "Directives": [] - } - ] - }, - "Location": { - "Start": 10, - "End": 63, - "Line": 2, - "Column": 3 - }, - "Name": { - "Kind": "Name", - "Location": { - "Start": 10, - "End": 16, - "Line": 2, - "Column": 3 - }, - "Value": "field" - }, - "Directives": [] - } - ] - } - } - ] -} diff --git a/src/HotChocolate/Language/test/Language.Tests/Visitors/SchemaCoordinateVisitorTests.cs b/src/HotChocolate/Language/test/Language.Tests/Visitors/SchemaCoordinateVisitorTests.cs new file mode 100644 index 00000000000..5c050bfdc79 --- /dev/null +++ b/src/HotChocolate/Language/test/Language.Tests/Visitors/SchemaCoordinateVisitorTests.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using Xunit; +using HotChocolate.Language.Visitors; + +namespace HotChocolate.Language; + +public class SchemaCoordinateVisitorTests +{ + [Fact] + public static void VisitAllNodes() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), new("def"), new("ghi")); + + // act + var list = new List(); + + SyntaxVisitor + .Create + (node => + { + if (node is NameNode n) + { + list.Add(n.Value); + } + return SyntaxVisitor.Continue; + }, + options: new() { VisitNames = true }) + .Visit(node); + + // assert + Assert.Collection( + list, + s => Assert.Equal("Abc", s), + s => Assert.Equal("def", s), + s => Assert.Equal("ghi", s)); + } + + [Fact] + public static void VisitAllNodes_With_Walker() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), new("def"), new("ghi")); + + // act + var list = new List(); + var walker = new CustomSyntaxWalker(list); + walker.Visit(node); + + // assert + Assert.Collection( + list, + s => Assert.Equal("Abc", s), + s => Assert.Equal("def", s), + s => Assert.Equal("ghi", s)); + } + + [Fact] + public static void VisitAllNodes_With_Generic_Walker() + { + // arrange + var node = new SchemaCoordinateNode(null, false, new("Abc"), new("def"), new("ghi")); + + // act + var list = new List(); + var context = new CustomContext(list); + var walker = new CustomGenericSyntaxWalker(); + walker.Visit(node, context); + + // assert + Assert.Collection( + list, + s => Assert.Equal("Abc", s), + s => Assert.Equal("def", s), + s => Assert.Equal("ghi", s)); + } + + public class CustomSyntaxWalker : SyntaxWalker + { + private readonly List _list; + + public CustomSyntaxWalker(List list) + : base(new() { VisitNames = true }) + { + _list = list; + } + + protected override ISyntaxVisitorAction Enter(NameNode node, ISyntaxVisitorContext context) + { + _list.Add(node.Value); + return DefaultAction; + } + } + + public class CustomGenericSyntaxWalker : SyntaxWalker + { + public CustomGenericSyntaxWalker() + : base(new() { VisitNames = true }) + { + } + + protected override ISyntaxVisitorAction Enter(NameNode node, CustomContext context) + { + context.List.Add(node.Value); + return DefaultAction; + } + } + + public class CustomContext : ISyntaxVisitorContext + { + public CustomContext(List list) + { + List = list; + } + + public List List { get; } + } +}