From 63ba1f8a9e1f0500a3cdf7325a4d137864f9a6f7 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 03:17:31 +0300 Subject: [PATCH 01/18] AstVisitor rework --- .../GraphQL-Parser.approved.txt | 204 ++++- .../GraphQLAstVisitorTests.cs | 428 ---------- .../GraphQLParser.Tests.csproj | 1 - src/GraphQLParser.Tests/ParserTests.cs | 19 + .../Visitors/GraphQLAstVisitorTests.cs | 576 ++++++++++++++ .../Visitors/SDLWriterTests.cs | 222 ++++++ .../Visitors/StructureWriterTests.cs | 48 ++ src/GraphQLParser/AST/GraphQLDirective.cs | 2 +- src/GraphQLParser/AST/GraphQLField.cs | 2 +- .../AST/GraphQLInterfaceTypeDefinition.cs | 2 +- .../AST/GraphQLObjectTypeDefinition.cs | 2 +- .../AST/GraphQLVariableDefinition.cs | 11 +- src/GraphQLParser/AST/IHasArgumentsNode.cs | 15 + src/GraphQLParser/AST/IHasInterfacesNode.cs | 15 + src/GraphQLParser/GraphQLAstVisitor.cs | 264 ------ src/GraphQLParser/ParserContext.Parse.cs | 1 + .../Visitors/DefaultNodeVisitor.cs | 509 ++++++++++++ src/GraphQLParser/Visitors/INodeVisitor.cs | 207 +++++ src/GraphQLParser/Visitors/IVisitorContext.cs | 9 + src/GraphQLParser/Visitors/IWriteContext.cs | 12 + src/GraphQLParser/Visitors/SDLWriter.cs | 753 ++++++++++++++++++ src/GraphQLParser/Visitors/StructureWriter.cs | 28 + 22 files changed, 2588 insertions(+), 742 deletions(-) delete mode 100644 src/GraphQLParser.Tests/GraphQLAstVisitorTests.cs create mode 100644 src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs create mode 100644 src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs create mode 100644 src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs create mode 100644 src/GraphQLParser/AST/IHasArgumentsNode.cs create mode 100644 src/GraphQLParser/AST/IHasInterfacesNode.cs delete mode 100644 src/GraphQLParser/GraphQLAstVisitor.cs create mode 100644 src/GraphQLParser/Visitors/DefaultNodeVisitor.cs create mode 100644 src/GraphQLParser/Visitors/INodeVisitor.cs create mode 100644 src/GraphQLParser/Visitors/IVisitorContext.cs create mode 100644 src/GraphQLParser/Visitors/IWriteContext.cs create mode 100644 src/GraphQLParser/Visitors/SDLWriter.cs create mode 100644 src/GraphQLParser/Visitors/StructureWriter.cs diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index d3a87b0a..ab99c019 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -68,7 +68,7 @@ namespace GraphQLParser.AST public override GraphQLParser.AST.ASTNodeKind Kind { get; } public GraphQLParser.ROM Value { get; set; } } - public class GraphQLDirective : GraphQLParser.AST.ASTNode, GraphQLParser.AST.INamedNode + public class GraphQLDirective : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasArgumentsNode, GraphQLParser.AST.INamedNode { public GraphQLDirective() { } public System.Collections.Generic.List? Arguments { get; set; } @@ -105,7 +105,7 @@ namespace GraphQLParser.AST public System.Collections.Generic.List? Directives { get; set; } public override GraphQLParser.AST.ASTNodeKind Kind { get; } } - public class GraphQLField : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasDirectivesNode, GraphQLParser.AST.INamedNode + public class GraphQLField : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasArgumentsNode, GraphQLParser.AST.IHasDirectivesNode, GraphQLParser.AST.INamedNode { public GraphQLField() { } public GraphQLParser.AST.GraphQLName? Alias { get; set; } @@ -159,7 +159,7 @@ namespace GraphQLParser.AST public override GraphQLParser.AST.ASTNodeKind Kind { get; } public GraphQLParser.AST.GraphQLType? Type { get; set; } } - public class GraphQLInterfaceTypeDefinition : GraphQLParser.AST.GraphQLTypeDefinition, GraphQLParser.AST.IHasDirectivesNode + public class GraphQLInterfaceTypeDefinition : GraphQLParser.AST.GraphQLTypeDefinition, GraphQLParser.AST.IHasDirectivesNode, GraphQLParser.AST.IHasInterfacesNode { public GraphQLInterfaceTypeDefinition() { } public System.Collections.Generic.List? Directives { get; set; } @@ -221,7 +221,7 @@ namespace GraphQLParser.AST public GraphQLParser.AST.GraphQLName? Name { get; set; } public GraphQLParser.AST.GraphQLValue? Value { get; set; } } - public class GraphQLObjectTypeDefinition : GraphQLParser.AST.GraphQLTypeDefinition, GraphQLParser.AST.IHasDirectivesNode + public class GraphQLObjectTypeDefinition : GraphQLParser.AST.GraphQLTypeDefinition, GraphQLParser.AST.IHasDirectivesNode, GraphQLParser.AST.IHasInterfacesNode { public GraphQLObjectTypeDefinition() { } public System.Collections.Generic.List? Directives { get; set; } @@ -312,14 +312,19 @@ namespace GraphQLParser.AST public override GraphQLParser.AST.ASTNodeKind Kind { get; } public GraphQLParser.AST.GraphQLName? Name { get; set; } } - public class GraphQLVariableDefinition : GraphQLParser.AST.ASTNode + public class GraphQLVariableDefinition : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasDirectivesNode { public GraphQLVariableDefinition() { } - public object? DefaultValue { get; set; } + public GraphQLParser.AST.GraphQLValue? DefaultValue { get; set; } + public System.Collections.Generic.List? Directives { get; set; } public override GraphQLParser.AST.ASTNodeKind Kind { get; } public GraphQLParser.AST.GraphQLType? Type { get; set; } public GraphQLParser.AST.GraphQLVariable? Variable { get; set; } } + public interface IHasArgumentsNode + { + System.Collections.Generic.List? Arguments { get; set; } + } public interface IHasDescriptionNode { GraphQLParser.AST.GraphQLDescription? Description { get; set; } @@ -328,6 +333,10 @@ namespace GraphQLParser.AST { System.Collections.Generic.List? Directives { get; set; } } + public interface IHasInterfacesNode + { + System.Collections.Generic.List? Interfaces { get; set; } + } public interface INamedNode { GraphQLParser.AST.GraphQLName? Name { get; set; } @@ -351,42 +360,6 @@ namespace GraphQLParser.Exceptions } namespace GraphQLParser { - public class GraphQLAstVisitor - { - public GraphQLAstVisitor() { } - protected System.Collections.Generic.IDictionary Fragments { get; } - public virtual GraphQLParser.AST.GraphQLName BeginVisitAlias(GraphQLParser.AST.GraphQLName alias) { } - public virtual GraphQLParser.AST.GraphQLArgument BeginVisitArgument(GraphQLParser.AST.GraphQLArgument argument) { } - public virtual System.Collections.Generic.IEnumerable BeginVisitArguments(System.Collections.Generic.IEnumerable arguments) { } - public virtual GraphQLParser.AST.GraphQLScalarValue BeginVisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue value) { } - public virtual GraphQLParser.AST.GraphQLDirective BeginVisitDirective(GraphQLParser.AST.GraphQLDirective directive) { } - public virtual System.Collections.Generic.IEnumerable BeginVisitDirectives(System.Collections.Generic.IEnumerable directives) { } - public virtual GraphQLParser.AST.GraphQLScalarValue BeginVisitEnumValue(GraphQLParser.AST.GraphQLScalarValue value) { } - public virtual GraphQLParser.AST.GraphQLField BeginVisitField(GraphQLParser.AST.GraphQLField selection) { } - public virtual GraphQLParser.AST.GraphQLScalarValue BeginVisitFloatValue(GraphQLParser.AST.GraphQLScalarValue value) { } - public virtual GraphQLParser.AST.GraphQLFragmentDefinition BeginVisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition node) { } - public virtual GraphQLParser.AST.GraphQLFragmentSpread BeginVisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread) { } - public virtual GraphQLParser.AST.GraphQLInlineFragment BeginVisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment) { } - public virtual GraphQLParser.AST.GraphQLScalarValue BeginVisitIntValue(GraphQLParser.AST.GraphQLScalarValue value) { } - public virtual GraphQLParser.AST.GraphQLName BeginVisitName(GraphQLParser.AST.GraphQLName name) { } - public virtual GraphQLParser.AST.GraphQLNamedType BeginVisitNamedType(GraphQLParser.AST.GraphQLNamedType typeCondition) { } - public virtual GraphQLParser.AST.ASTNode? BeginVisitNode(GraphQLParser.AST.ASTNode? node) { } - public virtual GraphQLParser.AST.GraphQLObjectField BeginVisitObjectField(GraphQLParser.AST.GraphQLObjectField node) { } - public virtual GraphQLParser.AST.GraphQLObjectValue BeginVisitObjectValue(GraphQLParser.AST.GraphQLObjectValue node) { } - public virtual GraphQLParser.AST.GraphQLOperationDefinition BeginVisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition definition) { } - public virtual GraphQLParser.AST.GraphQLSelectionSet BeginVisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet) { } - public virtual GraphQLParser.AST.GraphQLScalarValue BeginVisitStringValue(GraphQLParser.AST.GraphQLScalarValue value) { } - public virtual GraphQLParser.AST.GraphQLVariable BeginVisitVariable(GraphQLParser.AST.GraphQLVariable variable) { } - public virtual GraphQLParser.AST.GraphQLVariableDefinition BeginVisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition node) { } - public virtual System.Collections.Generic.IEnumerable BeginVisitVariableDefinitions(System.Collections.Generic.IEnumerable variableDefinitions) { } - public virtual GraphQLParser.AST.GraphQLArgument EndVisitArgument(GraphQLParser.AST.GraphQLArgument argument) { } - public virtual GraphQLParser.AST.GraphQLField EndVisitField(GraphQLParser.AST.GraphQLField selection) { } - public virtual GraphQLParser.AST.GraphQLListValue EndVisitListValue(GraphQLParser.AST.GraphQLListValue node) { } - public virtual GraphQLParser.AST.GraphQLObjectValue EndVisitObjectValue(GraphQLParser.AST.GraphQLObjectValue node) { } - public virtual GraphQLParser.AST.GraphQLOperationDefinition EndVisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition definition) { } - public virtual GraphQLParser.AST.GraphQLVariable EndVisitVariable(GraphQLParser.AST.GraphQLVariable variable) { } - public virtual void Visit(GraphQLParser.AST.GraphQLDocument ast) { } - } [System.Flags] public enum IgnoreOptions { @@ -472,4 +445,151 @@ namespace GraphQLParser UNKNOWN = 20, AMPERSAND = 21, } +} +namespace GraphQLParser.Visitors +{ + public class DefaultNodeVisitor : GraphQLParser.Visitors.INodeVisitor + where TContext : GraphQLParser.Visitors.IVisitorContext + { + public DefaultNodeVisitor() { } + public virtual void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + protected void Visit(System.Collections.Generic.List? nodes, TContext context) + where T : GraphQLParser.AST.ASTNode { } + public virtual void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } + public virtual void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } + public virtual void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } + public virtual void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } + public virtual void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } + public virtual void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } + public virtual void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } + public virtual void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } + public virtual void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } + public virtual void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } + public virtual void VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } + public virtual void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } + public virtual void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } + public virtual void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } + public virtual void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } + public virtual void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } + public virtual void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } + public virtual void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } + public virtual void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } + public virtual void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } + public virtual void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } + public virtual void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } + public virtual void VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } + public virtual void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } + public virtual void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } + public virtual void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } + public virtual void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } + public virtual void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } + public virtual void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } + public virtual void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } + public virtual void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } + public virtual void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } + public virtual void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } + public virtual void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } + public virtual void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } + public virtual void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } + public virtual void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } + public virtual void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } + } + public interface INodeVisitor + where TContext : GraphQLParser.Visitors.IVisitorContext + { + void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context); + void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context); + void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context); + void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context); + void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context); + void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context); + void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context); + void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); + void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context); + void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context); + void VisitField(GraphQLParser.AST.GraphQLField field, TContext context); + void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context); + void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context); + void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context); + void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context); + void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context); + void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); + void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context); + void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context); + void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); + void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context); + void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context); + void VisitName(GraphQLParser.AST.GraphQLName name, TContext context); + void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context); + void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context); + void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context); + void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context); + void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); + void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context); + void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context); + void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); + void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); + void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context); + void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context); + void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context); + void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); + void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context); + void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context); + } + public interface IVisitorContext { } + public interface IWriteContext : GraphQLParser.Visitors.IVisitorContext + { + System.Collections.Generic.Stack Parent { get; } + System.IO.TextWriter Writer { get; } + } + public class SDLWriter : GraphQLParser.Visitors.DefaultNodeVisitor + where TContext : GraphQLParser.Visitors.IWriteContext + { + public SDLWriter() { } + public override void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + public override void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } + public override void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } + public override void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } + public override void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } + public override void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } + public override void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } + public override void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } + public override void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } + public override void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } + public override void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } + public override void VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } + public override void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } + public override void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } + public override void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } + public override void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } + public override void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } + public override void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } + public override void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } + public override void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } + public override void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } + public override void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } + public override void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } + public override void VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } + public override void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } + public override void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } + public override void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } + public override void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } + public override void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } + public override void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } + public override void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } + public override void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } + public override void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } + public override void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } + public override void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } + public override void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } + public override void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } + public override void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } + public override void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } + } + public class StructureWriter : GraphQLParser.Visitors.DefaultNodeVisitor + where TContext : GraphQLParser.Visitors.IWriteContext + { + public StructureWriter() { } + public override void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + } } \ No newline at end of file diff --git a/src/GraphQLParser.Tests/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/GraphQLAstVisitorTests.cs deleted file mode 100644 index f14569f3..00000000 --- a/src/GraphQLParser.Tests/GraphQLAstVisitorTests.cs +++ /dev/null @@ -1,428 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GraphQLParser.AST; -using NSubstitute; -using Shouldly; -using Xunit; - -namespace GraphQLParser.Tests -{ - public class GraphQLAstVisitorTests - { - private readonly List _visitedAliases; - private readonly List _visitedArguments; - private readonly List _visitedDefinitions; - private readonly List _visitedDirectives; - private readonly List _visitedEnumValues; - private readonly List _visitedFields; - private readonly List _visitedFloatValues; - private readonly List _visitedFragmentDefinitions; - private readonly List _visitedFragmentSpreads; - private readonly List _visitedFragmentTypeConditions; - private readonly List _visitedInlineFragments; - private readonly List _visitedIntValues; - private readonly List _visitedNames; - private readonly List _visitedSelectionSets; - private readonly List _visitedStringValues; - private readonly List _visitedVariables; - private readonly GraphQLAstVisitor _visitor; - private readonly List _visitedBooleanValues; - - public GraphQLAstVisitorTests() - { - _visitor = Substitute.ForPartsOf(); - - _visitedDefinitions = MockVisitMethod((visitor) => visitor.BeginVisitOperationDefinition(null)); - _visitedSelectionSets = MockVisitMethod((visitor) => visitor.BeginVisitSelectionSet(null)); - _visitedFields = MockVisitMethod((visitor) => visitor.BeginVisitField(null)); - _visitedNames = MockVisitMethod((visitor) => visitor.BeginVisitName(null)); - _visitedArguments = MockVisitMethod((visitor) => visitor.BeginVisitArgument(null)); - _visitedAliases = MockVisitMethod((visitor) => visitor.BeginVisitAlias(null)); - _visitedFragmentSpreads = MockVisitMethod((visitor) => visitor.BeginVisitFragmentSpread(null)); - _visitedFragmentDefinitions = MockVisitMethod((visitor) => visitor.BeginVisitFragmentDefinition(null)); - _visitedFragmentTypeConditions = MockVisitMethod((visitor) => visitor.BeginVisitNamedType(null)); - _visitedInlineFragments = MockVisitMethod((visitor) => visitor.BeginVisitInlineFragment(null)); - _visitedDirectives = MockVisitMethod((visitor) => visitor.BeginVisitDirective(null)); - _visitedVariables = MockVisitMethod((visitor) => visitor.BeginVisitVariable(null)); - _visitedIntValues = MockVisitMethod((visitor) => visitor.BeginVisitIntValue(null)); - _visitedFloatValues = MockVisitMethod((visitor) => visitor.BeginVisitFloatValue(null)); - _visitedStringValues = MockVisitMethod((visitor) => visitor.BeginVisitStringValue(null)); - _visitedBooleanValues = MockVisitMethod((visitor) => visitor.BeginVisitBooleanValue(null)); - _visitedEnumValues = MockVisitMethod((visitor) => visitor.BeginVisitEnumValue(null)); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_BooleanValueArgument_VisitsOneBooleanValue(IgnoreOptions options) - { - using var d = "{ stuff(id : true) }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedBooleanValues.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_DefinitionWithSingleFragmentSpread_VisitsFragmentSpreadOneTime(IgnoreOptions options) - { - using var d = "{ foo { ...fragment } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFragmentSpreads.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_DefinitionWithSingleFragmentSpread_VisitsNameOfPropertyAndFragmentSpread(IgnoreOptions options) - { - using var d = "{ foo { ...fragment } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedNames.Count.ShouldBe(2); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_DirectiveWithVariable_VisitsVariableOnce(IgnoreOptions options) - { - using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedVariables.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_EnumValueArgument_VisitsOneEnumValue(IgnoreOptions options) - { - using var d = "{ stuff(id : TEST_ENUM) }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedEnumValues.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_FloatValueArgument_VisitsOneFloatValue(IgnoreOptions options) - { - using var d = "{ stuff(id : 1.2) }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFloatValues.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_FragmentWithTypeCondition_VisitsFragmentDefinitionOnce(IgnoreOptions options) - { - using var d = "fragment testFragment on Stuff { field }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFragmentDefinitions.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_FragmentWithTypeCondition_VisitsTypeConditionOnce(IgnoreOptions options) - { - using var d = "fragment testFragment on Stuff { field }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFragmentTypeConditions.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsArgumentsOnce(IgnoreOptions options) - { - using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedArguments.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsDirectiveOnce(IgnoreOptions options) - { - using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedDirectives.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsNameThreeTimes(IgnoreOptions options) - { - using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedNames.Count.ShouldBe(4); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithOneField_VisitsOneField(IgnoreOptions options) - { - using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFields.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithTypeCondition_VisitsInlineFragmentOnce(IgnoreOptions options) - { - using var d = "{ ... on Stuff { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedInlineFragments.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_InlineFragmentWithTypeCondition_VisitsTypeConditionOnce(IgnoreOptions options) - { - using var d = "{ ... on Stuff { field } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFragmentTypeConditions.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_IntValueArgument_VisitsOneIntValue(IgnoreOptions options) - { - using var d = "{ stuff(id : 1) }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedIntValues.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinition_CallsVisitDefinitionOnce(IgnoreOptions options) - { - using var d = "{ a }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedDefinitions.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinition_ProvidesCorrectDefinitionAsParameter(IgnoreOptions options) - { - using var d = "{ a }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedDefinitions.Single().ShouldBe(d.Definitions.Single()); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinition_VisitsOneSelectionSet(IgnoreOptions options) - { - using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedSelectionSets.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinitionWithOneAliasedField_VisitsOneAlias(IgnoreOptions options) - { - using var d = "{ foo, foo : bar }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedAliases.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinitionWithOneArgument_VisitsOneArgument(IgnoreOptions options) - { - using var d = "{ foo(id : 1) { name } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedArguments.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_OneDefinitionWithOneNestedArgument_VisitsOneArgument(IgnoreOptions options) - { - using var d = "{ foo{ names(size: 10) } }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedArguments.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_StringValueArgument_VisitsOneStringValue(IgnoreOptions options) - { - using var d = "{ stuff(id : \"abc\") }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedStringValues.ShouldHaveSingleItem(); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoDefinitions_CallsVisitDefinitionTwice(IgnoreOptions options) - { - using var d = "{ a }\n{ b }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedDefinitions.Count.ShouldBe(2); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoFields_VisitsFieldTwice(IgnoreOptions options) - { - using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFields.Count.ShouldBe(2); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoFields_VisitsTwoFieldNames(IgnoreOptions options) - { - using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedNames.Count.ShouldBe(2); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoFields_VisitsTwoFieldNamesAndDefinitionName(IgnoreOptions options) - { - using var d = "query foo { a, b }".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedNames.Count.ShouldBe(3); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoFieldsWithOneNested_VisitsFiveFields(IgnoreOptions options) - { - using var d = "{a, nested { x, y }, b}".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedFields.Count.ShouldBe(5); - } - - [Theory] - [InlineData(IgnoreOptions.None)] - [InlineData(IgnoreOptions.Comments)] - [InlineData(IgnoreOptions.Locations)] - [InlineData(IgnoreOptions.All)] - public void Visit_TwoFieldsWithOneNested_VisitsFiveNames(IgnoreOptions options) - { - using var d = "{a, nested { x, y }, b}".Parse(new ParserOptions { Ignore = options }); - _visitor.Visit(d); - - _visitedNames.Count.ShouldBe(5); - } - - private List MockVisitMethod(Action visitorMethod) - { - var collection = new List(); - _visitor.WhenForAnyArgs(visitorMethod) - .Do(e => collection.Add(e.Arg())); - - return collection; - } - } -} diff --git a/src/GraphQLParser.Tests/GraphQLParser.Tests.csproj b/src/GraphQLParser.Tests/GraphQLParser.Tests.csproj index 2b115d04..d0063b08 100644 --- a/src/GraphQLParser.Tests/GraphQLParser.Tests.csproj +++ b/src/GraphQLParser.Tests/GraphQLParser.Tests.csproj @@ -19,7 +19,6 @@ - diff --git a/src/GraphQLParser.Tests/ParserTests.cs b/src/GraphQLParser.Tests/ParserTests.cs index 5fc91994..de7ed929 100644 --- a/src/GraphQLParser.Tests/ParserTests.cs +++ b/src/GraphQLParser.Tests/ParserTests.cs @@ -547,6 +547,25 @@ public void Parse_VariableInlineValues_DoesNotThrowError(IgnoreOptions options) } } + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Should_Read_Directives_on_VariableDefinition(IgnoreOptions options) + { + using (var document = "query A($id: String @a @b(priority: 1, managed: true)) { name }".Parse(new ParserOptions { Ignore = options })) + { + document.Definitions.Count.ShouldBe(1); + var def = document.Definitions[0].ShouldBeAssignableTo(); + def.VariableDefinitions.Count.ShouldBe(1); + def.VariableDefinitions[0].Directives.Count.ShouldBe(2); + def.VariableDefinitions[0].Directives[0].Name.Value.ShouldBe("a"); + def.VariableDefinitions[0].Directives[1].Name.Value.ShouldBe("b"); + def.VariableDefinitions[0].Directives[1].Arguments.Count.ShouldBe(2); + } + } + [Theory] [InlineData(IgnoreOptions.None)] [InlineData(IgnoreOptions.Comments)] diff --git a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs new file mode 100644 index 00000000..cf3fdc26 --- /dev/null +++ b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs @@ -0,0 +1,576 @@ +using System.Collections.Generic; +using System.Linq; +using GraphQLParser.AST; +using GraphQLParser.Visitors; +using Shouldly; +using Xunit; + +namespace GraphQLParser.Tests.Visitors +{ + public class GraphQLAstVisitorTests + { + public class CountVisitor : DefaultNodeVisitor + { + public override void VisitBooleanValue(GraphQLScalarValue booleanValue, CountContext context) + { + context.VisitedBooleanValues.Add(booleanValue); + base.VisitBooleanValue(booleanValue, context); + } + + public override void VisitIntValue(GraphQLScalarValue intValue, CountContext context) + { + context.VisitedIntValues.Add(intValue); + base.VisitIntValue(intValue, context); + } + + public override void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, CountContext context) + { + context.VisitedFragmentSpreads.Add(fragmentSpread); + base.VisitFragmentSpread(fragmentSpread, context); + } + + public override void VisitArgument(GraphQLArgument argument, CountContext context) + { + context.VisitedArguments.Add(argument); + base.VisitArgument(argument, context); + } + + public override void VisitVariable(GraphQLVariable variable, CountContext context) + { + context.VisitedVariables.Add(variable); + base.VisitVariable(variable, context); + } + + public override void VisitSelectionSet(GraphQLSelectionSet selectionSet, CountContext context) + { + context.VisitedSelectionSets.Add(selectionSet); + base.VisitSelectionSet(selectionSet, context); + } + + public override void VisitDirective(GraphQLDirective directive, CountContext context) + { + context.VisitedDirectives.Add(directive); + base.VisitDirective(directive, context); + } + + public override void VisitEnumValue(GraphQLScalarValue enumValue, CountContext context) + { + context.VisitedEnumValues.Add(enumValue); + base.VisitEnumValue(enumValue, context); + } + + public override void VisitStringValue(GraphQLScalarValue stringValue, CountContext context) + { + context.VisitedStringValues.Add(stringValue); + base.VisitStringValue(stringValue, context); + } + + public override void VisitName(GraphQLName name, CountContext context) + { + context.VisitedNames.Add(name); + base.VisitName(name, context); + } + + public override void VisitField(GraphQLField field, CountContext context) + { + context.VisitedFields.Add(field); + if (field.Alias != null) + context.VisitedAliases.Add(field.Alias); + base.VisitField(field, context); + } + + public override void VisitFloatValue(GraphQLScalarValue floatValue, CountContext context) + { + context.VisitedFloatValues.Add(floatValue); + base.VisitFloatValue(floatValue, context); + } + + public override void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(enumTypeDefinition); + base.VisitEnumTypeDefinition(enumTypeDefinition, context); + } + + public override void VisitInlineFragment(GraphQLInlineFragment inlineFragment, CountContext context) + { + context.VisitedInlineFragments.Add(inlineFragment); + context.VisitedFragmentTypeConditions.Add(inlineFragment.TypeCondition); + base.VisitInlineFragment(inlineFragment, context); + } + + public override void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, CountContext context) + { + context.VisitedFragmentDefinitions.Add(fragmentDefinition); + context.VisitedFragmentTypeConditions.Add(fragmentDefinition.TypeCondition); + base.VisitFragmentDefinition(fragmentDefinition, context); + } + + public override void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, CountContext context) + { + context.VisitedDefinitions.Add(fieldDefinition); + base.VisitFieldDefinition(fieldDefinition, context); + } + + public override void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, CountContext context) + { + context.VisitedDefinitions.Add(directiveDefinition); + base.VisitDirectiveDefinition(directiveDefinition, context); + } + + public override void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, CountContext context) + { + context.VisitedDefinitions.Add(enumValueDefinition); + base.VisitEnumValueDefinition(enumValueDefinition, context); + } + + public override void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(inputObjectTypeDefinition); + base.VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context); + } + + public override void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, CountContext context) + { + context.VisitedDefinitions.Add(inputValueDefinition); + base.VisitInputValueDefinition(inputValueDefinition, context); + } + + public override void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(interfaceTypeDefinition); + base.VisitInterfaceTypeDefinition(interfaceTypeDefinition, context); + } + + public override void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(objectTypeDefinition); + base.VisitObjectTypeDefinition(objectTypeDefinition, context); + } + + public override void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, CountContext context) + { + context.VisitedDefinitions.Add(operationDefinition); + base.VisitOperationDefinition(operationDefinition, context); + } + + public override void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(scalarTypeDefinition); + base.VisitScalarTypeDefinition(scalarTypeDefinition, context); + } + + public override void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(rootOperationTypeDefinition); + base.VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context); + } + + public override void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, CountContext context) + { + context.VisitedDefinitions.Add(variableDefinition); + base.VisitVariableDefinition(variableDefinition, context); + } + + public override void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, CountContext context) + { + context.VisitedDefinitions.Add(unionTypeDefinition); + base.VisitUnionTypeDefinition(unionTypeDefinition, context); + } + + public override void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, CountContext context) + { + context.VisitedDefinitions.Add(schemaDefinition); + base.VisitSchemaDefinition(schemaDefinition, context); + } + } + + public class CountContext : IVisitorContext + { + public List VisitedAliases = new(); + public List VisitedArguments = new(); + public List VisitedDefinitions = new(); + public List VisitedDirectives = new(); + public List VisitedEnumValues = new(); + public List VisitedFields = new(); + public List VisitedFloatValues = new(); + public List VisitedFragmentDefinitions = new(); + public List VisitedFragmentSpreads = new(); + public List VisitedFragmentTypeConditions = new(); + public List VisitedInlineFragments = new(); + public List VisitedIntValues = new(); + public List VisitedNames = new(); + public List VisitedSelectionSets = new(); + public List VisitedStringValues = new(); + public List VisitedVariables = new(); + public List VisitedBooleanValues = new(); + } + + private readonly CountVisitor _visitor = new(); + + public CountContext Context = new(); + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_BooleanValueArgument_VisitsOneBooleanValue(IgnoreOptions options) + { + using var d = "{ stuff(id : true) }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedBooleanValues.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_DefinitionWithSingleFragmentSpread_VisitsFragmentSpreadOneTime(IgnoreOptions options) + { + using var d = "{ foo { ...fragment } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFragmentSpreads.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_DefinitionWithSingleFragmentSpread_VisitsNameOfPropertyAndFragmentSpread(IgnoreOptions options) + { + using var d = "{ foo { ...fragment } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedNames.Count.ShouldBe(2); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_DirectiveWithVariable_VisitsVariableOnce(IgnoreOptions options) + { + using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedVariables.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_EnumValueArgument_VisitsOneEnumValue(IgnoreOptions options) + { + using var d = "{ stuff(id : TEST_ENUM) }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedEnumValues.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_FloatValueArgument_VisitsOneFloatValue(IgnoreOptions options) + { + using var d = "{ stuff(id : 1.2) }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFloatValues.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_FragmentWithTypeCondition_VisitsFragmentDefinitionOnce(IgnoreOptions options) + { + using var d = "fragment testFragment on Stuff { field }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFragmentDefinitions.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_FragmentWithTypeCondition_VisitsTypeConditionOnce(IgnoreOptions options) + { + using var d = "fragment testFragment on Stuff { field }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFragmentTypeConditions.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsArgumentsOnce(IgnoreOptions options) + { + using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedArguments.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsDirectiveOnce(IgnoreOptions options) + { + using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedDirectives.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithDirectiveAndArgument_VisitsNameThreeTimes(IgnoreOptions options) + { + using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedNames.Count.ShouldBe(4); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithOneField_VisitsOneField(IgnoreOptions options) + { + using var d = "{ ... @include(if : $stuff) { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFields.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithTypeCondition_VisitsInlineFragmentOnce(IgnoreOptions options) + { + using var d = "{ ... on Stuff { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedInlineFragments.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_InlineFragmentWithTypeCondition_VisitsTypeConditionOnce(IgnoreOptions options) + { + using var d = "{ ... on Stuff { field } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFragmentTypeConditions.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_IntValueArgument_VisitsOneIntValue(IgnoreOptions options) + { + using var d = "{ stuff(id : 1) }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedIntValues.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinition_CallsVisitDefinitionOnce(IgnoreOptions options) + { + using var d = "{ a }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedDefinitions.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinition_ProvidesCorrectDefinitionAsParameter(IgnoreOptions options) + { + using var d = "{ a }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedDefinitions.Single().ShouldBe(d.Definitions.Single()); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinition_VisitsOneSelectionSet(IgnoreOptions options) + { + using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedSelectionSets.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinitionWithOneAliasedField_VisitsOneAlias(IgnoreOptions options) + { + using var d = "{ foo, foo : bar }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedAliases.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinitionWithOneArgument_VisitsOneArgument(IgnoreOptions options) + { + using var d = "{ foo(id : 1) { name } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedArguments.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_OneDefinitionWithOneNestedArgument_VisitsOneArgument(IgnoreOptions options) + { + using var d = "{ foo{ names(size: 10) } }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedArguments.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_StringValueArgument_VisitsOneStringValue(IgnoreOptions options) + { + using var d = "{ stuff(id : \"abc\") }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedStringValues.ShouldHaveSingleItem(); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoDefinitions_CallsVisitDefinitionTwice(IgnoreOptions options) + { + using var d = "{ a }\n{ b }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedDefinitions.Count.ShouldBe(2); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoFields_VisitsFieldTwice(IgnoreOptions options) + { + using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFields.Count.ShouldBe(2); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoFields_VisitsTwoFieldNames(IgnoreOptions options) + { + using var d = "{ a, b }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedNames.Count.ShouldBe(2); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoFields_VisitsTwoFieldNamesAndDefinitionName(IgnoreOptions options) + { + using var d = "query foo { a, b }".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedNames.Count.ShouldBe(3); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoFieldsWithOneNested_VisitsFiveFields(IgnoreOptions options) + { + using var d = "{a, nested { x, y }, b}".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedFields.Count.ShouldBe(5); + } + + [Theory] + [InlineData(IgnoreOptions.None)] + [InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + [InlineData(IgnoreOptions.All)] + public void Visit_TwoFieldsWithOneNested_VisitsFiveNames(IgnoreOptions options) + { + using var d = "{a, nested { x, y }, b}".Parse(new ParserOptions { Ignore = options }); + _visitor.Visit(d, Context); + + Context.VisitedNames.Count.ShouldBe(5); + } + } +} diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs new file mode 100644 index 00000000..22a79260 --- /dev/null +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -0,0 +1,222 @@ +using System.Collections.Generic; +using System.IO; +using GraphQLParser.Visitors; +using Shouldly; +using Xunit; + +namespace GraphQLParser.Tests.Visitors +{ + public class SDLWriterTests + { + private class TestContext : IWriteContext + { + public TextWriter Writer { get; set; } = new StringWriter(); + + public Stack Parent { get; set; } = new Stack(); + } + + private static readonly SDLWriter _sdlWriter = new(); + + [Theory] + [InlineData(@"#comment +input Example @x { + self: [Example!]! + value: String = ""xyz"" +} +input B +input C +", +@"#comment +input Example @x +{ + self: [Example!]! + value: String = ""xyz"" +} + +input B + +input C +")] + [InlineData(@"query inlineFragmentTyping { + profiles(handles: [""zuck"", ""coca - cola""]) { + handle + ... on User { + friends { + count + } +} +... on Page +{ + likers + { + count + } +} + } +} +", @"query inlineFragmentTyping +{ + profiles(handles: [""zuck"", ""coca - cola""]) + { + handle + ... on User + { + friends + { + count + } + } + ... on Page + { + likers + { + count + } + } + } +} +")] + [InlineData(@"scalar a scalar b scalar c", @"scalar a + +scalar b + +scalar c +")] + [InlineData(@"{ + foo + #comment on fragment + ...Frag + qux +} + +fragment Frag on Query { + bar + baz +} +", + +@" +{ + foo + #comment on fragment + ...Frag + qux +} + +fragment Frag on Query +{ + bar + baz +} +")] + [InlineData(@"union Animal @immutable = |Cat | Dog", @"union Animal @immutable = Cat | Dog")] + [InlineData(@"schema @checked { mutation: MyMutation subscription: MySub }", @"schema @checked +{ + mutation: MyMutation + subscription: MySub +} +")] + [InlineData(@"interface Dog implements & Eat & Bark { volume: Int! }", + @"interface Dog implements Eat & Bark +{ + volume: Int! +} +")] + [InlineData(@"enum Color { RED, +#good color +GREEN @directive(list: [1,2,3,null,{}, {name:""tom"" age:42}]), +"""""" +another good color +"""""" +BLUE }", @"enum Color +{ + RED + #good color + GREEN @directive(list: [1, 2, 3, null, { }, { name: ""tom"", age: 42 }]) + """""" + another good color + """""" + BLUE +} +")] + [InlineData(@"# super query +# +# multiline +query summary($id: ID!) { name(full:true,kind: UPPER) age1:age address { street @short(length:5,x:""a"", pi: 3.14) +#need +building } }", + +@"# super query +# +# multiline +query summary($id: ID!) +{ + name(full: true, kind: UPPER) + age1: age + address + { + street @short(length: 5, x: ""a"", pi: 3.14) + #need + building + } +} +")] + [InlineData(@" +"""""" + description + indent 2 + indent4 +"""""" +scalar JSON @exportable +# A dog +type Dog implements &Animal { + """"""inline docs"""""" + volume: Float + """""" + multiline + docs + """""" + friends: [Dog!] + age: Int! +}", + +@""""""" +description + indent 2 + indent4 +"""""" +scalar JSON @exportable + +# A dog +type Dog implements Animal +{ + """""" + inline docs + """""" + volume: Float + """""" + multiline + docs + """""" + friends: [Dog!] + age: Int! +} +")] + public void WriteDocumentVisitor_Should_Print_Document(string text, string expected) + { + var context = new TestContext(); + + using (var document = text.Parse()) + { + _sdlWriter.Visit(document, context); + var actual = context.Writer.ToString(); + actual.ShouldBe(expected); + + using (var parsedBack = actual.Parse()) + { + // should be parsed back + } + } + } + } +} diff --git a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs new file mode 100644 index 00000000..daccaefc --- /dev/null +++ b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.IO; +using GraphQLParser.Visitors; +using Shouldly; +using Xunit; + +namespace GraphQLParser.Tests.Visitors +{ + public class StructureWriterTests + { + private class TestContext : IWriteContext + { + public TextWriter Writer { get; set; } = new StringWriter(); + + public Stack Parent { get; set; } = new Stack(); + } + + private static readonly StructureWriter _structWriter = new(); + + [Theory] + [InlineData("query a { name age }", @"Document + OperationDefinition + Name + SelectionSet + Field + Name + Field + Name +")] + [InlineData("scalar JSON @exportable", @"Document + ScalarTypeDefinition + Name + Directive + Name +")] + public void WriteTreeVisitor_Should_Print_Tree(string text, string expected) + { + var context = new TestContext(); + + using (var document = text.Parse()) + { + _structWriter.Visit(document, context); + var actual = context.Writer.ToString(); + actual.ShouldBe(expected); + } + } + } +} diff --git a/src/GraphQLParser/AST/GraphQLDirective.cs b/src/GraphQLParser/AST/GraphQLDirective.cs index a20d5279..69c52985 100644 --- a/src/GraphQLParser/AST/GraphQLDirective.cs +++ b/src/GraphQLParser/AST/GraphQLDirective.cs @@ -5,7 +5,7 @@ namespace GraphQLParser.AST /// /// Represents a directive, applied to some GraphQL element. /// - public class GraphQLDirective : ASTNode, INamedNode + public class GraphQLDirective : ASTNode, INamedNode, IHasArgumentsNode { public List? Arguments { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLField.cs b/src/GraphQLParser/AST/GraphQLField.cs index 993e8c63..b6085e89 100644 --- a/src/GraphQLParser/AST/GraphQLField.cs +++ b/src/GraphQLParser/AST/GraphQLField.cs @@ -2,7 +2,7 @@ namespace GraphQLParser.AST { - public class GraphQLField : ASTNode, IHasDirectivesNode, INamedNode + public class GraphQLField : ASTNode, IHasDirectivesNode, IHasArgumentsNode, INamedNode { public GraphQLName? Alias { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs index 2132c513..f5437cca 100644 --- a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs @@ -2,7 +2,7 @@ namespace GraphQLParser.AST { - public class GraphQLInterfaceTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode + public class GraphQLInterfaceTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode, IHasInterfacesNode { /// public List? Directives { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs index 5a55d18e..47870982 100644 --- a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs @@ -2,7 +2,7 @@ namespace GraphQLParser.AST { - public class GraphQLObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode + public class GraphQLObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode, IHasInterfacesNode { /// public List? Directives { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs index 2da67930..2e6f1c09 100644 --- a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs @@ -1,15 +1,20 @@ +using System.Collections.Generic; + namespace GraphQLParser.AST { - public class GraphQLVariableDefinition : ASTNode + public class GraphQLVariableDefinition : ASTNode, IHasDirectivesNode { - public object? DefaultValue { get; set; } - /// public override ASTNodeKind Kind => ASTNodeKind.VariableDefinition; + public GraphQLValue? DefaultValue { get; set; } + public GraphQLType? Type { get; set; } public GraphQLVariable? Variable { get; set; } + + /// + public List? Directives { get; set; } } internal sealed class GraphQLVariableDefinitionWithLocation : GraphQLVariableDefinition diff --git a/src/GraphQLParser/AST/IHasArgumentsNode.cs b/src/GraphQLParser/AST/IHasArgumentsNode.cs new file mode 100644 index 00000000..612e0e7e --- /dev/null +++ b/src/GraphQLParser/AST/IHasArgumentsNode.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace GraphQLParser.AST +{ + /// + /// Represents an AST node that may have arguments. + /// + public interface IHasArgumentsNode + { + /// + /// Arguments of the node represented as a list of nested nodes. + /// + List? Arguments { get; set; } + } +} diff --git a/src/GraphQLParser/AST/IHasInterfacesNode.cs b/src/GraphQLParser/AST/IHasInterfacesNode.cs new file mode 100644 index 00000000..294d7595 --- /dev/null +++ b/src/GraphQLParser/AST/IHasInterfacesNode.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace GraphQLParser.AST +{ + /// + /// Represents an AST node that may implement interfaces. + /// + public interface IHasInterfacesNode + { + /// + /// Implemented interfaces of the node represented as a list of nested nodes. + /// + List? Interfaces { get; set; } + } +} diff --git a/src/GraphQLParser/GraphQLAstVisitor.cs b/src/GraphQLParser/GraphQLAstVisitor.cs deleted file mode 100644 index 089709d3..00000000 --- a/src/GraphQLParser/GraphQLAstVisitor.cs +++ /dev/null @@ -1,264 +0,0 @@ -using System; -using System.Collections.Generic; -using GraphQLParser.AST; - -namespace GraphQLParser -{ - public class GraphQLAstVisitor // TODO: not used - { - protected IDictionary Fragments { get; private set; } - - public GraphQLAstVisitor() - { - Fragments = new Dictionary(); - } - - public virtual GraphQLName BeginVisitAlias(GraphQLName alias) => alias; - - public virtual GraphQLArgument BeginVisitArgument(GraphQLArgument argument) - { - if (argument.Name != null) - BeginVisitNode(argument.Name); - - if (argument.Value != null) - BeginVisitNode(argument.Value); - - return EndVisitArgument(argument); - } - - public virtual IEnumerable BeginVisitArguments(IEnumerable arguments) - { - foreach (var argument in arguments) - BeginVisitNode(argument); - - return arguments; - } - - public virtual GraphQLScalarValue BeginVisitBooleanValue(GraphQLScalarValue value) => value; - - public virtual GraphQLDirective BeginVisitDirective(GraphQLDirective directive) - { - if (directive.Name != null) - BeginVisitNode(directive.Name); - - if (directive.Arguments != null) - BeginVisitArguments(directive.Arguments); - - return directive; - } - - public virtual IEnumerable BeginVisitDirectives(IEnumerable directives) - { - foreach (var directive in directives) - BeginVisitNode(directive); - - return directives; - } - - public virtual GraphQLScalarValue BeginVisitEnumValue(GraphQLScalarValue value) => value; - - public virtual GraphQLField BeginVisitField(GraphQLField selection) - { - BeginVisitNode(selection.Name); - - if (selection.Alias != null) - BeginVisitAlias((GraphQLName)BeginVisitNode(selection.Alias)!); - - if (selection.Arguments != null) - BeginVisitArguments(selection.Arguments); - - if (selection.SelectionSet != null) - BeginVisitNode(selection.SelectionSet); - - if (selection.Directives != null) - BeginVisitDirectives(selection.Directives); - - return EndVisitField(selection); - } - - public virtual GraphQLScalarValue BeginVisitFloatValue(GraphQLScalarValue value) => value; - - public virtual GraphQLFragmentDefinition BeginVisitFragmentDefinition(GraphQLFragmentDefinition node) - { - BeginVisitNode(node.TypeCondition); - BeginVisitNode(node.Name); - - if (node.SelectionSet != null) - BeginVisitNode(node.SelectionSet); - - return node; - } - - public virtual GraphQLFragmentSpread BeginVisitFragmentSpread(GraphQLFragmentSpread fragmentSpread) - { - BeginVisitNode(fragmentSpread.Name); - return fragmentSpread; - } - - public virtual GraphQLInlineFragment BeginVisitInlineFragment(GraphQLInlineFragment inlineFragment) - { - if (inlineFragment.TypeCondition != null) - BeginVisitNode(inlineFragment.TypeCondition); - - if (inlineFragment.Directives != null) - BeginVisitDirectives(inlineFragment.Directives); - - if (inlineFragment.SelectionSet != null) - BeginVisitSelectionSet(inlineFragment.SelectionSet); - - return inlineFragment; - } - - public virtual GraphQLScalarValue BeginVisitIntValue(GraphQLScalarValue value) => value; - - public virtual GraphQLName BeginVisitName(GraphQLName name) => name; - - public virtual GraphQLNamedType BeginVisitNamedType(GraphQLNamedType typeCondition) => typeCondition; - - public virtual ASTNode? BeginVisitNode(ASTNode? node) => node?.Kind switch - { - ASTNodeKind.OperationDefinition => BeginVisitOperationDefinition((GraphQLOperationDefinition)node), - ASTNodeKind.SelectionSet => BeginVisitSelectionSet((GraphQLSelectionSet)node), - ASTNodeKind.Field => BeginVisitNonIntrospectionField((GraphQLField)node), - ASTNodeKind.Name => BeginVisitName((GraphQLName)node), - ASTNodeKind.Argument => BeginVisitArgument((GraphQLArgument)node), - ASTNodeKind.FragmentSpread => BeginVisitFragmentSpread((GraphQLFragmentSpread)node), - ASTNodeKind.FragmentDefinition => BeginVisitFragmentDefinition((GraphQLFragmentDefinition)node), - ASTNodeKind.InlineFragment => BeginVisitInlineFragment((GraphQLInlineFragment)node), - ASTNodeKind.NamedType => BeginVisitNamedType((GraphQLNamedType)node), - ASTNodeKind.Directive => BeginVisitDirective((GraphQLDirective)node), - ASTNodeKind.Variable => BeginVisitVariable((GraphQLVariable)node), - ASTNodeKind.IntValue => BeginVisitIntValue((GraphQLScalarValue)node), - ASTNodeKind.FloatValue => BeginVisitFloatValue((GraphQLScalarValue)node), - ASTNodeKind.StringValue => BeginVisitStringValue((GraphQLScalarValue)node), - ASTNodeKind.BooleanValue => BeginVisitBooleanValue((GraphQLScalarValue)node), - ASTNodeKind.EnumValue => BeginVisitEnumValue((GraphQLScalarValue)node), - ASTNodeKind.ListValue => BeginVisitListValue((GraphQLListValue)node), - ASTNodeKind.ObjectValue => BeginVisitObjectValue((GraphQLObjectValue)node), - ASTNodeKind.ObjectField => BeginVisitObjectField((GraphQLObjectField)node), - ASTNodeKind.VariableDefinition => BeginVisitVariableDefinition((GraphQLVariableDefinition)node), - _ => null - }; - - public virtual GraphQLOperationDefinition BeginVisitOperationDefinition(GraphQLOperationDefinition definition) - { - if (definition.Name != null) - BeginVisitNode(definition.Name); - - if (definition.VariableDefinitions != null) - BeginVisitVariableDefinitions(definition.VariableDefinitions); - - BeginVisitNode(definition.SelectionSet); - - return EndVisitOperationDefinition(definition); - } - - public virtual GraphQLOperationDefinition EndVisitOperationDefinition(GraphQLOperationDefinition definition) => definition; - - public virtual GraphQLSelectionSet BeginVisitSelectionSet(GraphQLSelectionSet selectionSet) - { - if (selectionSet.Selections != null) - { - foreach (var selection in selectionSet.Selections) - BeginVisitNode(selection); - } - - return selectionSet; - } - - public virtual GraphQLScalarValue BeginVisitStringValue(GraphQLScalarValue value) => value; - - public virtual GraphQLVariable BeginVisitVariable(GraphQLVariable variable) - { - if (variable.Name != null) - BeginVisitNode(variable.Name); - - return EndVisitVariable(variable); - } - - public virtual GraphQLVariableDefinition BeginVisitVariableDefinition(GraphQLVariableDefinition node) - { - BeginVisitNode(node.Type); - - return node; - } - - public virtual IEnumerable BeginVisitVariableDefinitions(IEnumerable variableDefinitions) - { - foreach (var definition in variableDefinitions) - BeginVisitNode(definition); - - return variableDefinitions; - } - - public virtual GraphQLArgument EndVisitArgument(GraphQLArgument argument) => argument; - - public virtual GraphQLField EndVisitField(GraphQLField selection) => selection; - - public virtual GraphQLVariable EndVisitVariable(GraphQLVariable variable) => variable; - - public virtual void Visit(GraphQLDocument ast) - { - if (ast.Definitions != null) - { - foreach (var definition in ast.Definitions) - { - if (definition.Kind == ASTNodeKind.FragmentDefinition) - { - var fragment = (GraphQLFragmentDefinition)definition; - string? name = fragment.Name?.Value.ToString(); // TODO: heap allocation - if (name == null) - throw new InvalidOperationException("Fragment name cannot be null"); - - Fragments.Add(name, fragment); - } - } - - foreach (var definition in ast.Definitions) - { - BeginVisitNode(definition); - } - } - } - - public virtual GraphQLObjectField BeginVisitObjectField(GraphQLObjectField node) - { - BeginVisitNode(node.Name); - - BeginVisitNode(node.Value); - - return node; - } - - public virtual GraphQLObjectValue BeginVisitObjectValue(GraphQLObjectValue node) - { - if (node.Fields != null) - { - foreach (var field in node.Fields) - BeginVisitNode(field); - } - - return EndVisitObjectValue(node); - } - - public virtual GraphQLObjectValue EndVisitObjectValue(GraphQLObjectValue node) => node; - - public virtual GraphQLListValue EndVisitListValue(GraphQLListValue node) => node; - - private ASTNode BeginVisitListValue(GraphQLListValue node) - { - if (node.Values != null) - { - foreach (var value in node.Values) - BeginVisitNode(value); - } - - return EndVisitListValue(node); - } - - private ASTNode BeginVisitNonIntrospectionField(GraphQLField selection) - { - return BeginVisitField(selection); - } - } -} diff --git a/src/GraphQLParser/ParserContext.Parse.cs b/src/GraphQLParser/ParserContext.Parse.cs index 0b965a51..21cf11d6 100644 --- a/src/GraphQLParser/ParserContext.Parse.cs +++ b/src/GraphQLParser/ParserContext.Parse.cs @@ -1149,6 +1149,7 @@ private GraphQLVariableDefinition ParseVariableDefinition() def.Type = ParseType(); def.DefaultValue = Skip(TokenKind.EQUALS) ? ParseValueLiteral(true) : null; + def.Directives = ParseDirectives(); def.Comment = comment; def.Location = GetLocation(start); return def; diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs new file mode 100644 index 00000000..f2f0e332 --- /dev/null +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -0,0 +1,509 @@ +using System; +using System.Collections.Generic; +using GraphQLParser.AST; + +namespace GraphQLParser.Visitors +{ + /// + /// Default implementation of . + /// Traverses all AST nodes of the provided one. + /// + /// Type of the context object passed into all VisitXXX methods. + public class DefaultNodeVisitor : INodeVisitor + where TContext : IVisitorContext + { + /// + public virtual void VisitDocument(GraphQLDocument document, TContext context) + { + Visit(document.Definitions, context); + } + + /// + public virtual void VisitArgument(GraphQLArgument argument, TContext context) + { + Visit(argument.Comment, context); + Visit(argument.Name, context); + Visit(argument.Value, context); + } + + /// + public virtual void VisitComment(GraphQLComment comment, TContext context) + { + } + + /// + public virtual void VisitDescription(GraphQLDescription description, TContext context) + { + } + + /// + public virtual void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) + { + Visit(operationDefinition.Comment, context); + Visit(operationDefinition.Name, context); + Visit(operationDefinition.VariableDefinitions, context); + Visit(operationDefinition.Directives, context); + Visit(operationDefinition.SelectionSet, context); + } + + /// + public virtual void VisitName(GraphQLName name, TContext context) + { + Visit(name.Comment, context); + } + + /// + public virtual void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) + { + Visit(variableDefinition.Comment, context); + Visit(variableDefinition.Variable, context); + Visit(variableDefinition.Type, context); + Visit(variableDefinition.DefaultValue, context); + Visit(variableDefinition.Directives, context); + } + + /// + public virtual void VisitVariable(GraphQLVariable variable, TContext context) + { + Visit(variable.Comment, context); + Visit(variable.Name, context); + } + + /// + public virtual void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) + { + Visit(selectionSet.Comment, context); + Visit(selectionSet.Selections, context); + } + + /// + public virtual void VisitField(GraphQLField field, TContext context) + { + Visit(field.Comment, context); + Visit(field.Alias, context); + Visit(field.Name, context); + Visit(field.Arguments, context); + Visit(field.Directives, context); + Visit(field.SelectionSet, context); + } + + /// + public virtual void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) + { + Visit(fragmentSpread.Comment, context); + Visit(fragmentSpread.Name, context); + Visit(fragmentSpread.Directives, context); + } + + /// + public virtual void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) + { + Visit(inlineFragment.Comment, context); + Visit(inlineFragment.TypeCondition, context); + Visit(inlineFragment.Directives, context); + Visit(inlineFragment.SelectionSet, context); + } + + /// + public virtual void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) + { + Visit(fragmentDefinition.Comment, context); + Visit(fragmentDefinition.Name, context); + Visit(fragmentDefinition.TypeCondition, context); + Visit(fragmentDefinition.Directives, context); + Visit(fragmentDefinition.SelectionSet, context); + } + + /// + public virtual void VisitIntValue(GraphQLScalarValue intValue, TContext context) + { + Visit(intValue.Comment, context); + } + + /// + public virtual void VisitFloatValue(GraphQLScalarValue floatValue, TContext context) + { + Visit(floatValue.Comment, context); + } + + /// + public virtual void VisitStringValue(GraphQLScalarValue stringValue, TContext context) + { + Visit(stringValue.Comment, context); + } + + /// + public virtual void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) + { + Visit(booleanValue.Comment, context); + } + + /// + public virtual void VisitEnumValue(GraphQLScalarValue enumValue, TContext context) + { + Visit(enumValue.Comment, context); + } + + /// + public virtual void VisitListValue(GraphQLListValue listValue, TContext context) + { + Visit(listValue.Comment, context); + Visit(listValue.Values, context); + } + + /// + public virtual void VisitObjectValue(GraphQLObjectValue objectValue, TContext context) + { + Visit(objectValue.Comment, context); + Visit(objectValue.Fields, context); + } + + /// + public virtual void VisitObjectField(GraphQLObjectField objectField, TContext context) + { + Visit(objectField.Comment, context); + Visit(objectField.Name, context); + Visit(objectField.Value, context); + } + + /// + public virtual void VisitDirective(GraphQLDirective directive, TContext context) + { + Visit(directive.Comment, context); + Visit(directive.Name, context); + Visit(directive.Arguments, context); + } + + /// + public virtual void VisitNamedType(GraphQLNamedType namedType, TContext context) + { + Visit(namedType.Comment, context); + Visit(namedType.Name, context); + } + + /// + public virtual void VisitListType(GraphQLListType listType, TContext context) + { + Visit(listType.Comment, context); + Visit(listType.Type, context); + } + + /// + public virtual void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) + { + Visit(nonNullType.Comment, context); + Visit(nonNullType.Type, context); + } + + /// + public virtual void VisitNullValue(GraphQLScalarValue nullValue, TContext context) + { + Visit(nullValue.Comment, context); + } + + /// + public virtual void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) + { + Visit(schemaDefinition.Comment, context); + Visit(schemaDefinition.Description, context); + Visit(schemaDefinition.Directives, context); + Visit(schemaDefinition.OperationTypes, context); + } + + /// + public virtual void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) + { + Visit(rootOperationTypeDefinition.Comment, context); + Visit(rootOperationTypeDefinition.Type, context); + } + + /// + public virtual void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) + { + Visit(scalarTypeDefinition.Comment, context); + Visit(scalarTypeDefinition.Description, context); + Visit(scalarTypeDefinition.Name, context); + Visit(scalarTypeDefinition.Directives, context); + } + + /// + public virtual void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) + { + Visit(objectTypeDefinition.Comment, context); + Visit(objectTypeDefinition.Description, context); + Visit(objectTypeDefinition.Name, context); + Visit(objectTypeDefinition.Interfaces, context); + Visit(objectTypeDefinition.Directives, context); + Visit(objectTypeDefinition.Fields, context); + } + + /// + public virtual void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) + { + Visit(fieldDefinition.Comment, context); + Visit(fieldDefinition.Description, context); + Visit(fieldDefinition.Name, context); + Visit(fieldDefinition.Arguments, context); + Visit(fieldDefinition.Type, context); + Visit(fieldDefinition.Directives, context); + } + + /// + public virtual void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) + { + Visit(inputValueDefinition.Comment, context); + Visit(inputValueDefinition.Description, context); + Visit(inputValueDefinition.Name, context); + Visit(inputValueDefinition.Type, context); + Visit(inputValueDefinition.DefaultValue, context); + Visit(inputValueDefinition.Directives, context); + } + + /// + public virtual void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) + { + Visit(interfaceTypeDefinition.Comment, context); + Visit(interfaceTypeDefinition.Description, context); + Visit(interfaceTypeDefinition.Name, context); + Visit(interfaceTypeDefinition.Interfaces, context); + Visit(interfaceTypeDefinition.Directives, context); + Visit(interfaceTypeDefinition.Fields, context); + } + + /// + public virtual void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) + { + Visit(unionTypeDefinition.Comment, context); + Visit(unionTypeDefinition.Description, context); + Visit(unionTypeDefinition.Name, context); + Visit(unionTypeDefinition.Directives, context); + Visit(unionTypeDefinition.Types, context); + } + + /// + public virtual void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) + { + Visit(enumTypeDefinition.Comment, context); + Visit(enumTypeDefinition.Description, context); + Visit(enumTypeDefinition.Name, context); + Visit(enumTypeDefinition.Directives, context); + Visit(enumTypeDefinition.Values, context); + } + + /// + public virtual void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) + { + Visit(enumValueDefinition.Comment, context); + Visit(enumValueDefinition.Description, context); + Visit(enumValueDefinition.Name, context); + Visit(enumValueDefinition.Directives, context); + } + + /// + public virtual void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) + { + Visit(inputObjectTypeDefinition.Comment, context); + Visit(inputObjectTypeDefinition.Description, context); + Visit(inputObjectTypeDefinition.Name, context); + Visit(inputObjectTypeDefinition.Directives, context); + Visit(inputObjectTypeDefinition.Fields, context); + } + + /// + public virtual void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) + { + Visit(directiveDefinition.Comment, context); + Visit(directiveDefinition.Description, context); + Visit(directiveDefinition.Name, context); + Visit(directiveDefinition.Arguments, context); + } + + /// + /// Dispatches node to the appropriate VisitXXX method. + /// + /// AST node to dispatch. + /// Context passed into all INodeVisitor.VisitXXX methods. + public virtual void Visit(ASTNode? node, TContext context) + { + if (node == null) + return; + + switch (node) + { + case GraphQLArgument argument: + VisitArgument(argument, context); + break; + + case GraphQLComment comment: + VisitComment(comment, context); + break; + + case GraphQLDescription description: + VisitDescription(description, context); + break; + + case GraphQLDirective directive: + VisitDirective(directive, context); + break; + + case GraphQLDirectiveDefinition directiveDefinition: + VisitDirectiveDefinition(directiveDefinition, context); + break; + + case GraphQLDocument document: + VisitDocument(document, context); + break; + + case GraphQLEnumTypeDefinition enumTypeDefinition: + VisitEnumTypeDefinition(enumTypeDefinition, context); + break; + + case GraphQLEnumValueDefinition enumValueDefinition: + VisitEnumValueDefinition(enumValueDefinition, context); + break; + + case GraphQLField field: + VisitField(field, context); + break; + + case GraphQLFieldDefinition fieldDefinition: + VisitFieldDefinition(fieldDefinition, context); + break; + + case GraphQLFragmentDefinition fragmentDefinition: + VisitFragmentDefinition(fragmentDefinition, context); + break; + + case GraphQLFragmentSpread fragmentSpread: + VisitFragmentSpread(fragmentSpread, context); + break; + + case GraphQLInlineFragment inlineFragment: + VisitInlineFragment(inlineFragment, context); + break; + + case GraphQLInputObjectTypeDefinition inputObjectTypeDefinition: + VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context); + break; + + case GraphQLInputValueDefinition inputValueDefinition: + VisitInputValueDefinition(inputValueDefinition, context); + break; + + case GraphQLInterfaceTypeDefinition interfaceTypeDefinition: + VisitInterfaceTypeDefinition(interfaceTypeDefinition, context); + break; + + case GraphQLListType listType: + VisitListType(listType, context); + break; + + case GraphQLListValue listValue: + VisitListValue(listValue, context); + break; + + case GraphQLName name: + VisitName(name, context); + break; + + case GraphQLNamedType namedType: + VisitNamedType(namedType, context); + break; + + case GraphQLNonNullType nonNullType: + VisitNonNullType(nonNullType, context); + break; + + case GraphQLObjectField objectField: + VisitObjectField(objectField, context); + break; + + case GraphQLObjectTypeDefinition objectTypeDefinition: + VisitObjectTypeDefinition(objectTypeDefinition, context); + break; + + case GraphQLObjectValue objectValue: + VisitObjectValue(objectValue, context); + break; + + case GraphQLOperationDefinition operationDefinition: + VisitOperationDefinition(operationDefinition, context); + break; + + case GraphQLRootOperationTypeDefinition rootOperationTypeDefinition: + VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context); + break; + + case GraphQLScalarTypeDefinition scalarTypeDefinition: + VisitScalarTypeDefinition(scalarTypeDefinition, context); + break; + + case GraphQLScalarValue scalarValue: + switch (scalarValue.Kind) + { + case ASTNodeKind.BooleanValue: + VisitBooleanValue(scalarValue, context); + break; + + case ASTNodeKind.EnumValue: + VisitEnumValue(scalarValue, context); + break; + + case ASTNodeKind.FloatValue: + VisitFloatValue(scalarValue, context); + break; + + case ASTNodeKind.IntValue: + VisitIntValue(scalarValue, context); + break; + + case ASTNodeKind.NullValue: + VisitNullValue(scalarValue, context); + break; + + case ASTNodeKind.StringValue: + VisitStringValue(scalarValue, context); + break; + + default: + throw new NotSupportedException($"Unknown GraphQLScalarValue of kind '{scalarValue.Kind}'."); + } + break; + + case GraphQLSchemaDefinition schemaDefinition: + VisitSchemaDefinition(schemaDefinition, context); + break; + + case GraphQLSelectionSet selectionSet: + VisitSelectionSet(selectionSet, context); + break; + + // case GraphQLTypeExtensionDefinition n => VisitTypeDE + case GraphQLUnionTypeDefinition unionTypeDefinition: + VisitUnionTypeDefinition(unionTypeDefinition, context); + break; + + case GraphQLVariable variable: + VisitVariable(variable, context); + break; + + case GraphQLVariableDefinition variableDefinition: + VisitVariableDefinition(variableDefinition, context); + break; + + default: + throw new NotSupportedException($"Unknown node '{node.GetType().Name}'."); + }; + } + + protected void Visit(List? nodes, TContext context) + where T : ASTNode + { + if (nodes != null) + { + foreach (var node in nodes) + Visit(node, context); + } + } + } +} diff --git a/src/GraphQLParser/Visitors/INodeVisitor.cs b/src/GraphQLParser/Visitors/INodeVisitor.cs new file mode 100644 index 00000000..c25857bb --- /dev/null +++ b/src/GraphQLParser/Visitors/INodeVisitor.cs @@ -0,0 +1,207 @@ +using GraphQLParser.AST; + +namespace GraphQLParser.Visitors +{ + /// + /// Visitor which methods are called when traversing AST. + /// Type of the context object passed into all VisitXXX methods. + /// + public interface INodeVisitor + where TContext : IVisitorContext + { + /// + /// Visits node. + /// + void VisitName(GraphQLName name, TContext context); + + /// + /// Visits node. + /// + void VisitDocument(GraphQLDocument document, TContext context); + + /// + /// Visits node. + /// + void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitVariable(GraphQLVariable variable, TContext context); + + /// + /// Visits node. + /// + void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context); + + /// + /// Visits node. + /// + void VisitField(GraphQLField field, TContext context); + + /// + /// Visits node. + /// + void VisitArgument(GraphQLArgument argument, TContext context); + + /// + /// Visits node. + /// + void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context); + + /// + /// Visits node. + /// + void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context); + + /// + /// Visits node. + /// + void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitIntValue(GraphQLScalarValue intValue, TContext context); + + /// + /// Visits node. + /// + void VisitFloatValue(GraphQLScalarValue floatValue, TContext context); + + /// + /// Visits node. + /// + void VisitStringValue(GraphQLScalarValue stringValue, TContext context); + + /// + /// Visits node. + /// + void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context); + + /// + /// Visits node. + /// + void VisitEnumValue(GraphQLScalarValue enumValue, TContext context); + + /// + /// Visits node. + /// + void VisitListValue(GraphQLListValue listValue, TContext context); + + /// + /// Visits node. + /// + void VisitObjectValue(GraphQLObjectValue objectValue, TContext context); + + /// + /// Visits node. + /// + void VisitObjectField(GraphQLObjectField objectField, TContext context); + + /// + /// Visits node. + /// + void VisitDirective(GraphQLDirective directive, TContext context); + + /// + /// Visits node. + /// + void VisitNamedType(GraphQLNamedType namedType, TContext context); + + /// + /// Visits node. + /// + void VisitListType(GraphQLListType listType, TContext context); + + /// + /// Visits node. + /// + void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context); + + /// + /// Visits node. + /// + void VisitNullValue(GraphQLScalarValue nullValue, TContext context); + + /// + /// Visits node. + /// + void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); + + // + // Visits node. + // + //void VisitTypeExtensionDefinition(); //TODO + + /// + /// Visits node. + /// + void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context); + + /// + /// Visits node. + /// + void VisitComment(GraphQLComment comment, TContext context); + + /// + /// Visits node. + /// + void VisitDescription(GraphQLDescription description, TContext context); + } +} diff --git a/src/GraphQLParser/Visitors/IVisitorContext.cs b/src/GraphQLParser/Visitors/IVisitorContext.cs new file mode 100644 index 00000000..256f9fd1 --- /dev/null +++ b/src/GraphQLParser/Visitors/IVisitorContext.cs @@ -0,0 +1,9 @@ +namespace GraphQLParser.Visitors +{ + /// + /// Context passed into all INodeVisitor.VisitXXX methods. + /// + public interface IVisitorContext + { + } +} diff --git a/src/GraphQLParser/Visitors/IWriteContext.cs b/src/GraphQLParser/Visitors/IWriteContext.cs new file mode 100644 index 00000000..9e2f132e --- /dev/null +++ b/src/GraphQLParser/Visitors/IWriteContext.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.IO; + +namespace GraphQLParser.Visitors +{ + public interface IWriteContext : IVisitorContext + { + TextWriter Writer { get; } + + Stack Parent { get; } + } +} diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs new file mode 100644 index 00000000..dbd581b1 --- /dev/null +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -0,0 +1,753 @@ +using System.Collections.Generic; +using System.IO; +using GraphQLParser.AST; + +namespace GraphQLParser.Visitors +{ + /// + /// Prints AST into the provided as a SDL document. + /// + /// Type of the context object passed into all VisitXXX methods. + public class SDLWriter : DefaultNodeVisitor + where TContext : IWriteContext + { + /// + public override void VisitDocument(GraphQLDocument document, TContext context) + { + if (document.Definitions?.Count > 0) + { + for (int i = 0; i < document.Definitions.Count; ++i) + { + Visit(document.Definitions[i], context); + + if (i < document.Definitions.Count - 1) + { + context.Writer.WriteLine(); + } + } + } + } + + /// + public override void VisitComment(GraphQLComment comment, TContext context) + { + int level = GetLevel(context); + + bool needStartNewLine = true; + var span = comment.Text.Span; + for (int i = 0; i < span.Length; ++i) + { + if (needStartNewLine) + { + WriteIndent(context, level); + context.Writer.Write('#'); + needStartNewLine = false; + } + + switch (span[i]) + { + case '\r': + break; + + case '\n': + context.Writer.WriteLine(); + needStartNewLine = true; + break; + + default: + context.Writer.Write(span[i]); + break; + } + } + + context.Writer.WriteLine(); + } + + /// + public override void VisitDescription(GraphQLDescription description, TContext context) + { + int level = GetLevel(context); + + WriteIndent(context, level); + context.Writer.Write("\"\"\""); + context.Writer.WriteLine(); + + bool needStartNewLine = true; + var span = description.Value.Span; + for (int i = 0; i < span.Length; ++i) + { + if (needStartNewLine) + { + WriteIndent(context, level); + needStartNewLine = false; + } + + switch (span[i]) + { + case '\r': + break; + + case '\n': + context.Writer.WriteLine(); + needStartNewLine = true; + break; + + default: + context.Writer.Write(span[i]); + break; + } + } + + context.Writer.WriteLine(); + WriteIndent(context, level); + context.Writer.Write("\"\"\""); + context.Writer.WriteLine(); + } + + /// + public override void VisitName(GraphQLName name, TContext context) + { + Visit(name.Comment, context); + Write(context, name.Value); + } + + /// + public override void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) + { + Visit(fragmentDefinition.Comment, context); + context.Writer.Write("fragment "); + Visit(fragmentDefinition.Name, context); + context.Writer.Write(" on "); + Visit(fragmentDefinition.TypeCondition, context); + VisitDirectives(fragmentDefinition, context); + Visit(fragmentDefinition.SelectionSet, context); + } + + /// + public override void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) + { + Visit(fragmentSpread.Comment, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + context.Writer.Write("..."); + Visit(fragmentSpread.Name, context); + VisitDirectives(fragmentSpread, context); + context.Writer.WriteLine(); + } + + /// + public override void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) + { + Visit(inlineFragment.Comment, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + context.Writer.Write("... on "); + Visit(inlineFragment.TypeCondition, context); + VisitDirectives(inlineFragment, context); + Visit(inlineFragment.SelectionSet, context); + } + + /// + public override void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) + { + Visit(selectionSet.Comment, context); + context.Writer.WriteLine(); + int level = GetLevel(context); + WriteIndent(context, level); + context.Writer.WriteLine('{'); + + if (selectionSet.Selections?.Count > 0) + { + foreach (var selection in selectionSet.Selections) + Visit(selection, context); + } + + WriteIndent(context, level); + context.Writer.WriteLine('}'); + } + + /// + public override void VisitField(GraphQLField field, TContext context) + { + Visit(field.Comment, context); + + var level = GetLevel(context); + WriteIndent(context, level); + + if (field.Alias != null) + { + Visit(field.Alias, context); + context.Writer.Write(": "); + } + Visit(field.Name, context); + if (field.Arguments != null) + { + context.Writer.Write('('); + VisitArguments(field, context); + context.Writer.Write(')'); + } + VisitDirectives(field, context); + + if (field.SelectionSet == null) + context.Writer.WriteLine(); + else + Visit(field.SelectionSet, context); + } + + /// + public override void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) + { + Visit(operationDefinition.Comment, context); + + if (operationDefinition.Name != null) + { + context.Writer.Write(GetOperationType(operationDefinition.Operation)); + context.Writer.Write(' '); + Visit(operationDefinition.Name, context); + } + + if (operationDefinition.VariableDefinitions?.Count > 0) + { + context.Writer.Write('('); + Visit(operationDefinition.VariableDefinitions, context, ", ", ""); + context.Writer.Write(')'); + } + + VisitDirectives(operationDefinition, context); + Visit(operationDefinition.SelectionSet, context); + } + + /// + public override void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) + { + Visit(directiveDefinition.Comment, context); + Visit(directiveDefinition.Description, context); + context.Writer.Write("directive "); + Visit(directiveDefinition.Name, context); + if (directiveDefinition.Arguments != null) + { + context.Writer.Write('('); + Visit(directiveDefinition, context); + context.Writer.Write(')'); + } + } + + /// + public override void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) + { + Visit(variableDefinition.Comment, context); + Visit(variableDefinition.Variable, context); + context.Writer.Write(": "); + Visit(variableDefinition.Type, context); + if (variableDefinition.DefaultValue != null) + { + context.Writer.Write(" = "); + Visit(variableDefinition.DefaultValue, context); + } + VisitDirectives(variableDefinition, context); + } + + /// + public override void VisitVariable(GraphQLVariable variable, TContext context) + { + Visit(variable.Comment, context); + context.Writer.Write('$'); + Visit(variable.Name, context); + } + + /// + public override void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) + { + Visit(booleanValue.Comment, context); + Write(context, booleanValue.Value); + } + + /// + public override void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) + { + Visit(scalarTypeDefinition.Comment, context); + Visit(scalarTypeDefinition.Description, context); + context.Writer.Write("scalar "); + Visit(scalarTypeDefinition.Name, context); + VisitDirectives(scalarTypeDefinition, context); + context.Writer.WriteLine(); + } + + /// + public override void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) + { + Visit(enumTypeDefinition.Comment, context); + Visit(enumTypeDefinition.Description, context); + context.Writer.Write("enum "); + Visit(enumTypeDefinition.Name, context); + VisitDirectives(enumTypeDefinition, context); + if (enumTypeDefinition.Values?.Count > 0) + { + context.Writer.WriteLine(); + context.Writer.WriteLine('{'); + for (int i = 0; i < enumTypeDefinition.Values.Count; ++i) + { + Visit(enumTypeDefinition.Values[i], context); + context.Writer.WriteLine(); + } + context.Writer.WriteLine('}'); + } + } + + /// + public override void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) + { + Visit(enumValueDefinition.Comment, context); + Visit(enumValueDefinition.Description, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + Visit(enumValueDefinition.Name, context); + VisitDirectives(enumValueDefinition, context); + } + + /// + public override void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) + { + Visit(inputObjectTypeDefinition.Comment, context); + Visit(inputObjectTypeDefinition.Description, context); + context.Writer.Write("input "); + Visit(inputObjectTypeDefinition.Name, context); + VisitDirectives(inputObjectTypeDefinition, context); + if (inputObjectTypeDefinition.Fields?.Count > 0) + { + context.Writer.WriteLine(); + context.Writer.WriteLine('{'); + + for (int i = 0; i < inputObjectTypeDefinition.Fields.Count; ++i) + { + Visit(inputObjectTypeDefinition.Fields[i], context); + context.Writer.WriteLine(); + } + + context.Writer.WriteLine('}'); + } + else + { + context.Writer.WriteLine(); + } + } + + /// + public override void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) + { + Visit(inputValueDefinition.Comment, context); + Visit(inputValueDefinition.Description, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + Visit(inputValueDefinition.Name, context); + context.Writer.Write(": "); + Visit(inputValueDefinition.Type, context); + if (inputValueDefinition.DefaultValue != null) + { + context.Writer.Write(" = "); + Visit(inputValueDefinition.DefaultValue, context); + } + VisitDirectives(inputValueDefinition, context); + } + + /// + public override void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) + { + Visit(objectTypeDefinition.Comment, context); + Visit(objectTypeDefinition.Description, context); + context.Writer.Write("type "); + Visit(objectTypeDefinition.Name, context); + VisitInterfaces(objectTypeDefinition, context); + VisitDirectives(objectTypeDefinition, context); + + if (objectTypeDefinition.Fields?.Count > 0) + { + context.Writer.WriteLine(); + context.Writer.WriteLine('{'); + + for (int i = 0; i < objectTypeDefinition.Fields.Count; ++i) + { + Visit(objectTypeDefinition.Fields[i], context); + context.Writer.WriteLine(); + } + + context.Writer.WriteLine('}'); + } + else + { + context.Writer.WriteLine(); + } + } + + /// + public override void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) + { + Visit(interfaceTypeDefinition.Comment, context); + Visit(interfaceTypeDefinition.Description, context); + context.Writer.Write("interface "); + Visit(interfaceTypeDefinition.Name, context); + VisitInterfaces(interfaceTypeDefinition, context); + VisitDirectives(interfaceTypeDefinition, context); + context.Writer.WriteLine(); + context.Writer.WriteLine('{'); + + if (interfaceTypeDefinition.Fields?.Count > 0) + { + for (int i = 0; i < interfaceTypeDefinition.Fields.Count; ++i) + { + Visit(interfaceTypeDefinition.Fields[i], context); + context.Writer.WriteLine(); + } + } + + context.Writer.WriteLine('}'); + } + + /// + public override void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) + { + Visit(fieldDefinition.Comment, context); + Visit(fieldDefinition.Description, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + Visit(fieldDefinition.Name, context); + if (fieldDefinition.Arguments?.Count > 0) + { + context.Writer.Write('('); + for (int i = 0; i < fieldDefinition.Arguments.Count; ++i) + { + Visit(fieldDefinition.Arguments[i], context); + if (i < fieldDefinition.Arguments.Count - 1) + context.Writer.Write(", "); + } + context.Writer.Write(')'); + } + context.Writer.Write(": "); + Visit(fieldDefinition.Type, context); + VisitDirectives(fieldDefinition, context); + } + + /// + public override void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) + { + Visit(schemaDefinition.Comment, context); + Visit(schemaDefinition.Description, context); + context.Writer.Write("schema"); + VisitDirectives(schemaDefinition, context); + + context.Writer.WriteLine(); + context.Writer.WriteLine('{'); + + if (schemaDefinition.OperationTypes?.Count > 0) + { + for (int i = 0; i < schemaDefinition.OperationTypes.Count; ++i) + { + Visit(schemaDefinition.OperationTypes[i], context); + context.Writer.WriteLine(); + } + } + + context.Writer.WriteLine('}'); + } + + /// + public override void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) + { + Visit(rootOperationTypeDefinition.Comment, context); + + int level = GetLevel(context); + WriteIndent(context, level); + + context.Writer.Write(GetOperationType(rootOperationTypeDefinition.Operation)); + context.Writer.Write(": "); + Visit(rootOperationTypeDefinition.Type, context); + } + + /// + public override void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) + { + Visit(unionTypeDefinition.Comment, context); + Visit(unionTypeDefinition.Description, context); + context.Writer.Write("union "); + Visit(unionTypeDefinition.Name, context); + VisitDirectives(unionTypeDefinition, context); + + if (unionTypeDefinition.Types?.Count > 0) + { + context.Writer.Write(" = "); + + for (int i = 0; i < unionTypeDefinition.Types.Count; ++i) + { + Visit(unionTypeDefinition.Types[i], context); + if (i < unionTypeDefinition.Types.Count - 1) + context.Writer.Write(" | "); + } + } + } + + /// + public override void VisitDirective(GraphQLDirective directive, TContext context) + { + Visit(directive.Comment, context); + context.Writer.Write('@'); + Visit(directive.Name, context); + if (directive.Arguments != null) + { + context.Writer.Write('('); + VisitArguments(directive, context); + context.Writer.Write(')'); + } + } + + /// + public override void VisitArgument(GraphQLArgument argument, TContext context) + { + Visit(argument.Comment, context); + Visit(argument.Name, context); + context.Writer.Write(": "); + Visit(argument.Value, context); + } + + /// + public override void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) + { + Visit(nonNullType.Comment, context); + Visit(nonNullType.Type, context); + context.Writer.Write('!'); + } + + /// + public override void VisitListType(GraphQLListType listType, TContext context) + { + Visit(listType.Comment, context); + context.Writer.Write('['); + Visit(listType.Type, context); + context.Writer.Write(']'); + } + + /// + public override void VisitListValue(GraphQLListValue listValue, TContext context) + { + Visit(listValue.Comment, context); + if (listValue.Values?.Count > 0) + { + context.Writer.Write('['); + for (int i=0; i + public override void VisitNullValue(GraphQLScalarValue nullValue, TContext context) + { + Visit(nullValue.Comment, context); + context.Writer.Write("null"); + } + + /// + public override void VisitStringValue(GraphQLScalarValue stringValue, TContext context) + { + Visit(stringValue.Comment, context); + context.Writer.Write('\"'); + Write(context, stringValue.Value); + context.Writer.Write('\"'); + } + + /// + public override void VisitIntValue(GraphQLScalarValue intValue, TContext context) + { + Visit(intValue.Comment, context); + Write(context, intValue.Value); + } + + /// + public override void VisitFloatValue(GraphQLScalarValue floatValue, TContext context) + { + Visit(floatValue.Comment, context); + Write(context, floatValue.Value); + } + + /// + public override void VisitEnumValue(GraphQLScalarValue enumValue, TContext context) + { + Visit(enumValue.Comment, context); + Write(context, enumValue.Value); + } + + /// + public override void VisitObjectValue(GraphQLObjectValue objectValue, TContext context) + { + Visit(objectValue.Comment, context); + + if (objectValue.Fields?.Count > 0) + { + context.Writer.Write("{ "); + for (int i = 0; i < objectValue.Fields.Count; ++i) + { + Visit(objectValue.Fields[i], context); + if (i < objectValue.Fields.Count - 1) + context.Writer.Write(", "); + } + context.Writer.Write(" }"); + } + else + { + context.Writer.Write("{ }"); + } + } + + /// + public override void VisitObjectField(GraphQLObjectField objectField, TContext context) + { + Visit(objectField.Comment, context); + Visit(objectField.Name, context); + context.Writer.Write(": "); + Visit(objectField.Value, context); + } + + /// + public override void VisitNamedType(GraphQLNamedType namedType, TContext context) + { + base.VisitNamedType(namedType, context); + } + + /// + public override void Visit(ASTNode? node, TContext context) + { + if (node == null) + return; + + context.Parent.Push(node); + + base.Visit(node, context); + + context.Parent.Pop(); + } + + private void VisitArguments(IHasArgumentsNode node, TContext context) + { + if (node.Arguments?.Count > 0) + { + for (int i = 0; i < node.Arguments.Count; ++i) + { + Visit(node.Arguments[i], context); + if (i < node.Arguments.Count - 1) + context.Writer.Write(", "); + } + } + } + + private void VisitInterfaces(IHasInterfacesNode node, TContext context) + { + if (node.Interfaces?.Count > 0) + { + context.Writer.Write(" implements "); + + for (int i = 0; i < node.Interfaces.Count; ++i) + { + Visit(node.Interfaces[i], context); + if (i < node.Interfaces.Count - 1) + context.Writer.Write(" & "); + } + } + } + + //TODO: remove + private void Visit(List? nodes, TContext context, string delimiter, string start) + where T : ASTNode + { + if (nodes != null) + { + if (!string.IsNullOrEmpty(start)) + context.Writer.Write(start); + + for (int i = 0; i < nodes.Count; ++i) + { + Visit(nodes[i], context); + if (i < nodes.Count - 1) + context.Writer.Write(delimiter); + } + } + } + + private void VisitDirectives(IHasDirectivesNode node, TContext context) + { + if (node.Directives?.Count > 0) + { + context.Writer.Write(' '); + + for (int i = 0; i < node.Directives.Count; ++i) + { + Visit(node.Directives[i], context); + if (i < node.Directives.Count - 1) + context.Writer.Write(' '); + } + } + } + + private string GetOperationType(OperationType type) => type switch + { + OperationType.Mutation => "mutation", + OperationType.Subscription => "subscription", + _ => "query", + }; + + private void WriteIndent(TContext context, int level) + { + for (int i = 0; i < level; ++i) + context.Writer.Write(" "); + } + + private int GetLevel(TContext context) + { + int level = 0; + + if (context.Parent.Count > 0) + { + var currentNode = context.Parent.Pop(); + + foreach (var node in context.Parent) + { + if (node is GraphQLSelectionSet || + node is GraphQLTypeDefinition || + node is GraphQLInputObjectTypeDefinition || + node is GraphQLSchemaDefinition) + ++level; + } + + if (currentNode is GraphQLDescription) + --level; + else if (currentNode is GraphQLComment && context.Parent.Peek() is GraphQLTypeDefinition) + --level; + + context.Parent.Push(currentNode); + } + + return level; + } + + private void Write(TContext context, ROM value) + { +#if NETSTANDARD2_0 + context.Writer.Write(value.ToString()); +#elif NETSTANDARD2_1_OR_GREATER + context.Writer.Write(value.Span); +#endif + } + } +} diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs new file mode 100644 index 00000000..f243f2ce --- /dev/null +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -0,0 +1,28 @@ +using System.IO; +using GraphQLParser.AST; + +namespace GraphQLParser.Visitors +{ + /// + /// Prints AST into the provided as a hierarchy of node types. + /// + /// Type of the context object passed into all VisitXXX methods. + public class StructureWriter : DefaultNodeVisitor + where TContext : IWriteContext + { + /// + public override void Visit(ASTNode? node, TContext context) + { + if (node == null) + return; + + for (int i = 0; i < context.Parent.Count; ++i) + context.Writer.Write(" "); + + context.Parent.Push(node); + context.Writer.WriteLine(node.Kind.ToString()); + base.Visit(node, context); + context.Parent.Pop(); + } + } +} From 877b60840eb56c367f0207873d57470ecc3f2fd5 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 19:30:47 +0300 Subject: [PATCH 02/18] async visitor API + TypeCondition node --- src/Directory.Build.props | 2 +- .../GraphQL-Parser.approved.txt | 248 ++++---- src/GraphQLParser.Tests/ParserTests.cs | 2 +- .../Visitors/GraphQLAstVisitorTests.cs | 115 ++-- .../Visitors/SDLWriterTests.cs | 5 +- .../Visitors/StructureWriterTests.cs | 5 +- .../AST/GraphQLInlineFragment.cs | 8 +- src/GraphQLParser/AST/GraphQLTypeCondition.cs | 53 ++ src/GraphQLParser/GraphQLParser.csproj | 1 + src/GraphQLParser/NodeHelper.cs | 12 + src/GraphQLParser/ParserContext.Parse.cs | 27 +- .../Visitors/DefaultNodeVisitor.cs | 537 +++++++--------- src/GraphQLParser/Visitors/INodeVisitor.cs | 84 +-- src/GraphQLParser/Visitors/SDLWriter.cs | 596 +++++++++--------- src/GraphQLParser/Visitors/StructureWriter.cs | 9 +- 15 files changed, 845 insertions(+), 859 deletions(-) create mode 100644 src/GraphQLParser/AST/GraphQLTypeCondition.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0f68b091..effb0ea7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -19,7 +19,7 @@ True true - $(NoWarn);1591 + $(NoWarn);1591;IDE1006 enable diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index ab99c019..622fa49a 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -48,6 +48,7 @@ namespace GraphQLParser.AST DirectiveDefinition = 36, Comment = 37, Description = 38, + TypeCondition = 39, } public class GraphQLArgument : GraphQLParser.AST.ASTNode, GraphQLParser.AST.INamedNode { @@ -142,7 +143,7 @@ namespace GraphQLParser.AST public System.Collections.Generic.List? Directives { get; set; } public override GraphQLParser.AST.ASTNodeKind Kind { get; } public GraphQLParser.AST.GraphQLSelectionSet? SelectionSet { get; set; } - public GraphQLParser.AST.GraphQLNamedType? TypeCondition { get; set; } + public GraphQLParser.AST.GraphQLTypeCondition? TypeCondition { get; set; } } public class GraphQLInputObjectTypeDefinition : GraphQLParser.AST.GraphQLTypeDefinition, GraphQLParser.AST.IHasDirectivesNode { @@ -283,6 +284,12 @@ namespace GraphQLParser.AST { protected GraphQLType() { } } + public class GraphQLTypeCondition : GraphQLParser.AST.ASTNode + { + public GraphQLTypeCondition() { } + public override GraphQLParser.AST.ASTNodeKind Kind { get; } + public GraphQLParser.AST.GraphQLNamedType? Type { get; set; } + } public abstract class GraphQLTypeDefinition : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasDescriptionNode, GraphQLParser.AST.INamedNode { protected GraphQLTypeDefinition() { } @@ -452,89 +459,91 @@ namespace GraphQLParser.Visitors where TContext : GraphQLParser.Visitors.IVisitorContext { public DefaultNodeVisitor() { } - public virtual void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } - protected void Visit(System.Collections.Generic.List? nodes, TContext context) + public virtual System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + protected System.Threading.Tasks.ValueTask Visit(System.Collections.Generic.List? nodes, TContext context) where T : GraphQLParser.AST.ASTNode { } - public virtual void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } - public virtual void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } - public virtual void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } - public virtual void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } - public virtual void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } - public virtual void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } - public virtual void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } - public virtual void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } - public virtual void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } - public virtual void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } - public virtual void VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } - public virtual void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } - public virtual void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } - public virtual void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } - public virtual void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } - public virtual void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } - public virtual void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } - public virtual void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } - public virtual void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } - public virtual void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } - public virtual void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } - public virtual void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } - public virtual void VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } - public virtual void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } - public virtual void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } - public virtual void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } - public virtual void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } - public virtual void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } - public virtual void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } - public virtual void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } - public virtual void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } - public virtual void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } - public virtual void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } - public virtual void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } - public virtual void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } - public virtual void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } - public virtual void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } - public virtual void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitTypeCondition(GraphQLParser.AST.GraphQLTypeCondition typeCondition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } + public virtual System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } } public interface INodeVisitor where TContext : GraphQLParser.Visitors.IVisitorContext { - void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context); - void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context); - void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context); - void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context); - void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context); - void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context); - void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context); - void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); - void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context); - void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context); - void VisitField(GraphQLParser.AST.GraphQLField field, TContext context); - void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context); - void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context); - void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context); - void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context); - void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context); - void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); - void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context); - void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context); - void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); - void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context); - void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context); - void VisitName(GraphQLParser.AST.GraphQLName name, TContext context); - void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context); - void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context); - void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context); - void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context); - void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); - void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context); - void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context); - void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); - void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); - void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context); - void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context); - void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context); - void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); - void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context); - void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context); + System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context); + System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context); + System.Threading.Tasks.ValueTask VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context); + System.Threading.Tasks.ValueTask VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context); + System.Threading.Tasks.ValueTask VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context); + System.Threading.Tasks.ValueTask VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context); + System.Threading.Tasks.ValueTask VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitField(GraphQLParser.AST.GraphQLField field, TContext context); + System.Threading.Tasks.ValueTask VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context); + System.Threading.Tasks.ValueTask VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context); + System.Threading.Tasks.ValueTask VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context); + System.Threading.Tasks.ValueTask VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context); + System.Threading.Tasks.ValueTask VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context); + System.Threading.Tasks.ValueTask VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context); + System.Threading.Tasks.ValueTask VisitName(GraphQLParser.AST.GraphQLName name, TContext context); + System.Threading.Tasks.ValueTask VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context); + System.Threading.Tasks.ValueTask VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context); + System.Threading.Tasks.ValueTask VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context); + System.Threading.Tasks.ValueTask VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context); + System.Threading.Tasks.ValueTask VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context); + System.Threading.Tasks.ValueTask VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context); + System.Threading.Tasks.ValueTask VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context); + System.Threading.Tasks.ValueTask VisitTypeCondition(GraphQLParser.AST.GraphQLTypeCondition typeCondition, TContext context); + System.Threading.Tasks.ValueTask VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); + System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context); + System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context); } public interface IVisitorContext { } public interface IWriteContext : GraphQLParser.Visitors.IVisitorContext @@ -546,50 +555,51 @@ namespace GraphQLParser.Visitors where TContext : GraphQLParser.Visitors.IWriteContext { public SDLWriter() { } - public override void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } - public override void VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } - public override void VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } - public override void VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } - public override void VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } - public override void VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } - public override void VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } - public override void VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } - public override void VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } - public override void VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } - public override void VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } - public override void VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } - public override void VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } - public override void VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } - public override void VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } - public override void VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } - public override void VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } - public override void VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } - public override void VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } - public override void VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } - public override void VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } - public override void VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } - public override void VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } - public override void VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } - public override void VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } - public override void VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } - public override void VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } - public override void VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } - public override void VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } - public override void VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } - public override void VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } - public override void VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } - public override void VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } - public override void VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } - public override void VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } - public override void VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } - public override void VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } - public override void VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } - public override void VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitDescription(GraphQLParser.AST.GraphQLDescription description, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitDirective(GraphQLParser.AST.GraphQLDirective directive, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitDirectiveDefinition(GraphQLParser.AST.GraphQLDirectiveDefinition directiveDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitDocument(GraphQLParser.AST.GraphQLDocument document, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitEnumTypeDefinition(GraphQLParser.AST.GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitEnumValue(GraphQLParser.AST.GraphQLScalarValue enumValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitEnumValueDefinition(GraphQLParser.AST.GraphQLEnumValueDefinition enumValueDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitField(GraphQLParser.AST.GraphQLField field, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitFieldDefinition(GraphQLParser.AST.GraphQLFieldDefinition fieldDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitFloatValue(GraphQLParser.AST.GraphQLScalarValue floatValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitFragmentDefinition(GraphQLParser.AST.GraphQLFragmentDefinition fragmentDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitFragmentSpread(GraphQLParser.AST.GraphQLFragmentSpread fragmentSpread, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitInlineFragment(GraphQLParser.AST.GraphQLInlineFragment inlineFragment, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitInputObjectTypeDefinition(GraphQLParser.AST.GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitInputValueDefinition(GraphQLParser.AST.GraphQLInputValueDefinition inputValueDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitIntValue(GraphQLParser.AST.GraphQLScalarValue intValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitInterfaceTypeDefinition(GraphQLParser.AST.GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitListType(GraphQLParser.AST.GraphQLListType listType, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitListValue(GraphQLParser.AST.GraphQLListValue listValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitName(GraphQLParser.AST.GraphQLName name, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitNamedType(GraphQLParser.AST.GraphQLNamedType namedType, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitNonNullType(GraphQLParser.AST.GraphQLNonNullType nonNullType, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitNullValue(GraphQLParser.AST.GraphQLScalarValue nullValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitObjectField(GraphQLParser.AST.GraphQLObjectField objectField, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitObjectTypeDefinition(GraphQLParser.AST.GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitObjectValue(GraphQLParser.AST.GraphQLObjectValue objectValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitOperationDefinition(GraphQLParser.AST.GraphQLOperationDefinition operationDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitRootOperationTypeDefinition(GraphQLParser.AST.GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitScalarTypeDefinition(GraphQLParser.AST.GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitSchemaDefinition(GraphQLParser.AST.GraphQLSchemaDefinition schemaDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitSelectionSet(GraphQLParser.AST.GraphQLSelectionSet selectionSet, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitStringValue(GraphQLParser.AST.GraphQLScalarValue stringValue, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitTypeCondition(GraphQLParser.AST.GraphQLTypeCondition typeCondition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitUnionTypeDefinition(GraphQLParser.AST.GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } } public class StructureWriter : GraphQLParser.Visitors.DefaultNodeVisitor where TContext : GraphQLParser.Visitors.IWriteContext { public StructureWriter() { } - public override void Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + public override System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } } } \ No newline at end of file diff --git a/src/GraphQLParser.Tests/ParserTests.cs b/src/GraphQLParser.Tests/ParserTests.cs index de7ed929..5b9b2bb5 100644 --- a/src/GraphQLParser.Tests/ParserTests.cs +++ b/src/GraphQLParser.Tests/ParserTests.cs @@ -168,7 +168,7 @@ public void Comments_on_NamedTypes_Should_Read_Correctly(IgnoreOptions options) var def1 = document.Definitions[0] as GraphQLOperationDefinition; var field = def1.SelectionSet.Selections[0] as GraphQLField; var frag = field.SelectionSet.Selections[0] as GraphQLInlineFragment; - frag.TypeCondition.Comment.Text.ShouldBe("comment for named type from TypeCondition"); + frag.TypeCondition.Type.Comment.Text.ShouldBe("comment for named type from TypeCondition"); var def2 = document.Definitions[1] as GraphQLObjectTypeDefinition; def2.Interfaces[0].Comment.Text.ShouldBe("comment for named type from ImplementsInterfaces"); diff --git a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs index cf3fdc26..aafb106d 100644 --- a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs +++ b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using GraphQLParser.AST; using GraphQLParser.Visitors; using Shouldly; @@ -11,176 +12,176 @@ public class GraphQLAstVisitorTests { public class CountVisitor : DefaultNodeVisitor { - public override void VisitBooleanValue(GraphQLScalarValue booleanValue, CountContext context) + public override async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, CountContext context) { context.VisitedBooleanValues.Add(booleanValue); - base.VisitBooleanValue(booleanValue, context); + await base.VisitBooleanValue(booleanValue, context); } - public override void VisitIntValue(GraphQLScalarValue intValue, CountContext context) + public override async ValueTask VisitIntValue(GraphQLScalarValue intValue, CountContext context) { context.VisitedIntValues.Add(intValue); - base.VisitIntValue(intValue, context); + await base.VisitIntValue(intValue, context); } - public override void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, CountContext context) + public override async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, CountContext context) { context.VisitedFragmentSpreads.Add(fragmentSpread); - base.VisitFragmentSpread(fragmentSpread, context); + await base.VisitFragmentSpread(fragmentSpread, context); } - public override void VisitArgument(GraphQLArgument argument, CountContext context) + public override async ValueTask VisitArgument(GraphQLArgument argument, CountContext context) { context.VisitedArguments.Add(argument); - base.VisitArgument(argument, context); + await base.VisitArgument(argument, context); } - public override void VisitVariable(GraphQLVariable variable, CountContext context) + public override async ValueTask VisitVariable(GraphQLVariable variable, CountContext context) { context.VisitedVariables.Add(variable); - base.VisitVariable(variable, context); + await base.VisitVariable(variable, context); } - public override void VisitSelectionSet(GraphQLSelectionSet selectionSet, CountContext context) + public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, CountContext context) { context.VisitedSelectionSets.Add(selectionSet); - base.VisitSelectionSet(selectionSet, context); + await base.VisitSelectionSet(selectionSet, context); } - public override void VisitDirective(GraphQLDirective directive, CountContext context) + public override async ValueTask VisitDirective(GraphQLDirective directive, CountContext context) { context.VisitedDirectives.Add(directive); - base.VisitDirective(directive, context); + await base.VisitDirective(directive, context); } - public override void VisitEnumValue(GraphQLScalarValue enumValue, CountContext context) + public override async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, CountContext context) { context.VisitedEnumValues.Add(enumValue); - base.VisitEnumValue(enumValue, context); + await base.VisitEnumValue(enumValue, context); } - public override void VisitStringValue(GraphQLScalarValue stringValue, CountContext context) + public override async ValueTask VisitStringValue(GraphQLScalarValue stringValue, CountContext context) { context.VisitedStringValues.Add(stringValue); - base.VisitStringValue(stringValue, context); + await base.VisitStringValue(stringValue, context); } - public override void VisitName(GraphQLName name, CountContext context) + public override async ValueTask VisitName(GraphQLName name, CountContext context) { context.VisitedNames.Add(name); - base.VisitName(name, context); + await base.VisitName(name, context); } - public override void VisitField(GraphQLField field, CountContext context) + public override async ValueTask VisitField(GraphQLField field, CountContext context) { context.VisitedFields.Add(field); if (field.Alias != null) context.VisitedAliases.Add(field.Alias); - base.VisitField(field, context); + await base.VisitField(field, context); } - public override void VisitFloatValue(GraphQLScalarValue floatValue, CountContext context) + public override async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, CountContext context) { context.VisitedFloatValues.Add(floatValue); - base.VisitFloatValue(floatValue, context); + await base.VisitFloatValue(floatValue, context); } - public override void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, CountContext context) + public override async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(enumTypeDefinition); - base.VisitEnumTypeDefinition(enumTypeDefinition, context); + await base.VisitEnumTypeDefinition(enumTypeDefinition, context); } - public override void VisitInlineFragment(GraphQLInlineFragment inlineFragment, CountContext context) + public override async ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, CountContext context) { context.VisitedInlineFragments.Add(inlineFragment); context.VisitedFragmentTypeConditions.Add(inlineFragment.TypeCondition); - base.VisitInlineFragment(inlineFragment, context); + await base.VisitInlineFragment(inlineFragment, context); } - public override void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, CountContext context) + public override async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, CountContext context) { context.VisitedFragmentDefinitions.Add(fragmentDefinition); context.VisitedFragmentTypeConditions.Add(fragmentDefinition.TypeCondition); - base.VisitFragmentDefinition(fragmentDefinition, context); + await base.VisitFragmentDefinition(fragmentDefinition, context); } - public override void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, CountContext context) + public override async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, CountContext context) { context.VisitedDefinitions.Add(fieldDefinition); - base.VisitFieldDefinition(fieldDefinition, context); + await base.VisitFieldDefinition(fieldDefinition, context); } - public override void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, CountContext context) + public override async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, CountContext context) { context.VisitedDefinitions.Add(directiveDefinition); - base.VisitDirectiveDefinition(directiveDefinition, context); + await base.VisitDirectiveDefinition(directiveDefinition, context); } - public override void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, CountContext context) + public override async ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, CountContext context) { context.VisitedDefinitions.Add(enumValueDefinition); - base.VisitEnumValueDefinition(enumValueDefinition, context); + await base.VisitEnumValueDefinition(enumValueDefinition, context); } - public override void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, CountContext context) + public override async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(inputObjectTypeDefinition); - base.VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context); + await base.VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context); } - public override void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, CountContext context) + public override async ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, CountContext context) { context.VisitedDefinitions.Add(inputValueDefinition); - base.VisitInputValueDefinition(inputValueDefinition, context); + await base.VisitInputValueDefinition(inputValueDefinition, context); } - public override void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, CountContext context) + public override async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(interfaceTypeDefinition); - base.VisitInterfaceTypeDefinition(interfaceTypeDefinition, context); + await base.VisitInterfaceTypeDefinition(interfaceTypeDefinition, context); } - public override void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, CountContext context) + public override async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(objectTypeDefinition); - base.VisitObjectTypeDefinition(objectTypeDefinition, context); + await base.VisitObjectTypeDefinition(objectTypeDefinition, context); } - public override void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, CountContext context) + public override async ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, CountContext context) { context.VisitedDefinitions.Add(operationDefinition); - base.VisitOperationDefinition(operationDefinition, context); + await base.VisitOperationDefinition(operationDefinition, context); } - public override void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, CountContext context) + public override async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(scalarTypeDefinition); - base.VisitScalarTypeDefinition(scalarTypeDefinition, context); + await base.VisitScalarTypeDefinition(scalarTypeDefinition, context); } - public override void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, CountContext context) + public override async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(rootOperationTypeDefinition); - base.VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context); + await base.VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context); } - public override void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, CountContext context) + public override async ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, CountContext context) { context.VisitedDefinitions.Add(variableDefinition); - base.VisitVariableDefinition(variableDefinition, context); + await base.VisitVariableDefinition(variableDefinition, context); } - public override void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, CountContext context) + public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, CountContext context) { context.VisitedDefinitions.Add(unionTypeDefinition); - base.VisitUnionTypeDefinition(unionTypeDefinition, context); + await base.VisitUnionTypeDefinition(unionTypeDefinition, context); } - public override void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, CountContext context) + public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, CountContext context) { context.VisitedDefinitions.Add(schemaDefinition); - base.VisitSchemaDefinition(schemaDefinition, context); + await base.VisitSchemaDefinition(schemaDefinition, context); } } @@ -195,7 +196,7 @@ public class CountContext : IVisitorContext public List VisitedFloatValues = new(); public List VisitedFragmentDefinitions = new(); public List VisitedFragmentSpreads = new(); - public List VisitedFragmentTypeConditions = new(); + public List VisitedFragmentTypeConditions = new(); public List VisitedInlineFragments = new(); public List VisitedIntValues = new(); public List VisitedNames = new(); diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index 22a79260..822eb5a0 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using GraphQLParser.Visitors; using Shouldly; using Xunit; @@ -202,13 +203,13 @@ inline docs age: Int! } ")] - public void WriteDocumentVisitor_Should_Print_Document(string text, string expected) + public async Task WriteDocumentVisitor_Should_Print_Document(string text, string expected) { var context = new TestContext(); using (var document = text.Parse()) { - _sdlWriter.Visit(document, context); + await _sdlWriter.Visit(document, context); var actual = context.Writer.ToString(); actual.ShouldBe(expected); diff --git a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs index daccaefc..f20c996f 100644 --- a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using GraphQLParser.Visitors; using Shouldly; using Xunit; @@ -33,13 +34,13 @@ private class TestContext : IWriteContext Directive Name ")] - public void WriteTreeVisitor_Should_Print_Tree(string text, string expected) + public async Task WriteTreeVisitor_Should_Print_Tree(string text, string expected) { var context = new TestContext(); using (var document = text.Parse()) { - _structWriter.Visit(document, context); + await _structWriter.Visit(document, context).ConfigureAwait(false); var actual = context.Writer.ToString(); actual.ShouldBe(expected); } diff --git a/src/GraphQLParser/AST/GraphQLInlineFragment.cs b/src/GraphQLParser/AST/GraphQLInlineFragment.cs index 79c431d3..bd8dd2cd 100644 --- a/src/GraphQLParser/AST/GraphQLInlineFragment.cs +++ b/src/GraphQLParser/AST/GraphQLInlineFragment.cs @@ -5,14 +5,14 @@ namespace GraphQLParser.AST public class GraphQLInlineFragment : ASTNode, IHasDirectivesNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.InlineFragment; + + public GraphQLTypeCondition? TypeCondition { get; set; } /// - public override ASTNodeKind Kind => ASTNodeKind.InlineFragment; + public List? Directives { get; set; } public GraphQLSelectionSet? SelectionSet { get; set; } - - public GraphQLNamedType? TypeCondition { get; set; } } internal sealed class GraphQLInlineFragmentWithLocation : GraphQLInlineFragment diff --git a/src/GraphQLParser/AST/GraphQLTypeCondition.cs b/src/GraphQLParser/AST/GraphQLTypeCondition.cs new file mode 100644 index 00000000..61251e5f --- /dev/null +++ b/src/GraphQLParser/AST/GraphQLTypeCondition.cs @@ -0,0 +1,53 @@ +namespace GraphQLParser.AST +{ + public class GraphQLTypeCondition : ASTNode + { + /// + public override ASTNodeKind Kind => ASTNodeKind.TypeCondition; + + /// + /// Type to which this condition is applied. + /// + public GraphQLNamedType? Type { get; set; } + } + + internal sealed class GraphQLTypeConditionWithLocation : GraphQLTypeCondition + { + private GraphQLLocation _location; + + public override GraphQLLocation Location + { + get => _location; + set => _location = value; + } + } + + internal sealed class GraphQLTypeConditionWithComment : GraphQLTypeCondition + { + private GraphQLComment? _comment; + + public override GraphQLComment? Comment + { + get => _comment; + set => _comment = value; + } + } + + internal sealed class GraphQLTypeConditionFull : GraphQLTypeCondition + { + private GraphQLLocation _location; + private GraphQLComment? _comment; + + public override GraphQLLocation Location + { + get => _location; + set => _location = value; + } + + public override GraphQLComment? Comment + { + get => _comment; + set => _comment = value; + } + } +} diff --git a/src/GraphQLParser/GraphQLParser.csproj b/src/GraphQLParser/GraphQLParser.csproj index ea0a806e..c0017ef0 100644 --- a/src/GraphQLParser/GraphQLParser.csproj +++ b/src/GraphQLParser/GraphQLParser.csproj @@ -11,6 +11,7 @@ + diff --git a/src/GraphQLParser/NodeHelper.cs b/src/GraphQLParser/NodeHelper.cs index aa69ccf2..2bdc248f 100644 --- a/src/GraphQLParser/NodeHelper.cs +++ b/src/GraphQLParser/NodeHelper.cs @@ -419,6 +419,18 @@ public static GraphQLInputValueDefinition CreateGraphQLInputValueDefinition(Igno }; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static GraphQLTypeCondition CreateGraphQLTypeCondition(IgnoreOptions options) + { + return options switch + { + IgnoreOptions.All => new GraphQLTypeCondition(), + IgnoreOptions.Comments => new GraphQLTypeConditionWithLocation(), + IgnoreOptions.Locations => new GraphQLTypeConditionWithComment(), + _ => new GraphQLTypeConditionFull(), + }; + } + #endregion } } diff --git a/src/GraphQLParser/ParserContext.Parse.cs b/src/GraphQLParser/ParserContext.Parse.cs index 21cf11d6..7654ab52 100644 --- a/src/GraphQLParser/ParserContext.Parse.cs +++ b/src/GraphQLParser/ParserContext.Parse.cs @@ -29,23 +29,18 @@ public GraphQLDocument ParseDocument() } // http://spec.graphql.org/October2021/#TypeCondition - private GraphQLNamedType? ParseTypeCondition(bool optional) + private GraphQLTypeCondition? ParseTypeCondition(bool optional) { - if (optional) - { - GraphQLNamedType? typeCondition = null; - if (_currentToken.Value == "on") - { - Advance(); - typeCondition = ParseNamedType(); - } - return typeCondition; - } - else - { - ExpectKeyword("on"); - return ParseNamedType(); - } + if (optional && _currentToken.Value != "on") + return null; + + int start = _currentToken.Start; + var condition = NodeHelper.CreateGraphQLTypeCondition(_ignoreOptions); + condition.Comment = GetComment(); + ExpectKeyword("on"); + condition.Type = ParseNamedType(); + condition.Location = GetLocation(start); + return condition; } // http://spec.graphql.org/October2021/#Argument diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index f2f0e332..dbd32107 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using GraphQLParser.AST; namespace GraphQLParser.Visitors @@ -13,309 +14,318 @@ public class DefaultNodeVisitor : INodeVisitor where TContext : IVisitorContext { /// - public virtual void VisitDocument(GraphQLDocument document, TContext context) + public virtual async ValueTask VisitDocument(GraphQLDocument document, TContext context) { - Visit(document.Definitions, context); + await Visit(document.Definitions, context); } /// - public virtual void VisitArgument(GraphQLArgument argument, TContext context) + public virtual async ValueTask VisitArgument(GraphQLArgument argument, TContext context) { - Visit(argument.Comment, context); - Visit(argument.Name, context); - Visit(argument.Value, context); + await Visit(argument.Comment, context); + await Visit(argument.Name, context); + await Visit(argument.Value, context); } /// - public virtual void VisitComment(GraphQLComment comment, TContext context) + public virtual ValueTask VisitComment(GraphQLComment comment, TContext context) { + return new ValueTask(Task.CompletedTask); } /// - public virtual void VisitDescription(GraphQLDescription description, TContext context) + public virtual ValueTask VisitDescription(GraphQLDescription description, TContext context) { + return new ValueTask(Task.CompletedTask); } /// - public virtual void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) + public virtual async ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) { - Visit(operationDefinition.Comment, context); - Visit(operationDefinition.Name, context); - Visit(operationDefinition.VariableDefinitions, context); - Visit(operationDefinition.Directives, context); - Visit(operationDefinition.SelectionSet, context); + await Visit(operationDefinition.Comment, context); + await Visit(operationDefinition.Name, context); + await Visit(operationDefinition.VariableDefinitions, context); + await Visit(operationDefinition.Directives, context); + await Visit(operationDefinition.SelectionSet, context); } /// - public virtual void VisitName(GraphQLName name, TContext context) + public virtual async ValueTask VisitName(GraphQLName name, TContext context) { - Visit(name.Comment, context); + await Visit(name.Comment, context); } /// - public virtual void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) + public virtual async ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) { - Visit(variableDefinition.Comment, context); - Visit(variableDefinition.Variable, context); - Visit(variableDefinition.Type, context); - Visit(variableDefinition.DefaultValue, context); - Visit(variableDefinition.Directives, context); + await Visit(variableDefinition.Comment, context); + await Visit(variableDefinition.Variable, context); + await Visit(variableDefinition.Type, context); + await Visit(variableDefinition.DefaultValue, context); + await Visit(variableDefinition.Directives, context); } /// - public virtual void VisitVariable(GraphQLVariable variable, TContext context) + public virtual async ValueTask VisitVariable(GraphQLVariable variable, TContext context) { - Visit(variable.Comment, context); - Visit(variable.Name, context); + await Visit(variable.Comment, context); + await Visit(variable.Name, context); } /// - public virtual void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) + public virtual async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) { - Visit(selectionSet.Comment, context); - Visit(selectionSet.Selections, context); + await Visit(selectionSet.Comment, context); + await Visit(selectionSet.Selections, context); } /// - public virtual void VisitField(GraphQLField field, TContext context) + public virtual async ValueTask VisitField(GraphQLField field, TContext context) { - Visit(field.Comment, context); - Visit(field.Alias, context); - Visit(field.Name, context); - Visit(field.Arguments, context); - Visit(field.Directives, context); - Visit(field.SelectionSet, context); + await Visit(field.Comment, context); + await Visit(field.Alias, context); + await Visit(field.Name, context); + await Visit(field.Arguments, context); + await Visit(field.Directives, context); + await Visit(field.SelectionSet, context); } /// - public virtual void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) + public virtual async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) { - Visit(fragmentSpread.Comment, context); - Visit(fragmentSpread.Name, context); - Visit(fragmentSpread.Directives, context); + await Visit(fragmentSpread.Comment, context); + await Visit(fragmentSpread.Name, context); + await Visit(fragmentSpread.Directives, context); } /// - public virtual void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) + public virtual async ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) { - Visit(inlineFragment.Comment, context); - Visit(inlineFragment.TypeCondition, context); - Visit(inlineFragment.Directives, context); - Visit(inlineFragment.SelectionSet, context); + await Visit(inlineFragment.Comment, context); + await Visit(inlineFragment.TypeCondition, context); + await Visit(inlineFragment.Directives, context); + await Visit(inlineFragment.SelectionSet, context); } /// - public virtual void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) + public virtual async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context) { - Visit(fragmentDefinition.Comment, context); - Visit(fragmentDefinition.Name, context); - Visit(fragmentDefinition.TypeCondition, context); - Visit(fragmentDefinition.Directives, context); - Visit(fragmentDefinition.SelectionSet, context); + await Visit(typeCondition.Comment, context); + await Visit(typeCondition.Type, context); } /// - public virtual void VisitIntValue(GraphQLScalarValue intValue, TContext context) + public virtual async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) { - Visit(intValue.Comment, context); + await Visit(fragmentDefinition.Comment, context); + await Visit(fragmentDefinition.Name, context); + await Visit(fragmentDefinition.TypeCondition, context); + await Visit(fragmentDefinition.Directives, context); + await Visit(fragmentDefinition.SelectionSet, context); } /// - public virtual void VisitFloatValue(GraphQLScalarValue floatValue, TContext context) + public virtual async ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context) { - Visit(floatValue.Comment, context); + await Visit(intValue.Comment, context); } /// - public virtual void VisitStringValue(GraphQLScalarValue stringValue, TContext context) + public virtual async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context) { - Visit(stringValue.Comment, context); + await Visit(floatValue.Comment, context); } /// - public virtual void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) + public virtual async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { - Visit(booleanValue.Comment, context); + await Visit(stringValue.Comment, context); } /// - public virtual void VisitEnumValue(GraphQLScalarValue enumValue, TContext context) + public virtual async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) { - Visit(enumValue.Comment, context); + await Visit(booleanValue.Comment, context); } /// - public virtual void VisitListValue(GraphQLListValue listValue, TContext context) + public virtual async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context) { - Visit(listValue.Comment, context); - Visit(listValue.Values, context); + await Visit(enumValue.Comment, context); } /// - public virtual void VisitObjectValue(GraphQLObjectValue objectValue, TContext context) + public virtual async ValueTask VisitListValue(GraphQLListValue listValue, TContext context) { - Visit(objectValue.Comment, context); - Visit(objectValue.Fields, context); + await Visit(listValue.Comment, context); + await Visit(listValue.Values, context); } /// - public virtual void VisitObjectField(GraphQLObjectField objectField, TContext context) + public virtual async ValueTask VisitObjectValue(GraphQLObjectValue objectValue, TContext context) { - Visit(objectField.Comment, context); - Visit(objectField.Name, context); - Visit(objectField.Value, context); + await Visit(objectValue.Comment, context); + await Visit(objectValue.Fields, context); } /// - public virtual void VisitDirective(GraphQLDirective directive, TContext context) + public virtual async ValueTask VisitObjectField(GraphQLObjectField objectField, TContext context) { - Visit(directive.Comment, context); - Visit(directive.Name, context); - Visit(directive.Arguments, context); + await Visit(objectField.Comment, context); + await Visit(objectField.Name, context); + await Visit(objectField.Value, context); } /// - public virtual void VisitNamedType(GraphQLNamedType namedType, TContext context) + public virtual async ValueTask VisitDirective(GraphQLDirective directive, TContext context) { - Visit(namedType.Comment, context); - Visit(namedType.Name, context); + await Visit(directive.Comment, context); + await Visit(directive.Name, context); + await Visit(directive.Arguments, context); } /// - public virtual void VisitListType(GraphQLListType listType, TContext context) + public virtual async ValueTask VisitNamedType(GraphQLNamedType namedType, TContext context) { - Visit(listType.Comment, context); - Visit(listType.Type, context); + await Visit(namedType.Comment, context); + await Visit(namedType.Name, context); } /// - public virtual void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) + public virtual async ValueTask VisitListType(GraphQLListType listType, TContext context) { - Visit(nonNullType.Comment, context); - Visit(nonNullType.Type, context); + await Visit(listType.Comment, context); + await Visit(listType.Type, context); } /// - public virtual void VisitNullValue(GraphQLScalarValue nullValue, TContext context) + public virtual async ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) { - Visit(nullValue.Comment, context); + await Visit(nonNullType.Comment, context); + await Visit(nonNullType.Type, context); } /// - public virtual void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) + public virtual async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context) { - Visit(schemaDefinition.Comment, context); - Visit(schemaDefinition.Description, context); - Visit(schemaDefinition.Directives, context); - Visit(schemaDefinition.OperationTypes, context); + await Visit(nullValue.Comment, context); } /// - public virtual void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) + public virtual async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) { - Visit(rootOperationTypeDefinition.Comment, context); - Visit(rootOperationTypeDefinition.Type, context); + await Visit(schemaDefinition.Comment, context); + await Visit(schemaDefinition.Description, context); + await Visit(schemaDefinition.Directives, context); + await Visit(schemaDefinition.OperationTypes, context); } /// - public virtual void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) + public virtual async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { - Visit(scalarTypeDefinition.Comment, context); - Visit(scalarTypeDefinition.Description, context); - Visit(scalarTypeDefinition.Name, context); - Visit(scalarTypeDefinition.Directives, context); + await Visit(rootOperationTypeDefinition.Comment, context); + await Visit(rootOperationTypeDefinition.Type, context); } /// - public virtual void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) + public virtual async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { - Visit(objectTypeDefinition.Comment, context); - Visit(objectTypeDefinition.Description, context); - Visit(objectTypeDefinition.Name, context); - Visit(objectTypeDefinition.Interfaces, context); - Visit(objectTypeDefinition.Directives, context); - Visit(objectTypeDefinition.Fields, context); + await Visit(scalarTypeDefinition.Comment, context); + await Visit(scalarTypeDefinition.Description, context); + await Visit(scalarTypeDefinition.Name, context); + await Visit(scalarTypeDefinition.Directives, context); } /// - public virtual void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) + public virtual async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { - Visit(fieldDefinition.Comment, context); - Visit(fieldDefinition.Description, context); - Visit(fieldDefinition.Name, context); - Visit(fieldDefinition.Arguments, context); - Visit(fieldDefinition.Type, context); - Visit(fieldDefinition.Directives, context); + await Visit(objectTypeDefinition.Comment, context); + await Visit(objectTypeDefinition.Description, context); + await Visit(objectTypeDefinition.Name, context); + await Visit(objectTypeDefinition.Interfaces, context); + await Visit(objectTypeDefinition.Directives, context); + await Visit(objectTypeDefinition.Fields, context); } /// - public virtual void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) + public virtual async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) { - Visit(inputValueDefinition.Comment, context); - Visit(inputValueDefinition.Description, context); - Visit(inputValueDefinition.Name, context); - Visit(inputValueDefinition.Type, context); - Visit(inputValueDefinition.DefaultValue, context); - Visit(inputValueDefinition.Directives, context); + await Visit(fieldDefinition.Comment, context); + await Visit(fieldDefinition.Description, context); + await Visit(fieldDefinition.Name, context); + await Visit(fieldDefinition.Arguments, context); + await Visit(fieldDefinition.Type, context); + await Visit(fieldDefinition.Directives, context); } /// - public virtual void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) + public virtual async ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) { - Visit(interfaceTypeDefinition.Comment, context); - Visit(interfaceTypeDefinition.Description, context); - Visit(interfaceTypeDefinition.Name, context); - Visit(interfaceTypeDefinition.Interfaces, context); - Visit(interfaceTypeDefinition.Directives, context); - Visit(interfaceTypeDefinition.Fields, context); + await Visit(inputValueDefinition.Comment, context); + await Visit(inputValueDefinition.Description, context); + await Visit(inputValueDefinition.Name, context); + await Visit(inputValueDefinition.Type, context); + await Visit(inputValueDefinition.DefaultValue, context); + await Visit(inputValueDefinition.Directives, context); } /// - public virtual void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) + public virtual async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { - Visit(unionTypeDefinition.Comment, context); - Visit(unionTypeDefinition.Description, context); - Visit(unionTypeDefinition.Name, context); - Visit(unionTypeDefinition.Directives, context); - Visit(unionTypeDefinition.Types, context); + await Visit(interfaceTypeDefinition.Comment, context); + await Visit(interfaceTypeDefinition.Description, context); + await Visit(interfaceTypeDefinition.Name, context); + await Visit(interfaceTypeDefinition.Interfaces, context); + await Visit(interfaceTypeDefinition.Directives, context); + await Visit(interfaceTypeDefinition.Fields, context); } /// - public virtual void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) + public virtual async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { - Visit(enumTypeDefinition.Comment, context); - Visit(enumTypeDefinition.Description, context); - Visit(enumTypeDefinition.Name, context); - Visit(enumTypeDefinition.Directives, context); - Visit(enumTypeDefinition.Values, context); + await Visit(unionTypeDefinition.Comment, context); + await Visit(unionTypeDefinition.Description, context); + await Visit(unionTypeDefinition.Name, context); + await Visit(unionTypeDefinition.Directives, context); + await Visit(unionTypeDefinition.Types, context); } /// - public virtual void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) + public virtual async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { - Visit(enumValueDefinition.Comment, context); - Visit(enumValueDefinition.Description, context); - Visit(enumValueDefinition.Name, context); - Visit(enumValueDefinition.Directives, context); + await Visit(enumTypeDefinition.Comment, context); + await Visit(enumTypeDefinition.Description, context); + await Visit(enumTypeDefinition.Name, context); + await Visit(enumTypeDefinition.Directives, context); + await Visit(enumTypeDefinition.Values, context); } /// - public virtual void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) + public virtual async ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) { - Visit(inputObjectTypeDefinition.Comment, context); - Visit(inputObjectTypeDefinition.Description, context); - Visit(inputObjectTypeDefinition.Name, context); - Visit(inputObjectTypeDefinition.Directives, context); - Visit(inputObjectTypeDefinition.Fields, context); + await Visit(enumValueDefinition.Comment, context); + await Visit(enumValueDefinition.Description, context); + await Visit(enumValueDefinition.Name, context); + await Visit(enumValueDefinition.Directives, context); } /// - public virtual void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) + public virtual async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { - Visit(directiveDefinition.Comment, context); - Visit(directiveDefinition.Description, context); - Visit(directiveDefinition.Name, context); - Visit(directiveDefinition.Arguments, context); + await Visit(inputObjectTypeDefinition.Comment, context); + await Visit(inputObjectTypeDefinition.Description, context); + await Visit(inputObjectTypeDefinition.Name, context); + await Visit(inputObjectTypeDefinition.Directives, context); + await Visit(inputObjectTypeDefinition.Fields, context); + } + + /// + public virtual async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) + { + await Visit(directiveDefinition.Comment, context); + await Visit(directiveDefinition.Description, context); + await Visit(directiveDefinition.Name, context); + await Visit(directiveDefinition.Arguments, context); } /// @@ -323,186 +333,69 @@ public virtual void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiv /// /// AST node to dispatch. /// Context passed into all INodeVisitor.VisitXXX methods. - public virtual void Visit(ASTNode? node, TContext context) + public virtual ValueTask Visit(ASTNode? node, TContext context) { if (node == null) - return; + return new ValueTask(Task.CompletedTask); - switch (node) + return node switch { - case GraphQLArgument argument: - VisitArgument(argument, context); - break; - - case GraphQLComment comment: - VisitComment(comment, context); - break; - - case GraphQLDescription description: - VisitDescription(description, context); - break; - - case GraphQLDirective directive: - VisitDirective(directive, context); - break; - - case GraphQLDirectiveDefinition directiveDefinition: - VisitDirectiveDefinition(directiveDefinition, context); - break; - - case GraphQLDocument document: - VisitDocument(document, context); - break; - - case GraphQLEnumTypeDefinition enumTypeDefinition: - VisitEnumTypeDefinition(enumTypeDefinition, context); - break; - - case GraphQLEnumValueDefinition enumValueDefinition: - VisitEnumValueDefinition(enumValueDefinition, context); - break; - - case GraphQLField field: - VisitField(field, context); - break; - - case GraphQLFieldDefinition fieldDefinition: - VisitFieldDefinition(fieldDefinition, context); - break; - - case GraphQLFragmentDefinition fragmentDefinition: - VisitFragmentDefinition(fragmentDefinition, context); - break; - - case GraphQLFragmentSpread fragmentSpread: - VisitFragmentSpread(fragmentSpread, context); - break; - - case GraphQLInlineFragment inlineFragment: - VisitInlineFragment(inlineFragment, context); - break; - - case GraphQLInputObjectTypeDefinition inputObjectTypeDefinition: - VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context); - break; - - case GraphQLInputValueDefinition inputValueDefinition: - VisitInputValueDefinition(inputValueDefinition, context); - break; - - case GraphQLInterfaceTypeDefinition interfaceTypeDefinition: - VisitInterfaceTypeDefinition(interfaceTypeDefinition, context); - break; - - case GraphQLListType listType: - VisitListType(listType, context); - break; - - case GraphQLListValue listValue: - VisitListValue(listValue, context); - break; - - case GraphQLName name: - VisitName(name, context); - break; - - case GraphQLNamedType namedType: - VisitNamedType(namedType, context); - break; - - case GraphQLNonNullType nonNullType: - VisitNonNullType(nonNullType, context); - break; - - case GraphQLObjectField objectField: - VisitObjectField(objectField, context); - break; - - case GraphQLObjectTypeDefinition objectTypeDefinition: - VisitObjectTypeDefinition(objectTypeDefinition, context); - break; - - case GraphQLObjectValue objectValue: - VisitObjectValue(objectValue, context); - break; - - case GraphQLOperationDefinition operationDefinition: - VisitOperationDefinition(operationDefinition, context); - break; - - case GraphQLRootOperationTypeDefinition rootOperationTypeDefinition: - VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context); - break; - - case GraphQLScalarTypeDefinition scalarTypeDefinition: - VisitScalarTypeDefinition(scalarTypeDefinition, context); - break; - - case GraphQLScalarValue scalarValue: - switch (scalarValue.Kind) - { - case ASTNodeKind.BooleanValue: - VisitBooleanValue(scalarValue, context); - break; - - case ASTNodeKind.EnumValue: - VisitEnumValue(scalarValue, context); - break; - - case ASTNodeKind.FloatValue: - VisitFloatValue(scalarValue, context); - break; - - case ASTNodeKind.IntValue: - VisitIntValue(scalarValue, context); - break; - - case ASTNodeKind.NullValue: - VisitNullValue(scalarValue, context); - break; - - case ASTNodeKind.StringValue: - VisitStringValue(scalarValue, context); - break; - - default: - throw new NotSupportedException($"Unknown GraphQLScalarValue of kind '{scalarValue.Kind}'."); - } - break; - - case GraphQLSchemaDefinition schemaDefinition: - VisitSchemaDefinition(schemaDefinition, context); - break; - - case GraphQLSelectionSet selectionSet: - VisitSelectionSet(selectionSet, context); - break; - - // case GraphQLTypeExtensionDefinition n => VisitTypeDE - case GraphQLUnionTypeDefinition unionTypeDefinition: - VisitUnionTypeDefinition(unionTypeDefinition, context); - break; - - case GraphQLVariable variable: - VisitVariable(variable, context); - break; - - case GraphQLVariableDefinition variableDefinition: - VisitVariableDefinition(variableDefinition, context); - break; - - default: - throw new NotSupportedException($"Unknown node '{node.GetType().Name}'."); + GraphQLArgument argument => VisitArgument(argument, context), + GraphQLComment comment => VisitComment(comment, context), + GraphQLDescription description => VisitDescription(description, context), + GraphQLDirective directive => VisitDirective(directive, context), + GraphQLDirectiveDefinition directiveDefinition => VisitDirectiveDefinition(directiveDefinition, context), + GraphQLDocument document => VisitDocument(document, context), + GraphQLEnumTypeDefinition enumTypeDefinition => VisitEnumTypeDefinition(enumTypeDefinition, context), + GraphQLEnumValueDefinition enumValueDefinition => VisitEnumValueDefinition(enumValueDefinition, context), + GraphQLField field => VisitField(field, context), + GraphQLFieldDefinition fieldDefinition => VisitFieldDefinition(fieldDefinition, context), + GraphQLFragmentDefinition fragmentDefinition => VisitFragmentDefinition(fragmentDefinition, context), // inherits from GraphQLInlineFragment so should be above + GraphQLFragmentSpread fragmentSpread => VisitFragmentSpread(fragmentSpread, context), + GraphQLInlineFragment inlineFragment => VisitInlineFragment(inlineFragment, context), + GraphQLTypeCondition typeCondition => VisitTypeCondition(typeCondition, context), + GraphQLInputObjectTypeDefinition inputObjectTypeDefinition => VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context), + GraphQLInputValueDefinition inputValueDefinition => VisitInputValueDefinition(inputValueDefinition, context), + GraphQLInterfaceTypeDefinition interfaceTypeDefinition => VisitInterfaceTypeDefinition(interfaceTypeDefinition, context), + GraphQLListType listType => VisitListType(listType, context), + GraphQLListValue listValue => VisitListValue(listValue, context), + GraphQLName name => VisitName(name, context), + GraphQLNamedType namedType => VisitNamedType(namedType, context), + GraphQLNonNullType nonNullType => VisitNonNullType(nonNullType, context), + GraphQLObjectField objectField => VisitObjectField(objectField, context), + GraphQLObjectTypeDefinition objectTypeDefinition => VisitObjectTypeDefinition(objectTypeDefinition, context), + GraphQLObjectValue objectValue => VisitObjectValue(objectValue, context), + GraphQLOperationDefinition operationDefinition => VisitOperationDefinition(operationDefinition, context), + GraphQLRootOperationTypeDefinition rootOperationTypeDefinition => VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context), + GraphQLScalarTypeDefinition scalarTypeDefinition => VisitScalarTypeDefinition(scalarTypeDefinition, context), + GraphQLScalarValue scalarValue => scalarValue.Kind switch + { + ASTNodeKind.BooleanValue => VisitBooleanValue(scalarValue, context), + ASTNodeKind.EnumValue => VisitEnumValue(scalarValue, context), + ASTNodeKind.FloatValue => VisitFloatValue(scalarValue, context), + ASTNodeKind.IntValue => VisitIntValue(scalarValue, context), + ASTNodeKind.NullValue => VisitNullValue(scalarValue, context), + ASTNodeKind.StringValue => VisitStringValue(scalarValue, context), + _ => throw new NotSupportedException($"Unknown GraphQLScalarValue of kind '{scalarValue.Kind}'."), + + }, + GraphQLSchemaDefinition schemaDefinition => VisitSchemaDefinition(schemaDefinition, context), + GraphQLSelectionSet selectionSet => VisitSelectionSet(selectionSet, context), + //GraphQLTypeExtensionDefinition n => VisitTypeDE + GraphQLUnionTypeDefinition unionTypeDefinition => VisitUnionTypeDefinition(unionTypeDefinition, context), + GraphQLVariable variable => VisitVariable(variable, context), + GraphQLVariableDefinition variableDefinition => VisitVariableDefinition(variableDefinition, context), + _ => throw new NotSupportedException($"Unknown node '{node.GetType().Name}'."), }; } - protected void Visit(List? nodes, TContext context) + protected async ValueTask Visit(List? nodes, TContext context) where T : ASTNode { if (nodes != null) { foreach (var node in nodes) - Visit(node, context); + await Visit(node, context); } } } diff --git a/src/GraphQLParser/Visitors/INodeVisitor.cs b/src/GraphQLParser/Visitors/INodeVisitor.cs index c25857bb..228561f0 100644 --- a/src/GraphQLParser/Visitors/INodeVisitor.cs +++ b/src/GraphQLParser/Visitors/INodeVisitor.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using GraphQLParser.AST; namespace GraphQLParser.Visitors @@ -12,196 +13,201 @@ public interface INodeVisitor /// /// Visits node. /// - void VisitName(GraphQLName name, TContext context); + ValueTask VisitName(GraphQLName name, TContext context); /// /// Visits node. /// - void VisitDocument(GraphQLDocument document, TContext context); + ValueTask VisitDocument(GraphQLDocument document, TContext context); /// /// Visits node. /// - void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context); + ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context); /// /// Visits node. /// - void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context); + ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context); /// /// Visits node. /// - void VisitVariable(GraphQLVariable variable, TContext context); + ValueTask VisitVariable(GraphQLVariable variable, TContext context); /// /// Visits node. /// - void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context); + ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context); /// /// Visits node. /// - void VisitField(GraphQLField field, TContext context); + ValueTask VisitField(GraphQLField field, TContext context); /// /// Visits node. /// - void VisitArgument(GraphQLArgument argument, TContext context); + ValueTask VisitArgument(GraphQLArgument argument, TContext context); /// /// Visits node. /// - void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context); + ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context); /// /// Visits node. /// - void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context); + ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context); /// /// Visits node. /// - void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context); + ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context); /// /// Visits node. /// - void VisitIntValue(GraphQLScalarValue intValue, TContext context); + ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context); /// /// Visits node. /// - void VisitFloatValue(GraphQLScalarValue floatValue, TContext context); + ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context); /// /// Visits node. /// - void VisitStringValue(GraphQLScalarValue stringValue, TContext context); + ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context); /// /// Visits node. /// - void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context); + ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context); /// /// Visits node. /// - void VisitEnumValue(GraphQLScalarValue enumValue, TContext context); + ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context); /// /// Visits node. /// - void VisitListValue(GraphQLListValue listValue, TContext context); + ValueTask VisitListValue(GraphQLListValue listValue, TContext context); /// /// Visits node. /// - void VisitObjectValue(GraphQLObjectValue objectValue, TContext context); + ValueTask VisitObjectValue(GraphQLObjectValue objectValue, TContext context); /// /// Visits node. /// - void VisitObjectField(GraphQLObjectField objectField, TContext context); + ValueTask VisitObjectField(GraphQLObjectField objectField, TContext context); /// /// Visits node. /// - void VisitDirective(GraphQLDirective directive, TContext context); + ValueTask VisitDirective(GraphQLDirective directive, TContext context); /// /// Visits node. /// - void VisitNamedType(GraphQLNamedType namedType, TContext context); + ValueTask VisitNamedType(GraphQLNamedType namedType, TContext context); /// /// Visits node. /// - void VisitListType(GraphQLListType listType, TContext context); + ValueTask VisitListType(GraphQLListType listType, TContext context); /// /// Visits node. /// - void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context); + ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, TContext context); /// /// Visits node. /// - void VisitNullValue(GraphQLScalarValue nullValue, TContext context); + ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context); /// /// Visits node. /// - void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context); + ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context); /// /// Visits node. /// - void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); + ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context); /// /// Visits node. /// - void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); + ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context); /// /// Visits node. /// - void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); + ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context); /// /// Visits node. /// - void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context); + ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context); /// /// Visits node. /// - void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context); + ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context); /// /// Visits node. /// - void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); + ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context); /// /// Visits node. /// - void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); + ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context); /// /// Visits node. /// - void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); + ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context); /// /// Visits node. /// - void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context); + ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context); /// /// Visits node. /// - void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); + ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context); // // Visits node. // - //void VisitTypeExtensionDefinition(); //TODO + //ValueTask VisitTypeExtensionDefinition(); //TODO /// /// Visits node. /// - void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context); + ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context); /// /// Visits node. /// - void VisitComment(GraphQLComment comment, TContext context); + ValueTask VisitComment(GraphQLComment comment, TContext context); /// /// Visits node. /// - void VisitDescription(GraphQLDescription description, TContext context); + ValueTask VisitDescription(GraphQLDescription description, TContext context); + + /// + /// Visits node. + /// + ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context); } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index dbd581b1..77ab7329 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using GraphQLParser.AST; namespace GraphQLParser.Visitors @@ -12,690 +13,699 @@ public class SDLWriter : DefaultNodeVisitor where TContext : IWriteContext { /// - public override void VisitDocument(GraphQLDocument document, TContext context) + public override async ValueTask VisitDocument(GraphQLDocument document, TContext context) { if (document.Definitions?.Count > 0) { for (int i = 0; i < document.Definitions.Count; ++i) { - Visit(document.Definitions[i], context); + await Visit(document.Definitions[i], context); if (i < document.Definitions.Count - 1) { - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); } } } } /// - public override void VisitComment(GraphQLComment comment, TContext context) + public override async ValueTask VisitComment(GraphQLComment comment, TContext context) { int level = GetLevel(context); bool needStartNewLine = true; - var span = comment.Text.Span; - for (int i = 0; i < span.Length; ++i) + int length = comment.Text.Span.Length; + for (int i = 0; i < length; ++i) { if (needStartNewLine) { - WriteIndent(context, level); - context.Writer.Write('#'); + await WriteIndent(context, level); + await context.Writer.WriteAsync('#'); needStartNewLine = false; } - switch (span[i]) + char current = comment.Text.Span[i]; + switch (current) { case '\r': break; case '\n': - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); needStartNewLine = true; break; default: - context.Writer.Write(span[i]); + await context.Writer.WriteAsync(current); break; } } - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); } /// - public override void VisitDescription(GraphQLDescription description, TContext context) + public override async ValueTask VisitDescription(GraphQLDescription description, TContext context) { int level = GetLevel(context); - WriteIndent(context, level); - context.Writer.Write("\"\"\""); - context.Writer.WriteLine(); + await WriteIndent(context, level); + await context.Writer.WriteAsync("\"\"\""); + await context.Writer.WriteLineAsync(); bool needStartNewLine = true; - var span = description.Value.Span; - for (int i = 0; i < span.Length; ++i) + int length = description.Value.Span.Length; + for (int i = 0; i < length; ++i) { if (needStartNewLine) { - WriteIndent(context, level); + await WriteIndent(context, level); needStartNewLine = false; } - switch (span[i]) + char current = description.Value.Span[i]; + switch (current) { case '\r': break; case '\n': - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); needStartNewLine = true; break; default: - context.Writer.Write(span[i]); + await context.Writer.WriteAsync(current); break; } } - context.Writer.WriteLine(); - WriteIndent(context, level); - context.Writer.Write("\"\"\""); - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); + await WriteIndent(context, level); + await context.Writer.WriteAsync("\"\"\""); + await context.Writer.WriteLineAsync(); } /// - public override void VisitName(GraphQLName name, TContext context) + public override async ValueTask VisitName(GraphQLName name, TContext context) { - Visit(name.Comment, context); - Write(context, name.Value); + await Visit (name.Comment, context); + await Write(context, name.Value); } /// - public override void VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) + public override async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) { - Visit(fragmentDefinition.Comment, context); - context.Writer.Write("fragment "); - Visit(fragmentDefinition.Name, context); - context.Writer.Write(" on "); - Visit(fragmentDefinition.TypeCondition, context); - VisitDirectives(fragmentDefinition, context); - Visit(fragmentDefinition.SelectionSet, context); + await Visit(fragmentDefinition.Comment, context); + await context.Writer.WriteAsync("fragment "); + await Visit(fragmentDefinition.Name, context); + await context.Writer.WriteAsync(" "); + await Visit(fragmentDefinition.TypeCondition, context); + await VisitDirectives(fragmentDefinition, context); + await Visit(fragmentDefinition.SelectionSet, context); } /// - public override void VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) + public override async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) { - Visit(fragmentSpread.Comment, context); + await Visit(fragmentSpread.Comment, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - context.Writer.Write("..."); - Visit(fragmentSpread.Name, context); - VisitDirectives(fragmentSpread, context); - context.Writer.WriteLine(); + await context.Writer.WriteAsync("..."); + await Visit(fragmentSpread.Name, context); + await VisitDirectives(fragmentSpread, context); + await context.Writer.WriteLineAsync(); } /// - public override void VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) + public override async ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) { - Visit(inlineFragment.Comment, context); + await Visit(inlineFragment.Comment, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - context.Writer.Write("... on "); - Visit(inlineFragment.TypeCondition, context); - VisitDirectives(inlineFragment, context); - Visit(inlineFragment.SelectionSet, context); + await context.Writer.WriteAsync("... "); + await Visit(inlineFragment.TypeCondition, context); + await VisitDirectives(inlineFragment, context); + await Visit(inlineFragment.SelectionSet, context); + } + + public override async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context) + { + await Visit(typeCondition.Comment, context); + await context.Writer.WriteAsync("on "); + await Visit(typeCondition.Type, context); } /// - public override void VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) + public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) { - Visit(selectionSet.Comment, context); - context.Writer.WriteLine(); + await Visit(selectionSet.Comment, context); + await context.Writer.WriteLineAsync(); int level = GetLevel(context); - WriteIndent(context, level); - context.Writer.WriteLine('{'); + await WriteIndent(context, level); + await context.Writer.WriteLineAsync('{'); if (selectionSet.Selections?.Count > 0) { foreach (var selection in selectionSet.Selections) - Visit(selection, context); + await Visit(selection, context); } - WriteIndent(context, level); - context.Writer.WriteLine('}'); + await WriteIndent(context, level); + await context.Writer.WriteLineAsync('}'); } /// - public override void VisitField(GraphQLField field, TContext context) + public override async ValueTask VisitField(GraphQLField field, TContext context) { - Visit(field.Comment, context); + await Visit(field.Comment, context); var level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); if (field.Alias != null) { - Visit(field.Alias, context); - context.Writer.Write(": "); + await Visit(field.Alias, context); + await context.Writer.WriteAsync(": "); } - Visit(field.Name, context); + await Visit(field.Name, context); if (field.Arguments != null) { - context.Writer.Write('('); - VisitArguments(field, context); - context.Writer.Write(')'); + await context.Writer.WriteAsync('('); + await VisitArguments(field, context); + await context.Writer.WriteAsync(')'); } - VisitDirectives(field, context); + await VisitDirectives(field, context); if (field.SelectionSet == null) - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); else - Visit(field.SelectionSet, context); + await Visit(field.SelectionSet, context); } /// - public override void VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) + public override async ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) { - Visit(operationDefinition.Comment, context); + await Visit(operationDefinition.Comment, context); if (operationDefinition.Name != null) { - context.Writer.Write(GetOperationType(operationDefinition.Operation)); - context.Writer.Write(' '); - Visit(operationDefinition.Name, context); + await context.Writer.WriteAsync(GetOperationType(operationDefinition.Operation)); + await context.Writer.WriteAsync(' '); + await Visit(operationDefinition.Name, context); } if (operationDefinition.VariableDefinitions?.Count > 0) { - context.Writer.Write('('); - Visit(operationDefinition.VariableDefinitions, context, ", ", ""); - context.Writer.Write(')'); + await context.Writer.WriteAsync('('); + await Visit(operationDefinition.VariableDefinitions, context, ", ", ""); + await context.Writer.WriteAsync(')'); } - VisitDirectives(operationDefinition, context); - Visit(operationDefinition.SelectionSet, context); + await VisitDirectives(operationDefinition, context); + await Visit(operationDefinition.SelectionSet, context); } /// - public override void VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) + public override async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) { - Visit(directiveDefinition.Comment, context); - Visit(directiveDefinition.Description, context); - context.Writer.Write("directive "); - Visit(directiveDefinition.Name, context); + await Visit(directiveDefinition.Comment, context); + await Visit(directiveDefinition.Description, context); + await context.Writer.WriteAsync("directive "); + await Visit(directiveDefinition.Name, context); if (directiveDefinition.Arguments != null) { - context.Writer.Write('('); - Visit(directiveDefinition, context); - context.Writer.Write(')'); + await context.Writer.WriteAsync('('); + await Visit(directiveDefinition, context); + await context.Writer.WriteAsync(')'); } } /// - public override void VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) + public override async ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) { - Visit(variableDefinition.Comment, context); - Visit(variableDefinition.Variable, context); - context.Writer.Write(": "); - Visit(variableDefinition.Type, context); + await Visit(variableDefinition.Comment, context); + await Visit(variableDefinition.Variable, context); + await context.Writer.WriteAsync(": "); + await Visit(variableDefinition.Type, context); if (variableDefinition.DefaultValue != null) { - context.Writer.Write(" = "); - Visit(variableDefinition.DefaultValue, context); + await context.Writer.WriteAsync(" = "); + await Visit(variableDefinition.DefaultValue, context); } - VisitDirectives(variableDefinition, context); + await VisitDirectives(variableDefinition, context); } /// - public override void VisitVariable(GraphQLVariable variable, TContext context) + public override async ValueTask VisitVariable(GraphQLVariable variable, TContext context) { - Visit(variable.Comment, context); - context.Writer.Write('$'); - Visit(variable.Name, context); + await Visit(variable.Comment, context); + await context.Writer.WriteAsync('$'); + await Visit(variable.Name, context); } /// - public override void VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) + public override async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) { - Visit(booleanValue.Comment, context); - Write(context, booleanValue.Value); + await Visit(booleanValue.Comment, context); + await Write(context, booleanValue.Value); } /// - public override void VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) + public override async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { - Visit(scalarTypeDefinition.Comment, context); - Visit(scalarTypeDefinition.Description, context); - context.Writer.Write("scalar "); - Visit(scalarTypeDefinition.Name, context); - VisitDirectives(scalarTypeDefinition, context); - context.Writer.WriteLine(); + await Visit(scalarTypeDefinition.Comment, context); + await Visit(scalarTypeDefinition.Description, context); + await context.Writer.WriteAsync("scalar "); + await Visit(scalarTypeDefinition.Name, context); + await VisitDirectives(scalarTypeDefinition, context); + await context.Writer.WriteLineAsync(); } /// - public override void VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) + public override async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { - Visit(enumTypeDefinition.Comment, context); - Visit(enumTypeDefinition.Description, context); - context.Writer.Write("enum "); - Visit(enumTypeDefinition.Name, context); - VisitDirectives(enumTypeDefinition, context); + await Visit(enumTypeDefinition.Comment, context); + await Visit(enumTypeDefinition.Description, context); + await context.Writer.WriteAsync("enum "); + await Visit(enumTypeDefinition.Name, context); + await VisitDirectives(enumTypeDefinition, context); if (enumTypeDefinition.Values?.Count > 0) { - context.Writer.WriteLine(); - context.Writer.WriteLine('{'); + await context.Writer.WriteLineAsync(); + await context.Writer.WriteLineAsync('{'); for (int i = 0; i < enumTypeDefinition.Values.Count; ++i) { - Visit(enumTypeDefinition.Values[i], context); - context.Writer.WriteLine(); + await Visit(enumTypeDefinition.Values[i], context); + await context.Writer.WriteLineAsync(); } - context.Writer.WriteLine('}'); + await context.Writer.WriteLineAsync('}'); } } /// - public override void VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) + public override async ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) { - Visit(enumValueDefinition.Comment, context); - Visit(enumValueDefinition.Description, context); + await Visit(enumValueDefinition.Comment, context); + await Visit(enumValueDefinition.Description, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - Visit(enumValueDefinition.Name, context); - VisitDirectives(enumValueDefinition, context); + await Visit(enumValueDefinition.Name, context); + await VisitDirectives(enumValueDefinition, context); } /// - public override void VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) + public override async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { - Visit(inputObjectTypeDefinition.Comment, context); - Visit(inputObjectTypeDefinition.Description, context); - context.Writer.Write("input "); - Visit(inputObjectTypeDefinition.Name, context); - VisitDirectives(inputObjectTypeDefinition, context); + await Visit(inputObjectTypeDefinition.Comment, context); + await Visit(inputObjectTypeDefinition.Description, context); + await context.Writer.WriteAsync("input "); + await Visit(inputObjectTypeDefinition.Name, context); + await VisitDirectives(inputObjectTypeDefinition, context); if (inputObjectTypeDefinition.Fields?.Count > 0) { - context.Writer.WriteLine(); - context.Writer.WriteLine('{'); + await context.Writer.WriteLineAsync(); + await context.Writer.WriteLineAsync('{'); for (int i = 0; i < inputObjectTypeDefinition.Fields.Count; ++i) { - Visit(inputObjectTypeDefinition.Fields[i], context); - context.Writer.WriteLine(); + await Visit(inputObjectTypeDefinition.Fields[i], context); + await context.Writer.WriteLineAsync(); } - context.Writer.WriteLine('}'); + await context.Writer.WriteLineAsync('}'); } else { - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); } } /// - public override void VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) + public override async ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) { - Visit(inputValueDefinition.Comment, context); - Visit(inputValueDefinition.Description, context); + await Visit(inputValueDefinition.Comment, context); + await Visit(inputValueDefinition.Description, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - Visit(inputValueDefinition.Name, context); - context.Writer.Write(": "); - Visit(inputValueDefinition.Type, context); + await Visit(inputValueDefinition.Name, context); + await context.Writer.WriteAsync(": "); + await Visit(inputValueDefinition.Type, context); if (inputValueDefinition.DefaultValue != null) { - context.Writer.Write(" = "); - Visit(inputValueDefinition.DefaultValue, context); + await context.Writer.WriteAsync(" = "); + await Visit(inputValueDefinition.DefaultValue, context); } - VisitDirectives(inputValueDefinition, context); + await VisitDirectives(inputValueDefinition, context); } /// - public override void VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) + public override async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { - Visit(objectTypeDefinition.Comment, context); - Visit(objectTypeDefinition.Description, context); - context.Writer.Write("type "); - Visit(objectTypeDefinition.Name, context); - VisitInterfaces(objectTypeDefinition, context); - VisitDirectives(objectTypeDefinition, context); + await Visit(objectTypeDefinition.Comment, context); + await Visit(objectTypeDefinition.Description, context); + await context.Writer.WriteAsync("type "); + await Visit(objectTypeDefinition.Name, context); + await VisitInterfaces(objectTypeDefinition, context); + await VisitDirectives(objectTypeDefinition, context); if (objectTypeDefinition.Fields?.Count > 0) { - context.Writer.WriteLine(); - context.Writer.WriteLine('{'); + await context.Writer.WriteLineAsync(); + await context.Writer.WriteLineAsync('{'); for (int i = 0; i < objectTypeDefinition.Fields.Count; ++i) { - Visit(objectTypeDefinition.Fields[i], context); - context.Writer.WriteLine(); + await Visit(objectTypeDefinition.Fields[i], context); + await context.Writer.WriteLineAsync(); } - context.Writer.WriteLine('}'); + await context.Writer.WriteLineAsync('}'); } else { - context.Writer.WriteLine(); + await context.Writer.WriteLineAsync(); } } /// - public override void VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) + public override async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { - Visit(interfaceTypeDefinition.Comment, context); - Visit(interfaceTypeDefinition.Description, context); - context.Writer.Write("interface "); - Visit(interfaceTypeDefinition.Name, context); - VisitInterfaces(interfaceTypeDefinition, context); - VisitDirectives(interfaceTypeDefinition, context); - context.Writer.WriteLine(); - context.Writer.WriteLine('{'); + await Visit(interfaceTypeDefinition.Comment, context); + await Visit(interfaceTypeDefinition.Description, context); + await context.Writer.WriteAsync("interface "); + await Visit(interfaceTypeDefinition.Name, context); + await VisitInterfaces(interfaceTypeDefinition, context); + await VisitDirectives(interfaceTypeDefinition, context); + await context.Writer.WriteLineAsync(); + await context.Writer.WriteLineAsync('{'); if (interfaceTypeDefinition.Fields?.Count > 0) { for (int i = 0; i < interfaceTypeDefinition.Fields.Count; ++i) { - Visit(interfaceTypeDefinition.Fields[i], context); - context.Writer.WriteLine(); + await Visit(interfaceTypeDefinition.Fields[i], context); + await context.Writer.WriteLineAsync(); } } - context.Writer.WriteLine('}'); + await context.Writer.WriteLineAsync('}'); } /// - public override void VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) + public override async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) { - Visit(fieldDefinition.Comment, context); - Visit(fieldDefinition.Description, context); + await Visit(fieldDefinition.Comment, context); + await Visit(fieldDefinition.Description, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - Visit(fieldDefinition.Name, context); + await Visit(fieldDefinition.Name, context); if (fieldDefinition.Arguments?.Count > 0) { - context.Writer.Write('('); + await context.Writer.WriteAsync('('); for (int i = 0; i < fieldDefinition.Arguments.Count; ++i) { - Visit(fieldDefinition.Arguments[i], context); + await Visit(fieldDefinition.Arguments[i], context); if (i < fieldDefinition.Arguments.Count - 1) - context.Writer.Write(", "); + await context.Writer.WriteAsync(", "); } - context.Writer.Write(')'); + await context.Writer.WriteAsync(')'); } - context.Writer.Write(": "); - Visit(fieldDefinition.Type, context); - VisitDirectives(fieldDefinition, context); + await context.Writer.WriteAsync(": "); + await Visit(fieldDefinition.Type, context); + await VisitDirectives(fieldDefinition, context); } /// - public override void VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) + public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) { - Visit(schemaDefinition.Comment, context); - Visit(schemaDefinition.Description, context); - context.Writer.Write("schema"); - VisitDirectives(schemaDefinition, context); + await Visit(schemaDefinition.Comment, context); + await Visit(schemaDefinition.Description, context); + await context.Writer.WriteAsync("schema"); + await VisitDirectives(schemaDefinition, context); - context.Writer.WriteLine(); - context.Writer.WriteLine('{'); + await context.Writer.WriteLineAsync(); + await context.Writer.WriteLineAsync('{'); if (schemaDefinition.OperationTypes?.Count > 0) { for (int i = 0; i < schemaDefinition.OperationTypes.Count; ++i) { - Visit(schemaDefinition.OperationTypes[i], context); - context.Writer.WriteLine(); + await Visit(schemaDefinition.OperationTypes[i], context); + await context.Writer.WriteLineAsync(); } } - context.Writer.WriteLine('}'); + await context.Writer.WriteLineAsync('}'); } /// - public override void VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) + public override async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { - Visit(rootOperationTypeDefinition.Comment, context); + await Visit(rootOperationTypeDefinition.Comment, context); int level = GetLevel(context); - WriteIndent(context, level); + await WriteIndent(context, level); - context.Writer.Write(GetOperationType(rootOperationTypeDefinition.Operation)); - context.Writer.Write(": "); - Visit(rootOperationTypeDefinition.Type, context); + await context.Writer.WriteAsync(GetOperationType(rootOperationTypeDefinition.Operation)); + await context.Writer.WriteAsync(": "); + await Visit(rootOperationTypeDefinition.Type, context); } /// - public override void VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) + public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { - Visit(unionTypeDefinition.Comment, context); - Visit(unionTypeDefinition.Description, context); - context.Writer.Write("union "); - Visit(unionTypeDefinition.Name, context); - VisitDirectives(unionTypeDefinition, context); + await Visit(unionTypeDefinition.Comment, context); + await Visit(unionTypeDefinition.Description, context); + await context.Writer.WriteAsync("union "); + await Visit(unionTypeDefinition.Name, context); + await VisitDirectives(unionTypeDefinition, context); if (unionTypeDefinition.Types?.Count > 0) { - context.Writer.Write(" = "); + await context.Writer.WriteAsync(" = "); for (int i = 0; i < unionTypeDefinition.Types.Count; ++i) { - Visit(unionTypeDefinition.Types[i], context); + await Visit(unionTypeDefinition.Types[i], context); if (i < unionTypeDefinition.Types.Count - 1) - context.Writer.Write(" | "); + await context.Writer.WriteAsync(" | "); } } } /// - public override void VisitDirective(GraphQLDirective directive, TContext context) + public override async ValueTask VisitDirective(GraphQLDirective directive, TContext context) { - Visit(directive.Comment, context); - context.Writer.Write('@'); - Visit(directive.Name, context); + await Visit(directive.Comment, context); + await context.Writer.WriteAsync('@'); + await Visit(directive.Name, context); if (directive.Arguments != null) { - context.Writer.Write('('); - VisitArguments(directive, context); - context.Writer.Write(')'); + await context.Writer.WriteAsync('('); + await VisitArguments(directive, context); + await context.Writer.WriteAsync(')'); } } /// - public override void VisitArgument(GraphQLArgument argument, TContext context) + public override async ValueTask VisitArgument(GraphQLArgument argument, TContext context) { - Visit(argument.Comment, context); - Visit(argument.Name, context); - context.Writer.Write(": "); - Visit(argument.Value, context); + await Visit(argument.Comment, context); + await Visit(argument.Name, context); + await context.Writer.WriteAsync(": "); + await Visit(argument.Value, context); } /// - public override void VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) + public override async ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) { - Visit(nonNullType.Comment, context); - Visit(nonNullType.Type, context); - context.Writer.Write('!'); + await Visit(nonNullType.Comment, context); + await Visit(nonNullType.Type, context); + await context.Writer.WriteAsync('!'); } /// - public override void VisitListType(GraphQLListType listType, TContext context) + public override async ValueTask VisitListType(GraphQLListType listType, TContext context) { - Visit(listType.Comment, context); - context.Writer.Write('['); - Visit(listType.Type, context); - context.Writer.Write(']'); + await Visit(listType.Comment, context); + await context.Writer.WriteAsync('['); + await Visit(listType.Type, context); + await context.Writer.WriteAsync(']'); } /// - public override void VisitListValue(GraphQLListValue listValue, TContext context) + public override async ValueTask VisitListValue(GraphQLListValue listValue, TContext context) { - Visit(listValue.Comment, context); + await Visit(listValue.Comment, context); if (listValue.Values?.Count > 0) { - context.Writer.Write('['); + await context.Writer.WriteAsync('['); for (int i=0; i - public override void VisitNullValue(GraphQLScalarValue nullValue, TContext context) + public override async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context) { - Visit(nullValue.Comment, context); - context.Writer.Write("null"); + await Visit(nullValue.Comment, context); + await context.Writer.WriteAsync("null"); } /// - public override void VisitStringValue(GraphQLScalarValue stringValue, TContext context) + public override async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { - Visit(stringValue.Comment, context); - context.Writer.Write('\"'); - Write(context, stringValue.Value); - context.Writer.Write('\"'); + await Visit(stringValue.Comment, context); + await context.Writer.WriteAsync('\"'); + await Write(context, stringValue.Value); + await context.Writer.WriteAsync('\"'); } /// - public override void VisitIntValue(GraphQLScalarValue intValue, TContext context) + public override async ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context) { - Visit(intValue.Comment, context); - Write(context, intValue.Value); + await Visit(intValue.Comment, context); + await Write(context, intValue.Value); } /// - public override void VisitFloatValue(GraphQLScalarValue floatValue, TContext context) + public override async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context) { - Visit(floatValue.Comment, context); - Write(context, floatValue.Value); + await Visit(floatValue.Comment, context); + await Write(context, floatValue.Value); } /// - public override void VisitEnumValue(GraphQLScalarValue enumValue, TContext context) + public override async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context) { - Visit(enumValue.Comment, context); - Write(context, enumValue.Value); + await Visit(enumValue.Comment, context); + await Write(context, enumValue.Value); } /// - public override void VisitObjectValue(GraphQLObjectValue objectValue, TContext context) + public override async ValueTask VisitObjectValue(GraphQLObjectValue objectValue, TContext context) { - Visit(objectValue.Comment, context); + await Visit(objectValue.Comment, context); if (objectValue.Fields?.Count > 0) { - context.Writer.Write("{ "); + await context.Writer.WriteAsync("{ "); for (int i = 0; i < objectValue.Fields.Count; ++i) { - Visit(objectValue.Fields[i], context); + await Visit(objectValue.Fields[i], context); if (i < objectValue.Fields.Count - 1) - context.Writer.Write(", "); + await context.Writer.WriteAsync(", "); } - context.Writer.Write(" }"); + await context.Writer.WriteAsync(" }"); } else { - context.Writer.Write("{ }"); + await context.Writer.WriteAsync("{ }"); } } /// - public override void VisitObjectField(GraphQLObjectField objectField, TContext context) + public override async ValueTask VisitObjectField(GraphQLObjectField objectField, TContext context) { - Visit(objectField.Comment, context); - Visit(objectField.Name, context); - context.Writer.Write(": "); - Visit(objectField.Value, context); + await Visit(objectField.Comment, context); + await Visit(objectField.Name, context); + await context.Writer.WriteAsync(": "); + await Visit(objectField.Value, context); } /// - public override void VisitNamedType(GraphQLNamedType namedType, TContext context) + public override ValueTask VisitNamedType(GraphQLNamedType namedType, TContext context) { - base.VisitNamedType(namedType, context); + return base.VisitNamedType(namedType, context); } /// - public override void Visit(ASTNode? node, TContext context) + public override async ValueTask Visit(ASTNode? node, TContext context) { if (node == null) return; context.Parent.Push(node); - base.Visit(node, context); + await base.Visit(node, context); context.Parent.Pop(); } - private void VisitArguments(IHasArgumentsNode node, TContext context) + private async ValueTask VisitArguments(IHasArgumentsNode node, TContext context) { if (node.Arguments?.Count > 0) { for (int i = 0; i < node.Arguments.Count; ++i) { - Visit(node.Arguments[i], context); + await Visit(node.Arguments[i], context); if (i < node.Arguments.Count - 1) - context.Writer.Write(", "); + await context.Writer.WriteAsync(", "); } } } - private void VisitInterfaces(IHasInterfacesNode node, TContext context) + private async ValueTask VisitInterfaces(IHasInterfacesNode node, TContext context) { if (node.Interfaces?.Count > 0) { - context.Writer.Write(" implements "); + await context.Writer.WriteAsync(" implements "); for (int i = 0; i < node.Interfaces.Count; ++i) { - Visit(node.Interfaces[i], context); + await Visit(node.Interfaces[i], context); if (i < node.Interfaces.Count - 1) - context.Writer.Write(" & "); + await context.Writer.WriteAsync(" & "); } } } //TODO: remove - private void Visit(List? nodes, TContext context, string delimiter, string start) + private async ValueTask Visit(List? nodes, TContext context, string delimiter, string start) where T : ASTNode { if (nodes != null) { if (!string.IsNullOrEmpty(start)) - context.Writer.Write(start); + await context.Writer.WriteAsync(start); for (int i = 0; i < nodes.Count; ++i) { - Visit(nodes[i], context); + await Visit(nodes[i], context); if (i < nodes.Count - 1) - context.Writer.Write(delimiter); + await context.Writer.WriteAsync(delimiter); } } } - private void VisitDirectives(IHasDirectivesNode node, TContext context) + private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext context) { if (node.Directives?.Count > 0) { - context.Writer.Write(' '); + await context.Writer.WriteAsync(' '); for (int i = 0; i < node.Directives.Count; ++i) { - Visit(node.Directives[i], context); + await Visit(node.Directives[i], context); if (i < node.Directives.Count - 1) - context.Writer.Write(' '); + await context.Writer.WriteAsync(' '); } } } @@ -707,10 +717,10 @@ private void VisitDirectives(IHasDirectivesNode node, TContext context) _ => "query", }; - private void WriteIndent(TContext context, int level) + private async ValueTask WriteIndent(TContext context, int level) { for (int i = 0; i < level; ++i) - context.Writer.Write(" "); + await context.Writer.WriteAsync(" "); } private int GetLevel(TContext context) @@ -741,13 +751,15 @@ node is GraphQLInputObjectTypeDefinition || return level; } - private void Write(TContext context, ROM value) + private ValueTask Write(TContext context, ROM value) { + var task = #if NETSTANDARD2_0 - context.Writer.Write(value.ToString()); + context.Writer.WriteAsync(value.ToString()); #elif NETSTANDARD2_1_OR_GREATER - context.Writer.Write(value.Span); + context.Writer.WriteAsync(value); #endif + return new ValueTask(task); } } } diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs index f243f2ce..f83a903b 100644 --- a/src/GraphQLParser/Visitors/StructureWriter.cs +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Threading.Tasks; using GraphQLParser.AST; namespace GraphQLParser.Visitors @@ -11,17 +12,17 @@ public class StructureWriter : DefaultNodeVisitor where TContext : IWriteContext { /// - public override void Visit(ASTNode? node, TContext context) + public override async ValueTask Visit(ASTNode? node, TContext context) { if (node == null) return; for (int i = 0; i < context.Parent.Count; ++i) - context.Writer.Write(" "); + await context.Writer.WriteAsync(" "); context.Parent.Push(node); - context.Writer.WriteLine(node.Kind.ToString()); - base.Visit(node, context); + await context.Writer.WriteLineAsync(node.Kind.ToString()); + await base.Visit(node, context); context.Parent.Pop(); } } From 5f0bb90b26d9dc6fb8326cc1d6568aa6b810497b Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 19:35:20 +0300 Subject: [PATCH 03/18] oops --- .editorconfig | 2 +- src/Directory.Build.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3a7f70f0..b8228a5e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -253,7 +253,7 @@ dotnet_naming_style.end_in_async_style.required_prefix = dotnet_naming_style.end_in_async_style.required_suffix = Async # dotnet_naming_rule..severity = -dotnet_naming_rule.async_methods_end_in_async.severity = warning +dotnet_naming_rule.async_methods_end_in_async.severity = suggestion # Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 dotnet_diagnostic.IDE0005.severity = warning diff --git a/src/Directory.Build.props b/src/Directory.Build.props index effb0ea7..0f68b091 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -19,7 +19,7 @@ True true - $(NoWarn);1591;IDE1006 + $(NoWarn);1591 enable From 719ef48b8db90fdf1f8917fba1e72eb93ec3aa1f Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 20:01:41 +0300 Subject: [PATCH 04/18] rename --- .../GraphQL-Parser.approved.txt | 8 ++--- .../Visitors/GraphQLAstVisitorTests.cs | 2 +- .../Visitors/SDLWriterTests.cs | 2 +- .../Visitors/DefaultNodeVisitor.cs | 2 +- src/GraphQLParser/Visitors/INodeVisitor.cs | 2 +- ...sitorContext.cs => INodeVisitorContext.cs} | 2 +- src/GraphQLParser/Visitors/IWriteContext.cs | 2 +- src/GraphQLParser/Visitors/SDLWriter.cs | 29 ++++++------------- 8 files changed, 19 insertions(+), 30 deletions(-) rename src/GraphQLParser/Visitors/{IVisitorContext.cs => INodeVisitorContext.cs} (78%) diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index 622fa49a..4190b770 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -456,7 +456,7 @@ namespace GraphQLParser namespace GraphQLParser.Visitors { public class DefaultNodeVisitor : GraphQLParser.Visitors.INodeVisitor - where TContext : GraphQLParser.Visitors.IVisitorContext + where TContext : GraphQLParser.Visitors.INodeVisitorContext { public DefaultNodeVisitor() { } public virtual System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } @@ -503,7 +503,7 @@ namespace GraphQLParser.Visitors public virtual System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } } public interface INodeVisitor - where TContext : GraphQLParser.Visitors.IVisitorContext + where TContext : GraphQLParser.Visitors.INodeVisitorContext { System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context); System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context); @@ -545,8 +545,8 @@ namespace GraphQLParser.Visitors System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context); System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context); } - public interface IVisitorContext { } - public interface IWriteContext : GraphQLParser.Visitors.IVisitorContext + public interface INodeVisitorContext { } + public interface IWriteContext : GraphQLParser.Visitors.INodeVisitorContext { System.Collections.Generic.Stack Parent { get; } System.IO.TextWriter Writer { get; } diff --git a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs index aafb106d..6cd41871 100644 --- a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs +++ b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs @@ -185,7 +185,7 @@ public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition sc } } - public class CountContext : IVisitorContext + public class CountContext : INodeVisitorContext { public List VisitedAliases = new(); public List VisitedArguments = new(); diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index 822eb5a0..9f499b8b 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -209,7 +209,7 @@ public async Task WriteDocumentVisitor_Should_Print_Document(string text, string using (var document = text.Parse()) { - await _sdlWriter.Visit(document, context); + await _sdlWriter.Visit(document, context).ConfigureAwait(false); var actual = context.Writer.ToString(); actual.ShouldBe(expected); diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index dbd32107..e5323846 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -11,7 +11,7 @@ namespace GraphQLParser.Visitors /// /// Type of the context object passed into all VisitXXX methods. public class DefaultNodeVisitor : INodeVisitor - where TContext : IVisitorContext + where TContext : INodeVisitorContext { /// public virtual async ValueTask VisitDocument(GraphQLDocument document, TContext context) diff --git a/src/GraphQLParser/Visitors/INodeVisitor.cs b/src/GraphQLParser/Visitors/INodeVisitor.cs index 228561f0..7c4619c9 100644 --- a/src/GraphQLParser/Visitors/INodeVisitor.cs +++ b/src/GraphQLParser/Visitors/INodeVisitor.cs @@ -8,7 +8,7 @@ namespace GraphQLParser.Visitors /// Type of the context object passed into all VisitXXX methods. /// public interface INodeVisitor - where TContext : IVisitorContext + where TContext : INodeVisitorContext { /// /// Visits node. diff --git a/src/GraphQLParser/Visitors/IVisitorContext.cs b/src/GraphQLParser/Visitors/INodeVisitorContext.cs similarity index 78% rename from src/GraphQLParser/Visitors/IVisitorContext.cs rename to src/GraphQLParser/Visitors/INodeVisitorContext.cs index 256f9fd1..4fd58291 100644 --- a/src/GraphQLParser/Visitors/IVisitorContext.cs +++ b/src/GraphQLParser/Visitors/INodeVisitorContext.cs @@ -3,7 +3,7 @@ namespace GraphQLParser.Visitors /// /// Context passed into all INodeVisitor.VisitXXX methods. /// - public interface IVisitorContext + public interface INodeVisitorContext { } } diff --git a/src/GraphQLParser/Visitors/IWriteContext.cs b/src/GraphQLParser/Visitors/IWriteContext.cs index 9e2f132e..ee7df835 100644 --- a/src/GraphQLParser/Visitors/IWriteContext.cs +++ b/src/GraphQLParser/Visitors/IWriteContext.cs @@ -3,7 +3,7 @@ namespace GraphQLParser.Visitors { - public interface IWriteContext : IVisitorContext + public interface IWriteContext : INodeVisitorContext { TextWriter Writer { get; } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 77ab7329..247784ce 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using GraphQLParser.AST; @@ -223,7 +222,15 @@ public override async ValueTask VisitOperationDefinition(GraphQLOperationDefinit if (operationDefinition.VariableDefinitions?.Count > 0) { await context.Writer.WriteAsync('('); - await Visit(operationDefinition.VariableDefinitions, context, ", ", ""); + if (operationDefinition.VariableDefinitions?.Count > 0) + { + for (int i = 0; i < operationDefinition.VariableDefinitions.Count; ++i) + { + await Visit(operationDefinition.VariableDefinitions[i], context); + if (i < operationDefinition.VariableDefinitions.Count - 1) + await context.Writer.WriteAsync(", "); + } + } await context.Writer.WriteAsync(')'); } @@ -677,24 +684,6 @@ private async ValueTask VisitInterfaces(IHasInterfacesNode node, TContext contex } } - //TODO: remove - private async ValueTask Visit(List? nodes, TContext context, string delimiter, string start) - where T : ASTNode - { - if (nodes != null) - { - if (!string.IsNullOrEmpty(start)) - await context.Writer.WriteAsync(start); - - for (int i = 0; i < nodes.Count; ++i) - { - await Visit(nodes[i], context); - if (i < nodes.Count - 1) - await context.Writer.WriteAsync(delimiter); - } - } - } - private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext context) { if (node.Directives?.Count > 0) From 813adb27d0882a29c44835f43b1618a6c75f39be Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 20:07:51 +0300 Subject: [PATCH 05/18] format --- src/GraphQLParser/Visitors/SDLWriter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 247784ce..2e1f4f10 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -109,7 +109,7 @@ public override async ValueTask VisitDescription(GraphQLDescription description, /// public override async ValueTask VisitName(GraphQLName name, TContext context) { - await Visit (name.Comment, context); + await Visit(name.Comment, context); await Write(context, name.Value); } @@ -559,7 +559,7 @@ public override async ValueTask VisitListValue(GraphQLListValue listValue, TCont if (listValue.Values?.Count > 0) { await context.Writer.WriteAsync('['); - for (int i=0; i Date: Sat, 13 Nov 2021 20:13:13 +0300 Subject: [PATCH 06/18] oops --- src/GraphQLParser/AST/ASTNodeKind.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/GraphQLParser/AST/ASTNodeKind.cs b/src/GraphQLParser/AST/ASTNodeKind.cs index fdeee4e9..3e8262de 100644 --- a/src/GraphQLParser/AST/ASTNodeKind.cs +++ b/src/GraphQLParser/AST/ASTNodeKind.cs @@ -325,5 +325,12 @@ public enum ASTNodeKind /// /// Description, + + /// + /// Fragments must specify the type they apply to. + ///
+ /// + ///
+ TypeCondition, } } From 01240a5a5d541dee3d8509aa82d041e2408874bf Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 23:02:33 +0300 Subject: [PATCH 07/18] remove kind field from GraphQLListValue add cancellation support add comments --- .../GraphQL-Parser.approved.txt | 14 +- .../Visitors/GraphQLAstVisitorTests.cs | 3 + .../Visitors/SDLWriterTests.cs | 3 + .../Visitors/StructureWriterTests.cs | 3 + src/GraphQLParser/AST/ASTNodeKind.cs | 6 +- src/GraphQLParser/AST/GraphQLArgument.cs | 3 + src/GraphQLParser/AST/GraphQLComment.cs | 4 +- src/GraphQLParser/AST/GraphQLDescription.cs | 4 +- src/GraphQLParser/AST/GraphQLDirective.cs | 9 +- .../AST/GraphQLDirectiveDefinition.cs | 9 +- src/GraphQLParser/AST/GraphQLDocument.cs | 8 +- .../AST/GraphQLEnumTypeDefinition.cs | 7 +- .../AST/GraphQLEnumValueDefinition.cs | 7 +- src/GraphQLParser/AST/GraphQLField.cs | 9 +- .../AST/GraphQLFieldDefinition.cs | 9 +- .../AST/GraphQLFragmentDefinition.cs | 3 + .../AST/GraphQLFragmentSpread.cs | 7 +- .../AST/GraphQLInlineFragment.cs | 3 + .../AST/GraphQLInputObjectTypeDefinition.cs | 9 +- .../AST/GraphQLInputValueDefinition.cs | 9 +- .../AST/GraphQLInterfaceTypeDefinition.cs | 9 +- src/GraphQLParser/AST/GraphQLListType.cs | 3 + src/GraphQLParser/AST/GraphQLListValue.cs | 29 +-- src/GraphQLParser/AST/GraphQLName.cs | 4 +- src/GraphQLParser/AST/GraphQLNamedType.cs | 3 + src/GraphQLParser/AST/GraphQLNonNullType.cs | 3 + src/GraphQLParser/AST/GraphQLObjectField.cs | 3 + .../AST/GraphQLObjectTypeDefinition.cs | 9 +- src/GraphQLParser/AST/GraphQLObjectValue.cs | 7 +- .../AST/GraphQLOperationDefinition.cs | 7 +- .../AST/GraphQLRootOperationTypeDefinition.cs | 9 + .../AST/GraphQLScalarTypeDefinition.cs | 7 +- .../AST/GraphQLSchemaDefinition.cs | 9 +- src/GraphQLParser/AST/GraphQLSelectionSet.cs | 3 + src/GraphQLParser/AST/GraphQLType.cs | 9 + src/GraphQLParser/AST/GraphQLTypeCondition.cs | 3 + .../AST/GraphQLTypeDefinition.cs | 7 +- .../AST/GraphQLTypeExtensionDefinition.cs | 5 +- .../AST/GraphQLUnionTypeDefinition.cs | 7 +- src/GraphQLParser/AST/GraphQLValue.cs | 11 + src/GraphQLParser/AST/GraphQLVariable.cs | 3 + .../AST/GraphQLVariableDefinition.cs | 3 + src/GraphQLParser/NodeHelper.cs | 10 +- src/GraphQLParser/ParserContext.Parse.cs | 2 +- .../Visitors/DefaultNodeVisitor.cs | 5 + .../Visitors/INodeVisitorContext.cs | 6 + src/GraphQLParser/Visitors/IWriteContext.cs | 9 + src/GraphQLParser/Visitors/SDLWriter.cs | 236 +++++++++--------- src/GraphQLParser/Visitors/StructureWriter.cs | 5 +- .../Visitors/WriteContextExtensions.cs | 43 ++++ 50 files changed, 393 insertions(+), 205 deletions(-) create mode 100644 src/GraphQLParser/Visitors/WriteContextExtensions.cs diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index 4190b770..44ab7035 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -177,7 +177,7 @@ namespace GraphQLParser.AST } public class GraphQLListValue : GraphQLParser.AST.GraphQLValue { - public GraphQLListValue(GraphQLParser.AST.ASTNodeKind kind) { } + public GraphQLListValue() { } public GraphQLParser.ROM AstValue { get; set; } public override GraphQLParser.AST.ASTNodeKind Kind { get; } public System.Collections.Generic.List? Values { get; set; } @@ -502,6 +502,10 @@ namespace GraphQLParser.Visitors public virtual System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } public virtual System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } } + public interface INodeVisitorContext + { + System.Threading.CancellationToken CancellationToken { get; } + } public interface INodeVisitor where TContext : GraphQLParser.Visitors.INodeVisitorContext { @@ -545,7 +549,6 @@ namespace GraphQLParser.Visitors System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context); System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context); } - public interface INodeVisitorContext { } public interface IWriteContext : GraphQLParser.Visitors.INodeVisitorContext { System.Collections.Generic.Stack Parent { get; } @@ -602,4 +605,11 @@ namespace GraphQLParser.Visitors public StructureWriter() { } public override System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } } + public static class WriteContextExtensions + { + public static System.Threading.Tasks.ValueTask Write(this TContext context, GraphQLParser.ROM value) + where TContext : GraphQLParser.Visitors.IWriteContext { } + public static System.Threading.Tasks.ValueTask WriteLine(this TContext context) + where TContext : GraphQLParser.Visitors.IWriteContext { } + } } \ No newline at end of file diff --git a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs index 6cd41871..fccad7d3 100644 --- a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs +++ b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using GraphQLParser.AST; using GraphQLParser.Visitors; @@ -204,6 +205,8 @@ public class CountContext : INodeVisitorContext public List VisitedStringValues = new(); public List VisitedVariables = new(); public List VisitedBooleanValues = new(); + + public CancellationToken CancellationToken { get; set; } } private readonly CountVisitor _visitor = new(); diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index 9f499b8b..ff7ed744 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading; using System.Threading.Tasks; using GraphQLParser.Visitors; using Shouldly; @@ -14,6 +15,8 @@ private class TestContext : IWriteContext public TextWriter Writer { get; set; } = new StringWriter(); public Stack Parent { get; set; } = new Stack(); + + public CancellationToken CancellationToken { get; set; } } private static readonly SDLWriter _sdlWriter = new(); diff --git a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs index f20c996f..382a55aa 100644 --- a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Threading; using System.Threading.Tasks; using GraphQLParser.Visitors; using Shouldly; @@ -14,6 +15,8 @@ private class TestContext : IWriteContext public TextWriter Writer { get; set; } = new StringWriter(); public Stack Parent { get; set; } = new Stack(); + + public CancellationToken CancellationToken { get; set; } } private static readonly StructureWriter _structWriter = new(); diff --git a/src/GraphQLParser/AST/ASTNodeKind.cs b/src/GraphQLParser/AST/ASTNodeKind.cs index 3e8262de..4ba02797 100644 --- a/src/GraphQLParser/AST/ASTNodeKind.cs +++ b/src/GraphQLParser/AST/ASTNodeKind.cs @@ -296,8 +296,10 @@ public enum ASTNodeKind /// InputObjectTypeDefinition, - // TODO: change - TypeExtensionDefinition, + /// + /// TO BE DONE + /// + TypeExtensionDefinition, // TODO: change /// /// Directive definition. Directives provide a way to describe alternate runtime execution diff --git a/src/GraphQLParser/AST/GraphQLArgument.cs b/src/GraphQLParser/AST/GraphQLArgument.cs index 0a961f49..c0bc6e64 100644 --- a/src/GraphQLParser/AST/GraphQLArgument.cs +++ b/src/GraphQLParser/AST/GraphQLArgument.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLArgument : ASTNode, INamedNode { /// diff --git a/src/GraphQLParser/AST/GraphQLComment.cs b/src/GraphQLParser/AST/GraphQLComment.cs index 942a1081..ec053ec6 100644 --- a/src/GraphQLParser/AST/GraphQLComment.cs +++ b/src/GraphQLParser/AST/GraphQLComment.cs @@ -2,7 +2,9 @@ namespace GraphQLParser.AST { - /// + /// + /// AST node for . + /// [DebuggerDisplay("{Text}")] public class GraphQLComment : ASTNode { diff --git a/src/GraphQLParser/AST/GraphQLDescription.cs b/src/GraphQLParser/AST/GraphQLDescription.cs index 8c620d4b..befcf2ce 100644 --- a/src/GraphQLParser/AST/GraphQLDescription.cs +++ b/src/GraphQLParser/AST/GraphQLDescription.cs @@ -2,7 +2,9 @@ namespace GraphQLParser.AST { - /// + /// + /// AST node for . + /// [DebuggerDisplay("{Value}")] public class GraphQLDescription : ASTNode { diff --git a/src/GraphQLParser/AST/GraphQLDirective.cs b/src/GraphQLParser/AST/GraphQLDirective.cs index 69c52985..5ab863c5 100644 --- a/src/GraphQLParser/AST/GraphQLDirective.cs +++ b/src/GraphQLParser/AST/GraphQLDirective.cs @@ -3,17 +3,20 @@ namespace GraphQLParser.AST { /// - /// Represents a directive, applied to some GraphQL element. + /// AST node for . /// public class GraphQLDirective : ASTNode, INamedNode, IHasArgumentsNode { - public List? Arguments { get; set; } - /// public override ASTNodeKind Kind => ASTNodeKind.Directive; /// public GraphQLName? Name { get; set; } + + /// + /// List of arguments for this directive. + /// + public List? Arguments { get; set; } } internal sealed class GraphQLDirectiveWithLocation : GraphQLDirective diff --git a/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs b/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs index a27dcda1..8b80b0a9 100644 --- a/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs @@ -3,15 +3,18 @@ namespace GraphQLParser.AST { /// - /// Represents a directive definition. + /// AST node for . /// public class GraphQLDirectiveDefinition : GraphQLTypeDefinition { - public List? Arguments { get; set; } - /// public override ASTNodeKind Kind => ASTNodeKind.DirectiveDefinition; + /// + /// List of arguments for this directive definition. + /// + public List? Arguments { get; set; } + /// /// Returns a list of locations representing the valid locations this directive may be placed. /// diff --git a/src/GraphQLParser/AST/GraphQLDocument.cs b/src/GraphQLParser/AST/GraphQLDocument.cs index 21383763..79e96f0b 100644 --- a/src/GraphQLParser/AST/GraphQLDocument.cs +++ b/src/GraphQLParser/AST/GraphQLDocument.cs @@ -5,10 +5,13 @@ namespace GraphQLParser.AST { /// - /// Represents the root of AST (Abstract Syntax Tree) for GraphQL document. + /// AST node for . /// public class GraphQLDocument : ASTNode, IDisposable { + /// + public override ASTNodeKind Kind => ASTNodeKind.Document; + // In some cases, the parser is forced to change the text (escape symbols, comments), // so it is impossible to simply point to the desired section (span) of the source text. // In this case, array pools are used, memory from which then need to be returned to the pool. @@ -21,9 +24,6 @@ public class GraphQLDocument : ASTNode, IDisposable /// public List? UnattachedComments { get; set; } - /// - public override ASTNodeKind Kind => ASTNodeKind.Document; - protected virtual void Dispose(bool disposing) { if (disposing) diff --git a/src/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs index 1d61d691..1afd2c13 100644 --- a/src/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLEnumTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.EnumTypeDefinition; /// - public override ASTNodeKind Kind => ASTNodeKind.EnumTypeDefinition; + public List? Directives { get; set; } public List? Values { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLEnumValueDefinition.cs b/src/GraphQLParser/AST/GraphQLEnumValueDefinition.cs index d7b3230f..f6c7ee17 100644 --- a/src/GraphQLParser/AST/GraphQLEnumValueDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLEnumValueDefinition.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLEnumValueDefinition : GraphQLTypeDefinition, IHasDirectivesNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.EnumValueDefinition; /// - public override ASTNodeKind Kind => ASTNodeKind.EnumValueDefinition; + public List? Directives { get; set; } } internal sealed class GraphQLEnumValueDefinitionWithLocation : GraphQLEnumValueDefinition diff --git a/src/GraphQLParser/AST/GraphQLField.cs b/src/GraphQLParser/AST/GraphQLField.cs index b6085e89..7a210a09 100644 --- a/src/GraphQLParser/AST/GraphQLField.cs +++ b/src/GraphQLParser/AST/GraphQLField.cs @@ -2,8 +2,14 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLField : ASTNode, IHasDirectivesNode, IHasArgumentsNode, INamedNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.Field; + public GraphQLName? Alias { get; set; } public List? Arguments { get; set; } @@ -11,9 +17,6 @@ public class GraphQLField : ASTNode, IHasDirectivesNode, IHasArgumentsNode, INam /// public List? Directives { get; set; } - /// - public override ASTNodeKind Kind => ASTNodeKind.Field; - /// public GraphQLName? Name { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLFieldDefinition.cs b/src/GraphQLParser/AST/GraphQLFieldDefinition.cs index f637d477..d1cfd8b1 100644 --- a/src/GraphQLParser/AST/GraphQLFieldDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLFieldDefinition.cs @@ -2,16 +2,19 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLFieldDefinition : GraphQLTypeDefinition, IHasDirectivesNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.FieldDefinition; + public List? Arguments { get; set; } /// public List? Directives { get; set; } - /// - public override ASTNodeKind Kind => ASTNodeKind.FieldDefinition; - public GraphQLType? Type { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLFragmentDefinition.cs b/src/GraphQLParser/AST/GraphQLFragmentDefinition.cs index 120d4040..b07f0fce 100644 --- a/src/GraphQLParser/AST/GraphQLFragmentDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLFragmentDefinition.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLFragmentDefinition : GraphQLInlineFragment, INamedNode { /// diff --git a/src/GraphQLParser/AST/GraphQLFragmentSpread.cs b/src/GraphQLParser/AST/GraphQLFragmentSpread.cs index 2604677d..d9aff80e 100644 --- a/src/GraphQLParser/AST/GraphQLFragmentSpread.cs +++ b/src/GraphQLParser/AST/GraphQLFragmentSpread.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLFragmentSpread : ASTNode, IHasDirectivesNode, INamedNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.FragmentSpread; /// - public override ASTNodeKind Kind => ASTNodeKind.FragmentSpread; + public List? Directives { get; set; } /// public GraphQLName? Name { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLInlineFragment.cs b/src/GraphQLParser/AST/GraphQLInlineFragment.cs index bd8dd2cd..a82d8edd 100644 --- a/src/GraphQLParser/AST/GraphQLInlineFragment.cs +++ b/src/GraphQLParser/AST/GraphQLInlineFragment.cs @@ -2,6 +2,9 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLInlineFragment : ASTNode, IHasDirectivesNode { /// diff --git a/src/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs index 12a80d81..9d2da666 100644 --- a/src/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs @@ -2,15 +2,18 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLInputObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.InputObjectTypeDefinition; + /// public List? Directives { get; set; } public List? Fields { get; set; } - - /// - public override ASTNodeKind Kind => ASTNodeKind.InputObjectTypeDefinition; } internal sealed class GraphQLInputObjectTypeDefinitionWithLocation : GraphQLInputObjectTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs b/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs index 9f096589..014fde5c 100644 --- a/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs @@ -2,16 +2,19 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLInputValueDefinition : GraphQLTypeDefinition, IHasDirectivesNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.InputValueDefinition; + public GraphQLValue? DefaultValue { get; set; } /// public List? Directives { get; set; } - /// - public override ASTNodeKind Kind => ASTNodeKind.InputValueDefinition; - public GraphQLType? Type { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs index f5437cca..f7d01c29 100644 --- a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs @@ -2,17 +2,20 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLInterfaceTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode, IHasInterfacesNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.InterfaceTypeDefinition; + /// public List? Directives { get; set; } public List? Fields { get; set; } public List? Interfaces { get; set; } - - /// - public override ASTNodeKind Kind => ASTNodeKind.InterfaceTypeDefinition; } internal sealed class GraphQLInterfaceTypeDefinitionWithLocation : GraphQLInterfaceTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLListType.cs b/src/GraphQLParser/AST/GraphQLListType.cs index 9b3c70ec..26603e0c 100644 --- a/src/GraphQLParser/AST/GraphQLListType.cs +++ b/src/GraphQLParser/AST/GraphQLListType.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLListType : GraphQLType { /// diff --git a/src/GraphQLParser/AST/GraphQLListValue.cs b/src/GraphQLParser/AST/GraphQLListValue.cs index 4b65e5bb..62aa1750 100644 --- a/src/GraphQLParser/AST/GraphQLListValue.cs +++ b/src/GraphQLParser/AST/GraphQLListValue.cs @@ -2,20 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLListValue : GraphQLValue { - private readonly ASTNodeKind _kind; - - public GraphQLListValue(ASTNodeKind kind) - { - _kind = kind; - } + /// + public override ASTNodeKind Kind => ASTNodeKind.ListValue; public ROM AstValue { get; set; } - /// - public override ASTNodeKind Kind => _kind; - public List? Values { get; set; } /// @@ -26,11 +22,6 @@ internal sealed class GraphQLListValueWithLocation : GraphQLListValue { private GraphQLLocation _location; - public GraphQLListValueWithLocation(ASTNodeKind kind) - : base(kind) - { - } - public override GraphQLLocation Location { get => _location; @@ -42,11 +33,6 @@ internal sealed class GraphQLListValueWithComment : GraphQLListValue { private GraphQLComment? _comment; - public GraphQLListValueWithComment(ASTNodeKind kind) - : base(kind) - { - } - public override GraphQLComment? Comment { get => _comment; @@ -59,11 +45,6 @@ internal sealed class GraphQLListValueFull : GraphQLListValue private GraphQLLocation _location; private GraphQLComment? _comment; - public GraphQLListValueFull(ASTNodeKind kind) - : base(kind) - { - } - public override GraphQLLocation Location { get => _location; diff --git a/src/GraphQLParser/AST/GraphQLName.cs b/src/GraphQLParser/AST/GraphQLName.cs index 2a64ddb2..882795a9 100644 --- a/src/GraphQLParser/AST/GraphQLName.cs +++ b/src/GraphQLParser/AST/GraphQLName.cs @@ -2,7 +2,9 @@ namespace GraphQLParser.AST { - /// + /// + /// AST node for . + /// [DebuggerDisplay("{Value}")] public class GraphQLName : ASTNode { diff --git a/src/GraphQLParser/AST/GraphQLNamedType.cs b/src/GraphQLParser/AST/GraphQLNamedType.cs index 836c77db..8fcbe6e5 100644 --- a/src/GraphQLParser/AST/GraphQLNamedType.cs +++ b/src/GraphQLParser/AST/GraphQLNamedType.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLNamedType : GraphQLType, INamedNode { /// diff --git a/src/GraphQLParser/AST/GraphQLNonNullType.cs b/src/GraphQLParser/AST/GraphQLNonNullType.cs index 8c746356..4970c50f 100644 --- a/src/GraphQLParser/AST/GraphQLNonNullType.cs +++ b/src/GraphQLParser/AST/GraphQLNonNullType.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLNonNullType : GraphQLType { /// diff --git a/src/GraphQLParser/AST/GraphQLObjectField.cs b/src/GraphQLParser/AST/GraphQLObjectField.cs index 04183bf5..64a1759c 100644 --- a/src/GraphQLParser/AST/GraphQLObjectField.cs +++ b/src/GraphQLParser/AST/GraphQLObjectField.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLObjectField : ASTNode, INamedNode { /// diff --git a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs index 47870982..3cfe45ab 100644 --- a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs @@ -2,17 +2,20 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode, IHasInterfacesNode { + /// + public override ASTNodeKind Kind => ASTNodeKind.ObjectTypeDefinition; + /// public List? Directives { get; set; } public List? Fields { get; set; } public List? Interfaces { get; set; } - - /// - public override ASTNodeKind Kind => ASTNodeKind.ObjectTypeDefinition; } internal sealed class GraphQLObjectTypeDefinitionWithLocation : GraphQLObjectTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLObjectValue.cs b/src/GraphQLParser/AST/GraphQLObjectValue.cs index fd1f04ce..01f41ccd 100644 --- a/src/GraphQLParser/AST/GraphQLObjectValue.cs +++ b/src/GraphQLParser/AST/GraphQLObjectValue.cs @@ -2,12 +2,15 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLObjectValue : GraphQLValue { - public List? Fields { get; set; } - /// public override ASTNodeKind Kind => ASTNodeKind.ObjectValue; + + public List? Fields { get; set; } } internal sealed class GraphQLObjectValueWithLocation : GraphQLObjectValue diff --git a/src/GraphQLParser/AST/GraphQLOperationDefinition.cs b/src/GraphQLParser/AST/GraphQLOperationDefinition.cs index f91df112..b81cd231 100644 --- a/src/GraphQLParser/AST/GraphQLOperationDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLOperationDefinition.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLOperationDefinition : ASTNode, IHasDirectivesNode, INamedNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.OperationDefinition; /// - public override ASTNodeKind Kind => ASTNodeKind.OperationDefinition; + public List? Directives { get; set; } /// public GraphQLName? Name { get; set; } diff --git a/src/GraphQLParser/AST/GraphQLRootOperationTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLRootOperationTypeDefinition.cs index 9f226a0d..3983a886 100644 --- a/src/GraphQLParser/AST/GraphQLRootOperationTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLRootOperationTypeDefinition.cs @@ -1,12 +1,21 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLRootOperationTypeDefinition : ASTNode { /// public override ASTNodeKind Kind => ASTNodeKind.RootOperationTypeDefinition; + /// + /// Kind of operation: query, mutation or subscription. + /// public OperationType Operation { get; set; } + /// + /// Type of this root operation. + /// public GraphQLNamedType? Type { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs index 96048ade..cfee0c59 100644 --- a/src/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLScalarTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.ScalarTypeDefinition; /// - public override ASTNodeKind Kind => ASTNodeKind.ScalarTypeDefinition; + public List? Directives { get; set; } } internal sealed class GraphQLScalarTypeDefinitionWithLocation : GraphQLScalarTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs b/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs index a2cc04c5..e9d6d89d 100644 --- a/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs @@ -2,16 +2,19 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLSchemaDefinition : ASTNode, IHasDirectivesNode, IHasDescriptionNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.SchemaDefinition; /// - public GraphQLDescription? Description { get; set; } + public List? Directives { get; set; } /// - public override ASTNodeKind Kind => ASTNodeKind.SchemaDefinition; + public GraphQLDescription? Description { get; set; } public List? OperationTypes { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLSelectionSet.cs b/src/GraphQLParser/AST/GraphQLSelectionSet.cs index 8b4ba21f..521d98ea 100644 --- a/src/GraphQLParser/AST/GraphQLSelectionSet.cs +++ b/src/GraphQLParser/AST/GraphQLSelectionSet.cs @@ -2,6 +2,9 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLSelectionSet : ASTNode { /// diff --git a/src/GraphQLParser/AST/GraphQLType.cs b/src/GraphQLParser/AST/GraphQLType.cs index 63daa723..d64ec2fa 100644 --- a/src/GraphQLParser/AST/GraphQLType.cs +++ b/src/GraphQLParser/AST/GraphQLType.cs @@ -1,5 +1,14 @@ namespace GraphQLParser.AST { + /// + /// Base AST node for three type nodes: + ///
+ /// Named + ///
+ /// NonNull + ///
+ /// List + ///
public abstract class GraphQLType : ASTNode { } diff --git a/src/GraphQLParser/AST/GraphQLTypeCondition.cs b/src/GraphQLParser/AST/GraphQLTypeCondition.cs index 61251e5f..4715bba7 100644 --- a/src/GraphQLParser/AST/GraphQLTypeCondition.cs +++ b/src/GraphQLParser/AST/GraphQLTypeCondition.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLTypeCondition : ASTNode { /// diff --git a/src/GraphQLParser/AST/GraphQLTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLTypeDefinition.cs index 2f81b7a7..da937d2b 100644 --- a/src/GraphQLParser/AST/GraphQLTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLTypeDefinition.cs @@ -1,11 +1,14 @@ namespace GraphQLParser.AST { + /// + /// Base AST node for all type definition nodes. + /// public abstract class GraphQLTypeDefinition : ASTNode, INamedNode, IHasDescriptionNode { /// - public GraphQLName? Name { get; set; } + public GraphQLDescription? Description { get; set; } /// - public GraphQLDescription? Description { get; set; } + public GraphQLName? Name { get; set; } } } diff --git a/src/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs b/src/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs index e6f96760..718cb4c6 100644 --- a/src/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs @@ -1,11 +1,12 @@ namespace GraphQLParser.AST { + //TODO: change public class GraphQLTypeExtensionDefinition : GraphQLTypeDefinition { - public GraphQLObjectTypeDefinition? Definition { get; set; } - /// public override ASTNodeKind Kind => ASTNodeKind.TypeExtensionDefinition; + + public GraphQLObjectTypeDefinition? Definition { get; set; } } internal sealed class GraphQLTypeExtensionDefinitionWithLocation : GraphQLTypeExtensionDefinition diff --git a/src/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs index cc88601c..fec4adb3 100644 --- a/src/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs @@ -2,13 +2,16 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLUnionTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode { /// - public List? Directives { get; set; } + public override ASTNodeKind Kind => ASTNodeKind.UnionTypeDefinition; /// - public override ASTNodeKind Kind => ASTNodeKind.UnionTypeDefinition; + public List? Directives { get; set; } public List? Types { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLValue.cs b/src/GraphQLParser/AST/GraphQLValue.cs index 89c975c6..8b154e9d 100644 --- a/src/GraphQLParser/AST/GraphQLValue.cs +++ b/src/GraphQLParser/AST/GraphQLValue.cs @@ -1,5 +1,16 @@ namespace GraphQLParser.AST { + /// + /// Base AST node for four value nodes: + ///
+ /// Scalar + ///
+ /// List + ///
+ /// Object + ///
+ /// Variable + ///
public abstract class GraphQLValue : ASTNode { } diff --git a/src/GraphQLParser/AST/GraphQLVariable.cs b/src/GraphQLParser/AST/GraphQLVariable.cs index 5dba68f1..094e4894 100644 --- a/src/GraphQLParser/AST/GraphQLVariable.cs +++ b/src/GraphQLParser/AST/GraphQLVariable.cs @@ -1,5 +1,8 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLVariable : GraphQLValue, INamedNode { /// diff --git a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs index 2e6f1c09..7a8082ee 100644 --- a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs @@ -2,6 +2,9 @@ namespace GraphQLParser.AST { + /// + /// AST node for . + /// public class GraphQLVariableDefinition : ASTNode, IHasDirectivesNode { /// diff --git a/src/GraphQLParser/NodeHelper.cs b/src/GraphQLParser/NodeHelper.cs index 2bdc248f..0c000a13 100644 --- a/src/GraphQLParser/NodeHelper.cs +++ b/src/GraphQLParser/NodeHelper.cs @@ -192,14 +192,14 @@ public static GraphQLName CreateGraphQLName(IgnoreOptions options) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static GraphQLListValue CreateGraphQLListValue(IgnoreOptions options, ASTNodeKind kind) + public static GraphQLListValue CreateGraphQLListValue(IgnoreOptions options) { return options switch { - IgnoreOptions.All => new GraphQLListValue(kind), - IgnoreOptions.Comments => new GraphQLListValueWithLocation(kind), - IgnoreOptions.Locations => new GraphQLListValueWithComment(kind), - _ => new GraphQLListValueFull(kind), + IgnoreOptions.All => new GraphQLListValue(), + IgnoreOptions.Comments => new GraphQLListValueWithLocation(), + IgnoreOptions.Locations => new GraphQLListValueWithComment(), + _ => new GraphQLListValueFull(), }; } diff --git a/src/GraphQLParser/ParserContext.Parse.cs b/src/GraphQLParser/ParserContext.Parse.cs index 7654ab52..015349d7 100644 --- a/src/GraphQLParser/ParserContext.Parse.cs +++ b/src/GraphQLParser/ParserContext.Parse.cs @@ -628,7 +628,7 @@ private GraphQLValue ParseListValue(bool isConstant) ParseCallback constant = (ref ParserContext context) => context.ParseValueLiteral(true); ParseCallback value = (ref ParserContext context) => context.ParseValueLiteral(false); - var val = NodeHelper.CreateGraphQLListValue(_ignoreOptions, ASTNodeKind.ListValue); + var val = NodeHelper.CreateGraphQLListValue(_ignoreOptions); val.Values = ZeroOrMore(TokenKind.BRACKET_L, isConstant ? constant : value, TokenKind.BRACKET_R); val.AstValue = _source.Slice(start, _currentToken.End - start - 1); val.Comment = comment; diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index e5323846..cef01d01 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -389,6 +389,11 @@ public virtual ValueTask Visit(ASTNode? node, TContext context) }; } + /// + /// Visits all nodes from the provided list. As a rule, these are nested + /// sibling nodes of some parent node, for example, argument nodes for + /// parent field node or value nodes for parent list node. + /// protected async ValueTask Visit(List? nodes, TContext context) where T : ASTNode { diff --git a/src/GraphQLParser/Visitors/INodeVisitorContext.cs b/src/GraphQLParser/Visitors/INodeVisitorContext.cs index 4fd58291..dc596446 100644 --- a/src/GraphQLParser/Visitors/INodeVisitorContext.cs +++ b/src/GraphQLParser/Visitors/INodeVisitorContext.cs @@ -1,3 +1,5 @@ +using System.Threading; + namespace GraphQLParser.Visitors { /// @@ -5,5 +7,9 @@ namespace GraphQLParser.Visitors /// public interface INodeVisitorContext { + /// + /// The token to monitor for cancellation requests. + /// + CancellationToken CancellationToken { get; } } } diff --git a/src/GraphQLParser/Visitors/IWriteContext.cs b/src/GraphQLParser/Visitors/IWriteContext.cs index ee7df835..c6d72f38 100644 --- a/src/GraphQLParser/Visitors/IWriteContext.cs +++ b/src/GraphQLParser/Visitors/IWriteContext.cs @@ -3,10 +3,19 @@ namespace GraphQLParser.Visitors { + /// + /// Context used by and . + /// public interface IWriteContext : INodeVisitorContext { + /// + /// A writer to write document. + /// TextWriter Writer { get; } + /// + /// Stack of AST nodes to track the current visitor position. + /// Stack Parent { get; } } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 2e1f4f10..41a56d23 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -22,7 +22,7 @@ public override async ValueTask VisitDocument(GraphQLDocument document, TContext if (i < document.Definitions.Count - 1) { - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } } } @@ -40,7 +40,7 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co if (needStartNewLine) { await WriteIndent(context, level); - await context.Writer.WriteAsync('#'); + await context.Write("#"); needStartNewLine = false; } @@ -51,17 +51,17 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co break; case '\n': - await context.Writer.WriteLineAsync(); + await context.WriteLine(); needStartNewLine = true; break; default: - await context.Writer.WriteAsync(current); + await context.Write(comment.Text.Slice(i, 1)/*current*/); break; } } - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } /// @@ -70,8 +70,8 @@ public override async ValueTask VisitDescription(GraphQLDescription description, int level = GetLevel(context); await WriteIndent(context, level); - await context.Writer.WriteAsync("\"\"\""); - await context.Writer.WriteLineAsync(); + await context.Write("\"\"\""); + await context.WriteLine(); bool needStartNewLine = true; int length = description.Value.Span.Length; @@ -90,36 +90,36 @@ public override async ValueTask VisitDescription(GraphQLDescription description, break; case '\n': - await context.Writer.WriteLineAsync(); + await context.WriteLine(); needStartNewLine = true; break; default: - await context.Writer.WriteAsync(current); + await context.Write(description.Value.Slice(i, 1)/*current*/); //TODO: change break; } } - await context.Writer.WriteLineAsync(); + await context.WriteLine(); await WriteIndent(context, level); - await context.Writer.WriteAsync("\"\"\""); - await context.Writer.WriteLineAsync(); + await context.Write("\"\"\""); + await context.WriteLine(); } /// public override async ValueTask VisitName(GraphQLName name, TContext context) { await Visit(name.Comment, context); - await Write(context, name.Value); + await context.Write(name.Value); } /// public override async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) { await Visit(fragmentDefinition.Comment, context); - await context.Writer.WriteAsync("fragment "); + await context.Write("fragment "); await Visit(fragmentDefinition.Name, context); - await context.Writer.WriteAsync(" "); + await context.Write(" "); await Visit(fragmentDefinition.TypeCondition, context); await VisitDirectives(fragmentDefinition, context); await Visit(fragmentDefinition.SelectionSet, context); @@ -133,10 +133,10 @@ public override async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragme int level = GetLevel(context); await WriteIndent(context, level); - await context.Writer.WriteAsync("..."); + await context.Write("..."); await Visit(fragmentSpread.Name, context); await VisitDirectives(fragmentSpread, context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } /// @@ -147,16 +147,17 @@ public override async ValueTask VisitInlineFragment(GraphQLInlineFragment inline int level = GetLevel(context); await WriteIndent(context, level); - await context.Writer.WriteAsync("... "); + await context.Write("... "); await Visit(inlineFragment.TypeCondition, context); await VisitDirectives(inlineFragment, context); await Visit(inlineFragment.SelectionSet, context); } + /// public override async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context) { await Visit(typeCondition.Comment, context); - await context.Writer.WriteAsync("on "); + await context.Write("on "); await Visit(typeCondition.Type, context); } @@ -164,10 +165,11 @@ public override async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCond public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) { await Visit(selectionSet.Comment, context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); int level = GetLevel(context); await WriteIndent(context, level); - await context.Writer.WriteLineAsync('{'); + await context.Write("{"); + await context.WriteLine(); if (selectionSet.Selections?.Count > 0) { @@ -176,7 +178,8 @@ public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionS } await WriteIndent(context, level); - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } /// @@ -190,19 +193,19 @@ public override async ValueTask VisitField(GraphQLField field, TContext context) if (field.Alias != null) { await Visit(field.Alias, context); - await context.Writer.WriteAsync(": "); + await context.Write(": "); } await Visit(field.Name, context); if (field.Arguments != null) { - await context.Writer.WriteAsync('('); + await context.Write("("); await VisitArguments(field, context); - await context.Writer.WriteAsync(')'); + await context.Write(")"); } await VisitDirectives(field, context); if (field.SelectionSet == null) - await context.Writer.WriteLineAsync(); + await context.WriteLine(); else await Visit(field.SelectionSet, context); } @@ -214,24 +217,24 @@ public override async ValueTask VisitOperationDefinition(GraphQLOperationDefinit if (operationDefinition.Name != null) { - await context.Writer.WriteAsync(GetOperationType(operationDefinition.Operation)); - await context.Writer.WriteAsync(' '); + await context.Write(GetOperationType(operationDefinition.Operation)); + await context.Write(" "); await Visit(operationDefinition.Name, context); } if (operationDefinition.VariableDefinitions?.Count > 0) { - await context.Writer.WriteAsync('('); + await context.Write("("); if (operationDefinition.VariableDefinitions?.Count > 0) { for (int i = 0; i < operationDefinition.VariableDefinitions.Count; ++i) { await Visit(operationDefinition.VariableDefinitions[i], context); if (i < operationDefinition.VariableDefinitions.Count - 1) - await context.Writer.WriteAsync(", "); + await context.Write(", "); } } - await context.Writer.WriteAsync(')'); + await context.Write(")"); } await VisitDirectives(operationDefinition, context); @@ -243,13 +246,13 @@ public override async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinit { await Visit(directiveDefinition.Comment, context); await Visit(directiveDefinition.Description, context); - await context.Writer.WriteAsync("directive "); + await context.Write("directive "); await Visit(directiveDefinition.Name, context); if (directiveDefinition.Arguments != null) { - await context.Writer.WriteAsync('('); + await context.Write("("); await Visit(directiveDefinition, context); - await context.Writer.WriteAsync(')'); + await context.Write(")"); } } @@ -258,11 +261,11 @@ public override async ValueTask VisitVariableDefinition(GraphQLVariableDefinitio { await Visit(variableDefinition.Comment, context); await Visit(variableDefinition.Variable, context); - await context.Writer.WriteAsync(": "); + await context.Write(": "); await Visit(variableDefinition.Type, context); if (variableDefinition.DefaultValue != null) { - await context.Writer.WriteAsync(" = "); + await context.Write(" = "); await Visit(variableDefinition.DefaultValue, context); } await VisitDirectives(variableDefinition, context); @@ -272,7 +275,7 @@ public override async ValueTask VisitVariableDefinition(GraphQLVariableDefinitio public override async ValueTask VisitVariable(GraphQLVariable variable, TContext context) { await Visit(variable.Comment, context); - await context.Writer.WriteAsync('$'); + await context.Write("$"); await Visit(variable.Name, context); } @@ -280,7 +283,7 @@ public override async ValueTask VisitVariable(GraphQLVariable variable, TContext public override async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) { await Visit(booleanValue.Comment, context); - await Write(context, booleanValue.Value); + await context.Write(booleanValue.Value); } /// @@ -288,10 +291,10 @@ public override async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefin { await Visit(scalarTypeDefinition.Comment, context); await Visit(scalarTypeDefinition.Description, context); - await context.Writer.WriteAsync("scalar "); + await context.Write("scalar "); await Visit(scalarTypeDefinition.Name, context); await VisitDirectives(scalarTypeDefinition, context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } /// @@ -299,19 +302,21 @@ public override async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinitio { await Visit(enumTypeDefinition.Comment, context); await Visit(enumTypeDefinition.Description, context); - await context.Writer.WriteAsync("enum "); + await context.Write("enum "); await Visit(enumTypeDefinition.Name, context); await VisitDirectives(enumTypeDefinition, context); if (enumTypeDefinition.Values?.Count > 0) { - await context.Writer.WriteLineAsync(); - await context.Writer.WriteLineAsync('{'); + await context.WriteLine(); + await context.Write("{"); + await context.WriteLine(); for (int i = 0; i < enumTypeDefinition.Values.Count; ++i) { await Visit(enumTypeDefinition.Values[i], context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } } @@ -333,25 +338,27 @@ public override async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjec { await Visit(inputObjectTypeDefinition.Comment, context); await Visit(inputObjectTypeDefinition.Description, context); - await context.Writer.WriteAsync("input "); + await context.Write("input "); await Visit(inputObjectTypeDefinition.Name, context); await VisitDirectives(inputObjectTypeDefinition, context); if (inputObjectTypeDefinition.Fields?.Count > 0) { - await context.Writer.WriteLineAsync(); - await context.Writer.WriteLineAsync('{'); + await context.WriteLine(); + await context.Write("{"); + await context.WriteLine(); for (int i = 0; i < inputObjectTypeDefinition.Fields.Count; ++i) { await Visit(inputObjectTypeDefinition.Fields[i], context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } else { - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } } @@ -365,11 +372,11 @@ public override async ValueTask VisitInputValueDefinition(GraphQLInputValueDefin await WriteIndent(context, level); await Visit(inputValueDefinition.Name, context); - await context.Writer.WriteAsync(": "); + await context.Write(": "); await Visit(inputValueDefinition.Type, context); if (inputValueDefinition.DefaultValue != null) { - await context.Writer.WriteAsync(" = "); + await context.Write(" = "); await Visit(inputValueDefinition.DefaultValue, context); } await VisitDirectives(inputValueDefinition, context); @@ -380,27 +387,29 @@ public override async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefin { await Visit(objectTypeDefinition.Comment, context); await Visit(objectTypeDefinition.Description, context); - await context.Writer.WriteAsync("type "); + await context.Write("type "); await Visit(objectTypeDefinition.Name, context); await VisitInterfaces(objectTypeDefinition, context); await VisitDirectives(objectTypeDefinition, context); if (objectTypeDefinition.Fields?.Count > 0) { - await context.Writer.WriteLineAsync(); - await context.Writer.WriteLineAsync('{'); + await context.WriteLine(); + await context.Write("{"); + await context.WriteLine(); for (int i = 0; i < objectTypeDefinition.Fields.Count; ++i) { await Visit(objectTypeDefinition.Fields[i], context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } else { - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } } @@ -409,23 +418,25 @@ public override async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTyp { await Visit(interfaceTypeDefinition.Comment, context); await Visit(interfaceTypeDefinition.Description, context); - await context.Writer.WriteAsync("interface "); + await context.Write("interface "); await Visit(interfaceTypeDefinition.Name, context); await VisitInterfaces(interfaceTypeDefinition, context); await VisitDirectives(interfaceTypeDefinition, context); - await context.Writer.WriteLineAsync(); - await context.Writer.WriteLineAsync('{'); + await context.WriteLine(); + await context.Write("{"); + await context.WriteLine(); if (interfaceTypeDefinition.Fields?.Count > 0) { for (int i = 0; i < interfaceTypeDefinition.Fields.Count; ++i) { await Visit(interfaceTypeDefinition.Fields[i], context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } } - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } /// @@ -440,16 +451,16 @@ public override async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fiel await Visit(fieldDefinition.Name, context); if (fieldDefinition.Arguments?.Count > 0) { - await context.Writer.WriteAsync('('); + await context.Write("("); for (int i = 0; i < fieldDefinition.Arguments.Count; ++i) { await Visit(fieldDefinition.Arguments[i], context); if (i < fieldDefinition.Arguments.Count - 1) - await context.Writer.WriteAsync(", "); + await context.Write(", "); } - await context.Writer.WriteAsync(')'); + await context.Write(")"); } - await context.Writer.WriteAsync(": "); + await context.Write(": "); await Visit(fieldDefinition.Type, context); await VisitDirectives(fieldDefinition, context); } @@ -459,22 +470,24 @@ public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition sc { await Visit(schemaDefinition.Comment, context); await Visit(schemaDefinition.Description, context); - await context.Writer.WriteAsync("schema"); + await context.Write("schema"); await VisitDirectives(schemaDefinition, context); - await context.Writer.WriteLineAsync(); - await context.Writer.WriteLineAsync('{'); + await context.WriteLine(); + await context.Write("{"); + await context.WriteLine(); if (schemaDefinition.OperationTypes?.Count > 0) { for (int i = 0; i < schemaDefinition.OperationTypes.Count; ++i) { await Visit(schemaDefinition.OperationTypes[i], context); - await context.Writer.WriteLineAsync(); + await context.WriteLine(); } } - await context.Writer.WriteLineAsync('}'); + await context.Write("}"); + await context.WriteLine(); } /// @@ -485,8 +498,8 @@ public override async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOper int level = GetLevel(context); await WriteIndent(context, level); - await context.Writer.WriteAsync(GetOperationType(rootOperationTypeDefinition.Operation)); - await context.Writer.WriteAsync(": "); + await context.Write(GetOperationType(rootOperationTypeDefinition.Operation)); + await context.Write(": "); await Visit(rootOperationTypeDefinition.Type, context); } @@ -495,19 +508,19 @@ public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinit { await Visit(unionTypeDefinition.Comment, context); await Visit(unionTypeDefinition.Description, context); - await context.Writer.WriteAsync("union "); + await context.Write("union "); await Visit(unionTypeDefinition.Name, context); await VisitDirectives(unionTypeDefinition, context); if (unionTypeDefinition.Types?.Count > 0) { - await context.Writer.WriteAsync(" = "); + await context.Write(" = "); for (int i = 0; i < unionTypeDefinition.Types.Count; ++i) { await Visit(unionTypeDefinition.Types[i], context); if (i < unionTypeDefinition.Types.Count - 1) - await context.Writer.WriteAsync(" | "); + await context.Write(" | "); } } } @@ -516,13 +529,13 @@ public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinit public override async ValueTask VisitDirective(GraphQLDirective directive, TContext context) { await Visit(directive.Comment, context); - await context.Writer.WriteAsync('@'); + await context.Write("@"); await Visit(directive.Name, context); if (directive.Arguments != null) { - await context.Writer.WriteAsync('('); + await context.Write("("); await VisitArguments(directive, context); - await context.Writer.WriteAsync(')'); + await context.Write(")"); } } @@ -531,7 +544,7 @@ public override async ValueTask VisitArgument(GraphQLArgument argument, TContext { await Visit(argument.Comment, context); await Visit(argument.Name, context); - await context.Writer.WriteAsync(": "); + await context.Write(": "); await Visit(argument.Value, context); } @@ -540,16 +553,16 @@ public override async ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, { await Visit(nonNullType.Comment, context); await Visit(nonNullType.Type, context); - await context.Writer.WriteAsync('!'); + await context.Write("!"); } /// public override async ValueTask VisitListType(GraphQLListType listType, TContext context) { await Visit(listType.Comment, context); - await context.Writer.WriteAsync('['); + await context.Write("["); await Visit(listType.Type, context); - await context.Writer.WriteAsync(']'); + await context.Write("]"); } /// @@ -558,14 +571,14 @@ public override async ValueTask VisitListValue(GraphQLListValue listValue, TCont await Visit(listValue.Comment, context); if (listValue.Values?.Count > 0) { - await context.Writer.WriteAsync('['); + await context.Write("["); for (int i = 0; i < listValue.Values.Count; ++i) { await Visit(listValue.Values[i], context); if (i < listValue.Values.Count - 1) - await context.Writer.WriteAsync(", "); + await context.Write(", "); } - await context.Writer.WriteAsync(']'); + await context.Write("]"); } } @@ -573,37 +586,37 @@ public override async ValueTask VisitListValue(GraphQLListValue listValue, TCont public override async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context) { await Visit(nullValue.Comment, context); - await context.Writer.WriteAsync("null"); + await context.Write("null"); } /// public override async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { await Visit(stringValue.Comment, context); - await context.Writer.WriteAsync('\"'); - await Write(context, stringValue.Value); - await context.Writer.WriteAsync('\"'); + await context.Write("\""); + await context.Write(stringValue.Value); + await context.Write("\""); } /// public override async ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context) { await Visit(intValue.Comment, context); - await Write(context, intValue.Value); + await context.Write(intValue.Value); } /// public override async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context) { await Visit(floatValue.Comment, context); - await Write(context, floatValue.Value); + await context.Write(floatValue.Value); } /// public override async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context) { await Visit(enumValue.Comment, context); - await Write(context, enumValue.Value); + await context.Write(enumValue.Value); } /// @@ -613,18 +626,18 @@ public override async ValueTask VisitObjectValue(GraphQLObjectValue objectValue, if (objectValue.Fields?.Count > 0) { - await context.Writer.WriteAsync("{ "); + await context.Write("{ "); for (int i = 0; i < objectValue.Fields.Count; ++i) { await Visit(objectValue.Fields[i], context); if (i < objectValue.Fields.Count - 1) - await context.Writer.WriteAsync(", "); + await context.Write(", "); } - await context.Writer.WriteAsync(" }"); + await context.Write(" }"); } else { - await context.Writer.WriteAsync("{ }"); + await context.Write("{ }"); } } @@ -633,7 +646,7 @@ public override async ValueTask VisitObjectField(GraphQLObjectField objectField, { await Visit(objectField.Comment, context); await Visit(objectField.Name, context); - await context.Writer.WriteAsync(": "); + await context.Write(": "); await Visit(objectField.Value, context); } @@ -664,7 +677,7 @@ private async ValueTask VisitArguments(IHasArgumentsNode node, TContext context) { await Visit(node.Arguments[i], context); if (i < node.Arguments.Count - 1) - await context.Writer.WriteAsync(", "); + await context.Write(", "); } } } @@ -673,13 +686,13 @@ private async ValueTask VisitInterfaces(IHasInterfacesNode node, TContext contex { if (node.Interfaces?.Count > 0) { - await context.Writer.WriteAsync(" implements "); + await context.Write(" implements "); for (int i = 0; i < node.Interfaces.Count; ++i) { await Visit(node.Interfaces[i], context); if (i < node.Interfaces.Count - 1) - await context.Writer.WriteAsync(" & "); + await context.Write(" & "); } } } @@ -688,13 +701,13 @@ private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext contex { if (node.Directives?.Count > 0) { - await context.Writer.WriteAsync(' '); + await context.Write(" "); for (int i = 0; i < node.Directives.Count; ++i) { await Visit(node.Directives[i], context); if (i < node.Directives.Count - 1) - await context.Writer.WriteAsync(' '); + await context.Write(" "); } } } @@ -709,7 +722,7 @@ private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext contex private async ValueTask WriteIndent(TContext context, int level) { for (int i = 0; i < level; ++i) - await context.Writer.WriteAsync(" "); + await context.Write(" "); } private int GetLevel(TContext context) @@ -739,16 +752,5 @@ node is GraphQLInputObjectTypeDefinition || return level; } - - private ValueTask Write(TContext context, ROM value) - { - var task = -#if NETSTANDARD2_0 - context.Writer.WriteAsync(value.ToString()); -#elif NETSTANDARD2_1_OR_GREATER - context.Writer.WriteAsync(value); -#endif - return new ValueTask(task); - } } } diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs index f83a903b..ec684c25 100644 --- a/src/GraphQLParser/Visitors/StructureWriter.cs +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -18,10 +18,11 @@ public override async ValueTask Visit(ASTNode? node, TContext context) return; for (int i = 0; i < context.Parent.Count; ++i) - await context.Writer.WriteAsync(" "); + await context.Write(" "); context.Parent.Push(node); - await context.Writer.WriteLineAsync(node.Kind.ToString()); + await context.Write(node.Kind.ToString()); + await context.WriteLine(); await base.Visit(node, context); context.Parent.Pop(); } diff --git a/src/GraphQLParser/Visitors/WriteContextExtensions.cs b/src/GraphQLParser/Visitors/WriteContextExtensions.cs new file mode 100644 index 00000000..e2f1915e --- /dev/null +++ b/src/GraphQLParser/Visitors/WriteContextExtensions.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace GraphQLParser.Visitors +{ + /// + /// Extension methods for writing into . + /// + public static class WriteContextExtensions + { + private static readonly ROM _newLine = Environment.NewLine; + + /// + /// Writes the specified to the provided context + /// using from it. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask Write(this TContext context, ROM value) + where TContext : IWriteContext + { + var task = +#if NETSTANDARD2_0 + // no cancellationToken support on netstandard2.0 + context.Writer.WriteAsync(value.ToString()); +#elif NETSTANDARD2_1_OR_GREATER + context.Writer.WriteAsync(value, context.CancellationToken); +#endif + return new ValueTask(task); + } + + /// + /// Writes to the provided context + /// using from it. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask WriteLine(this TContext context) + where TContext : IWriteContext + => Write(context, _newLine); + } +} From 6cf5c77ece296f308962099e0e2787e58992d0bc Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 23:16:13 +0300 Subject: [PATCH 08/18] reorder ASTNodes properties according to the spec grammar --- src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs | 10 +++++----- src/GraphQLParser/AST/GraphQLDocument.cs | 10 +++++----- src/GraphQLParser/AST/GraphQLField.cs | 6 +++--- src/GraphQLParser/AST/GraphQLFieldDefinition.cs | 4 ++-- src/GraphQLParser/AST/GraphQLFragmentSpread.cs | 4 ++-- src/GraphQLParser/AST/GraphQLInputValueDefinition.cs | 4 ++-- .../AST/GraphQLInterfaceTypeDefinition.cs | 4 ++-- src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs | 4 ++-- src/GraphQLParser/AST/GraphQLOperationDefinition.cs | 10 +++++----- src/GraphQLParser/AST/GraphQLSchemaDefinition.cs | 4 ++-- src/GraphQLParser/AST/GraphQLVariableDefinition.cs | 4 ++-- 11 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs b/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs index 8b80b0a9..ee985066 100644 --- a/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLDirectiveDefinition.cs @@ -15,11 +15,6 @@ public class GraphQLDirectiveDefinition : GraphQLTypeDefinition /// public List? Arguments { get; set; } - /// - /// Returns a list of locations representing the valid locations this directive may be placed. - /// - public List? Locations { get; set; } - /// /// Indicates if the directive may be used repeatedly at a single location. ///

@@ -29,6 +24,11 @@ public class GraphQLDirectiveDefinition : GraphQLTypeDefinition /// provided to a type or schema extension via a directive ///
public bool Repeatable { get; set; } + + /// + /// Returns a list of locations representing the valid locations this directive may be placed. + /// + public List? Locations { get; set; } } internal sealed class GraphQLDirectiveDefinitionWithLocation : GraphQLDirectiveDefinition diff --git a/src/GraphQLParser/AST/GraphQLDocument.cs b/src/GraphQLParser/AST/GraphQLDocument.cs index 79e96f0b..4215b748 100644 --- a/src/GraphQLParser/AST/GraphQLDocument.cs +++ b/src/GraphQLParser/AST/GraphQLDocument.cs @@ -12,11 +12,6 @@ public class GraphQLDocument : ASTNode, IDisposable /// public override ASTNodeKind Kind => ASTNodeKind.Document; - // In some cases, the parser is forced to change the text (escape symbols, comments), - // so it is impossible to simply point to the desired section (span) of the source text. - // In this case, array pools are used, memory from which then need to be returned to the pool. - internal List<(IMemoryOwner owner, ASTNode rentedBy)>? RentedMemoryTracker { get; set; } - public List? Definitions { get; set; } /// @@ -24,6 +19,11 @@ public class GraphQLDocument : ASTNode, IDisposable /// public List? UnattachedComments { get; set; } + // In some cases, the parser is forced to change the text (escape symbols, comments), + // so it is impossible to simply point to the desired section (span) of the source text. + // In this case, array pools are used, memory from which then need to be returned to the pool. + internal List<(IMemoryOwner owner, ASTNode rentedBy)>? RentedMemoryTracker { get; set; } + protected virtual void Dispose(bool disposing) { if (disposing) diff --git a/src/GraphQLParser/AST/GraphQLField.cs b/src/GraphQLParser/AST/GraphQLField.cs index 7a210a09..76a76d76 100644 --- a/src/GraphQLParser/AST/GraphQLField.cs +++ b/src/GraphQLParser/AST/GraphQLField.cs @@ -12,14 +12,14 @@ public class GraphQLField : ASTNode, IHasDirectivesNode, IHasArgumentsNode, INam public GraphQLName? Alias { get; set; } + /// + public GraphQLName? Name { get; set; } + public List? Arguments { get; set; } /// public List? Directives { get; set; } - /// - public GraphQLName? Name { get; set; } - public GraphQLSelectionSet? SelectionSet { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLFieldDefinition.cs b/src/GraphQLParser/AST/GraphQLFieldDefinition.cs index d1cfd8b1..23b4f0f9 100644 --- a/src/GraphQLParser/AST/GraphQLFieldDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLFieldDefinition.cs @@ -12,10 +12,10 @@ public class GraphQLFieldDefinition : GraphQLTypeDefinition, IHasDirectivesNode public List? Arguments { get; set; } + public GraphQLType? Type { get; set; } + /// public List? Directives { get; set; } - - public GraphQLType? Type { get; set; } } internal sealed class GraphQLFieldDefinitionWithLocation : GraphQLFieldDefinition diff --git a/src/GraphQLParser/AST/GraphQLFragmentSpread.cs b/src/GraphQLParser/AST/GraphQLFragmentSpread.cs index d9aff80e..cd35f3ab 100644 --- a/src/GraphQLParser/AST/GraphQLFragmentSpread.cs +++ b/src/GraphQLParser/AST/GraphQLFragmentSpread.cs @@ -11,10 +11,10 @@ public class GraphQLFragmentSpread : ASTNode, IHasDirectivesNode, INamedNode public override ASTNodeKind Kind => ASTNodeKind.FragmentSpread; /// - public List? Directives { get; set; } + public GraphQLName? Name { get; set; } /// - public GraphQLName? Name { get; set; } + public List? Directives { get; set; } } internal sealed class GraphQLFragmentSpreadWithLocation : GraphQLFragmentSpread diff --git a/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs b/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs index 014fde5c..06a691ad 100644 --- a/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInputValueDefinition.cs @@ -10,12 +10,12 @@ public class GraphQLInputValueDefinition : GraphQLTypeDefinition, IHasDirectives /// public override ASTNodeKind Kind => ASTNodeKind.InputValueDefinition; + public GraphQLType? Type { get; set; } + public GraphQLValue? DefaultValue { get; set; } /// public List? Directives { get; set; } - - public GraphQLType? Type { get; set; } } internal sealed class GraphQLInputValueDefinitionWithLocation : GraphQLInputValueDefinition diff --git a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs index f7d01c29..6d44d4ce 100644 --- a/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs @@ -10,12 +10,12 @@ public class GraphQLInterfaceTypeDefinition : GraphQLTypeDefinition, IHasDirecti /// public override ASTNodeKind Kind => ASTNodeKind.InterfaceTypeDefinition; + public List? Interfaces { get; set; } + /// public List? Directives { get; set; } public List? Fields { get; set; } - - public List? Interfaces { get; set; } } internal sealed class GraphQLInterfaceTypeDefinitionWithLocation : GraphQLInterfaceTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs index 3cfe45ab..1e8508ea 100644 --- a/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs @@ -10,12 +10,12 @@ public class GraphQLObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectives /// public override ASTNodeKind Kind => ASTNodeKind.ObjectTypeDefinition; + public List? Interfaces { get; set; } + /// public List? Directives { get; set; } public List? Fields { get; set; } - - public List? Interfaces { get; set; } } internal sealed class GraphQLObjectTypeDefinitionWithLocation : GraphQLObjectTypeDefinition diff --git a/src/GraphQLParser/AST/GraphQLOperationDefinition.cs b/src/GraphQLParser/AST/GraphQLOperationDefinition.cs index b81cd231..71c953fb 100644 --- a/src/GraphQLParser/AST/GraphQLOperationDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLOperationDefinition.cs @@ -10,17 +10,17 @@ public class GraphQLOperationDefinition : ASTNode, IHasDirectivesNode, INamedNod /// public override ASTNodeKind Kind => ASTNodeKind.OperationDefinition; - /// - public List? Directives { get; set; } + public OperationType Operation { get; set; } /// public GraphQLName? Name { get; set; } - public OperationType Operation { get; set; } + public List? VariableDefinitions { get; set; } - public GraphQLSelectionSet? SelectionSet { get; set; } + /// + public List? Directives { get; set; } - public List? VariableDefinitions { get; set; } + public GraphQLSelectionSet? SelectionSet { get; set; } } internal sealed class GraphQLOperationDefinitionWithLocation : GraphQLOperationDefinition diff --git a/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs b/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs index e9d6d89d..87c7587f 100644 --- a/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLSchemaDefinition.cs @@ -11,10 +11,10 @@ public class GraphQLSchemaDefinition : ASTNode, IHasDirectivesNode, IHasDescript public override ASTNodeKind Kind => ASTNodeKind.SchemaDefinition; /// - public List? Directives { get; set; } + public GraphQLDescription? Description { get; set; } /// - public GraphQLDescription? Description { get; set; } + public List? Directives { get; set; } public List? OperationTypes { get; set; } } diff --git a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs index 7a8082ee..fffb5806 100644 --- a/src/GraphQLParser/AST/GraphQLVariableDefinition.cs +++ b/src/GraphQLParser/AST/GraphQLVariableDefinition.cs @@ -10,11 +10,11 @@ public class GraphQLVariableDefinition : ASTNode, IHasDirectivesNode /// public override ASTNodeKind Kind => ASTNodeKind.VariableDefinition; - public GraphQLValue? DefaultValue { get; set; } + public GraphQLVariable? Variable { get; set; } public GraphQLType? Type { get; set; } - public GraphQLVariable? Variable { get; set; } + public GraphQLValue? DefaultValue { get; set; } /// public List? Directives { get; set; } From 405f6acbc42267a0021dd7ec32a815bafebb83c0 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 23:17:45 +0300 Subject: [PATCH 09/18] encoding --- src/GraphQLParser/Visitors/WriteContextExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GraphQLParser/Visitors/WriteContextExtensions.cs b/src/GraphQLParser/Visitors/WriteContextExtensions.cs index e2f1915e..cd6463c4 100644 --- a/src/GraphQLParser/Visitors/WriteContextExtensions.cs +++ b/src/GraphQLParser/Visitors/WriteContextExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Runtime.CompilerServices; using System.Threading; From 856d2f0c2f16ffa5633f5ae486d6836c71fcb788 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 23:36:39 +0300 Subject: [PATCH 10/18] configureawait everywhere --- .../Visitors/DefaultNodeVisitor.cs | 245 +++++---- src/GraphQLParser/Visitors/SDLWriter.cs | 502 +++++++++--------- src/GraphQLParser/Visitors/StructureWriter.cs | 8 +- 3 files changed, 377 insertions(+), 378 deletions(-) diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index cef01d01..33665f5f 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -16,15 +16,15 @@ public class DefaultNodeVisitor : INodeVisitor /// public virtual async ValueTask VisitDocument(GraphQLDocument document, TContext context) { - await Visit(document.Definitions, context); + await Visit(document.Definitions, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitArgument(GraphQLArgument argument, TContext context) { - await Visit(argument.Comment, context); - await Visit(argument.Name, context); - await Visit(argument.Value, context); + await Visit(argument.Comment, context).ConfigureAwait(false); + await Visit(argument.Name, context).ConfigureAwait(false); + await Visit(argument.Value, context).ConfigureAwait(false); } /// @@ -42,290 +42,290 @@ public virtual ValueTask VisitDescription(GraphQLDescription description, TConte /// public virtual async ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) { - await Visit(operationDefinition.Comment, context); - await Visit(operationDefinition.Name, context); - await Visit(operationDefinition.VariableDefinitions, context); - await Visit(operationDefinition.Directives, context); - await Visit(operationDefinition.SelectionSet, context); + await Visit(operationDefinition.Comment, context).ConfigureAwait(false); + await Visit(operationDefinition.Name, context).ConfigureAwait(false); + await Visit(operationDefinition.VariableDefinitions, context).ConfigureAwait(false); + await Visit(operationDefinition.Directives, context).ConfigureAwait(false); + await Visit(operationDefinition.SelectionSet, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitName(GraphQLName name, TContext context) { - await Visit(name.Comment, context); + await Visit(name.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) { - await Visit(variableDefinition.Comment, context); - await Visit(variableDefinition.Variable, context); - await Visit(variableDefinition.Type, context); - await Visit(variableDefinition.DefaultValue, context); - await Visit(variableDefinition.Directives, context); + await Visit(variableDefinition.Comment, context).ConfigureAwait(false); + await Visit(variableDefinition.Variable, context).ConfigureAwait(false); + await Visit(variableDefinition.Type, context).ConfigureAwait(false); + await Visit(variableDefinition.DefaultValue, context).ConfigureAwait(false); + await Visit(variableDefinition.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitVariable(GraphQLVariable variable, TContext context) { - await Visit(variable.Comment, context); - await Visit(variable.Name, context); + await Visit(variable.Comment, context).ConfigureAwait(false); + await Visit(variable.Name, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) { - await Visit(selectionSet.Comment, context); - await Visit(selectionSet.Selections, context); + await Visit(selectionSet.Comment, context).ConfigureAwait(false); + await Visit(selectionSet.Selections, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitField(GraphQLField field, TContext context) { - await Visit(field.Comment, context); - await Visit(field.Alias, context); - await Visit(field.Name, context); - await Visit(field.Arguments, context); - await Visit(field.Directives, context); - await Visit(field.SelectionSet, context); + await Visit(field.Comment, context).ConfigureAwait(false); + await Visit(field.Alias, context).ConfigureAwait(false); + await Visit(field.Name, context).ConfigureAwait(false); + await Visit(field.Arguments, context).ConfigureAwait(false); + await Visit(field.Directives, context).ConfigureAwait(false); + await Visit(field.SelectionSet, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) { - await Visit(fragmentSpread.Comment, context); - await Visit(fragmentSpread.Name, context); - await Visit(fragmentSpread.Directives, context); + await Visit(fragmentSpread.Comment, context).ConfigureAwait(false); + await Visit(fragmentSpread.Name, context).ConfigureAwait(false); + await Visit(fragmentSpread.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) { - await Visit(inlineFragment.Comment, context); - await Visit(inlineFragment.TypeCondition, context); - await Visit(inlineFragment.Directives, context); - await Visit(inlineFragment.SelectionSet, context); + await Visit(inlineFragment.Comment, context).ConfigureAwait(false); + await Visit(inlineFragment.TypeCondition, context).ConfigureAwait(false); + await Visit(inlineFragment.Directives, context).ConfigureAwait(false); + await Visit(inlineFragment.SelectionSet, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context) { - await Visit(typeCondition.Comment, context); - await Visit(typeCondition.Type, context); + await Visit(typeCondition.Comment, context).ConfigureAwait(false); + await Visit(typeCondition.Type, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) { - await Visit(fragmentDefinition.Comment, context); - await Visit(fragmentDefinition.Name, context); - await Visit(fragmentDefinition.TypeCondition, context); - await Visit(fragmentDefinition.Directives, context); - await Visit(fragmentDefinition.SelectionSet, context); + await Visit(fragmentDefinition.Comment, context).ConfigureAwait(false); + await Visit(fragmentDefinition.Name, context).ConfigureAwait(false); + await Visit(fragmentDefinition.TypeCondition, context).ConfigureAwait(false); + await Visit(fragmentDefinition.Directives, context).ConfigureAwait(false); + await Visit(fragmentDefinition.SelectionSet, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context) { - await Visit(intValue.Comment, context); + await Visit(intValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context) { - await Visit(floatValue.Comment, context); + await Visit(floatValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { - await Visit(stringValue.Comment, context); + await Visit(stringValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) { - await Visit(booleanValue.Comment, context); + await Visit(booleanValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context) { - await Visit(enumValue.Comment, context); + await Visit(enumValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitListValue(GraphQLListValue listValue, TContext context) { - await Visit(listValue.Comment, context); - await Visit(listValue.Values, context); + await Visit(listValue.Comment, context).ConfigureAwait(false); + await Visit(listValue.Values, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitObjectValue(GraphQLObjectValue objectValue, TContext context) { - await Visit(objectValue.Comment, context); - await Visit(objectValue.Fields, context); + await Visit(objectValue.Comment, context).ConfigureAwait(false); + await Visit(objectValue.Fields, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitObjectField(GraphQLObjectField objectField, TContext context) { - await Visit(objectField.Comment, context); - await Visit(objectField.Name, context); - await Visit(objectField.Value, context); + await Visit(objectField.Comment, context).ConfigureAwait(false); + await Visit(objectField.Name, context).ConfigureAwait(false); + await Visit(objectField.Value, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitDirective(GraphQLDirective directive, TContext context) { - await Visit(directive.Comment, context); - await Visit(directive.Name, context); - await Visit(directive.Arguments, context); + await Visit(directive.Comment, context).ConfigureAwait(false); + await Visit(directive.Name, context).ConfigureAwait(false); + await Visit(directive.Arguments, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitNamedType(GraphQLNamedType namedType, TContext context) { - await Visit(namedType.Comment, context); - await Visit(namedType.Name, context); + await Visit(namedType.Comment, context).ConfigureAwait(false); + await Visit(namedType.Name, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitListType(GraphQLListType listType, TContext context) { - await Visit(listType.Comment, context); - await Visit(listType.Type, context); + await Visit(listType.Comment, context).ConfigureAwait(false); + await Visit(listType.Type, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) { - await Visit(nonNullType.Comment, context); - await Visit(nonNullType.Type, context); + await Visit(nonNullType.Comment, context).ConfigureAwait(false); + await Visit(nonNullType.Type, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context) { - await Visit(nullValue.Comment, context); + await Visit(nullValue.Comment, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) { - await Visit(schemaDefinition.Comment, context); - await Visit(schemaDefinition.Description, context); - await Visit(schemaDefinition.Directives, context); - await Visit(schemaDefinition.OperationTypes, context); + await Visit(schemaDefinition.Comment, context).ConfigureAwait(false); + await Visit(schemaDefinition.Description, context).ConfigureAwait(false); + await Visit(schemaDefinition.Directives, context).ConfigureAwait(false); + await Visit(schemaDefinition.OperationTypes, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { - await Visit(rootOperationTypeDefinition.Comment, context); - await Visit(rootOperationTypeDefinition.Type, context); + await Visit(rootOperationTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(rootOperationTypeDefinition.Type, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { - await Visit(scalarTypeDefinition.Comment, context); - await Visit(scalarTypeDefinition.Description, context); - await Visit(scalarTypeDefinition.Name, context); - await Visit(scalarTypeDefinition.Directives, context); + await Visit(scalarTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(scalarTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(scalarTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(scalarTypeDefinition.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { - await Visit(objectTypeDefinition.Comment, context); - await Visit(objectTypeDefinition.Description, context); - await Visit(objectTypeDefinition.Name, context); - await Visit(objectTypeDefinition.Interfaces, context); - await Visit(objectTypeDefinition.Directives, context); - await Visit(objectTypeDefinition.Fields, context); + await Visit(objectTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Interfaces, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Directives, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Fields, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) { - await Visit(fieldDefinition.Comment, context); - await Visit(fieldDefinition.Description, context); - await Visit(fieldDefinition.Name, context); - await Visit(fieldDefinition.Arguments, context); - await Visit(fieldDefinition.Type, context); - await Visit(fieldDefinition.Directives, context); + await Visit(fieldDefinition.Comment, context).ConfigureAwait(false); + await Visit(fieldDefinition.Description, context).ConfigureAwait(false); + await Visit(fieldDefinition.Name, context).ConfigureAwait(false); + await Visit(fieldDefinition.Arguments, context).ConfigureAwait(false); + await Visit(fieldDefinition.Type, context).ConfigureAwait(false); + await Visit(fieldDefinition.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) { - await Visit(inputValueDefinition.Comment, context); - await Visit(inputValueDefinition.Description, context); - await Visit(inputValueDefinition.Name, context); - await Visit(inputValueDefinition.Type, context); - await Visit(inputValueDefinition.DefaultValue, context); - await Visit(inputValueDefinition.Directives, context); + await Visit(inputValueDefinition.Comment, context).ConfigureAwait(false); + await Visit(inputValueDefinition.Description, context).ConfigureAwait(false); + await Visit(inputValueDefinition.Name, context).ConfigureAwait(false); + await Visit(inputValueDefinition.Type, context).ConfigureAwait(false); + await Visit(inputValueDefinition.DefaultValue, context).ConfigureAwait(false); + await Visit(inputValueDefinition.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { - await Visit(interfaceTypeDefinition.Comment, context); - await Visit(interfaceTypeDefinition.Description, context); - await Visit(interfaceTypeDefinition.Name, context); - await Visit(interfaceTypeDefinition.Interfaces, context); - await Visit(interfaceTypeDefinition.Directives, context); - await Visit(interfaceTypeDefinition.Fields, context); + await Visit(interfaceTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Interfaces, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Directives, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Fields, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { - await Visit(unionTypeDefinition.Comment, context); - await Visit(unionTypeDefinition.Description, context); - await Visit(unionTypeDefinition.Name, context); - await Visit(unionTypeDefinition.Directives, context); - await Visit(unionTypeDefinition.Types, context); + await Visit(unionTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(unionTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(unionTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(unionTypeDefinition.Directives, context).ConfigureAwait(false); + await Visit(unionTypeDefinition.Types, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { - await Visit(enumTypeDefinition.Comment, context); - await Visit(enumTypeDefinition.Description, context); - await Visit(enumTypeDefinition.Name, context); - await Visit(enumTypeDefinition.Directives, context); - await Visit(enumTypeDefinition.Values, context); + await Visit(enumTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(enumTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(enumTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(enumTypeDefinition.Directives, context).ConfigureAwait(false); + await Visit(enumTypeDefinition.Values, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) { - await Visit(enumValueDefinition.Comment, context); - await Visit(enumValueDefinition.Description, context); - await Visit(enumValueDefinition.Name, context); - await Visit(enumValueDefinition.Directives, context); + await Visit(enumValueDefinition.Comment, context).ConfigureAwait(false); + await Visit(enumValueDefinition.Description, context).ConfigureAwait(false); + await Visit(enumValueDefinition.Name, context).ConfigureAwait(false); + await Visit(enumValueDefinition.Directives, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { - await Visit(inputObjectTypeDefinition.Comment, context); - await Visit(inputObjectTypeDefinition.Description, context); - await Visit(inputObjectTypeDefinition.Name, context); - await Visit(inputObjectTypeDefinition.Directives, context); - await Visit(inputObjectTypeDefinition.Fields, context); + await Visit(inputObjectTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Description, context).ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Name, context).ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Directives, context).ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Fields, context).ConfigureAwait(false); } /// public virtual async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) { - await Visit(directiveDefinition.Comment, context); - await Visit(directiveDefinition.Description, context); - await Visit(directiveDefinition.Name, context); - await Visit(directiveDefinition.Arguments, context); + await Visit(directiveDefinition.Comment, context).ConfigureAwait(false); + await Visit(directiveDefinition.Description, context).ConfigureAwait(false); + await Visit(directiveDefinition.Name, context).ConfigureAwait(false); + await Visit(directiveDefinition.Arguments, context).ConfigureAwait(false); } /// @@ -335,10 +335,9 @@ public virtual async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefiniti /// Context passed into all INodeVisitor.VisitXXX methods. public virtual ValueTask Visit(ASTNode? node, TContext context) { - if (node == null) - return new ValueTask(Task.CompletedTask); - - return node switch + return node == null + ? new ValueTask(Task.CompletedTask) + : node switch { GraphQLArgument argument => VisitArgument(argument, context), GraphQLComment comment => VisitComment(comment, context), @@ -400,7 +399,7 @@ protected async ValueTask Visit(List? nodes, TContext context) if (nodes != null) { foreach (var node in nodes) - await Visit(node, context); + await Visit(node, context).ConfigureAwait(false); } } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 41a56d23..e6a9db30 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -18,11 +18,11 @@ public override async ValueTask VisitDocument(GraphQLDocument document, TContext { for (int i = 0; i < document.Definitions.Count; ++i) { - await Visit(document.Definitions[i], context); + await Visit(document.Definitions[i], context).ConfigureAwait(false); if (i < document.Definitions.Count - 1) { - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); } } } @@ -39,8 +39,8 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co { if (needStartNewLine) { - await WriteIndent(context, level); - await context.Write("#"); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("#").ConfigureAwait(false); needStartNewLine = false; } @@ -51,17 +51,17 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co break; case '\n': - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); needStartNewLine = true; break; default: - await context.Write(comment.Text.Slice(i, 1)/*current*/); + await context.Write(comment.Text.Slice(i, 1)/*current*/).ConfigureAwait(false); break; } } - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); } /// @@ -69,9 +69,9 @@ public override async ValueTask VisitDescription(GraphQLDescription description, { int level = GetLevel(context); - await WriteIndent(context, level); - await context.Write("\"\"\""); - await context.WriteLine(); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("\"\"\"").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); bool needStartNewLine = true; int length = description.Value.Span.Length; @@ -79,7 +79,7 @@ public override async ValueTask VisitDescription(GraphQLDescription description, { if (needStartNewLine) { - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); needStartNewLine = false; } @@ -90,437 +90,437 @@ public override async ValueTask VisitDescription(GraphQLDescription description, break; case '\n': - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); needStartNewLine = true; break; default: - await context.Write(description.Value.Slice(i, 1)/*current*/); //TODO: change + await context.Write(description.Value.Slice(i, 1)/*current*/).ConfigureAwait(false); //TODO: change break; } } - await context.WriteLine(); - await WriteIndent(context, level); - await context.Write("\"\"\""); - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("\"\"\"").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitName(GraphQLName name, TContext context) { - await Visit(name.Comment, context); - await context.Write(name.Value); + await Visit(name.Comment, context).ConfigureAwait(false); + await context.Write(name.Value).ConfigureAwait(false); } /// public override async ValueTask VisitFragmentDefinition(GraphQLFragmentDefinition fragmentDefinition, TContext context) { - await Visit(fragmentDefinition.Comment, context); - await context.Write("fragment "); - await Visit(fragmentDefinition.Name, context); - await context.Write(" "); - await Visit(fragmentDefinition.TypeCondition, context); - await VisitDirectives(fragmentDefinition, context); - await Visit(fragmentDefinition.SelectionSet, context); + await Visit(fragmentDefinition.Comment, context).ConfigureAwait(false); + await context.Write("fragment ").ConfigureAwait(false); + await Visit(fragmentDefinition.Name, context).ConfigureAwait(false); + await context.Write(" ").ConfigureAwait(false); + await Visit(fragmentDefinition.TypeCondition, context).ConfigureAwait(false); + await VisitDirectives(fragmentDefinition, context).ConfigureAwait(false); + await Visit(fragmentDefinition.SelectionSet, context).ConfigureAwait(false); } /// public override async ValueTask VisitFragmentSpread(GraphQLFragmentSpread fragmentSpread, TContext context) { - await Visit(fragmentSpread.Comment, context); + await Visit(fragmentSpread.Comment, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await context.Write("..."); - await Visit(fragmentSpread.Name, context); - await VisitDirectives(fragmentSpread, context); - await context.WriteLine(); + await context.Write("...").ConfigureAwait(false); + await Visit(fragmentSpread.Name, context).ConfigureAwait(false); + await VisitDirectives(fragmentSpread, context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitInlineFragment(GraphQLInlineFragment inlineFragment, TContext context) { - await Visit(inlineFragment.Comment, context); + await Visit(inlineFragment.Comment, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await context.Write("... "); - await Visit(inlineFragment.TypeCondition, context); - await VisitDirectives(inlineFragment, context); - await Visit(inlineFragment.SelectionSet, context); + await context.Write("... ").ConfigureAwait(false); + await Visit(inlineFragment.TypeCondition, context).ConfigureAwait(false); + await VisitDirectives(inlineFragment, context).ConfigureAwait(false); + await Visit(inlineFragment.SelectionSet, context).ConfigureAwait(false); } /// public override async ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context) { - await Visit(typeCondition.Comment, context); - await context.Write("on "); - await Visit(typeCondition.Type, context); + await Visit(typeCondition.Comment, context).ConfigureAwait(false); + await context.Write("on ").ConfigureAwait(false); + await Visit(typeCondition.Type, context).ConfigureAwait(false); } /// public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSet, TContext context) { - await Visit(selectionSet.Comment, context); - await context.WriteLine(); + await Visit(selectionSet.Comment, context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); - await context.Write("{"); - await context.WriteLine(); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); if (selectionSet.Selections?.Count > 0) { foreach (var selection in selectionSet.Selections) - await Visit(selection, context); + await Visit(selection, context).ConfigureAwait(false); } - await WriteIndent(context, level); - await context.Write("}"); - await context.WriteLine(); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitField(GraphQLField field, TContext context) { - await Visit(field.Comment, context); + await Visit(field.Comment, context).ConfigureAwait(false); var level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); if (field.Alias != null) { - await Visit(field.Alias, context); - await context.Write(": "); + await Visit(field.Alias, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); } - await Visit(field.Name, context); + await Visit(field.Name, context).ConfigureAwait(false); if (field.Arguments != null) { - await context.Write("("); - await VisitArguments(field, context); - await context.Write(")"); + await context.Write("(").ConfigureAwait(false); + await VisitArguments(field, context).ConfigureAwait(false); + await context.Write(")").ConfigureAwait(false); } - await VisitDirectives(field, context); + await VisitDirectives(field, context).ConfigureAwait(false); if (field.SelectionSet == null) - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); else - await Visit(field.SelectionSet, context); + await Visit(field.SelectionSet, context).ConfigureAwait(false); } /// public override async ValueTask VisitOperationDefinition(GraphQLOperationDefinition operationDefinition, TContext context) { - await Visit(operationDefinition.Comment, context); + await Visit(operationDefinition.Comment, context).ConfigureAwait(false); if (operationDefinition.Name != null) { - await context.Write(GetOperationType(operationDefinition.Operation)); - await context.Write(" "); - await Visit(operationDefinition.Name, context); + await context.Write(GetOperationType(operationDefinition.Operation)).ConfigureAwait(false); + await context.Write(" ").ConfigureAwait(false); + await Visit(operationDefinition.Name, context).ConfigureAwait(false); } if (operationDefinition.VariableDefinitions?.Count > 0) { - await context.Write("("); + await context.Write("(").ConfigureAwait(false); if (operationDefinition.VariableDefinitions?.Count > 0) { for (int i = 0; i < operationDefinition.VariableDefinitions.Count; ++i) { - await Visit(operationDefinition.VariableDefinitions[i], context); + await Visit(operationDefinition.VariableDefinitions[i], context).ConfigureAwait(false); if (i < operationDefinition.VariableDefinitions.Count - 1) - await context.Write(", "); + await context.Write(", ").ConfigureAwait(false); } } - await context.Write(")"); + await context.Write(")").ConfigureAwait(false); } - await VisitDirectives(operationDefinition, context); - await Visit(operationDefinition.SelectionSet, context); + await VisitDirectives(operationDefinition, context).ConfigureAwait(false); + await Visit(operationDefinition.SelectionSet, context).ConfigureAwait(false); } /// public override async ValueTask VisitDirectiveDefinition(GraphQLDirectiveDefinition directiveDefinition, TContext context) { - await Visit(directiveDefinition.Comment, context); - await Visit(directiveDefinition.Description, context); - await context.Write("directive "); - await Visit(directiveDefinition.Name, context); + await Visit(directiveDefinition.Comment, context).ConfigureAwait(false); + await Visit(directiveDefinition.Description, context).ConfigureAwait(false); + await context.Write("directive ").ConfigureAwait(false); + await Visit(directiveDefinition.Name, context).ConfigureAwait(false); if (directiveDefinition.Arguments != null) { - await context.Write("("); - await Visit(directiveDefinition, context); - await context.Write(")"); + await context.Write("(").ConfigureAwait(false); + await Visit(directiveDefinition, context).ConfigureAwait(false); + await context.Write(")").ConfigureAwait(false); } } /// public override async ValueTask VisitVariableDefinition(GraphQLVariableDefinition variableDefinition, TContext context) { - await Visit(variableDefinition.Comment, context); - await Visit(variableDefinition.Variable, context); - await context.Write(": "); - await Visit(variableDefinition.Type, context); + await Visit(variableDefinition.Comment, context).ConfigureAwait(false); + await Visit(variableDefinition.Variable, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + await Visit(variableDefinition.Type, context).ConfigureAwait(false); if (variableDefinition.DefaultValue != null) { - await context.Write(" = "); - await Visit(variableDefinition.DefaultValue, context); + await context.Write(" = ").ConfigureAwait(false); + await Visit(variableDefinition.DefaultValue, context).ConfigureAwait(false); } - await VisitDirectives(variableDefinition, context); + await VisitDirectives(variableDefinition, context).ConfigureAwait(false); } /// public override async ValueTask VisitVariable(GraphQLVariable variable, TContext context) { - await Visit(variable.Comment, context); - await context.Write("$"); - await Visit(variable.Name, context); + await Visit(variable.Comment, context).ConfigureAwait(false); + await context.Write("$").ConfigureAwait(false); + await Visit(variable.Name, context).ConfigureAwait(false); } /// public override async ValueTask VisitBooleanValue(GraphQLScalarValue booleanValue, TContext context) { - await Visit(booleanValue.Comment, context); - await context.Write(booleanValue.Value); + await Visit(booleanValue.Comment, context).ConfigureAwait(false); + await context.Write(booleanValue.Value).ConfigureAwait(false); } /// public override async ValueTask VisitScalarTypeDefinition(GraphQLScalarTypeDefinition scalarTypeDefinition, TContext context) { - await Visit(scalarTypeDefinition.Comment, context); - await Visit(scalarTypeDefinition.Description, context); - await context.Write("scalar "); - await Visit(scalarTypeDefinition.Name, context); - await VisitDirectives(scalarTypeDefinition, context); - await context.WriteLine(); + await Visit(scalarTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(scalarTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("scalar ").ConfigureAwait(false); + await Visit(scalarTypeDefinition.Name, context).ConfigureAwait(false); + await VisitDirectives(scalarTypeDefinition, context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitEnumTypeDefinition(GraphQLEnumTypeDefinition enumTypeDefinition, TContext context) { - await Visit(enumTypeDefinition.Comment, context); - await Visit(enumTypeDefinition.Description, context); - await context.Write("enum "); - await Visit(enumTypeDefinition.Name, context); - await VisitDirectives(enumTypeDefinition, context); + await Visit(enumTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(enumTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("enum ").ConfigureAwait(false); + await Visit(enumTypeDefinition.Name, context).ConfigureAwait(false); + await VisitDirectives(enumTypeDefinition, context).ConfigureAwait(false); if (enumTypeDefinition.Values?.Count > 0) { - await context.WriteLine(); - await context.Write("{"); - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); for (int i = 0; i < enumTypeDefinition.Values.Count; ++i) { - await Visit(enumTypeDefinition.Values[i], context); - await context.WriteLine(); + await Visit(enumTypeDefinition.Values[i], context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } - await context.Write("}"); - await context.WriteLine(); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } } /// public override async ValueTask VisitEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TContext context) { - await Visit(enumValueDefinition.Comment, context); - await Visit(enumValueDefinition.Description, context); + await Visit(enumValueDefinition.Comment, context).ConfigureAwait(false); + await Visit(enumValueDefinition.Description, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await Visit(enumValueDefinition.Name, context); - await VisitDirectives(enumValueDefinition, context); + await Visit(enumValueDefinition.Name, context).ConfigureAwait(false); + await VisitDirectives(enumValueDefinition, context).ConfigureAwait(false); } /// public override async ValueTask VisitInputObjectTypeDefinition(GraphQLInputObjectTypeDefinition inputObjectTypeDefinition, TContext context) { - await Visit(inputObjectTypeDefinition.Comment, context); - await Visit(inputObjectTypeDefinition.Description, context); - await context.Write("input "); - await Visit(inputObjectTypeDefinition.Name, context); - await VisitDirectives(inputObjectTypeDefinition, context); + await Visit(inputObjectTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("input ").ConfigureAwait(false); + await Visit(inputObjectTypeDefinition.Name, context).ConfigureAwait(false); + await VisitDirectives(inputObjectTypeDefinition, context).ConfigureAwait(false); if (inputObjectTypeDefinition.Fields?.Count > 0) { - await context.WriteLine(); - await context.Write("{"); - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); for (int i = 0; i < inputObjectTypeDefinition.Fields.Count; ++i) { - await Visit(inputObjectTypeDefinition.Fields[i], context); - await context.WriteLine(); + await Visit(inputObjectTypeDefinition.Fields[i], context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } - await context.Write("}"); - await context.WriteLine(); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } else { - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); } } /// public override async ValueTask VisitInputValueDefinition(GraphQLInputValueDefinition inputValueDefinition, TContext context) { - await Visit(inputValueDefinition.Comment, context); - await Visit(inputValueDefinition.Description, context); + await Visit(inputValueDefinition.Comment, context).ConfigureAwait(false); + await Visit(inputValueDefinition.Description, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await Visit(inputValueDefinition.Name, context); - await context.Write(": "); - await Visit(inputValueDefinition.Type, context); + await Visit(inputValueDefinition.Name, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + await Visit(inputValueDefinition.Type, context).ConfigureAwait(false); if (inputValueDefinition.DefaultValue != null) { - await context.Write(" = "); - await Visit(inputValueDefinition.DefaultValue, context); + await context.Write(" = ").ConfigureAwait(false); + await Visit(inputValueDefinition.DefaultValue, context).ConfigureAwait(false); } - await VisitDirectives(inputValueDefinition, context); + await VisitDirectives(inputValueDefinition, context).ConfigureAwait(false); } /// public override async ValueTask VisitObjectTypeDefinition(GraphQLObjectTypeDefinition objectTypeDefinition, TContext context) { - await Visit(objectTypeDefinition.Comment, context); - await Visit(objectTypeDefinition.Description, context); - await context.Write("type "); - await Visit(objectTypeDefinition.Name, context); - await VisitInterfaces(objectTypeDefinition, context); - await VisitDirectives(objectTypeDefinition, context); + await Visit(objectTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(objectTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("type ").ConfigureAwait(false); + await Visit(objectTypeDefinition.Name, context).ConfigureAwait(false); + await VisitInterfaces(objectTypeDefinition, context).ConfigureAwait(false); + await VisitDirectives(objectTypeDefinition, context).ConfigureAwait(false); if (objectTypeDefinition.Fields?.Count > 0) { - await context.WriteLine(); - await context.Write("{"); - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); for (int i = 0; i < objectTypeDefinition.Fields.Count; ++i) { - await Visit(objectTypeDefinition.Fields[i], context); - await context.WriteLine(); + await Visit(objectTypeDefinition.Fields[i], context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } - await context.Write("}"); - await context.WriteLine(); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } else { - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); } } /// public override async ValueTask VisitInterfaceTypeDefinition(GraphQLInterfaceTypeDefinition interfaceTypeDefinition, TContext context) { - await Visit(interfaceTypeDefinition.Comment, context); - await Visit(interfaceTypeDefinition.Description, context); - await context.Write("interface "); - await Visit(interfaceTypeDefinition.Name, context); - await VisitInterfaces(interfaceTypeDefinition, context); - await VisitDirectives(interfaceTypeDefinition, context); - await context.WriteLine(); - await context.Write("{"); - await context.WriteLine(); + await Visit(interfaceTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("interface ").ConfigureAwait(false); + await Visit(interfaceTypeDefinition.Name, context).ConfigureAwait(false); + await VisitInterfaces(interfaceTypeDefinition, context).ConfigureAwait(false); + await VisitDirectives(interfaceTypeDefinition, context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); if (interfaceTypeDefinition.Fields?.Count > 0) { for (int i = 0; i < interfaceTypeDefinition.Fields.Count; ++i) { - await Visit(interfaceTypeDefinition.Fields[i], context); - await context.WriteLine(); + await Visit(interfaceTypeDefinition.Fields[i], context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } } - await context.Write("}"); - await context.WriteLine(); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitFieldDefinition(GraphQLFieldDefinition fieldDefinition, TContext context) { - await Visit(fieldDefinition.Comment, context); - await Visit(fieldDefinition.Description, context); + await Visit(fieldDefinition.Comment, context).ConfigureAwait(false); + await Visit(fieldDefinition.Description, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await Visit(fieldDefinition.Name, context); + await Visit(fieldDefinition.Name, context).ConfigureAwait(false); if (fieldDefinition.Arguments?.Count > 0) { - await context.Write("("); + await context.Write("(").ConfigureAwait(false); for (int i = 0; i < fieldDefinition.Arguments.Count; ++i) { - await Visit(fieldDefinition.Arguments[i], context); + await Visit(fieldDefinition.Arguments[i], context).ConfigureAwait(false); if (i < fieldDefinition.Arguments.Count - 1) - await context.Write(", "); + await context.Write(", ").ConfigureAwait(false); } - await context.Write(")"); + await context.Write(")").ConfigureAwait(false); } - await context.Write(": "); - await Visit(fieldDefinition.Type, context); - await VisitDirectives(fieldDefinition, context); + await context.Write(": ").ConfigureAwait(false); + await Visit(fieldDefinition.Type, context).ConfigureAwait(false); + await VisitDirectives(fieldDefinition, context).ConfigureAwait(false); } /// public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition schemaDefinition, TContext context) { - await Visit(schemaDefinition.Comment, context); - await Visit(schemaDefinition.Description, context); - await context.Write("schema"); - await VisitDirectives(schemaDefinition, context); + await Visit(schemaDefinition.Comment, context).ConfigureAwait(false); + await Visit(schemaDefinition.Description, context).ConfigureAwait(false); + await context.Write("schema").ConfigureAwait(false); + await VisitDirectives(schemaDefinition, context).ConfigureAwait(false); - await context.WriteLine(); - await context.Write("{"); - await context.WriteLine(); + await context.WriteLine().ConfigureAwait(false); + await context.Write("{").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); if (schemaDefinition.OperationTypes?.Count > 0) { for (int i = 0; i < schemaDefinition.OperationTypes.Count; ++i) { - await Visit(schemaDefinition.OperationTypes[i], context); - await context.WriteLine(); + await Visit(schemaDefinition.OperationTypes[i], context).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } } - await context.Write("}"); - await context.WriteLine(); + await context.Write("}").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } /// public override async ValueTask VisitRootOperationTypeDefinition(GraphQLRootOperationTypeDefinition rootOperationTypeDefinition, TContext context) { - await Visit(rootOperationTypeDefinition.Comment, context); + await Visit(rootOperationTypeDefinition.Comment, context).ConfigureAwait(false); int level = GetLevel(context); - await WriteIndent(context, level); + await WriteIndent(context, level).ConfigureAwait(false); - await context.Write(GetOperationType(rootOperationTypeDefinition.Operation)); - await context.Write(": "); - await Visit(rootOperationTypeDefinition.Type, context); + await context.Write(GetOperationType(rootOperationTypeDefinition.Operation)).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + await Visit(rootOperationTypeDefinition.Type, context).ConfigureAwait(false); } /// public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinition unionTypeDefinition, TContext context) { - await Visit(unionTypeDefinition.Comment, context); - await Visit(unionTypeDefinition.Description, context); - await context.Write("union "); - await Visit(unionTypeDefinition.Name, context); - await VisitDirectives(unionTypeDefinition, context); + await Visit(unionTypeDefinition.Comment, context).ConfigureAwait(false); + await Visit(unionTypeDefinition.Description, context).ConfigureAwait(false); + await context.Write("union ").ConfigureAwait(false); + await Visit(unionTypeDefinition.Name, context).ConfigureAwait(false); + await VisitDirectives(unionTypeDefinition, context).ConfigureAwait(false); if (unionTypeDefinition.Types?.Count > 0) { - await context.Write(" = "); + await context.Write(" = ").ConfigureAwait(false); for (int i = 0; i < unionTypeDefinition.Types.Count; ++i) { - await Visit(unionTypeDefinition.Types[i], context); + await Visit(unionTypeDefinition.Types[i], context).ConfigureAwait(false); if (i < unionTypeDefinition.Types.Count - 1) - await context.Write(" | "); + await context.Write(" | ").ConfigureAwait(false); } } } @@ -528,126 +528,126 @@ public override async ValueTask VisitUnionTypeDefinition(GraphQLUnionTypeDefinit /// public override async ValueTask VisitDirective(GraphQLDirective directive, TContext context) { - await Visit(directive.Comment, context); - await context.Write("@"); - await Visit(directive.Name, context); + await Visit(directive.Comment, context).ConfigureAwait(false); + await context.Write("@").ConfigureAwait(false); + await Visit(directive.Name, context).ConfigureAwait(false); if (directive.Arguments != null) { - await context.Write("("); - await VisitArguments(directive, context); - await context.Write(")"); + await context.Write("(").ConfigureAwait(false); + await VisitArguments(directive, context).ConfigureAwait(false); + await context.Write(")").ConfigureAwait(false); } } /// public override async ValueTask VisitArgument(GraphQLArgument argument, TContext context) { - await Visit(argument.Comment, context); - await Visit(argument.Name, context); - await context.Write(": "); - await Visit(argument.Value, context); + await Visit(argument.Comment, context).ConfigureAwait(false); + await Visit(argument.Name, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + await Visit(argument.Value, context).ConfigureAwait(false); } /// public override async ValueTask VisitNonNullType(GraphQLNonNullType nonNullType, TContext context) { - await Visit(nonNullType.Comment, context); - await Visit(nonNullType.Type, context); - await context.Write("!"); + await Visit(nonNullType.Comment, context).ConfigureAwait(false); + await Visit(nonNullType.Type, context).ConfigureAwait(false); + await context.Write("!").ConfigureAwait(false); } /// public override async ValueTask VisitListType(GraphQLListType listType, TContext context) { - await Visit(listType.Comment, context); - await context.Write("["); - await Visit(listType.Type, context); - await context.Write("]"); + await Visit(listType.Comment, context).ConfigureAwait(false); + await context.Write("[").ConfigureAwait(false); + await Visit(listType.Type, context).ConfigureAwait(false); + await context.Write("]").ConfigureAwait(false); } /// public override async ValueTask VisitListValue(GraphQLListValue listValue, TContext context) { - await Visit(listValue.Comment, context); + await Visit(listValue.Comment, context).ConfigureAwait(false); if (listValue.Values?.Count > 0) { - await context.Write("["); + await context.Write("[").ConfigureAwait(false); for (int i = 0; i < listValue.Values.Count; ++i) { - await Visit(listValue.Values[i], context); + await Visit(listValue.Values[i], context).ConfigureAwait(false); if (i < listValue.Values.Count - 1) - await context.Write(", "); + await context.Write(", ").ConfigureAwait(false); } - await context.Write("]"); + await context.Write("]").ConfigureAwait(false); } } /// public override async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TContext context) { - await Visit(nullValue.Comment, context); - await context.Write("null"); + await Visit(nullValue.Comment, context).ConfigureAwait(false); + await context.Write("null").ConfigureAwait(false); } /// public override async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { - await Visit(stringValue.Comment, context); - await context.Write("\""); - await context.Write(stringValue.Value); - await context.Write("\""); + await Visit(stringValue.Comment, context).ConfigureAwait(false); + await context.Write("\"").ConfigureAwait(false); + await context.Write(stringValue.Value).ConfigureAwait(false); + await context.Write("\"").ConfigureAwait(false); } /// public override async ValueTask VisitIntValue(GraphQLScalarValue intValue, TContext context) { - await Visit(intValue.Comment, context); - await context.Write(intValue.Value); + await Visit(intValue.Comment, context).ConfigureAwait(false); + await context.Write(intValue.Value).ConfigureAwait(false); } /// public override async ValueTask VisitFloatValue(GraphQLScalarValue floatValue, TContext context) { - await Visit(floatValue.Comment, context); - await context.Write(floatValue.Value); + await Visit(floatValue.Comment, context).ConfigureAwait(false); + await context.Write(floatValue.Value).ConfigureAwait(false); } /// public override async ValueTask VisitEnumValue(GraphQLScalarValue enumValue, TContext context) { - await Visit(enumValue.Comment, context); - await context.Write(enumValue.Value); + await Visit(enumValue.Comment, context).ConfigureAwait(false); + await context.Write(enumValue.Value).ConfigureAwait(false); } /// public override async ValueTask VisitObjectValue(GraphQLObjectValue objectValue, TContext context) { - await Visit(objectValue.Comment, context); + await Visit(objectValue.Comment, context).ConfigureAwait(false); if (objectValue.Fields?.Count > 0) { - await context.Write("{ "); + await context.Write("{ ").ConfigureAwait(false); for (int i = 0; i < objectValue.Fields.Count; ++i) { - await Visit(objectValue.Fields[i], context); + await Visit(objectValue.Fields[i], context).ConfigureAwait(false); if (i < objectValue.Fields.Count - 1) - await context.Write(", "); + await context.Write(", ").ConfigureAwait(false); } - await context.Write(" }"); + await context.Write(" }").ConfigureAwait(false); } else { - await context.Write("{ }"); + await context.Write("{ }").ConfigureAwait(false); } } /// public override async ValueTask VisitObjectField(GraphQLObjectField objectField, TContext context) { - await Visit(objectField.Comment, context); - await Visit(objectField.Name, context); - await context.Write(": "); - await Visit(objectField.Value, context); + await Visit(objectField.Comment, context).ConfigureAwait(false); + await Visit(objectField.Name, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + await Visit(objectField.Value, context).ConfigureAwait(false); } /// @@ -664,7 +664,7 @@ public override async ValueTask Visit(ASTNode? node, TContext context) context.Parent.Push(node); - await base.Visit(node, context); + await base.Visit(node, context).ConfigureAwait(false); context.Parent.Pop(); } @@ -675,9 +675,9 @@ private async ValueTask VisitArguments(IHasArgumentsNode node, TContext context) { for (int i = 0; i < node.Arguments.Count; ++i) { - await Visit(node.Arguments[i], context); + await Visit(node.Arguments[i], context).ConfigureAwait(false); if (i < node.Arguments.Count - 1) - await context.Write(", "); + await context.Write(", ").ConfigureAwait(false); } } } @@ -686,13 +686,13 @@ private async ValueTask VisitInterfaces(IHasInterfacesNode node, TContext contex { if (node.Interfaces?.Count > 0) { - await context.Write(" implements "); + await context.Write(" implements ").ConfigureAwait(false); for (int i = 0; i < node.Interfaces.Count; ++i) { - await Visit(node.Interfaces[i], context); + await Visit(node.Interfaces[i], context).ConfigureAwait(false); if (i < node.Interfaces.Count - 1) - await context.Write(" & "); + await context.Write(" & ").ConfigureAwait(false); } } } @@ -701,13 +701,13 @@ private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext contex { if (node.Directives?.Count > 0) { - await context.Write(" "); + await context.Write(" ").ConfigureAwait(false); for (int i = 0; i < node.Directives.Count; ++i) { - await Visit(node.Directives[i], context); + await Visit(node.Directives[i], context).ConfigureAwait(false); if (i < node.Directives.Count - 1) - await context.Write(" "); + await context.Write(" ").ConfigureAwait(false); } } } @@ -722,7 +722,7 @@ private async ValueTask VisitDirectives(IHasDirectivesNode node, TContext contex private async ValueTask WriteIndent(TContext context, int level) { for (int i = 0; i < level; ++i) - await context.Write(" "); + await context.Write(" ").ConfigureAwait(false); } private int GetLevel(TContext context) diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs index ec684c25..f24555b6 100644 --- a/src/GraphQLParser/Visitors/StructureWriter.cs +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -18,12 +18,12 @@ public override async ValueTask Visit(ASTNode? node, TContext context) return; for (int i = 0; i < context.Parent.Count; ++i) - await context.Write(" "); + await context.Write(" ").ConfigureAwait(false); context.Parent.Push(node); - await context.Write(node.Kind.ToString()); - await context.WriteLine(); - await base.Visit(node, context); + await context.Write(node.Kind.ToString()).ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); + await base.Visit(node, context).ConfigureAwait(false); context.Parent.Pop(); } } From 4d78fa5e3f4b42e180d3d748c12a3143affeee6e Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sat, 13 Nov 2021 23:56:18 +0300 Subject: [PATCH 11/18] format --- .../Visitors/DefaultNodeVisitor.cs | 93 +++++++++---------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index 33665f5f..7bc9d5a7 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -338,54 +338,53 @@ public virtual ValueTask Visit(ASTNode? node, TContext context) return node == null ? new ValueTask(Task.CompletedTask) : node switch - { - GraphQLArgument argument => VisitArgument(argument, context), - GraphQLComment comment => VisitComment(comment, context), - GraphQLDescription description => VisitDescription(description, context), - GraphQLDirective directive => VisitDirective(directive, context), - GraphQLDirectiveDefinition directiveDefinition => VisitDirectiveDefinition(directiveDefinition, context), - GraphQLDocument document => VisitDocument(document, context), - GraphQLEnumTypeDefinition enumTypeDefinition => VisitEnumTypeDefinition(enumTypeDefinition, context), - GraphQLEnumValueDefinition enumValueDefinition => VisitEnumValueDefinition(enumValueDefinition, context), - GraphQLField field => VisitField(field, context), - GraphQLFieldDefinition fieldDefinition => VisitFieldDefinition(fieldDefinition, context), - GraphQLFragmentDefinition fragmentDefinition => VisitFragmentDefinition(fragmentDefinition, context), // inherits from GraphQLInlineFragment so should be above - GraphQLFragmentSpread fragmentSpread => VisitFragmentSpread(fragmentSpread, context), - GraphQLInlineFragment inlineFragment => VisitInlineFragment(inlineFragment, context), - GraphQLTypeCondition typeCondition => VisitTypeCondition(typeCondition, context), - GraphQLInputObjectTypeDefinition inputObjectTypeDefinition => VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context), - GraphQLInputValueDefinition inputValueDefinition => VisitInputValueDefinition(inputValueDefinition, context), - GraphQLInterfaceTypeDefinition interfaceTypeDefinition => VisitInterfaceTypeDefinition(interfaceTypeDefinition, context), - GraphQLListType listType => VisitListType(listType, context), - GraphQLListValue listValue => VisitListValue(listValue, context), - GraphQLName name => VisitName(name, context), - GraphQLNamedType namedType => VisitNamedType(namedType, context), - GraphQLNonNullType nonNullType => VisitNonNullType(nonNullType, context), - GraphQLObjectField objectField => VisitObjectField(objectField, context), - GraphQLObjectTypeDefinition objectTypeDefinition => VisitObjectTypeDefinition(objectTypeDefinition, context), - GraphQLObjectValue objectValue => VisitObjectValue(objectValue, context), - GraphQLOperationDefinition operationDefinition => VisitOperationDefinition(operationDefinition, context), - GraphQLRootOperationTypeDefinition rootOperationTypeDefinition => VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context), - GraphQLScalarTypeDefinition scalarTypeDefinition => VisitScalarTypeDefinition(scalarTypeDefinition, context), - GraphQLScalarValue scalarValue => scalarValue.Kind switch { - ASTNodeKind.BooleanValue => VisitBooleanValue(scalarValue, context), - ASTNodeKind.EnumValue => VisitEnumValue(scalarValue, context), - ASTNodeKind.FloatValue => VisitFloatValue(scalarValue, context), - ASTNodeKind.IntValue => VisitIntValue(scalarValue, context), - ASTNodeKind.NullValue => VisitNullValue(scalarValue, context), - ASTNodeKind.StringValue => VisitStringValue(scalarValue, context), - _ => throw new NotSupportedException($"Unknown GraphQLScalarValue of kind '{scalarValue.Kind}'."), - - }, - GraphQLSchemaDefinition schemaDefinition => VisitSchemaDefinition(schemaDefinition, context), - GraphQLSelectionSet selectionSet => VisitSelectionSet(selectionSet, context), - //GraphQLTypeExtensionDefinition n => VisitTypeDE - GraphQLUnionTypeDefinition unionTypeDefinition => VisitUnionTypeDefinition(unionTypeDefinition, context), - GraphQLVariable variable => VisitVariable(variable, context), - GraphQLVariableDefinition variableDefinition => VisitVariableDefinition(variableDefinition, context), - _ => throw new NotSupportedException($"Unknown node '{node.GetType().Name}'."), - }; + GraphQLArgument argument => VisitArgument(argument, context), + GraphQLComment comment => VisitComment(comment, context), + GraphQLDescription description => VisitDescription(description, context), + GraphQLDirective directive => VisitDirective(directive, context), + GraphQLDirectiveDefinition directiveDefinition => VisitDirectiveDefinition(directiveDefinition, context), + GraphQLDocument document => VisitDocument(document, context), + GraphQLEnumTypeDefinition enumTypeDefinition => VisitEnumTypeDefinition(enumTypeDefinition, context), + GraphQLEnumValueDefinition enumValueDefinition => VisitEnumValueDefinition(enumValueDefinition, context), + GraphQLField field => VisitField(field, context), + GraphQLFieldDefinition fieldDefinition => VisitFieldDefinition(fieldDefinition, context), + GraphQLFragmentDefinition fragmentDefinition => VisitFragmentDefinition(fragmentDefinition, context), // inherits from GraphQLInlineFragment so should be above + GraphQLFragmentSpread fragmentSpread => VisitFragmentSpread(fragmentSpread, context), + GraphQLInlineFragment inlineFragment => VisitInlineFragment(inlineFragment, context), + GraphQLTypeCondition typeCondition => VisitTypeCondition(typeCondition, context), + GraphQLInputObjectTypeDefinition inputObjectTypeDefinition => VisitInputObjectTypeDefinition(inputObjectTypeDefinition, context), + GraphQLInputValueDefinition inputValueDefinition => VisitInputValueDefinition(inputValueDefinition, context), + GraphQLInterfaceTypeDefinition interfaceTypeDefinition => VisitInterfaceTypeDefinition(interfaceTypeDefinition, context), + GraphQLListType listType => VisitListType(listType, context), + GraphQLListValue listValue => VisitListValue(listValue, context), + GraphQLName name => VisitName(name, context), + GraphQLNamedType namedType => VisitNamedType(namedType, context), + GraphQLNonNullType nonNullType => VisitNonNullType(nonNullType, context), + GraphQLObjectField objectField => VisitObjectField(objectField, context), + GraphQLObjectTypeDefinition objectTypeDefinition => VisitObjectTypeDefinition(objectTypeDefinition, context), + GraphQLObjectValue objectValue => VisitObjectValue(objectValue, context), + GraphQLOperationDefinition operationDefinition => VisitOperationDefinition(operationDefinition, context), + GraphQLRootOperationTypeDefinition rootOperationTypeDefinition => VisitRootOperationTypeDefinition(rootOperationTypeDefinition, context), + GraphQLScalarTypeDefinition scalarTypeDefinition => VisitScalarTypeDefinition(scalarTypeDefinition, context), + GraphQLScalarValue scalarValue => scalarValue.Kind switch + { + ASTNodeKind.BooleanValue => VisitBooleanValue(scalarValue, context), + ASTNodeKind.EnumValue => VisitEnumValue(scalarValue, context), + ASTNodeKind.FloatValue => VisitFloatValue(scalarValue, context), + ASTNodeKind.IntValue => VisitIntValue(scalarValue, context), + ASTNodeKind.NullValue => VisitNullValue(scalarValue, context), + ASTNodeKind.StringValue => VisitStringValue(scalarValue, context), + _ => throw new NotSupportedException($"Unknown GraphQLScalarValue of kind '{scalarValue.Kind}'."), + }, + GraphQLSchemaDefinition schemaDefinition => VisitSchemaDefinition(schemaDefinition, context), + GraphQLSelectionSet selectionSet => VisitSelectionSet(selectionSet, context), + //GraphQLTypeExtensionDefinition n => VisitTypeDE + GraphQLUnionTypeDefinition unionTypeDefinition => VisitUnionTypeDefinition(unionTypeDefinition, context), + GraphQLVariable variable => VisitVariable(variable, context), + GraphQLVariableDefinition variableDefinition => VisitVariableDefinition(variableDefinition, context), + _ => throw new NotSupportedException($"Unknown node '{node.GetType().Name}'."), + }; } /// From c0b47afda6a6c488e8fd2037fd060ec2b979e7ae Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 00:01:33 +0300 Subject: [PATCH 12/18] Parent -> Parents --- .../GraphQL-Parser.approved.txt | 2 +- src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs | 2 +- .../Visitors/StructureWriterTests.cs | 2 +- src/GraphQLParser/Visitors/IWriteContext.cs | 2 +- src/GraphQLParser/Visitors/SDLWriter.cs | 14 +++++++------- src/GraphQLParser/Visitors/StructureWriter.cs | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index 44ab7035..a1346fed 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -551,7 +551,7 @@ namespace GraphQLParser.Visitors } public interface IWriteContext : GraphQLParser.Visitors.INodeVisitorContext { - System.Collections.Generic.Stack Parent { get; } + System.Collections.Generic.Stack Parents { get; } System.IO.TextWriter Writer { get; } } public class SDLWriter : GraphQLParser.Visitors.DefaultNodeVisitor diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index ff7ed744..1ef2ab9a 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -14,7 +14,7 @@ private class TestContext : IWriteContext { public TextWriter Writer { get; set; } = new StringWriter(); - public Stack Parent { get; set; } = new Stack(); + public Stack Parents { get; set; } = new Stack(); public CancellationToken CancellationToken { get; set; } } diff --git a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs index 382a55aa..e1b01b1a 100644 --- a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs @@ -14,7 +14,7 @@ private class TestContext : IWriteContext { public TextWriter Writer { get; set; } = new StringWriter(); - public Stack Parent { get; set; } = new Stack(); + public Stack Parents { get; set; } = new Stack(); public CancellationToken CancellationToken { get; set; } } diff --git a/src/GraphQLParser/Visitors/IWriteContext.cs b/src/GraphQLParser/Visitors/IWriteContext.cs index c6d72f38..62a1d4cb 100644 --- a/src/GraphQLParser/Visitors/IWriteContext.cs +++ b/src/GraphQLParser/Visitors/IWriteContext.cs @@ -16,6 +16,6 @@ public interface IWriteContext : INodeVisitorContext /// /// Stack of AST nodes to track the current visitor position. /// - Stack Parent { get; } + Stack Parents { get; } } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index e6a9db30..60bb219b 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -662,11 +662,11 @@ public override async ValueTask Visit(ASTNode? node, TContext context) if (node == null) return; - context.Parent.Push(node); + context.Parents.Push(node); await base.Visit(node, context).ConfigureAwait(false); - context.Parent.Pop(); + context.Parents.Pop(); } private async ValueTask VisitArguments(IHasArgumentsNode node, TContext context) @@ -729,11 +729,11 @@ private int GetLevel(TContext context) { int level = 0; - if (context.Parent.Count > 0) + if (context.Parents.Count > 0) { - var currentNode = context.Parent.Pop(); + var currentNode = context.Parents.Pop(); - foreach (var node in context.Parent) + foreach (var node in context.Parents) { if (node is GraphQLSelectionSet || node is GraphQLTypeDefinition || @@ -744,10 +744,10 @@ node is GraphQLInputObjectTypeDefinition || if (currentNode is GraphQLDescription) --level; - else if (currentNode is GraphQLComment && context.Parent.Peek() is GraphQLTypeDefinition) + else if (currentNode is GraphQLComment && context.Parents.Peek() is GraphQLTypeDefinition) --level; - context.Parent.Push(currentNode); + context.Parents.Push(currentNode); } return level; diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs index f24555b6..7a5b07a0 100644 --- a/src/GraphQLParser/Visitors/StructureWriter.cs +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -17,14 +17,14 @@ public override async ValueTask Visit(ASTNode? node, TContext context) if (node == null) return; - for (int i = 0; i < context.Parent.Count; ++i) + for (int i = 0; i < context.Parents.Count; ++i) await context.Write(" ").ConfigureAwait(false); - context.Parent.Push(node); + context.Parents.Push(node); await context.Write(node.Kind.ToString()).ConfigureAwait(false); await context.WriteLine().ConfigureAwait(false); await base.Visit(node, context).ConfigureAwait(false); - context.Parent.Pop(); + context.Parents.Pop(); } } } From de2900a4a0d635397e4ee5fe5e65dd20f02d4a4a Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 01:25:02 +0300 Subject: [PATCH 13/18] add GraphQLAlias node --- .../GraphQL-Parser.approved.txt | 12 +++- .../Files/CommentsOnAlias.graphql | 9 +++ src/GraphQLParser.Tests/ParserTests.cs | 23 ++++++++ .../Visitors/GraphQLAstVisitorTests.cs | 2 +- .../Visitors/SDLWriterTests.cs | 13 +++++ src/GraphQLParser/AST/ASTNodeKind.cs | 9 +++ src/GraphQLParser/AST/GraphQLAlias.cs | 56 +++++++++++++++++++ src/GraphQLParser/AST/GraphQLField.cs | 2 +- src/GraphQLParser/NodeHelper.cs | 12 ++++ src/GraphQLParser/ParserContext.Parse.cs | 31 +++++++++- .../Visitors/DefaultNodeVisitor.cs | 8 +++ src/GraphQLParser/Visitors/INodeVisitor.cs | 5 ++ src/GraphQLParser/Visitors/SDLWriter.cs | 20 +++++-- 13 files changed, 190 insertions(+), 12 deletions(-) create mode 100644 src/GraphQLParser.Tests/Files/CommentsOnAlias.graphql create mode 100644 src/GraphQLParser/AST/GraphQLAlias.cs diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index a1346fed..9cbcdfa3 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -49,6 +49,13 @@ namespace GraphQLParser.AST Comment = 37, Description = 38, TypeCondition = 39, + Alias = 40, + } + public class GraphQLAlias : GraphQLParser.AST.ASTNode + { + public GraphQLAlias() { } + public override GraphQLParser.AST.ASTNodeKind Kind { get; } + public GraphQLParser.AST.GraphQLName? Name { get; set; } } public class GraphQLArgument : GraphQLParser.AST.ASTNode, GraphQLParser.AST.INamedNode { @@ -109,7 +116,7 @@ namespace GraphQLParser.AST public class GraphQLField : GraphQLParser.AST.ASTNode, GraphQLParser.AST.IHasArgumentsNode, GraphQLParser.AST.IHasDirectivesNode, GraphQLParser.AST.INamedNode { public GraphQLField() { } - public GraphQLParser.AST.GraphQLName? Alias { get; set; } + public GraphQLParser.AST.GraphQLAlias? Alias { get; set; } public System.Collections.Generic.List? Arguments { get; set; } public System.Collections.Generic.List? Directives { get; set; } public override GraphQLParser.AST.ASTNodeKind Kind { get; } @@ -462,6 +469,7 @@ namespace GraphQLParser.Visitors public virtual System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } protected System.Threading.Tasks.ValueTask Visit(System.Collections.Generic.List? nodes, TContext context) where T : GraphQLParser.AST.ASTNode { } + public virtual System.Threading.Tasks.ValueTask VisitAlias(GraphQLParser.AST.GraphQLAlias alias, TContext context) { } public virtual System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } public virtual System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } public virtual System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } @@ -509,6 +517,7 @@ namespace GraphQLParser.Visitors public interface INodeVisitor where TContext : GraphQLParser.Visitors.INodeVisitorContext { + System.Threading.Tasks.ValueTask VisitAlias(GraphQLParser.AST.GraphQLAlias alias, TContext context); System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context); System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context); System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context); @@ -559,6 +568,7 @@ namespace GraphQLParser.Visitors { public SDLWriter() { } public override System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } + public override System.Threading.Tasks.ValueTask VisitAlias(GraphQLParser.AST.GraphQLAlias alias, TContext context) { } public override System.Threading.Tasks.ValueTask VisitArgument(GraphQLParser.AST.GraphQLArgument argument, TContext context) { } public override System.Threading.Tasks.ValueTask VisitBooleanValue(GraphQLParser.AST.GraphQLScalarValue booleanValue, TContext context) { } public override System.Threading.Tasks.ValueTask VisitComment(GraphQLParser.AST.GraphQLComment comment, TContext context) { } diff --git a/src/GraphQLParser.Tests/Files/CommentsOnAlias.graphql b/src/GraphQLParser.Tests/Files/CommentsOnAlias.graphql new file mode 100644 index 00000000..70758efd --- /dev/null +++ b/src/GraphQLParser.Tests/Files/CommentsOnAlias.graphql @@ -0,0 +1,9 @@ +query q +{ +#alias comment + a +#colon comment + : +#field comment + name +} diff --git a/src/GraphQLParser.Tests/ParserTests.cs b/src/GraphQLParser.Tests/ParserTests.cs index 5b9b2bb5..e210feaf 100644 --- a/src/GraphQLParser.Tests/ParserTests.cs +++ b/src/GraphQLParser.Tests/ParserTests.cs @@ -246,6 +246,29 @@ public void Comments_on_Type_Should_Read_Correctly(IgnoreOptions options) (def.Fields[2].Type as GraphQLListType).Type.Comment.Text.ShouldBe("comment for item type"); } + [Theory] + [InlineData(IgnoreOptions.None)] + //[InlineData(IgnoreOptions.Comments)] + [InlineData(IgnoreOptions.Locations)] + //[InlineData(IgnoreOptions.All)] + public void Comments_on_Alias_Should_Read_Correctly(IgnoreOptions options) + { + string query = "CommentsOnAlias".ReadGraphQLFile(); + + using var document = query.Parse(new ParserOptions { Ignore = options }); + document.Definitions.Count.ShouldBe(1); + var def = document.Definitions[0] as GraphQLOperationDefinition; + def.SelectionSet.Selections.Count.ShouldBe(1); + var field = def.SelectionSet.Selections[0].ShouldBeAssignableTo(); + field.Name.Value.ShouldBe("name"); + field.Comment.Text.ShouldBe("field comment"); + field.Alias.Name.Value.ShouldBe("a"); + field.Alias.Comment.Text.ShouldBe("alias comment"); + + document.UnattachedComments.Count.ShouldBe(1); + document.UnattachedComments[0].Text.ShouldBe("colon comment"); + } + [Theory] [InlineData(IgnoreOptions.None)] //[InlineData(IgnoreOptions.Comments)] diff --git a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs index fccad7d3..cdaa2586 100644 --- a/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs +++ b/src/GraphQLParser.Tests/Visitors/GraphQLAstVisitorTests.cs @@ -188,7 +188,7 @@ public override async ValueTask VisitSchemaDefinition(GraphQLSchemaDefinition sc public class CountContext : INodeVisitorContext { - public List VisitedAliases = new(); + public List VisitedAliases = new(); public List VisitedArguments = new(); public List VisitedDefinitions = new(); public List VisitedDirectives = new(); diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index 1ef2ab9a..ccaf806f 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -114,6 +114,19 @@ fragment Frag on Query } ")] [InlineData(@"union Animal @immutable = |Cat | Dog", @"union Animal @immutable = Cat | Dog")] + [InlineData(@"query + q +{ + a : name + b + c : age +}", @"query q +{ + a: name + b + c: age +} +")] [InlineData(@"schema @checked { mutation: MyMutation subscription: MySub }", @"schema @checked { mutation: MyMutation diff --git a/src/GraphQLParser/AST/ASTNodeKind.cs b/src/GraphQLParser/AST/ASTNodeKind.cs index 4ba02797..7b278cdb 100644 --- a/src/GraphQLParser/AST/ASTNodeKind.cs +++ b/src/GraphQLParser/AST/ASTNodeKind.cs @@ -334,5 +334,14 @@ public enum ASTNodeKind /// /// TypeCondition, + + /// + /// By default a field's response key in the response object will use that + /// field's name. However, you can define a different response key by + /// specifying an alias.Fragments must specify the type they apply to. + ///
+ /// + ///
+ Alias, } } diff --git a/src/GraphQLParser/AST/GraphQLAlias.cs b/src/GraphQLParser/AST/GraphQLAlias.cs new file mode 100644 index 00000000..79d20d09 --- /dev/null +++ b/src/GraphQLParser/AST/GraphQLAlias.cs @@ -0,0 +1,56 @@ +namespace GraphQLParser.AST +{ + /// + /// AST node for . + /// + public class GraphQLAlias : ASTNode + { + /// + public override ASTNodeKind Kind => ASTNodeKind.TypeCondition; + + /// + /// Alias name. + /// + public GraphQLName? Name { get; set; } + } + + internal sealed class GraphQLAliasWithLocation : GraphQLAlias + { + private GraphQLLocation _location; + + public override GraphQLLocation Location + { + get => _location; + set => _location = value; + } + } + + internal sealed class GraphQLAliasWithComment : GraphQLAlias + { + private GraphQLComment? _comment; + + public override GraphQLComment? Comment + { + get => _comment; + set => _comment = value; + } + } + + internal sealed class GraphQLAliasFull : GraphQLAlias + { + private GraphQLLocation _location; + private GraphQLComment? _comment; + + public override GraphQLLocation Location + { + get => _location; + set => _location = value; + } + + public override GraphQLComment? Comment + { + get => _comment; + set => _comment = value; + } + } +} diff --git a/src/GraphQLParser/AST/GraphQLField.cs b/src/GraphQLParser/AST/GraphQLField.cs index 76a76d76..3ffd26b0 100644 --- a/src/GraphQLParser/AST/GraphQLField.cs +++ b/src/GraphQLParser/AST/GraphQLField.cs @@ -10,7 +10,7 @@ public class GraphQLField : ASTNode, IHasDirectivesNode, IHasArgumentsNode, INam /// public override ASTNodeKind Kind => ASTNodeKind.Field; - public GraphQLName? Alias { get; set; } + public GraphQLAlias? Alias { get; set; } /// public GraphQLName? Name { get; set; } diff --git a/src/GraphQLParser/NodeHelper.cs b/src/GraphQLParser/NodeHelper.cs index 0c000a13..d3f5d809 100644 --- a/src/GraphQLParser/NodeHelper.cs +++ b/src/GraphQLParser/NodeHelper.cs @@ -431,6 +431,18 @@ public static GraphQLTypeCondition CreateGraphQLTypeCondition(IgnoreOptions opti }; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static GraphQLAlias CreateGraphQLAlias(IgnoreOptions options) + { + return options switch + { + IgnoreOptions.All => new GraphQLAlias(), + IgnoreOptions.Comments => new GraphQLAliasWithLocation(), + IgnoreOptions.Locations => new GraphQLAliasWithComment(), + _ => new GraphQLAliasFull(), + }; + } + #endregion } } diff --git a/src/GraphQLParser/ParserContext.Parse.cs b/src/GraphQLParser/ParserContext.Parse.cs index 015349d7..e51dfef6 100644 --- a/src/GraphQLParser/ParserContext.Parse.cs +++ b/src/GraphQLParser/ParserContext.Parse.cs @@ -400,32 +400,57 @@ private GraphQLFieldDefinition ParseFieldDefinition() } // http://spec.graphql.org/October2021/#Field + // http://spec.graphql.org/October2021/#Alias private GraphQLField ParseField() { + // start of alias (if exists) equals start of field int start = _currentToken.Start; - var comment = GetComment(); + + var nameOrAliasComment = GetComment(); var nameOrAlias = ParseName(); + GraphQLName name; GraphQLName? alias; + GraphQLComment? nameComment; + GraphQLComment? aliasComment; + + GraphQLLocation aliasLocation = default; + if (Skip(TokenKind.COLON)) { + aliasLocation = GetLocation(start); + + nameComment = GetComment(); + aliasComment = nameOrAliasComment; + name = ParseName(); alias = nameOrAlias; } else { + aliasComment = null; + nameComment = nameOrAliasComment; + alias = null; name = nameOrAlias; } var field = NodeHelper.CreateGraphQLField(_ignoreOptions); - field.Alias = alias; + if (alias != null) + { + var aliasNode = NodeHelper.CreateGraphQLAlias(_ignoreOptions); + aliasNode.Comment = aliasComment; + aliasNode.Name = alias; + aliasNode.Location = aliasLocation; + + field.Alias = aliasNode; + } + field.Comment = nameComment; field.Name = name; field.Arguments = ParseArguments(); field.Directives = ParseDirectives(); field.SelectionSet = Peek(TokenKind.BRACE_L) ? ParseSelectionSet() : null; - field.Comment = comment; field.Location = GetLocation(start); return field; } diff --git a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs index 7bc9d5a7..da51661c 100644 --- a/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs +++ b/src/GraphQLParser/Visitors/DefaultNodeVisitor.cs @@ -79,6 +79,13 @@ public virtual async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionSe await Visit(selectionSet.Selections, context).ConfigureAwait(false); } + /// + public virtual async ValueTask VisitAlias(GraphQLAlias alias, TContext context) + { + await Visit(alias.Comment, context).ConfigureAwait(false); + await Visit(alias.Name, context).ConfigureAwait(false); + } + /// public virtual async ValueTask VisitField(GraphQLField field, TContext context) { @@ -347,6 +354,7 @@ public virtual ValueTask Visit(ASTNode? node, TContext context) GraphQLDocument document => VisitDocument(document, context), GraphQLEnumTypeDefinition enumTypeDefinition => VisitEnumTypeDefinition(enumTypeDefinition, context), GraphQLEnumValueDefinition enumValueDefinition => VisitEnumValueDefinition(enumValueDefinition, context), + GraphQLAlias alias => VisitAlias(alias, context), GraphQLField field => VisitField(field, context), GraphQLFieldDefinition fieldDefinition => VisitFieldDefinition(fieldDefinition, context), GraphQLFragmentDefinition fragmentDefinition => VisitFragmentDefinition(fragmentDefinition, context), // inherits from GraphQLInlineFragment so should be above diff --git a/src/GraphQLParser/Visitors/INodeVisitor.cs b/src/GraphQLParser/Visitors/INodeVisitor.cs index 7c4619c9..7c1ba493 100644 --- a/src/GraphQLParser/Visitors/INodeVisitor.cs +++ b/src/GraphQLParser/Visitors/INodeVisitor.cs @@ -209,5 +209,10 @@ public interface INodeVisitor /// Visits node. ///
ValueTask VisitTypeCondition(GraphQLTypeCondition typeCondition, TContext context); + + /// + /// Visits node. + /// + ValueTask VisitAlias(GraphQLAlias alias, TContext context); } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 60bb219b..845a7204 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -182,18 +182,26 @@ public override async ValueTask VisitSelectionSet(GraphQLSelectionSet selectionS await context.WriteLine().ConfigureAwait(false); } - /// - public override async ValueTask VisitField(GraphQLField field, TContext context) + public override async ValueTask VisitAlias(GraphQLAlias alias, TContext context) { - await Visit(field.Comment, context).ConfigureAwait(false); + await Visit(alias.Comment, context).ConfigureAwait(false); var level = GetLevel(context); await WriteIndent(context, level).ConfigureAwait(false); - if (field.Alias != null) + await Visit(alias.Name, context).ConfigureAwait(false); + await context.Write(": ").ConfigureAwait(false); + } + + /// + public override async ValueTask VisitField(GraphQLField field, TContext context) + { + await Visit(field.Comment, context).ConfigureAwait(false); + await Visit(field.Alias, context).ConfigureAwait(false); + if (field.Alias == null) { - await Visit(field.Alias, context).ConfigureAwait(false); - await context.Write(": ").ConfigureAwait(false); + var level = GetLevel(context); + await WriteIndent(context, level).ConfigureAwait(false); } await Visit(field.Name, context).ConfigureAwait(false); if (field.Arguments != null) From fa22a0bb11ab68052e5a9ea012e84c6c42d2039e Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 20:26:22 +0300 Subject: [PATCH 14/18] support for escape symbols --- src/GraphQLParser.Tests/LexerTests.cs | 66 ++++---- .../Visitors/SDLWriterTests.cs | 76 +++++++++- src/GraphQLParser/Visitors/SDLWriter.cs | 141 ++++++++++++++---- 3 files changed, 215 insertions(+), 68 deletions(-) diff --git a/src/GraphQLParser.Tests/LexerTests.cs b/src/GraphQLParser.Tests/LexerTests.cs index 5169e7f1..9a9df690 100644 --- a/src/GraphQLParser.Tests/LexerTests.cs +++ b/src/GraphQLParser.Tests/LexerTests.cs @@ -975,38 +975,40 @@ public void Lex_WhiteSpaceStringToken_HasStringKind() } [Theory] - [InlineData("test", "test")] - [InlineData("te\\\"\"\"st", "te\"\"\"st")] - [InlineData("\ntest", "test")] - [InlineData("\r\ntest", "test")] - [InlineData(" \ntest", "test")] - [InlineData("\t\ntest", "test")] - [InlineData("\n\ntest", "test")] - [InlineData("test\nline2", "test\nline2")] - [InlineData("test\rline2", "test\nline2")] - [InlineData("test\r\nline2", "test\nline2")] - [InlineData("test\r\r\nline2", "test\n\nline2")] - [InlineData("test\r\n\nline2", "test\n\nline2")] - [InlineData("test\n", "test")] - [InlineData("test\n ", "test")] - [InlineData("test\n\t", "test")] - [InlineData("test\n\n", "test")] - [InlineData("test\n line2", "test\nline2")] - [InlineData("test\n\t\tline2", "test\nline2")] - [InlineData("test\n \tline2", "test\nline2")] - [InlineData(" test\nline2", " test\nline2")] - [InlineData(" test\n line2", " test\nline2")] - [InlineData("\n test\n line2", "test\nline2")] - [InlineData(" test\n line2\n\t\tline3\n line4", " test\nline2\n\tline3\n line4")] - [InlineData(" test\n Hello,\n\n world!\n ", " test\nHello,\n\n world!")] - [InlineData(" \n Hello,\r\n\n world!\n ", "Hello,\n\n world!")] - [InlineData(" \n Hello,\r\n\n wor___ld!\n ", "Hello,\n\n wor___ld!")] - [InlineData("\r\n Hello,\r\n World!\r\n\r\n Yours,\r\n GraphQL.\r\n ", "Hello,\n World!\n\nYours,\n GraphQL.")] - [InlineData("Test \\n escaping", "Test \\n escaping")] - [InlineData("Test \\u1234 escaping", "Test \\u1234 escaping")] - [InlineData("Test \\ escaping", "Test \\ escaping")] - public void Lex_BlockString_Tests(string input, string expected) - { + [InlineData( 1, "test", "test")] + [InlineData( 2, "te\\\"\"\"st", "te\"\"\"st")] + [InlineData( 3, "\ntest", "test")] + [InlineData( 4,"\r\ntest", "test")] + [InlineData( 5, " \ntest", "test")] + [InlineData( 6, "\t\ntest", "test")] + [InlineData( 7, "\n\ntest", "test")] + [InlineData( 8, "test\nline2", "test\nline2")] + [InlineData( 9,"test\rline2", "test\nline2")] + [InlineData(10, "test\r\nline2", "test\nline2")] + [InlineData(11, "test\r\r\nline2", "test\n\nline2")] + [InlineData(12, "test\r\n\nline2", "test\n\nline2")] + [InlineData(13, "test\n", "test")] + [InlineData(14, "test\n ", "test")] + [InlineData(15, "test\n\t", "test")] + [InlineData(16, "test\n\n", "test")] + [InlineData(17, "test\n line2", "test\nline2")] + [InlineData(18, "test\n\t\tline2", "test\nline2")] + [InlineData(19, "test\n \tline2", "test\nline2")] + [InlineData(20, " test\nline2", " test\nline2")] + [InlineData(21, " test\n line2", " test\nline2")] + [InlineData(22, "\n test\n line2", "test\nline2")] + [InlineData(23, " test\n line2\n\t\tline3\n line4", " test\nline2\n\tline3\n line4")] + [InlineData(24, " test\n Hello,\n\n world!\n ", " test\nHello,\n\n world!")] + [InlineData(25, " \n Hello,\r\n\n world!\n ", "Hello,\n\n world!")] + [InlineData(26, " \n Hello,\r\n\n wor___ld!\n ", "Hello,\n\n wor___ld!")] + [InlineData(27, "\r\n Hello,\r\n World!\r\n\r\n Yours,\r\n GraphQL.\r\n ", "Hello,\n World!\n\nYours,\n GraphQL.")] + [InlineData(28, "Test \\n escaping", "Test \\n escaping")] + [InlineData(29, "Test \\u1234 escaping", "Test \\u1234 escaping")] + [InlineData(30, "Test \\ escaping", "Test \\ escaping")] + public void Lex_BlockString_Tests(int number, string input, string expected) + { + number.ShouldBeGreaterThan(0); + input = input.Replace("___", new string('_', 9000)); expected = expected.Replace("___", new string('_', 9000)); input = "\"\"\"" + input + "\"\"\""; diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index ccaf806f..5fde3b4c 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using GraphQLParser.Visitors; @@ -145,14 +147,13 @@ GREEN @directive(list: [1,2,3,null,{}, {name:""tom"" age:42}]), """""" another good color """""" -BLUE }", @"enum Color +BLUE }", +@"enum Color { RED #good color GREEN @directive(list: [1, 2, 3, null, { }, { name: ""tom"", age: 42 }]) - """""" - another good color - """""" + ""another good color"" BLUE } ")] @@ -207,9 +208,7 @@ scalar JSON @exportable # A dog type Dog implements Animal { - """""" - inline docs - """""" + ""inline docs"" volume: Float """""" multiline @@ -235,5 +234,68 @@ public async Task WriteDocumentVisitor_Should_Print_Document(string text, string } } } + + [Theory] + [InlineData( 1, "test", "test", false)] + [InlineData( 2, "te\\\"\"\"st", "te\\\"\\\"\\\"st", false)] + [InlineData( 3, "\ntest", "test", false)] + [InlineData( 4, "\r\ntest", "test", false)] + [InlineData( 5, " \ntest", "test", false)] + [InlineData( 6, "\t\ntest", "test", false)] + [InlineData( 7, "\n\ntest", "test", false)] + [InlineData( 8, "\ntest\nline2", "\ntest\nline2\n", true)] + [InlineData( 9, "test\rline2", "\ntest\nline2\n", true)] + [InlineData(10, "test\r\nline2", "\ntest\nline2\n", true)] + [InlineData(11, "test\r\r\nline2", "\ntest\n\nline2\n", true)] + [InlineData(12, "test\r\n\nline2", "\ntest\n\nline2\n", true)] + [InlineData(13, "test\n", "test", false)] + [InlineData(14, "test\n ", "test", false)] + [InlineData(15, "test\n\t", "test", false)] + [InlineData(16, "test\n\n", "test", false)] + [InlineData(17, "test\n line2", "\ntest\nline2\n", true)] + [InlineData(18, "test\n\t\tline2", "\ntest\nline2\n", true)] + [InlineData(19, "test\n \tline2", "\ntest\nline2\n", true)] + [InlineData(20, " test\nline2", "\n test\nline2\n", true)] + [InlineData(21, " test\n line2", "\n test\nline2\n", true)] + [InlineData(22, "\n test\n line2", "\ntest\nline2\n", true)] + [InlineData(23, " test\n line2\n\t\tline3\n line4", "\n test\nline2\n\tline3\n line4\n", true)] + [InlineData(24, " test\n Hello,\n\n world!\n ", "\n test\nHello,\n\n world!\n", true)] + [InlineData(25, " \n Hello,\r\n\n world!\n ", "\nHello,\n\n world!\n", true)] + [InlineData(26, " \n Hello,\r\n\n wor___ld!\n ", "\nHello,\n\n wor___ld!\n", true)] + [InlineData(27, "\r\n Hello,\r\n World!\r\n\r\n Yours,\r\n GraphQL.\r\n ", "\nHello,\n World!\n\nYours,\n GraphQL.\n", true)] + [InlineData(28, "Test \\n escaping", "Test \\\\n escaping", false)] + [InlineData(29, "Test \\u1234 escaping", "Test \\\\u1234 escaping", false)] + [InlineData(30, "Test \\ escaping", "Test \\\\ escaping", false)] + public async Task WriteDocumentVisitor_Should_Print_BlockStrings(int number, string input, string expected, bool isBlockString) + { + number.ShouldBeGreaterThan(0); + + input = input.Replace("___", new string('_', 9000)); + expected = expected.Replace("___", new string('_', 9000)); + + input = "\"\"\"" + input + "\"\"\""; + if (isBlockString) + expected = "\"\"\"" + expected + "\"\"\""; + else + expected = "\"" + expected + "\""; + + var context = new TestContext(); + + using (var document = (input + " scalar a").Parse()) + { + await _sdlWriter.Visit(document, context).ConfigureAwait(false); + var renderedOriginal = context.Writer.ToString(); + + var lines = renderedOriginal.Split(Environment.NewLine); + var renderedDescription = string.Join(Environment.NewLine, lines.SkipLast(2)); + renderedDescription = renderedDescription.Replace("\r\n", "\n"); + renderedDescription.ShouldBe(expected); + + using (var parsedBack = renderedOriginal.Parse()) + { + // should be parsed back + } + } + } } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 845a7204..76cf0638 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -44,8 +44,8 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co needStartNewLine = false; } - char current = comment.Text.Span[i]; - switch (current) + char code = comment.Text.Span[i]; + switch (code) { case '\r': break; @@ -56,7 +56,7 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co break; default: - await context.Write(comment.Text.Slice(i, 1)/*current*/).ConfigureAwait(false); + await context.Write(comment.Text.Slice(i, 1)/*code*/).ConfigureAwait(false); break; } } @@ -67,43 +67,126 @@ public override async ValueTask VisitComment(GraphQLComment comment, TContext co /// public override async ValueTask VisitDescription(GraphQLDescription description, TContext context) { - int level = GetLevel(context); + bool ShouldBeMultilineBlockString() + { + bool newLineDetected = false; + var span = description.Value.Span; + for (int i = 0; i < span.Length; ++i) + { + char code = span[i]; - await WriteIndent(context, level).ConfigureAwait(false); - await context.Write("\"\"\"").ConfigureAwait(false); - await context.WriteLine().ConfigureAwait(false); + if (code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D) + return false; - bool needStartNewLine = true; - int length = description.Value.Span.Length; - for (int i = 0; i < length; ++i) + if (code == 0x000A) + newLineDetected = true; + } + + // Note that string value without escape symbols and newline symbols + // MAY BE represented as a single-line BlockString, for example, + // """SOME TEXT""", but it was decided to use more brief "SOME TEXT" + // for such cases. WriteMultilineBlockString method ALWAYS builds + // BlockString printing """ on new line. + return newLineDetected; + } + + async ValueTask WriteMultilineBlockString() { - if (needStartNewLine) + int level = GetLevel(context); + + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("\"\"\"").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); + + bool needStartNewLine = true; + int length = description.Value.Span.Length; + // http://spec.graphql.org/October2021/#BlockStringCharacter + for (int i = 0; i < length; ++i) { - await WriteIndent(context, level).ConfigureAwait(false); - needStartNewLine = false; + if (needStartNewLine) + { + await WriteIndent(context, level).ConfigureAwait(false); + needStartNewLine = false; + } + + char code = description.Value.Span[i]; + switch (code) + { + case '\r': + break; + + case '\n': + await context.WriteLine().ConfigureAwait(false); + needStartNewLine = true; + break; + + case '"': + if (i < length - 2 && description.Value.Span[i + 1] == '"' && description.Value.Span[i + 2] == '"') + { + await context.Write("\\\"").ConfigureAwait(false); + } + else + { + await context.Write(description.Value.Slice(i, 1)/*code*/).ConfigureAwait(false); //TODO: change + } + break; + + default: + await context.Write(description.Value.Slice(i, 1)/*code*/).ConfigureAwait(false); //TODO: change + break; + } } - char current = description.Value.Span[i]; - switch (current) - { - case '\r': - break; + await context.WriteLine().ConfigureAwait(false); + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("\"\"\"").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); + } - case '\n': - await context.WriteLine().ConfigureAwait(false); - needStartNewLine = true; - break; + async ValueTask WriteString() + { + int level = GetLevel(context); - default: - await context.Write(description.Value.Slice(i, 1)/*current*/).ConfigureAwait(false); //TODO: change - break; + await WriteIndent(context, level).ConfigureAwait(false); + await context.Write("\"").ConfigureAwait(false); + + int length = description.Value.Span.Length; + // http://spec.graphql.org/October2021/#StringCharacter + for (int i = 0; i < length; ++i) + { + char code = description.Value.Span[i]; + if (code < ' ') + { + if (code == '\b') + await context.Write("\\b").ConfigureAwait(false); + else if (code == '\f') + await context.Write("\\f").ConfigureAwait(false); + else if (code == '\n') + await context.Write("\\n").ConfigureAwait(false); + else if (code == '\r') + await context.Write("\\r").ConfigureAwait(false); + else if (code == '\t') + await context.Write("\\t").ConfigureAwait(false); + else + await context.Write("\\u" + ((int)code).ToString("X4")).ConfigureAwait(false); + } + else if (code == '\\') + await context.Write("\\\\").ConfigureAwait(false); + else if (code == '"') + await context.Write("\\\"").ConfigureAwait(false); + else + await context.Write(description.Value.Slice(i, 1)/*code*/).ConfigureAwait(false); //TODO: change } + + await context.Write("\"").ConfigureAwait(false); + await context.WriteLine().ConfigureAwait(false); } - await context.WriteLine().ConfigureAwait(false); - await WriteIndent(context, level).ConfigureAwait(false); - await context.Write("\"\"\"").ConfigureAwait(false); - await context.WriteLine().ConfigureAwait(false); + // http://spec.graphql.org/October2021/#StringValue + if (ShouldBeMultilineBlockString()) + await WriteMultilineBlockString(); + else + await WriteString(); } /// From 0507a9cba50d73e1e96cf77e835e1883955cdd7a Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 20:39:00 +0300 Subject: [PATCH 15/18] format --- src/GraphQLParser.Tests/LexerTests.cs | 18 +++++++++--------- .../Visitors/SDLWriterTests.cs | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/GraphQLParser.Tests/LexerTests.cs b/src/GraphQLParser.Tests/LexerTests.cs index 9a9df690..32d37b6f 100644 --- a/src/GraphQLParser.Tests/LexerTests.cs +++ b/src/GraphQLParser.Tests/LexerTests.cs @@ -975,15 +975,15 @@ public void Lex_WhiteSpaceStringToken_HasStringKind() } [Theory] - [InlineData( 1, "test", "test")] - [InlineData( 2, "te\\\"\"\"st", "te\"\"\"st")] - [InlineData( 3, "\ntest", "test")] - [InlineData( 4,"\r\ntest", "test")] - [InlineData( 5, " \ntest", "test")] - [InlineData( 6, "\t\ntest", "test")] - [InlineData( 7, "\n\ntest", "test")] - [InlineData( 8, "test\nline2", "test\nline2")] - [InlineData( 9,"test\rline2", "test\nline2")] + [InlineData(1, "test", "test")] + [InlineData(2, "te\\\"\"\"st", "te\"\"\"st")] + [InlineData(3, "\ntest", "test")] + [InlineData(4,"\r\ntest", "test")] + [InlineData(5, " \ntest", "test")] + [InlineData(6, "\t\ntest", "test")] + [InlineData(7, "\n\ntest", "test")] + [InlineData(8, "test\nline2", "test\nline2")] + [InlineData(9,"test\rline2", "test\nline2")] [InlineData(10, "test\r\nline2", "test\nline2")] [InlineData(11, "test\r\r\nline2", "test\n\nline2")] [InlineData(12, "test\r\n\nline2", "test\n\nline2")] diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index 5fde3b4c..c64a30e2 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -236,15 +236,15 @@ public async Task WriteDocumentVisitor_Should_Print_Document(string text, string } [Theory] - [InlineData( 1, "test", "test", false)] - [InlineData( 2, "te\\\"\"\"st", "te\\\"\\\"\\\"st", false)] - [InlineData( 3, "\ntest", "test", false)] - [InlineData( 4, "\r\ntest", "test", false)] - [InlineData( 5, " \ntest", "test", false)] - [InlineData( 6, "\t\ntest", "test", false)] - [InlineData( 7, "\n\ntest", "test", false)] - [InlineData( 8, "\ntest\nline2", "\ntest\nline2\n", true)] - [InlineData( 9, "test\rline2", "\ntest\nline2\n", true)] + [InlineData(1, "test", "test", false)] + [InlineData(2, "te\\\"\"\"st", "te\\\"\\\"\\\"st", false)] + [InlineData(3, "\ntest", "test", false)] + [InlineData(4, "\r\ntest", "test", false)] + [InlineData(5, " \ntest", "test", false)] + [InlineData(6, "\t\ntest", "test", false)] + [InlineData(7, "\n\ntest", "test", false)] + [InlineData(8, "\ntest\nline2", "\ntest\nline2\n", true)] + [InlineData(9, "test\rline2", "\ntest\nline2\n", true)] [InlineData(10, "test\r\nline2", "\ntest\nline2\n", true)] [InlineData(11, "test\r\r\nline2", "\ntest\n\nline2\n", true)] [InlineData(12, "test\r\n\nline2", "\ntest\n\nline2\n", true)] From d562bc883a3b311d36fbae4075aaaee490a1c7b8 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 20:41:53 +0300 Subject: [PATCH 16/18] format --- src/GraphQLParser.Tests/LexerTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GraphQLParser.Tests/LexerTests.cs b/src/GraphQLParser.Tests/LexerTests.cs index 32d37b6f..cdba237f 100644 --- a/src/GraphQLParser.Tests/LexerTests.cs +++ b/src/GraphQLParser.Tests/LexerTests.cs @@ -978,12 +978,12 @@ public void Lex_WhiteSpaceStringToken_HasStringKind() [InlineData(1, "test", "test")] [InlineData(2, "te\\\"\"\"st", "te\"\"\"st")] [InlineData(3, "\ntest", "test")] - [InlineData(4,"\r\ntest", "test")] + [InlineData(4, "\r\ntest", "test")] [InlineData(5, " \ntest", "test")] [InlineData(6, "\t\ntest", "test")] [InlineData(7, "\n\ntest", "test")] [InlineData(8, "test\nline2", "test\nline2")] - [InlineData(9,"test\rline2", "test\nline2")] + [InlineData(9, "test\rline2", "test\nline2")] [InlineData(10, "test\r\nline2", "test\nline2")] [InlineData(11, "test\r\r\nline2", "test\n\nline2")] [InlineData(12, "test\r\n\nline2", "test\n\nline2")] From ea317dea4c52fbaea802424cd85512bdfdae4f0b Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Sun, 14 Nov 2021 23:42:43 +0300 Subject: [PATCH 17/18] Add documentation + options for StructureWriter --- README.md | 101 ++++++++++-------- .../GraphQL-Parser.approved.txt | 7 +- .../Visitors/StructureWriterTests.cs | 12 +-- src/GraphQLParser/Visitors/StructureWriter.cs | 28 +++++ 4 files changed, 95 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 862e44f7..f91af82d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The parser from this library is used in [GraphQL for .NET](https://github.com/gr Preview versions of this package are available on [GitHub Packages](https://github.com/orgs/graphql-dotnet/packages?repo_name=parser). -## Lexer +## 1. Lexer Generates token based on input text. Lexer takes advantage of `ReadOnlyMemory` and in most cases does not allocate memory on the managed heap at all. @@ -38,7 +38,7 @@ var token = Lexer.Lex("\"str\""); Lex method always returns the first token it finds. In this case case the result would look like following. ![lexer example](assets/lexer-example.png) -## Parser +## 2. Parser Parses provided GraphQL expression into AST (abstract syntax tree). Parser also takes advantage of `ReadOnlyMemory` but still allocates memory for AST. @@ -61,51 +61,60 @@ By default `ParserOptions.Ignore` is `IgnoreOptions.IgnoreComments` to improve p If you don't need information about tokens locations in the source document, then use `IgnoreOptions.IgnoreCommentsAndLocations`. This will maximize the saving of memory allocated in the managed heap for AST. -### Example of json representation of the resulting AST +## 3. INodeVisitor -```json +`INodeVisitor` provides API to traverse AST of the parsed GraphQL document. +Default implementation of this interface is `DefaultNodeVisitor` that +traverses all AST nodes of the provided one. You can inherit from it and +implement your own AST processing algorithm. + +For printing SDL from AST, you can use `SDLWriter` visitor. +This is a highly optimized visitor for asynchronous non-blocking SDL output +into provided `TextWriter`. In the majority of cases it does not allocate +memory in the managed heap at all. + +You can also find a `StructureWriter` visitor that prints AST +into the provided `TextWriter` as a hierarchy of node types. It can be useful +when debugging for better understanding the AST structure. +Consider GraphQL document + +```graphql +query a { name age } +``` + +After `StructureWriter` processing the output text will be + +``` +Document + OperationDefinition + Name [a] + SelectionSet + Field + Name [name] + Field + Name [age] +``` + +### Usage + +```c# +public class Context : IWriteContext { - "Definitions": [{ - "Directives": [], - "Kind": 2, - "Name": null, - "Operation": 0, - "SelectionSet": { - "Kind": 5, - "Selections": [{ - "Alias": null, - "Arguments": [], - "Directives": [], - "Kind": 6, - "Name": { - "Kind": 0, - "Value": "field", - "Location": { - "End": 50, - "Start": 31 - } - }, - "SelectionSet": null, - "Location": { - "End": 50, - "Start": 31 - } - }], - "Location": { - "End": 50, - "Start": 13 - } - }, - "VariableDefinitions": null, - "Location": { - "End": 50, - "Start": 13 - } - }], - "Kind": 1, - "Location": { - "End": 50, - "Start": 13 - } + public TextWriter Writer { get; set; } = new StringWriter(); + + public Stack Parents { get; set; } = new Stack(); + + public CancellationToken CancellationToken { get; set; } +} + +public static void Parse(string text) +{ + var document = Parser.Parse(text); + + var context = new Context(); + var visitor = new SDLWriter() + await visitor.Visit(document, context); + var rendered = context.Writer.ToString(); + Console.WriteLine(rendered); } ``` diff --git a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt index 9cbcdfa3..bdbab7ba 100644 --- a/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQL-Parser.approved.txt @@ -609,10 +609,15 @@ namespace GraphQLParser.Visitors public override System.Threading.Tasks.ValueTask VisitVariable(GraphQLParser.AST.GraphQLVariable variable, TContext context) { } public override System.Threading.Tasks.ValueTask VisitVariableDefinition(GraphQLParser.AST.GraphQLVariableDefinition variableDefinition, TContext context) { } } + public class StructureWriterOptions + { + public StructureWriterOptions() { } + public bool WriteNames { get; set; } + } public class StructureWriter : GraphQLParser.Visitors.DefaultNodeVisitor where TContext : GraphQLParser.Visitors.IWriteContext { - public StructureWriter() { } + public StructureWriter(GraphQLParser.Visitors.StructureWriterOptions options) { } public override System.Threading.Tasks.ValueTask Visit(GraphQLParser.AST.ASTNode? node, TContext context) { } } public static class WriteContextExtensions diff --git a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs index e1b01b1a..f71f1c74 100644 --- a/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/StructureWriterTests.cs @@ -19,23 +19,23 @@ private class TestContext : IWriteContext public CancellationToken CancellationToken { get; set; } } - private static readonly StructureWriter _structWriter = new(); + private static readonly StructureWriter _structWriter = new(new StructureWriterOptions()); [Theory] [InlineData("query a { name age }", @"Document OperationDefinition - Name + Name [a] SelectionSet Field - Name + Name [name] Field - Name + Name [age] ")] [InlineData("scalar JSON @exportable", @"Document ScalarTypeDefinition - Name + Name [JSON] Directive - Name + Name [exportable] ")] public async Task WriteTreeVisitor_Should_Print_Tree(string text, string expected) { diff --git a/src/GraphQLParser/Visitors/StructureWriter.cs b/src/GraphQLParser/Visitors/StructureWriter.cs index 7a5b07a0..764ee33e 100644 --- a/src/GraphQLParser/Visitors/StructureWriter.cs +++ b/src/GraphQLParser/Visitors/StructureWriter.cs @@ -11,6 +11,17 @@ namespace GraphQLParser.Visitors public class StructureWriter : DefaultNodeVisitor where TContext : IWriteContext { + /// + /// Creates visitor with the specified options. + /// + /// Visitor options. + public StructureWriter(StructureWriterOptions options) + { + Options = options; + } + + private StructureWriterOptions Options { get; } + /// public override async ValueTask Visit(ASTNode? node, TContext context) { @@ -22,9 +33,26 @@ public override async ValueTask Visit(ASTNode? node, TContext context) context.Parents.Push(node); await context.Write(node.Kind.ToString()).ConfigureAwait(false); + if (Options.WriteNames && node is GraphQLName name) + { + await context.Write(" [").ConfigureAwait(false); + await context.Write(name.Value).ConfigureAwait(false); + await context.Write("]").ConfigureAwait(false); + } await context.WriteLine().ConfigureAwait(false); await base.Visit(node, context).ConfigureAwait(false); context.Parents.Pop(); } } + + /// + /// Options for . + /// + public class StructureWriterOptions + { + /// + /// Write into the output. + /// + public bool WriteNames { get; set; } = true; + } } From 18dcf689e7688097a4f086c7fcb115d62ff6715c Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Tue, 16 Nov 2021 21:36:31 +0300 Subject: [PATCH 18/18] encode strings --- .../Visitors/SDLWriterTests.cs | 29 ++++++++ src/GraphQLParser/Visitors/SDLWriter.cs | 71 ++++++++++--------- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs index c64a30e2..4e9236a4 100644 --- a/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs +++ b/src/GraphQLParser.Tests/Visitors/SDLWriterTests.cs @@ -297,5 +297,34 @@ public async Task WriteDocumentVisitor_Should_Print_BlockStrings(int number, str } } } + + [Theory] + [InlineData("\"\"")] + [InlineData("\"\\\\\"")] + [InlineData("\"\\n\\b\\f\\r\\t\"")] + [InlineData("\" \u1234 \"")] + [InlineData("\"normal text\"")] + public async Task WriteDocumentVisitor_Should_Print_EscapedStrings(string stringValue) + { + string query = $"{{a(p:{stringValue})}}"; + string expected = @$" +{{ + a(p: {stringValue}) +}} +"; + var context = new TestContext(); + + using (var document = query.Parse()) + { + await _sdlWriter.Visit(document, context).ConfigureAwait(false); + var rendered = context.Writer.ToString(); + rendered.ShouldBe(expected); + + using (var parsedBack = rendered.Parse()) + { + // should be parsed back + } + } + } } } diff --git a/src/GraphQLParser/Visitors/SDLWriter.cs b/src/GraphQLParser/Visitors/SDLWriter.cs index 76cf0638..d242950f 100644 --- a/src/GraphQLParser/Visitors/SDLWriter.cs +++ b/src/GraphQLParser/Visitors/SDLWriter.cs @@ -146,39 +146,8 @@ async ValueTask WriteMultilineBlockString() async ValueTask WriteString() { int level = GetLevel(context); - await WriteIndent(context, level).ConfigureAwait(false); - await context.Write("\"").ConfigureAwait(false); - - int length = description.Value.Span.Length; - // http://spec.graphql.org/October2021/#StringCharacter - for (int i = 0; i < length; ++i) - { - char code = description.Value.Span[i]; - if (code < ' ') - { - if (code == '\b') - await context.Write("\\b").ConfigureAwait(false); - else if (code == '\f') - await context.Write("\\f").ConfigureAwait(false); - else if (code == '\n') - await context.Write("\\n").ConfigureAwait(false); - else if (code == '\r') - await context.Write("\\r").ConfigureAwait(false); - else if (code == '\t') - await context.Write("\\t").ConfigureAwait(false); - else - await context.Write("\\u" + ((int)code).ToString("X4")).ConfigureAwait(false); - } - else if (code == '\\') - await context.Write("\\\\").ConfigureAwait(false); - else if (code == '"') - await context.Write("\\\"").ConfigureAwait(false); - else - await context.Write(description.Value.Slice(i, 1)/*code*/).ConfigureAwait(false); //TODO: change - } - - await context.Write("\"").ConfigureAwait(false); + await WriteEncodedString(context, description.Value).ConfigureAwait(false); await context.WriteLine().ConfigureAwait(false); } @@ -684,9 +653,7 @@ public override async ValueTask VisitNullValue(GraphQLScalarValue nullValue, TCo public override async ValueTask VisitStringValue(GraphQLScalarValue stringValue, TContext context) { await Visit(stringValue.Comment, context).ConfigureAwait(false); - await context.Write("\"").ConfigureAwait(false); - await context.Write(stringValue.Value).ConfigureAwait(false); - await context.Write("\"").ConfigureAwait(false); + await WriteEncodedString(context, stringValue.Value); } /// @@ -843,5 +810,39 @@ node is GraphQLInputObjectTypeDefinition || return level; } + + // http://spec.graphql.org/October2021/#StringCharacter + private async ValueTask WriteEncodedString(TContext context, ROM value) + { + await context.Write("\"").ConfigureAwait(false); + + for (int i = 0; i < value.Span.Length; ++i) + { + char code = value.Span[i]; + if (code < ' ') + { + if (code == '\b') + await context.Write("\\b").ConfigureAwait(false); + else if (code == '\f') + await context.Write("\\f").ConfigureAwait(false); + else if (code == '\n') + await context.Write("\\n").ConfigureAwait(false); + else if (code == '\r') + await context.Write("\\r").ConfigureAwait(false); + else if (code == '\t') + await context.Write("\\t").ConfigureAwait(false); + else + await context.Write("\\u" + ((int)code).ToString("X4")).ConfigureAwait(false); + } + else if (code == '\\') + await context.Write("\\\\").ConfigureAwait(false); + else if (code == '"') + await context.Write("\\\"").ConfigureAwait(false); + else + await context.Write(value.Slice(i, 1)/*code*/).ConfigureAwait(false); // TODO: no method for char + } + + await context.Write("\"").ConfigureAwait(false); + } } }