Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed schema error when using static properties as resolver #5430

Merged
merged 2 commits into from
Sep 25, 2022
Merged
Changes from 1 commit
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
Next Next commit
Fixed schema error when using static properties as resolver
  • Loading branch information
michaelstaib committed Sep 24, 2022
commit a4b6c26eb410b215678aa190ca144bdacb290618

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

Original file line number Diff line number Diff line change
@@ -737,7 +737,7 @@ Type: `{0}`</value>
<data name="EventMessageParameterExpressionBuilder_MessageNotFound" xml:space="preserve">
<value>The event message parameter can only be used in a subscription context.</value>
</data>
<data name="DefaultResolverCompilerService_CreateResolver_ArgumentValudationError" xml:space="preserve">
<data name="DefaultResolverCompilerService_CreateResolver_ArgumentValidationError" xml:space="preserve">
<value>The public method should already have ensured that we do not have members other than method or property at this point.</value>
</data>
<data name="DefaultResolverCompilerService_CompileSubscribe_OnlyMethodsAllowed" xml:space="preserve">
Original file line number Diff line number Diff line change
@@ -199,6 +199,10 @@ public FieldResolverDelegates CompileResolve(
{
resolver = CompileStaticResolver(method, parameterExpressionBuilders ?? _empty);
}
else if (member is PropertyInfo { GetMethod: { IsStatic: true } getMethod })
{
resolver = CompileStaticResolver(getMethod, parameterExpressionBuilders ?? _empty);
}
else
{
resolver = CreateResolver(
@@ -334,7 +338,7 @@ private FieldResolverDelegate CreateResolver(
}

throw new NotSupportedException(
DefaultResolverCompilerService_CreateResolver_ArgumentValudationError);
DefaultResolverCompilerService_CreateResolver_ArgumentValidationError);
}

private PureFieldDelegate? TryCompilePureResolver(
@@ -528,7 +532,7 @@ private IParameterExpressionBuilder GetParameterExpressionBuilder(
#if NETSTANDARD
_cache[parameter] = builder;
#else
_cache.TryAdd(parameter, builder);
_cache.TryAdd(parameter, builder);
#endif
return builder;
}
73 changes: 69 additions & 4 deletions src/HotChocolate/Core/test/Types.Tests/Types/ObjectTypeTests.cs
Original file line number Diff line number Diff line change
@@ -5,17 +5,14 @@
using System.Linq.Expressions;
using System.Threading.Tasks;
using HotChocolate.Execution;
using HotChocolate.Language;
using HotChocolate.Resolvers;
using HotChocolate.Tests;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Relay;
using Microsoft.Extensions.DependencyInjection;
using Moq;
#if NETCOREAPP2_1
using Snapshooter;
#endif
using Snapshooter.Xunit;
using Xunit;
using static HotChocolate.Types.FieldBindingFlags;
using static HotChocolate.WellKnownContextData;
using SnapshotExtensions = CookieCrumble.SnapshotExtensions;
@@ -2019,6 +2016,22 @@ public async Task Static_Field_Inference_3()
SnapshotExtensions.MatchSnapshot(schema);
}

[Fact]
public async Task Static_Field_Inference_3_Execute()
{
// arrange
// act
var result =
await new ServiceCollection()
.AddGraphQL()
.AddQueryType<WithStaticField>()
.ModifyOptions(o => o.DefaultBindingBehavior = BindingBehavior.Explicit)
.ExecuteRequestAsync("{ hello }");

// assert
SnapshotExtensions.MatchSnapshot(result);
}

[Fact]
public async Task Static_Field_Inference_4()
{
@@ -2039,6 +2052,42 @@ public async Task Static_Field_Inference_4()
SnapshotExtensions.MatchSnapshot(schema);
}

[Fact]
public async Task Static_Field_Inference_4_Execute()
{
// arrange
// act
var result =
await new ServiceCollection()
.AddGraphQL()
.AddQueryType<WithStaticField>()
.ModifyOptions(o =>
{
o.DefaultBindingBehavior = BindingBehavior.Explicit;
o.DefaultFieldBindingFlags = Instance | Static;
})
.ExecuteRequestAsync("{ hello staticHello }");

// assert
SnapshotExtensions.MatchSnapshot(result);
}

[Fact]
public async Task Static_Field_Inference_5()
{
// arrange
// act
var schema =
await new ServiceCollection()
.AddGraphQL()
.AddQueryType()
.AddTypeExtension(typeof(BookQuery))
.ModifyOptions(o => o.DefaultFieldBindingFlags = InstanceAndStatic)
.BuildSchemaAsync();

// assert
SnapshotExtensions.MatchSnapshot(schema);
}

public class GenericFoo<T>
{
@@ -2338,4 +2387,20 @@ public class WithStaticField2

public string Hello() => "hello";
}

[ExtendObjectType(OperationType.Query)]
public static class BookQuery
{
public static Book GetBook()
=> new Book();
}

public class Book
{
public int Id { get; }

public string Title { get; set; }

public static bool IsComic => true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"data": {
"hello": "hello"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"data": {
"hello": "hello",
"staticHello": "hello"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
schema {
query: Query
}

type Book {
id: Int!
title: String!
isComic: Boolean!
}

type Query {
book: Book!
}

"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! = 0 "Streamed when true." if: Boolean) on FIELD