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: byte[] cannot be defined as a custom scalar. #345

Merged
merged 13 commits into from
Nov 19, 2018
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ We are currently working on the following features that are proposed for the nex
- [x] WebSockets
- [ ] Schema Builder (in development - 0.11.0)

## GraphQL Compatibility Acceptance Tests

We are now investing to implement the GraphQL Compatibility Acceptance Tests for Hot Chocolate. We should have the first test running with Version 0.8.0 and should have this finished until Version 0.11.0.

More about GraphQL compatibility acceptance tests can be read [here](https://github.com/graphql-cats/graphql-cats).

## Documentation

For more examples and detailed documentation, click [here](http://hotchocolate.io).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void CreateValues_IntValue_Int(int value)
"query test($test: Int) { a }");

var variableValues = new Dictionary<string, object>();
variableValues.Add("test", 1);
variableValues.Add("test", value);

var resolver = new VariableValueBuilder(schema, operation);

Expand All @@ -246,7 +246,7 @@ public void CreateValues_IntValue_Int(int value)

// assert
int result = coercedVariableValues.GetVariable<int>("test");
Assert.Equal(1, result);
Assert.Equal(value, result);
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Execution/DirectiveContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public object Result
public CancellationToken RequestAborted =>
_resolverContext.RequestAborted;

public T Argument<T>(string name) =>
public T Argument<T>(NameString name) =>
_resolverContext.Argument<T>(name);

public T CustomContext<T>() =>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Execution/ResolverContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public ResolverContext(

public CancellationToken RequestAborted { get; }

public T Argument<T>(string name)
public T Argument<T>(NameString name)
{
if (string.IsNullOrEmpty(name))
{
Expand Down
95 changes: 64 additions & 31 deletions src/Core/Execution/Utilities/FieldCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,37 +70,69 @@ private void ResolveFields(
{
if (selection is FieldNode fs)
{
string fieldName = fs.Name.Value;
if (type.Fields.TryGetField(fieldName, out ObjectField field))
{
string name = fs.Alias == null ? fs.Name.Value : fs.Alias.Value;
fields[name] = new FieldSelection(fs, field, name);
}
else
{
reportError(new QueryError(
"Could not resolve the specified field."));
}
ResolveFieldSelection(type, fs, reportError, fields);
}
else if (selection is FragmentSpreadNode fragmentSpread)
else if (selection is FragmentSpreadNode fragSpread)
{
Fragment fragment = _fragments.GetFragments(fragmentSpread.Name.Value)
.FirstOrDefault(t => DoesFragmentTypeApply(type, t.TypeCondition));
if (fragment != null)
{
CollectFields(type, fragment.SelectionSet, reportError, fields);
}
ResolveFragmentSpread(type, fragSpread, reportError, fields);
}
else if (selection is InlineFragmentNode inlineFragment)
else if (selection is InlineFragmentNode inlineFrag)
{
Fragment fragment = _fragments.GetFragment(type, inlineFragment);
if (DoesFragmentTypeApply(type, fragment.TypeCondition))
{
CollectFields(type, fragment.SelectionSet, reportError, fields);
}
ResolveInlineFragment(type, inlineFrag, reportError, fields);
}
}

private void ResolveFieldSelection(
ObjectType type,
FieldNode fieldSelection,
Action<QueryError> reportError,
Dictionary<string, FieldSelection> fields)
{
NameString fieldName = fieldSelection.Name.Value;
if (type.Fields.TryGetField(fieldName, out ObjectField field))
{
string name = fieldSelection.Alias == null
? fieldSelection.Name.Value
: fieldSelection.Alias.Value;
fields[name] = new FieldSelection(fieldSelection, field, name);
}
else
{
reportError(QueryError.CreateFieldError(
"Could not resolve the specified field.",
fieldSelection));
}
}

private void ResolveFragmentSpread(
ObjectType type,
FragmentSpreadNode fragmentSpread,
Action<QueryError> reportError,
Dictionary<string, FieldSelection> fields)
{
Fragment fragment = _fragments.GetFragment(
fragmentSpread.Name.Value);

if (fragment != null && DoesTypeApply(fragment.TypeCondition, type))
{
CollectFields(type, fragment.SelectionSet, reportError, fields);
}
}

private void ResolveInlineFragment(
ObjectType type,
InlineFragmentNode inlineFragment,
Action<QueryError> reportError,
Dictionary<string, FieldSelection> fields)
{
Fragment fragment = _fragments.GetFragment(type, inlineFragment);
if (DoesTypeApply(fragment.TypeCondition, type))
{
CollectFields(type, fragment.SelectionSet, reportError, fields);
}
}


private bool ShouldBeIncluded(ISelectionNode selection)
{
if (selection.Directives.Skip(_variables))
Expand All @@ -110,20 +142,21 @@ private bool ShouldBeIncluded(ISelectionNode selection)
return selection.Directives.Include(_variables);
}

private bool DoesFragmentTypeApply(ObjectType objectType, IType type)
private bool DoesTypeApply(IType typeCondition, ObjectType current)
{
if (type is ObjectType ot)
if (typeCondition is ObjectType ot)
{
return ot == objectType;
return ot == current;
}
else if (type is InterfaceType it)
else if (typeCondition is InterfaceType it)
{
return objectType.Interfaces.ContainsKey(it.Name);
return current.Interfaces.ContainsKey(it.Name);
}
else if (type is UnionType ut)
else if (typeCondition is UnionType ut)
{
return ut.Types.ContainsKey(objectType.Name);
return ut.Types.ContainsKey(current.Name);
}

return false;
}
}
Expand Down
46 changes: 25 additions & 21 deletions src/Core/Execution/Utilities/FragmentCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace HotChocolate.Execution
{
internal sealed class FragmentCollection
{
private readonly Dictionary<string, List<Fragment>> _fragments =
new Dictionary<string, List<Fragment>>();
private readonly Dictionary<string, Fragment> _fragments =
new Dictionary<string, Fragment>();
private readonly ISchema _schema;
private readonly DocumentNode _queryDocument;

Expand All @@ -29,37 +29,41 @@ public FragmentCollection(ISchema schema, DocumentNode queryDocument)
_queryDocument = queryDocument;
}

public IReadOnlyCollection<Fragment> GetFragments(string fragmentName)
public Fragment GetFragment(string fragmentName)
{
if (fragmentName == null)
{
throw new ArgumentNullException(nameof(fragmentName));
}

if (!_fragments.TryGetValue(fragmentName,
out List<Fragment> fragments))
out Fragment fragment))
{
fragments = new List<Fragment>();
fragments.AddRange(CreateFragments(fragmentName));
_fragments[fragmentName] = fragments;
fragment = CreateFragment(fragmentName);
_fragments[fragmentName] = fragment;
}

return fragments;
return fragment;
}

private IEnumerable<Fragment> CreateFragments(string fragmentName)
private Fragment CreateFragment(string fragmentName)
{
foreach (FragmentDefinitionNode fragmentDefinition in
_queryDocument.Definitions
.OfType<FragmentDefinitionNode>()
.Where(t => t.Name.Value == fragmentName))
var fragmentDefinition = _queryDocument.Definitions
.OfType<FragmentDefinitionNode>()
.FirstOrDefault(t => string.Equals(
t.Name.Value, fragmentName,
StringComparison.Ordinal));

if (fragmentDefinition != null)
{
string typeName = fragmentDefinition.TypeCondition.Name.Value;
if (_schema.TryGetType(typeName, out INamedType type))
{
yield return new Fragment(type, fragmentDefinition.SelectionSet);
return new Fragment(type, fragmentDefinition.SelectionSet);
}
}

return null;
}

public Fragment GetFragment(
Expand All @@ -78,15 +82,14 @@ public Fragment GetFragment(

string fragmentName = CreateInlineFragmentName(inlineFragment);

if (!_fragments.TryGetValue(fragmentName,
out List<Fragment> fragments))
if (!_fragments.TryGetValue(fragmentName, out Fragment fragment))
{
fragments = new List<Fragment>();
fragments.Add(CreateFragment(parentType, inlineFragment));
_fragments[fragmentName] = fragments;
fragment = CreateFragment(parentType, inlineFragment);
_fragments[fragmentName] = fragment;

}

return fragments.First();
return fragment;
}

private Fragment CreateFragment(
Expand All @@ -111,7 +114,8 @@ private Fragment CreateFragment(
private string CreateInlineFragmentName(
InlineFragmentNode inlineFragment)
{
return $"^__{inlineFragment.Location.Start}_{inlineFragment.Location.End}";
return $"^__{inlineFragment.Location.Start}_" +
inlineFragment.Location.End;
}
}
}
6 changes: 3 additions & 3 deletions src/Core/Validation/FieldMustBeDefinedVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private bool HasOnylTypeNameField(SelectionSetNode selectionSet)
.All(t => IsTypeNameField(t.Name.Value));
}

private bool FieldExists(IComplexOutputType type, string fieldName)
private bool FieldExists(IComplexOutputType type, NameString fieldName)
{
if (IsTypeNameField(fieldName))
{
Expand All @@ -68,9 +68,9 @@ private bool FieldExists(IComplexOutputType type, string fieldName)
return type.Fields.ContainsField(fieldName);
}

private static bool IsTypeNameField(string fieldName)
private static bool IsTypeNameField(NameString fieldName)
{
return fieldName.EqualsOrdinal(IntrospectionFields.TypeName);
return fieldName.Equals(IntrospectionFields.TypeName);
}
}
}
5 changes: 3 additions & 2 deletions src/Core/Validation/FieldSelectionMergingVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected override void VisitField(
IType type,
ImmutableStack<ISyntaxNode> path)
{
if (!field.Name.Value.EqualsOrdinal(IntrospectionFields.TypeName))
if (!IntrospectionFields.TypeName.Equals(field.Name.Value))
{
if (TryGetSelectionSet(path, out SelectionSetNode selectionSet)
&& _fieldSelectionSets.TryGetValue(selectionSet,
Expand Down Expand Up @@ -151,7 +151,8 @@ private bool CanFieldsInSetMerge(
if (fieldA.DeclaringType == fieldB.DeclaringType)
{
if (fieldA.Field.Name.Value
.EqualsOrdinal(fieldB.Field.Name.Value)
.Equals(fieldB.Field.Name.Value,
StringComparison.Ordinal)
&& AreFieldArgumentsEqual(fieldA, fieldB))
{
return true;
Expand Down
6 changes: 4 additions & 2 deletions src/Core/Validation/SubscriptionSingleRootFieldVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using HotChocolate.Utilities;
using HotChocolate.Language;
using HotChocolate.Types;
using System;

namespace HotChocolate.Validation
{
Expand Down Expand Up @@ -55,8 +56,9 @@ protected override void VisitFragmentSpread(
{
FragmentDefinitionNode fragment = d.Definitions
.OfType<FragmentDefinitionNode>()
.FirstOrDefault(t =>
t.Name.Value.EqualsOrdinal(fragmentSpread.Name.Value));
.FirstOrDefault(t => t.Name.Value
.Equals(fragmentSpread.Name.Value,
StringComparison.Ordinal));

if (fragment != null)
{
Expand Down
30 changes: 29 additions & 1 deletion src/Language/ValidationUtils.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System;
using System.Text;

namespace HotChocolate.Language
{
public static class ValidationUtils
public static class NameUtils
{
public static bool IsValidName(string name)
{
Expand Down Expand Up @@ -30,5 +31,32 @@ public static bool IsValidName(string name)
return false;
}

public static string RemoveInvalidCharacters(string name)
{
if (name == null || name.Length == 0)
{
return name;
}

char[] namearray = name.ToCharArray();

if (!namearray[0].IsLetterOrUnderscore())
{
namearray[0] = '_';
}

if (namearray.Length > 1)
{
for (int i = 1; i < namearray.Length; i++)
{
if (!namearray[i].IsLetterOrDigitOrUnderscore())
{
namearray[i] = '_';
}
}
}

return new string(namearray);
}
}
}
Loading