Please report any issues you find with this new behavior.
The core language types have been updated to more closely represent the Abstract Syntax Tree of GraphQL. This allows for the ability to "walk" the tree of the graph. The language types implement INode
, which looks like:
public interface INode
{
IEnumerable<INode> Children { get; }
SourceLocation SourceLocation { get; }
bool IsEqualTo(INode node);
}
Children
is a list of child nodes, such as aSelectionSet
.SourceLocation
contains the line/number of where the node is in the source operation.
Note: Selections
has been renamed to SelectionSet
and is now an INode
.
You can walk the graph with a simple visitor such as BasicVisitor
. An INodeVisitor
is passed to the BasicVisitor
which will walk the node graph and sequentially call Enter
and Leave
on each INodeVisitor
with the current INode
.
public void VisitDocument(string operation)
{
var builder = new AntlrDocumentBuilder();
var document = builder.Build(operation);
var debugVisitor = new DebugNodeVisitor();
var basicVisitor = new BasicVisitor(new[] {debugVisitor});
basicVisitor.Visit(document);
}
public class DebugNodeVisitor : INodeVisitor
{
public void Enter(INode node)
{
Debug.WriteLine($"Entering {node}");
}
public void Leave(INode node)
{
Debug.WriteLine($"Leaving {node}");
}
}
You can also use funcs to make matching a particular INode
easy:
new NodeVisitorMatchFuncListener<Field>(
n => n is Field,
field =>
{
// do something with the field
}
);
public class NodeVisitorMatchFuncListener<T> : INodeVisitor
where T : INode
{
private readonly Func<INode, bool> _match;
private readonly Action<T> _action;
public NodeVisitorMatchFuncListener(Func<INode, bool> match, Action<T> action)
{
_match = match;
_action = action;
}
public void Enter(INode node)
{
if (_match(node))
{
_action((T) node);
}
}
public void Leave(INode node)
{
}
}
Additional updates and changes will most likely be coming to the AST as more validation rules are implemented, however they should not be as drastic.
Coerce
has been removed and has been replaced by ParseValue
, ParseLiteral
, and Serialize
.
ParseValue
- This should contain the logic previously found inCoerce
.ParseLiteral
- This takes in an ASTIValue
that should be converted to a real value.StringValue
,IntValue
,LongValue
,FloatValue
,EnumValue
,ListValue
,ObjectValue
.Serialize
- The value to output.
An example from FloatGraphType
:
public class FloatGraphType : ScalarGraphType
{
public FloatGraphType()
{
Name = "Float";
}
public override object Serialize(object value)
{
return ParseValue(value);
}
public override object ParseValue(object value)
{
double result;
if (double.TryParse(value?.ToString() ?? string.Empty, out result))
{
return result;
}
return null;
}
public override object ParseLiteral(IValue value)
{
var floatVal = value as FloatValue;
return floatVal?.Value;
}
}