Skip to content

Commit

Permalink
[Fusion] Added pre-merge validation rule `ExternalArgumentDefaultMism…
Browse files Browse the repository at this point in the history
…atch` (#7844)
  • Loading branch information
danielreynolds1 authored Dec 20, 2024
1 parent f4233d2 commit d1e6ac3
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace HotChocolate.Fusion.Logging;
public static class LogEntryCodes
{
public const string DisallowedInaccessible = "DISALLOWED_INACCESSIBLE";
public const string ExternalArgumentDefaultMismatch = "EXTERNAL_ARGUMENT_DEFAULT_MISMATCH";
public const string ExternalMissingOnBase = "EXTERNAL_MISSING_ON_BASE";
public const string OutputFieldTypesNotMergeable = "OUTPUT_FIELD_TYPES_NOT_MERGEABLE";
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ public static LogEntry DisallowedInaccessibleDirectiveArgument(
new SchemaCoordinate(directiveName, argumentName: argument.Name, ofDirective: true),
schema: schema);

public static LogEntry ExternalArgumentDefaultMismatch(
string argumentName,
string fieldName,
string typeName)
{
var coordinate = new SchemaCoordinate(typeName, fieldName, argumentName);

return new LogEntry(
string.Format(LogEntryHelper_ExternalArgumentDefaultMismatch, coordinate),
LogEntryCodes.ExternalArgumentDefaultMismatch,
LogSeverity.Error,
coordinate);
}

public static LogEntry ExternalMissingOnBase(string fieldName, string typeName)
=> new(
string.Format(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Immutable;
using HotChocolate.Fusion.Events;
using HotChocolate.Language;
using static HotChocolate.Fusion.Logging.LogEntryHelper;

namespace HotChocolate.Fusion.PreMergeValidation.Rules;

/// <summary>
/// This rule ensures that arguments on fields marked as <c>@external</c> have default values
/// compatible with the corresponding arguments on fields from other source schemas where the field
/// is defined (non-<c>@external</c>).
/// </summary>
/// <seealso href="https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Default-Mismatch">
/// Specification
/// </seealso>
internal sealed class ExternalArgumentDefaultMismatchRule : IEventHandler<OutputFieldGroupEvent>
{
public void Handle(OutputFieldGroupEvent @event, CompositionContext context)
{
var (fieldName, fieldGroup, typeName) = @event;

var externalFields = fieldGroup
.Where(i => ValidationHelper.IsExternal(i.Field))
.ToImmutableArray();

if (externalFields.Length == 0)
{
return;
}

var argumentNames = fieldGroup
.SelectMany(i => i.Field.Arguments, (_, arg) => arg.Name)
.ToImmutableHashSet();

foreach (var argumentName in argumentNames)
{
var arguments = fieldGroup
.SelectMany(i => i.Field.Arguments.Where(a => a.Name == argumentName))
.ToImmutableArray();

var defaultValue = arguments[0].DefaultValue;

foreach (var argument in arguments)
{
if (!SyntaxComparer.BySyntax.Equals(argument.DefaultValue, defaultValue))
{
context.Log.Write(
ExternalArgumentDefaultMismatch(argumentName, fieldName, typeName));
}
}
}
}
}

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 @@ -36,6 +36,9 @@
<data name="LogEntryHelper_DisallowedInaccessibleDirectiveArgument" xml:space="preserve">
<value>The argument '{0}' on built-in directive type '{1}' is not accessible.</value>
</data>
<data name="LogEntryHelper_ExternalArgumentDefaultMismatch" xml:space="preserve">
<value>The argument with schema coordinate '{0}' has inconsistent default values.</value>
</data>
<data name="LogEntryHelper_ExternalMissingOnBase" xml:space="preserve">
<value>Field '{0}' on type '{1}' is only declared as external.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ private CompositionResult<SchemaDefinition> MergeSchemaDefinitions(CompositionCo
private static readonly List<object> _preMergeValidationRules =
[
new DisallowedInaccessibleElementsRule(),
new ExternalArgumentDefaultMismatchRule(),
new ExternalMissingOnBaseRule(),
new OutputFieldTypesMergeableRule()
];
Expand Down
Loading

0 comments on commit d1e6ac3

Please sign in to comment.