Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void Validate(
EnsureFieldNamesAreValid(objectType, errors);
EnsureInterfacesAreCorrectlyImplemented(objectType, errors);
EnsureArgumentDeprecationIsValid(objectType, errors);
EnsureArgumentDefaultValuesAreCompatible(objectType, errors);

if (nodeType?.IsAssignableFrom(objectType) == true)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace HotChocolate.Configuration.Validation;

internal static class TypeValidationHelper
{
private static readonly InputParser s_inputParser = new();

public static void EnsureTypeHasFields(
IComplexTypeDefinition type,
ICollection<ISchemaError> errors)
Expand Down Expand Up @@ -45,6 +47,29 @@ public static void EnsureArgumentDeprecationIsValid(
}
}

public static void EnsureArgumentDefaultValuesAreCompatible(
ObjectType type,
ICollection<ISchemaError> errors)
{
foreach (var field in type.Fields)
{
foreach (var argument in field.Arguments)
{
if (argument.DefaultValue is not null)
{
try
{
s_inputParser.ParseLiteral(argument.DefaultValue, argument);
}
catch (SerializationException)
{
errors.Add(ArgumentDefaultValueMustBeCompatible(type, field, argument));
}
}
}
}
}

public static void EnsureArgumentDeprecationIsValid(
IDirectiveDefinition type,
ICollection<ISchemaError> errors)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/HotChocolate/Core/src/Types/Properties/TypeResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,9 @@ Type: `{0}`</value>
<data name="ErrorHelper_RequiredArgumentCannotBeDeprecated" xml:space="preserve">
<value>Required argument {0} cannot be deprecated.</value>
</data>
<data name="ErrorHelper_ArgumentDefaultValueMustBeCompatible" xml:space="preserve">
<value>Argument {0} must have a compatible default value.</value>
</data>
<data name="ErrorHelper_RequiredFieldCannotBeDeprecated" xml:space="preserve">
<value>Required input field {0} cannot be deprecated.</value>
</data>
Expand Down
14 changes: 14 additions & 0 deletions src/HotChocolate/Core/src/Types/Utilities/ErrorHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,20 @@ public static ISchemaError RequiredArgumentCannotBeDeprecated(
.SetSpecifiedBy(TypeKind.Directive, rfc: 805)
.Build();

public static ISchemaError ArgumentDefaultValueMustBeCompatible(
IComplexTypeDefinition type,
IOutputFieldDefinition field,
IInputValueDefinition argument)
=> SchemaErrorBuilder.New()
.SetMessage(
ErrorHelper_ArgumentDefaultValueMustBeCompatible,
argument.Coordinate.ToString())
.SetType(type)
.SetField(field)
.SetArgument(argument)
.SetSpecifiedBy(type.Kind, rfc: 793)
.Build();

public static ISchemaError RequiredFieldCannotBeDeprecated(
IInputObjectTypeDefinition type,
IInputValueDefinition field)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,7 @@ public void Argument_Type_IsInferred_From_Parameter()
.AddQueryType<QueryWithIntArg>(
t => t
.Field(f => f.GetBar(1))
.Argument("foo", a => a.DefaultValue(null)))
.Argument("foo", a => a.DefaultValue(0)))
.Create();

// assert
Expand Down Expand Up @@ -2320,7 +2320,7 @@ public class QueryWithArgumentDefaults
string b = "abc") => null;

public string? Field2(
[DefaultValue(null)] string a,
[DefaultValue(null)] string? a,
[DefaultValue("abc")] string b) => null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,28 @@ type Foo {
}
");
}

[Fact]
public void AcceptArgumentWithCompatibleDefaultValue()
{
ExpectValid(@"
type Query { stub: String }

type Foo {
field(arg: Int! = 123): String
}
");
}

[Fact]
public void RejectArgumentWithIncompatibleDefaultValue()
{
ExpectError(@"
type Query { stub: String }

type Foo {
field(arg: Int! = { a: 1 }): String
}
");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"message": "Argument Foo.field(arg:) must have a compatible default value.",
"type": "Foo",
"extensions": {
"argument": "arg",
"field": "field",
"rfc": "https://github.com/graphql/graphql-spec/pull/793",
"specifiedBy": "https://spec.graphql.org/October2021/#sec-Objects.Type-Validation"
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ schema {
}

type QueryWithIntArg {
bar(foo: Int!): String!
bar(foo: Int! = 0): String!
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ schema {

type QueryWithArgumentDefaults {
field1(a: String b: String! = "abc"): String
field2(a: String! b: String = "abc"): String
field2(a: String b: String = "abc"): String
}
Loading