Skip to content

Commit

Permalink
[Fusion] Added pre-merge validation rule "ProvidesOnNonCompositeField…
Browse files Browse the repository at this point in the history
…Rule" (#7883)
  • Loading branch information
danielreynolds1 authored Jan 1, 2025
1 parent f7096e8 commit c23d62b
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public static class LogEntryCodes
public const string ProvidesDirectiveInFieldsArg = "PROVIDES_DIRECTIVE_IN_FIELDS_ARG";
public const string ProvidesFieldsHasArgs = "PROVIDES_FIELDS_HAS_ARGS";
public const string ProvidesFieldsMissingExternal = "PROVIDES_FIELDS_MISSING_EXTERNAL";
public const string ProvidesOnNonCompositeField = "PROVIDES_ON_NON_COMPOSITE_FIELD";
public const string QueryRootTypeInaccessible = "QUERY_ROOT_TYPE_INACCESSIBLE";
public const string RootMutationUsed = "ROOT_MUTATION_USED";
public const string RootQueryUsed = "ROOT_QUERY_USED";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,25 @@ public static LogEntry ProvidesFieldsMissingExternal(
schema);
}

public static LogEntry ProvidesOnNonCompositeField(
OutputFieldDefinition field,
INamedTypeDefinition type,
SchemaDefinition schema)
{
var coordinate = new SchemaCoordinate(type.Name, field.Name);

return new LogEntry(
string.Format(
LogEntryHelper_ProvidesOnNonCompositeField,
coordinate,
schema.Name),
LogEntryCodes.ProvidesOnNonCompositeField,
LogSeverity.Error,
coordinate,
field,
schema);
}

public static LogEntry QueryRootTypeInaccessible(
INamedTypeDefinition type,
SchemaDefinition schema)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using HotChocolate.Fusion.Events;
using HotChocolate.Fusion.Extensions;
using HotChocolate.Skimmed;
using static HotChocolate.Fusion.Logging.LogEntryHelper;

namespace HotChocolate.Fusion.PreMergeValidation.Rules;

/// <summary>
/// The <c>@provides</c> directive allows a field to “provide” additional nested fields on the
/// composite type it returns. If a field’s base type is not an object or interface type (e.g.,
/// String, Int, Boolean, Enum, Union, or an Input type), it cannot hold nested fields for
/// <c>@provides</c> to select. Consequently, attaching <c>@provides</c> to such a field is
/// invalid and raises a PROVIDES_ON_NON_OBJECT_FIELD error.
/// </summary>
/// <seealso href="https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-on-Non-Composite-Field">
/// Specification
/// </seealso>
internal sealed class ProvidesOnNonCompositeFieldRule : IEventHandler<OutputFieldEvent>
{
public void Handle(OutputFieldEvent @event, CompositionContext context)
{
var (field, type, schema) = @event;

if (ValidationHelper.HasProvidesDirective(field))
{
var fieldType = field.Type.NamedType();

if (fieldType is not ComplexTypeDefinition)
{
context.Log.Write(ProvidesOnNonCompositeField(field, type, schema));
}
}
}
}

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
Expand Up @@ -75,6 +75,9 @@
<data name="LogEntryHelper_ProvidesFieldsMissingExternal" xml:space="preserve">
<value>The @provides directive on field '{0}' in schema '{1}' references field '{2}', which must be marked as external.</value>
</data>
<data name="LogEntryHelper_ProvidesOnNonCompositeField" xml:space="preserve">
<value>The field '{0}' in schema '{1}' includes a @provides directive, but does not return a composite type.</value>
</data>
<data name="LogEntryHelper_QueryRootTypeInaccessible" xml:space="preserve">
<value>The root query type in schema '{0}' must be accessible.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private CompositionResult<SchemaDefinition> MergeSchemaDefinitions(CompositionCo
new ProvidesDirectiveInFieldsArgumentRule(),
new ProvidesFieldsHasArgumentsRule(),
new ProvidesFieldsMissingExternalRule(),
new ProvidesOnNonCompositeFieldRule(),
new QueryRootTypeInaccessibleRule(),
new RootMutationUsedRule(),
new RootQueryUsedRule(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace HotChocolate.Fusion;

internal sealed class ValidationHelper
{
public static bool HasProvidesDirective(IDirectivesProvider type)
{
return type.Directives.ContainsName(WellKnownDirectiveNames.Provides);
}

public static bool IsAccessible(IDirectivesProvider type)
{
return !type.Directives.ContainsName(WellKnownDirectiveNames.Inaccessible);
Expand Down
Loading

0 comments on commit c23d62b

Please sign in to comment.