Skip to content

Commit

Permalink
Fixed with the attribute order in C# (#4337)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Oct 28, 2021
1 parent a7617e4 commit 74644b3
Show file tree
Hide file tree
Showing 28 changed files with 119 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

Expand All @@ -11,9 +12,10 @@ public sealed class UseDataLoaderAttribute : ObjectFieldDescriptorAttribute
{
private readonly Type _dataLoaderType;

public UseDataLoaderAttribute(Type dataLoaderType)
public UseDataLoaderAttribute(Type dataLoaderType, [CallerLineNumber] int order = 0)
{
_dataLoaderType = dataLoaderType;
Order = order;
}

public override void OnConfigure(
Expand Down
1 change: 0 additions & 1 deletion src/HotChocolate/Core/src/Fetching/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ HotChocolate.Fetching.RegisterDataLoaderException.RegisterDataLoaderException(st
HotChocolate.Types.DataLoaderObjectFieldExtensions
HotChocolate.Types.DataLoaderResolverContextExtensions
HotChocolate.Types.UseDataLoaderAttribute
HotChocolate.Types.UseDataLoaderAttribute.UseDataLoaderAttribute(System.Type! dataLoaderType) -> void
override HotChocolate.Fetching.DataLoaderParameterExpressionBuilder.Build(System.Reflection.ParameterInfo! parameter, System.Linq.Expressions.Expression! context) -> System.Linq.Expressions.Expression!
override HotChocolate.Fetching.DataLoaderParameterExpressionBuilder.CanHandle(System.Reflection.ParameterInfo! parameter) -> bool
override HotChocolate.Types.UseDataLoaderAttribute.OnConfigure(HotChocolate.Types.Descriptors.IDescriptorContext! context, HotChocolate.Types.IObjectFieldDescriptor! descriptor, System.Reflection.MemberInfo! member) -> void
Expand Down
2 changes: 2 additions & 0 deletions src/HotChocolate/Core/src/Fetching/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HotChocolate.Types.UseDataLoaderAttribute.UseDataLoaderAttribute(System.Type! dataLoaderType, int order = 0) -> void
*REMOVED*HotChocolate.Types.UseDataLoaderAttribute.UseDataLoaderAttribute(System.Type! dataLoaderType) -> void
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Pagination;

Expand All @@ -24,9 +25,13 @@ public sealed class UsePagingAttribute : DescriptorAttribute
/// <param name="type">
/// The schema type representing the item type.
/// </param>
public UsePagingAttribute(Type? type = null)
/// <param name="order">
/// The explicit order priority for this attribute.
/// </param>
public UsePagingAttribute(Type? type = null, [CallerLineNumber] int order = 0)
{
Type = type;
Order = order;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ HotChocolate.Types.UsePagingAttribute.RequirePagingBoundaries.set -> void
HotChocolate.Types.UsePagingAttribute.SchemaType.get -> System.Type?
HotChocolate.Types.UsePagingAttribute.SchemaType.set -> void
HotChocolate.Types.UsePagingAttribute.Type.get -> System.Type?
HotChocolate.Types.UsePagingAttribute.UsePagingAttribute(System.Type? type = null) -> void
Microsoft.Extensions.DependencyInjection.CursorPagingRequestExecutorBuilderExtension
override HotChocolate.Types.Pagination.PageInfoType.Configure(HotChocolate.Types.IObjectTypeDescriptor<HotChocolate.Types.Pagination.ConnectionPageInfo!>! descriptor) -> void
override HotChocolate.Types.Pagination.QueryableCursorPagingProvider.CanHandle(HotChocolate.Internal.IExtendedType! source) -> bool
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HotChocolate.Types.UsePagingAttribute.UsePagingAttribute(System.Type? type = null, int order = 0) -> void
*REMOVED*HotChocolate.Types.UsePagingAttribute.UsePagingAttribute(System.Type? type = null) -> void
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Pagination;

Expand All @@ -22,11 +23,16 @@ public class UseOffsetPagingAttribute : DescriptorAttribute
/// <param name="type">
/// The schema type representing the item type.
/// </param>
public UseOffsetPagingAttribute(Type? type = null)
/// <param name="order">
/// The explicit order priority for this attribute.
/// </param>
public UseOffsetPagingAttribute(Type? type = null, [CallerLineNumber] int order = 0)
{
Type = type;
Order = order;
}


/// <summary>
/// The schema type representation of the item type.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ HotChocolate.Types.UseOffsetPagingAttribute.ProviderName.set -> void
HotChocolate.Types.UseOffsetPagingAttribute.RequirePagingBoundaries.get -> bool
HotChocolate.Types.UseOffsetPagingAttribute.RequirePagingBoundaries.set -> void
HotChocolate.Types.UseOffsetPagingAttribute.Type.get -> System.Type?
HotChocolate.Types.UseOffsetPagingAttribute.UseOffsetPagingAttribute(System.Type? type = null) -> void
Microsoft.Extensions.DependencyInjection.OffsetPagingRequestExecutorBuilderExtension
override HotChocolate.Types.Pagination.CollectionSegmentCountType<T>.Configure(HotChocolate.Types.IObjectTypeDescriptor<HotChocolate.Types.Pagination.CollectionSegment!>! descriptor) -> void
override HotChocolate.Types.Pagination.CollectionSegmentInfoType.Configure(HotChocolate.Types.IObjectTypeDescriptor<HotChocolate.Types.Pagination.CollectionSegmentInfo!>! descriptor) -> void
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HotChocolate.Types.UseOffsetPagingAttribute.UseOffsetPagingAttribute(System.Type? type = null, int order = 0) -> void
*REMOVED*HotChocolate.Types.UseOffsetPagingAttribute.UseOffsetPagingAttribute(System.Type? type = null) -> void
1 change: 0 additions & 1 deletion src/HotChocolate/Core/src/Types/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2976,7 +2976,6 @@ HotChocolate.Types.UrlType
HotChocolate.Types.UrlType.UrlType() -> void
HotChocolate.Types.UrlType.UrlType(HotChocolate.NameString name, string? description = null, HotChocolate.Types.BindingBehavior bind = HotChocolate.Types.BindingBehavior.Explicit) -> void
HotChocolate.Types.UseServiceScopeAttribute
HotChocolate.Types.UseServiceScopeAttribute.UseServiceScopeAttribute() -> void
HotChocolate.Types.UuidType
HotChocolate.Types.UuidType.UuidType() -> void
HotChocolate.Types.UuidType.UuidType(char defaultFormat = '\0', bool enforceFormat = false) -> void
Expand Down
4 changes: 4 additions & 0 deletions src/HotChocolate/Core/src/Types/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
HotChocolate.Types.DescriptorAttribute.Order.get -> int
HotChocolate.Types.DescriptorAttribute.Order.set -> void
HotChocolate.Types.UseServiceScopeAttribute.UseServiceScopeAttribute(int order = 0) -> void
*REMOVED*HotChocolate.Types.UseServiceScopeAttribute.UseServiceScopeAttribute() -> void
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
using System;
using System.Reflection;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;

#nullable enable

namespace HotChocolate.Types
{
public abstract class DescriptorAttribute : Attribute
{
/// <summary>
/// Gets the order in which the attributes shall be applied.
/// </summary>
public int Order { get; set; } = int.MaxValue;

/// <summary>
/// Override this to implement the configuration logic for this attribute.
/// </summary>
protected internal abstract void TryConfigure(
IDescriptorContext context,
IDescriptor descriptor,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Types
Expand All @@ -11,6 +12,11 @@ namespace HotChocolate.Types
/// </summary>
public sealed class UseServiceScopeAttribute : ObjectFieldDescriptorAttribute
{
public UseServiceScopeAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}

public override void OnConfigure(
IDescriptorContext context,
IObjectFieldDescriptor descriptor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,9 @@ public void ApplyAttributes(
IDescriptor descriptor,
ICustomAttributeProvider attributeProvider)
{
foreach (var attr in GetCustomAttributes<DescriptorAttribute>(attributeProvider, true))
foreach (DescriptorAttribute attr in
GetCustomAttributes<DescriptorAttribute>(attributeProvider, true)
.OrderBy(t => t.Order))
{
attr.TryConfigure(context, descriptor, attributeProvider);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

Expand All @@ -21,9 +22,10 @@ public sealed class UseFilteringAttribute : ObjectFieldDescriptorAttribute
m.GetParameters().Length == 2 &&
m.GetParameters()[0].ParameterType == typeof(IObjectFieldDescriptor));

public UseFilteringAttribute(Type? filterType = null)
public UseFilteringAttribute(Type? filterType = null, [CallerLineNumber] int order = 0)
{
Type = filterType;
Order = order;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

Expand All @@ -11,6 +12,11 @@ namespace HotChocolate.Data
public sealed class UseFirstOrDefaultAttribute
: ObjectFieldDescriptorAttribute
{
public UseFirstOrDefaultAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}

public override void OnConfigure(
IDescriptorContext context,
IObjectFieldDescriptor descriptor,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Data.Projections;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
Expand All @@ -12,6 +13,11 @@ namespace HotChocolate.Data
public sealed class UseProjectionAttribute
: ObjectFieldDescriptorAttribute
{
public UseProjectionAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}

/// <summary>
/// Sets the scope for the convention
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

Expand All @@ -11,6 +12,11 @@ namespace HotChocolate.Data
public sealed class UseSingleOrDefaultAttribute
: ObjectFieldDescriptorAttribute
{
public UseSingleOrDefaultAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}

public override void OnConfigure(
IDescriptorContext context,
IObjectFieldDescriptor descriptor,
Expand Down
5 changes: 0 additions & 5 deletions src/HotChocolate/Data/src/Data/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1235,21 +1235,16 @@ HotChocolate.Data.UseFilteringAttribute.Scope.get -> string?
HotChocolate.Data.UseFilteringAttribute.Scope.set -> void
HotChocolate.Data.UseFilteringAttribute.Type.get -> System.Type?
HotChocolate.Data.UseFilteringAttribute.Type.set -> void
HotChocolate.Data.UseFilteringAttribute.UseFilteringAttribute(System.Type? filterType = null) -> void
HotChocolate.Data.UseFirstOrDefaultAttribute
HotChocolate.Data.UseFirstOrDefaultAttribute.UseFirstOrDefaultAttribute() -> void
HotChocolate.Data.UseProjectionAttribute
HotChocolate.Data.UseProjectionAttribute.Scope.get -> string?
HotChocolate.Data.UseProjectionAttribute.Scope.set -> void
HotChocolate.Data.UseProjectionAttribute.UseProjectionAttribute() -> void
HotChocolate.Data.UseSingleOrDefaultAttribute
HotChocolate.Data.UseSingleOrDefaultAttribute.UseSingleOrDefaultAttribute() -> void
HotChocolate.Data.UseSortingAttribute
HotChocolate.Data.UseSortingAttribute.Scope.get -> string?
HotChocolate.Data.UseSortingAttribute.Scope.set -> void
HotChocolate.Data.UseSortingAttribute.Type.get -> System.Type?
HotChocolate.Data.UseSortingAttribute.Type.set -> void
HotChocolate.Data.UseSortingAttribute.UseSortingAttribute(System.Type? sortingType = null) -> void
HotChocolate.FilterSchemaBuilderExtensions
HotChocolate.ProjectionsSchemaBuilderExtensions
HotChocolate.SortingSchemaBuilderExtensions
Expand Down
10 changes: 10 additions & 0 deletions src/HotChocolate/Data/src/Data/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
HotChocolate.Data.UseFilteringAttribute.UseFilteringAttribute(System.Type? filterType = null, int order = 0) -> void
HotChocolate.Data.UseFirstOrDefaultAttribute.UseFirstOrDefaultAttribute(int order = 0) -> void
HotChocolate.Data.UseProjectionAttribute.UseProjectionAttribute(int order = 0) -> void
HotChocolate.Data.UseSingleOrDefaultAttribute.UseSingleOrDefaultAttribute(int order = 0) -> void
HotChocolate.Data.UseSortingAttribute.UseSortingAttribute(System.Type? sortingType = null, int order = 0) -> void
*REMOVED*HotChocolate.Data.UseFilteringAttribute.UseFilteringAttribute(System.Type? filterType = null) -> void
*REMOVED*HotChocolate.Data.UseProjectionAttribute.UseProjectionAttribute() -> void
*REMOVED*HotChocolate.Data.UseSortingAttribute.UseSortingAttribute(System.Type? sortingType = null) -> void
*REMOVED*HotChocolate.Data.UseFirstOrDefaultAttribute.UseFirstOrDefaultAttribute() -> void
*REMOVED*HotChocolate.Data.UseSingleOrDefaultAttribute.UseSingleOrDefaultAttribute() -> void
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;

Expand All @@ -20,9 +21,10 @@ public sealed class UseSortingAttribute : ObjectFieldDescriptorAttribute
&& m.GetParameters().Length == 2
&& m.GetParameters()[0].ParameterType == typeof(IObjectFieldDescriptor));

public UseSortingAttribute(Type? sortingType = null)
public UseSortingAttribute(Type? sortingType = null, [CallerLineNumber] int order = 0)
{
Type = sortingType;
Order = order;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ HotChocolate.Data.EntityFrameworkExecutable<T>
HotChocolate.Data.EntityFrameworkExecutable<T>.EntityFrameworkExecutable(System.Linq.IQueryable<T>! queryable) -> void
HotChocolate.Data.EntityFrameworkResolverContextExtensions
HotChocolate.Data.UseDbContextAttribute
HotChocolate.Data.UseDbContextAttribute.UseDbContextAttribute(System.Type! dbContext) -> void
HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions
override HotChocolate.Data.EntityFrameworkExecutable<T>.FirstOrDefaultAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask<object?>
override HotChocolate.Data.EntityFrameworkExecutable<T>.Print() -> string!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HotChocolate.Data.UseDbContextAttribute.UseDbContextAttribute(System.Type! dbContext, int order = 0) -> void
*REMOVED*HotChocolate.Data.UseDbContextAttribute.UseDbContextAttribute(System.Type! dbContext) -> void
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using Microsoft.EntityFrameworkCore;
Expand All @@ -17,9 +18,10 @@ public class UseDbContextAttribute : ObjectFieldDescriptorAttribute

private readonly Type _dbContext;

public UseDbContextAttribute(Type dbContext)
public UseDbContextAttribute(Type dbContext, [CallerLineNumber] int order = 0)
{
_dbContext = dbContext;
Order = order;
}

public override void OnConfigure(
Expand Down
32 changes: 30 additions & 2 deletions src/HotChocolate/Data/test/Data.Tests/TypeValidationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,27 @@ public void EnsureProjectionComesAfterDbContext()
{
void Action() =>
SchemaBuilder.New()
.AddQueryType<InvalidMiddlewarePipeline1>()
.AddQueryType<InvalidMiddlewarePipeline2>()
.AddProjections()
.AddFiltering()
.AddSorting()
.Create();

SchemaException exception = Assert.Throws<SchemaException>(Action);

Assert.Collection(
exception.Errors,
error => Assert.Equal("HC0050", error.Code));

exception.Message.MatchSnapshot();
}

[Fact]
public void UseOrderProperty()
{
void Action() =>
SchemaBuilder.New()
.AddQueryType<InvalidMiddlewarePipeline3>()
.AddProjections()
.AddFiltering()
.AddSorting()
Expand All @@ -46,7 +66,7 @@ void Action() =>
Assert.Collection(
exception.Errors,
error => Assert.Equal("HC0050", error.Code));

exception.Message.MatchSnapshot();
}

Expand Down Expand Up @@ -78,6 +98,14 @@ public class InvalidMiddlewarePipeline2
public IEnumerable<string> GetBars() => throw new NotImplementedException();
}

public class InvalidMiddlewarePipeline3
{
[UsePaging(Order = 1)]
[UseProjection(Order = 0)]
[UseFiltering(Order = 15)]
public IEnumerable<string> GetBars() => throw new NotImplementedException();
}

public class CorrectMiddlewarePipeline
{
[UsePaging]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
For more details look at the `Errors` property.

1. The middleware pipeline order for the field `InvalidMiddlewarePipeline1.bars` is invalid. Middleware order is important especially with data pipelines. The correct order of a data pipeline is as follows: UseDbContext -> UsePaging -> UseProjection -> UseFiltering -> UseSorting. You may omit any of these middleware or have other middleware in between but you need to abide by the overall order. Your order is: UseFiltering -> UsePaging. (HotChocolate.Types.ObjectType<HotChocolate.Data.Test.TypeValidationTests.InvalidMiddlewarePipeline1>)
1. The middleware pipeline order for the field `InvalidMiddlewarePipeline2.bars` is invalid. Middleware order is important especially with data pipelines. The correct order of a data pipeline is as follows: UseDbContext -> UsePaging -> UseProjection -> UseFiltering -> UseSorting. You may omit any of these middleware or have other middleware in between but you need to abide by the overall order. Your order is: UsePaging -> UseFiltering -> UseProjection. (HotChocolate.Types.ObjectType<HotChocolate.Data.Test.TypeValidationTests.InvalidMiddlewarePipeline2>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
For more details look at the `Errors` property.

1. The middleware pipeline order for the field `InvalidMiddlewarePipeline3.bars` is invalid. Middleware order is important especially with data pipelines. The correct order of a data pipeline is as follows: UseDbContext -> UsePaging -> UseProjection -> UseFiltering -> UseSorting. You may omit any of these middleware or have other middleware in between but you need to abide by the overall order. Your order is: UseProjection -> UsePaging -> UseFiltering. (HotChocolate.Types.ObjectType<HotChocolate.Data.Test.TypeValidationTests.InvalidMiddlewarePipeline3>)
Loading

0 comments on commit 74644b3

Please sign in to comment.