Skip to content

Commit

Permalink
Infer default values from parameters and when the DefaultValueAttribu…
Browse files Browse the repository at this point in the history
…te is used
  • Loading branch information
michaelstaib committed Feb 12, 2020
1 parent cac9c3c commit 5681273
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 4 deletions.
Expand Up @@ -16,7 +16,6 @@ public class ArgumentDescriptor
: base(context)
{
Definition.Name = argumentName.EnsureNotEmpty(nameof(argumentName));
Definition.DefaultValue = NullValueNode.Default;
}

public ArgumentDescriptor(
Expand All @@ -32,7 +31,6 @@ public class ArgumentDescriptor

Definition.Name = argumentName;
Definition.Type = argumentType.GetInputType();
Definition.DefaultValue = NullValueNode.Default;
}

public ArgumentDescriptor(
Expand All @@ -43,8 +41,12 @@ public class ArgumentDescriptor
Definition.Name = context.Naming.GetArgumentName(parameter);
Definition.Description = context.Naming.GetArgumentDescription(parameter);
Definition.Type = context.Inspector.GetArgumentType(parameter);
Definition.DefaultValue = NullValueNode.Default;
Definition.Parameter = parameter;

if (context.Inspector.TryGetDefaultValue(parameter, out object defaultValue))
{
Definition.NativeDefaultValue = defaultValue;
}
}

protected override void OnCreateDefinition(ArgumentDefinition definition)
Expand Down
Expand Up @@ -266,5 +266,35 @@ public Type ExtractType(Type type)
attribute.TryConfigure(context, descriptor, attributeProvider);
}
}

public virtual bool TryGetDefaultValue(ParameterInfo parameter, out object defaultValue)
{
if (parameter.IsDefined(typeof(DefaultValueAttribute)))
{
defaultValue = parameter.GetCustomAttribute<DefaultValueAttribute>().Value;
return true;
}

if (parameter.HasDefaultValue)
{
defaultValue = parameter.RawDefaultValue;
return true;
}

defaultValue = null;
return false;
}

public virtual bool TryGetDefaultValue(PropertyInfo parameter, out object defaultValue)
{
if (parameter.IsDefined(typeof(DefaultValueAttribute)))
{
defaultValue = parameter.GetCustomAttribute<DefaultValueAttribute>().Value;
return true;
}

defaultValue = null;
return false;
}
}
}
Expand Up @@ -48,5 +48,9 @@ public interface ITypeInspector
IDescriptorContext context,
IDescriptor descriptor,
ICustomAttributeProvider attributeProvider);

bool TryGetDefaultValue(ParameterInfo parameter, out object defaultValue);

bool TryGetDefaultValue(PropertyInfo parameter, out object defaultValue);
}
}
Expand Up @@ -15,7 +15,6 @@ public class DirectiveArgumentDescriptor
: base(context)
{
Definition.Name = argumentName;
Definition.DefaultValue = null;
}

public DirectiveArgumentDescriptor(
Expand All @@ -29,6 +28,11 @@ public class DirectiveArgumentDescriptor
property, MemberKind.DirectiveArgument);
Definition.Type = context.Inspector.GetInputReturnType(property);
Definition.Property = property;

if (context.Inspector.TryGetDefaultValue(property, out object defaultValue))
{
Definition.NativeDefaultValue = defaultValue;
}
}

protected override void OnCreateDefinition(DirectiveArgumentDefinition definition)
Expand Down
Expand Up @@ -29,6 +29,11 @@ public class InputFieldDescriptor
Definition.Description = context.Naming.GetMemberDescription(
property, MemberKind.InputObjectField);
Definition.Type = context.Inspector.GetInputReturnType(property);

if (context.Inspector.TryGetDefaultValue(property, out object defaultValue))
{
Definition.NativeDefaultValue = defaultValue;
}
}

protected override void OnCreateDefinition(InputFieldDefinition definition)
Expand Down
29 changes: 29 additions & 0 deletions src/HotChocolate/Core/test/Types.Tests/Types/DirectiveTypeTests.cs
Expand Up @@ -502,6 +502,28 @@ public void Use2_ClassMiddleware_WithFactoryNull_ArgumentNullException()
Assert.Throws<SchemaException>(action);
}

[Fact]
public void Infer_Directive_Argument_Defaults_From_Properties()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType(c => c
.Name("Query")
.Directive("foo")
.Field("foo")
.Type<StringType>()
.Resolver("bar"))
.AddDirectiveType(new DirectiveType<DirectiveWithDefaults>(d => d
.Name("foo")
.Location(DirectiveLocation.Object)
.Use<DirectiveMiddleware>()))
.Create();

// assert
schema.ToString().MatchSnapshot();
}

public class CustomDirectiveType
: DirectiveType<CustomDirective>
{
Expand Down Expand Up @@ -552,5 +574,12 @@ public class CustomDirective2
public string Argument1 { get; set; }
public string Argument2 { get; set; }
}

public class DirectiveWithDefaults
{
[DefaultValue("abc")]
public string Argument1 { get; set; }
public string Argument2 { get; set; }
}
}
}
Expand Up @@ -1074,6 +1074,23 @@ public async Task Input_With_Immutable_ClrType()
result.MatchSnapshot();
}

[Fact]
public void Input_Infer_Default_Values()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType(d => d
.Name("Query")
.Field("abc")
.Argument("def", a => a.Type<InputObjectType<InputWithDefault>>())
.Resolver("ghi"))
.Create();

// assert
schema.ToString().MatchSnapshot();
}

public class SimpleInput
{
public int Id { get; set; }
Expand Down Expand Up @@ -1211,5 +1228,16 @@ public FooImmutable(string bar, string baz)
public string Baz { get; set; }
public string Qux { get; private set; }
}

public class InputWithDefault
{
[DefaultValue("abc")]
public string WithStringDefault { get; set; }

[DefaultValue(null)]
public string WithNullDefault { get; set; }

public string WithoutDefault { get; set; }
}
}
}
24 changes: 24 additions & 0 deletions src/HotChocolate/Core/test/Types.Tests/Types/ObjectTypeTests.cs
Expand Up @@ -1612,6 +1612,19 @@ public void Declare_Resolver_With_Result_Type_Is_Null()
schema.ToString().MatchSnapshot();
}

[Fact]
public void Infer_Argument_Default_Values()
{
// arrange
// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<QueryWithArgumentDefaults>()
.Create();

// assert
schema.ToString().MatchSnapshot();
}

public class GenericFoo<T>
{
public T Value { get; }
Expand Down Expand Up @@ -1761,5 +1774,16 @@ public class FooWithNullable

public List<bool?> Bars { get; set; }
}

public class QueryWithArgumentDefaults
{
public string Field1(
string a = null,
string b = "abc") => null;

public string Field2(
[DefaultValue(null)]string a,
[DefaultValue("abc")]string b) => null;
}
}
}
@@ -0,0 +1,12 @@
schema {
query: Query
}

type Query @foo(argument1: "abc") {
foo: String
}

directive @foo(argument1: String = "abc" argument2: String) on OBJECT

"The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text."
scalar String
@@ -0,0 +1,16 @@
schema {
query: Query
}

type Query {
abc(def: InputWithDefaultInput): String
}

input InputWithDefaultInput {
withNullDefault: String
withoutDefault: String
withStringDefault: String = "abc"
}

"The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text."
scalar String
@@ -0,0 +1,11 @@
schema {
query: QueryWithArgumentDefaults
}

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

"The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text."
scalar String

0 comments on commit 5681273

Please sign in to comment.