Skip to content

Commit

Permalink
Schema Merge Blueprint (#4895)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed May 11, 2022
1 parent 39faf79 commit 5a368d4
Show file tree
Hide file tree
Showing 30 changed files with 1,339 additions and 51 deletions.
83 changes: 70 additions & 13 deletions src/HotChocolate/Core/src/Abstractions/SchemaCoordinate.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,46 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using HotChocolate.Language;
using static HotChocolate.Properties.AbstractionResources;

namespace HotChocolate;

/// <summary>
/// <para>
/// A <see cref="SchemaCoordinate"/> is a human readable string that uniquely identifies a
/// schema element within a GraphQL Schema.
/// A schema element is a specific instance of a named type, field, input field, enum value,
/// field argument, directive, or directive argument.
/// A <see cref="SchemaCoordinate"/> is always unique. Each schema element may be referenced
/// by exactly one possible schema coordinate.
///
/// </para>
/// <para>
/// A <see cref="SchemaCoordinate"/> may refer to either a defined or built-in schema element.
/// For example, `String` and `@deprecated(reason:)` are both valid schema coordinates which refer
/// to built-in schema elements. However it must not refer to a meta-field.
/// For example, `Business.__typename` is <b>not</b> a valid schema coordinate.
///
/// SchemaCoordinate :
/// </para>
/// <para>
/// SchemaCoordinate:
/// - Name
/// - Name . Name
/// - Name . Name ( Name : )
/// - @ Name
/// - @ Name ( Name : )
/// - Name.Name
/// - Name.Name(Name:)
/// - @Name
/// - @Name (Name:)
/// </para>
/// </summary>
public readonly struct SchemaCoordinate
public readonly struct SchemaCoordinate : IEquatable<SchemaCoordinate>
{
/// <summary>
/// Creates a new instance of <see cref="SchemaCoordinate"/>
/// </summary>
/// <exception cref="ArgumentNullException">
/// The <paramref name="name"/> is <c>null</c> or <see cref="String.Empty" />.
/// The <paramref name="name"/> is <c>null</c> or <see cref="string.Empty" />.
/// </exception>
/// <exception cref="ArgumentException">
/// - A directive cannot contain a <paramref name="memberName"/>.
/// - A <paramref name="argumentName"/>. without a <paramref name="memberName"/> is only allowed
/// - A <paramref name="argumentName"/>. without a <paramref name="memberName"/> is only allowed
/// on directive coordinates.
/// </exception>
public SchemaCoordinate(
Expand All @@ -57,7 +62,7 @@ namespace HotChocolate;
if (!ofDirective && memberName is null && argumentName is not null)
{
throw new ArgumentException(
ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName,
ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName,
nameof(argumentName));
}

Expand Down Expand Up @@ -94,7 +99,6 @@ public SchemaCoordinateNode ToSyntax()
{
NameNode? memberName = MemberName is null ? null : new(MemberName.Value);
NameNode? argumentName = ArgumentName is null ? null : new(ArgumentName.Value);

return new(null, OfDirective, new(Name.Value), memberName, argumentName);
}

Expand All @@ -108,7 +112,7 @@ public SchemaCoordinateNode ToSyntax()
/// </summary>
/// <param name="s">The string that may represent a <see cref="SchemaCoordinate"/>.</param>
/// <param name="coordinate">
/// If the string <paramref name="s"/> represented a valid schema coordinate string this
/// If the string <paramref name="s"/> represented a valid schema coordinate string this
/// will be the parsed schema coordinate.
/// </param>
/// <returns>
Expand Down Expand Up @@ -167,4 +171,57 @@ public static SchemaCoordinate FromSyntax(SchemaCoordinateNode node)

return new(node.Name.Value, memberName, argumentName, node.OfDirective);
}

/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other" /> parameter;
/// otherwise, <c>false</c>.
/// </returns>
public bool Equals(SchemaCoordinate other)
=> OfDirective == other.OfDirective &&
Name.Equals(other.Name) &&
Nullable.Equals(MemberName, other.MemberName) &&
Nullable.Equals(ArgumentName, other.ArgumentName);

/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="obj">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="obj" /> parameter;
/// otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object? obj)
=> obj is SchemaCoordinate other && Equals(other);

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
public override int GetHashCode()
{
unchecked
{
var hashCode = OfDirective.GetHashCode();
hashCode = (hashCode * 397) ^ Name.GetHashCode();
hashCode = (hashCode * 397) ^ MemberName.GetHashCode();
hashCode = (hashCode * 397) ^ ArgumentName.GetHashCode();
return hashCode;
}
}

public static bool operator ==(SchemaCoordinate left, SchemaCoordinate right)
=> left.Equals(right);

public static bool operator !=(SchemaCoordinate left, SchemaCoordinate right)
=> !left.Equals(right);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ namespace HotChocolate.Language;
{
public static class Syntax
{
/// <summary>
/// Parses a GraphQL object type definitions e.g. type Foo { bar: String }
/// </summary>
public static ObjectTypeDefinitionNode ParseObjectTypeDefinition(
string sourceText) =>
Parse(sourceText, parser => parser.ParseObjectTypeDefinition());

/// <summary>
/// Parses a GraphQL object type definitions e.g. type Foo { bar: String }
/// </summary>
public static ObjectTypeDefinitionNode ParseObjectTypeDefinition(
ReadOnlySpan<byte> sourceText) =>
Parse(sourceText, parser => parser.ParseObjectTypeDefinition());

/// <summary>
/// Parses a GraphQL object type definitions e.g. type Foo { bar: String }
/// </summary>
public static ObjectTypeDefinitionNode ParseObjectTypeDefinition(
Utf8GraphQLReader reader) =>
new Utf8GraphQLParser(reader).ParseObjectTypeDefinition();

/// <summary>
/// Parses a GraphQL field selection string e.g. field(arg: "abc")
/// </summary>
Expand All @@ -34,18 +55,14 @@ public static class Syntax
/// </summary>
public static FieldNode ParseField(
string sourceText) =>
Parse(
sourceText,
parser => parser.ParseField());
Parse(sourceText, parser => parser.ParseField());

/// <summary>
/// Parses a GraphQL field selection string e.g. field(arg: "abc")
/// </summary>
public static FieldNode ParseField(
ReadOnlySpan<byte> sourceText) =>
Parse(
sourceText,
parser => parser.ParseField());
Parse(sourceText, parser => parser.ParseField());

/// <summary>
/// Parses a GraphQL field selection string e.g. field(arg: "abc")
Expand All @@ -59,18 +76,14 @@ public static class Syntax
/// </summary>
public static SelectionSetNode ParseSelectionSet(
string sourceText) =>
Parse(
sourceText,
parser => parser.ParseSelectionSet());
Parse(sourceText, parser => parser.ParseSelectionSet());

/// <summary>
/// Parses a GraphQL selection set string e.g. { field(arg: "abc") }
/// </summary>
public static SelectionSetNode ParseSelectionSet(
ReadOnlySpan<byte> sourceText) =>
Parse(
sourceText,
parser => parser.ParseSelectionSet());
Parse(sourceText, parser => parser.ParseSelectionSet());

/// <summary>
/// Parses a GraphQL selection set string e.g. { field(arg: "abc") }
Expand All @@ -82,16 +95,12 @@ public static class Syntax
public static IValueNode ParseValueLiteral(
string sourceText,
bool constant = true) =>
Parse(
sourceText,
parser => parser.ParseValueLiteral(constant));
Parse(sourceText, parser => parser.ParseValueLiteral(constant));

public static IValueNode ParseValueLiteral(
ReadOnlySpan<byte> sourceText,
bool constant = true) =>
Parse(
sourceText,
parser => parser.ParseValueLiteral(constant));
Parse(sourceText, parser => parser.ParseValueLiteral(constant));

public static IValueNode ParseValueLiteral(
Utf8GraphQLReader reader,
Expand All @@ -101,16 +110,12 @@ public static class Syntax
public static ObjectValueNode ParseObjectLiteral(
string sourceText,
bool constant = true) =>
Parse(
sourceText,
parser => parser.ParseObject(constant));
Parse(sourceText, parser => parser.ParseObject(constant));

public static ObjectValueNode ParseObjectLiteral(
ReadOnlySpan<byte> sourceText,
bool constant = true) =>
Parse(
sourceText,
parser => parser.ParseObject(constant));
Parse(sourceText, parser => parser.ParseObject(constant));

public static ObjectValueNode ParseObjectLiteral(
Utf8GraphQLReader reader,
Expand All @@ -122,18 +127,14 @@ public static class Syntax
/// </summary>
public static ITypeNode ParseTypeReference(
string sourceText) =>
Parse(
sourceText,
parser => parser.ParseTypeReference());
Parse(sourceText, parser => parser.ParseTypeReference());

/// <summary>
/// Parses a GraphQL type reference e.g. [String!]
/// </summary>
public static ITypeNode ParseTypeReference(
ReadOnlySpan<byte> sourceText) =>
Parse(
sourceText,
parser => parser.ParseTypeReference());
Parse(sourceText, parser => parser.ParseTypeReference());

/// <summary>
/// Parses a GraphQL type reference e.g. [String!]
Expand All @@ -147,18 +148,14 @@ public static class Syntax
/// </summary>
public static SchemaCoordinateNode ParseSchemaCoordinate(
string sourceText) =>
Parse(
sourceText,
parser => parser.ParseSingleSchemaCoordinate());
Parse(sourceText, parser => parser.ParseSingleSchemaCoordinate());

/// <summary>
/// Parses a GraphQL schema coordinate e.g. Query.userById(id:)
/// </summary>
public static SchemaCoordinateNode ParseSchemaCoordinate(
ReadOnlySpan<byte> sourceText) =>
Parse(
sourceText,
parser => parser.ParseSingleSchemaCoordinate());
Parse(sourceText, parser => parser.ParseSingleSchemaCoordinate());

/// <summary>
/// Parses a GraphQL schema coordinate e.g. Query.userById(id:)
Expand Down Expand Up @@ -222,5 +219,5 @@ public static class Syntax
}
}

private delegate T ParseSyntax<T>(Utf8GraphQLParser parser) where T : ISyntaxNode;
private delegate T ParseSyntax<out T>(Utf8GraphQLParser parser) where T : ISyntaxNode;
}
2 changes: 1 addition & 1 deletion src/HotChocolate/Stitching/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />

<PropertyGroup>
<LibraryTargetFrameworks Condition="'$(IsMacOsArm)' == 'true'">net6.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks>net6.0</LibraryTargetFrameworks>
</PropertyGroup>

</Project>
30 changes: 30 additions & 0 deletions src/HotChocolate/Stitching/HotChocolate.Stitching.sln
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Stitching.Abst
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Stitching.Redis", "src\Stitching.Redis\HotChocolate.Stitching.Redis.csproj", "{46B6437B-5AC2-41E6-89C6-CC0FE42190A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Stitching.Types.Tests", "test\Stitching.Types.Tests\HotChocolate.Stitching.Types.Tests.csproj", "{12A50382-A67F-44AB-A665-56A10DE0E8E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.Stitching.Types", "src\Stitching.Types\HotChocolate.Stitching.Types.csproj", "{AD6A63BB-A445-4B44-A4A0-95B10279DB72}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -263,6 +267,30 @@ Global
{46B6437B-5AC2-41E6-89C6-CC0FE42190A1}.Release|x64.Build.0 = Release|Any CPU
{46B6437B-5AC2-41E6-89C6-CC0FE42190A1}.Release|x86.ActiveCfg = Release|Any CPU
{46B6437B-5AC2-41E6-89C6-CC0FE42190A1}.Release|x86.Build.0 = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|x64.ActiveCfg = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|x64.Build.0 = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|x86.ActiveCfg = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Debug|x86.Build.0 = Debug|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|Any CPU.Build.0 = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|x64.ActiveCfg = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|x64.Build.0 = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|x86.ActiveCfg = Release|Any CPU
{12A50382-A67F-44AB-A665-56A10DE0E8E8}.Release|x86.Build.0 = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|x64.ActiveCfg = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|x64.Build.0 = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|x86.ActiveCfg = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Debug|x86.Build.0 = Debug|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|Any CPU.Build.0 = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|x64.ActiveCfg = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|x64.Build.0 = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|x86.ActiveCfg = Release|Any CPU
{AD6A63BB-A445-4B44-A4A0-95B10279DB72}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -285,6 +313,8 @@ Global
{709EE9F8-BA48-4C5A-8BDA-96B96689A1FC} = {D7A7C1D4-6239-4B4C-A80C-E953334A83F8}
{E25716BB-CAD4-4FAA-BFFB-9D1F56E3B6AB} = {D530CEBF-33A3-4BCE-9887-A50F5AE789A3}
{46B6437B-5AC2-41E6-89C6-CC0FE42190A1} = {D530CEBF-33A3-4BCE-9887-A50F5AE789A3}
{12A50382-A67F-44AB-A665-56A10DE0E8E8} = {CA934242-6AB7-40F0-B433-A2D9BF10EF4A}
{AD6A63BB-A445-4B44-A4A0-95B10279DB72} = {D530CEBF-33A3-4BCE-9887-A50F5AE789A3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB1557E1-2F94-4540-93E5-B47698838B72}
Expand Down

0 comments on commit 5a368d4

Please sign in to comment.