diff --git a/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt b/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt index 22363a63..28d1e67d 100644 --- a/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt @@ -661,6 +661,7 @@ namespace GraphQLParser public static class Parser { public static GraphQLParser.AST.GraphQLDocument Parse(GraphQLParser.ROM source, GraphQLParser.ParserOptions options = default) { } + public static GraphQLParser.AST.GraphQLValue ParseValue(GraphQLParser.ROM source, GraphQLParser.ParserOptions options = default) { } } public struct ParserOptions { diff --git a/src/GraphQLParser.Tests/ParserTests.cs b/src/GraphQLParser.Tests/ParserTests.cs index ab9a6423..a8ce782f 100644 --- a/src/GraphQLParser.Tests/ParserTests.cs +++ b/src/GraphQLParser.Tests/ParserTests.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Runtime.InteropServices; +using GraphQLParser.Exceptions; namespace GraphQLParser.Tests; @@ -979,6 +980,27 @@ public void Should_Parse_Empty_Types(string text, ASTNodeKind kind) document.Definitions[0].Kind.ShouldBe(kind); } + [Theory] + [InlineData("null", ASTNodeKind.NullValue)] + [InlineData("1", ASTNodeKind.IntValue)] + [InlineData("1.1", ASTNodeKind.FloatValue)] + [InlineData("\"abc\"", ASTNodeKind.StringValue, "abc")] + [InlineData("\"escaped \\n\\r\\b\\t\\f\"", ASTNodeKind.StringValue, "escaped \n\r\b\t\f")] + [InlineData("true", ASTNodeKind.BooleanValue)] + [InlineData("RED", ASTNodeKind.EnumValue)] + [InlineData("[ 1, 2, 3]", ASTNodeKind.ListValue)] + [InlineData("{ a: 1, b: \"abc\", c: RED}", ASTNodeKind.ObjectValue)] + public void Should_Parse_Value_Literal_But_Not_Entire_Document(string text, ASTNodeKind kind, string expected = null) + { + Should.Throw(() => Parser.Parse(text)); + + var value = Parser.ParseValue(text); + value.ShouldNotBeNull(); + value.Kind.ShouldBe(kind); + if (expected != null) + ((GraphQLStringValue)value).Value.ShouldBe(expected); + } + [Theory] [InlineData(IgnoreOptions.None)] [InlineData(IgnoreOptions.Comments)] diff --git a/src/GraphQLParser/GraphQLParser.csproj b/src/GraphQLParser/GraphQLParser.csproj index 7cf41e2d..0782e98c 100644 --- a/src/GraphQLParser/GraphQLParser.csproj +++ b/src/GraphQLParser/GraphQLParser.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/GraphQLParser/Parser.cs b/src/GraphQLParser/Parser.cs index 2e3e93c2..cf3bbcfe 100644 --- a/src/GraphQLParser/Parser.cs +++ b/src/GraphQLParser/Parser.cs @@ -18,4 +18,20 @@ public static class Parser /// In case of syntax error. public static GraphQLDocument Parse(ROM source, ParserOptions options = default) => new ParserContext(source, options).ParseDocument(); + + /// + /// Generates AST of GraphQL value based on input text. + /// + /// Input data as a sequence of characters. + /// Parser options. + /// AST (Abstract Syntax Tree) for GraphQL value. + /// In case when parser recursion depth exceeds . + /// In case of syntax error. + public static GraphQLValue ParseValue(ROM source, ParserOptions options = default) + { + var context = new ParserContext(source, options); + var value = context.ParseValueLiteral(true); + context.Expect(TokenKind.EOF); + return value; + } } diff --git a/src/GraphQLParser/ParserContext.Parse.cs b/src/GraphQLParser/ParserContext.Parse.cs index a04cbe83..03af4b96 100644 --- a/src/GraphQLParser/ParserContext.Parse.cs +++ b/src/GraphQLParser/ParserContext.Parse.cs @@ -1418,7 +1418,7 @@ private GraphQLUnionTypeExtension ParseUnionTypeExtension(int start, List(ref ParserContext context); @@ -176,7 +176,7 @@ private void Advance(bool fromParseComment = false) } } - private void Expect(TokenKind kind, string? description = null) + internal void Expect(TokenKind kind, string? description = null) { if (_currentToken.Kind == kind) { diff --git a/src/GraphQLParser/Visitors/SDLPrinter.cs b/src/GraphQLParser/Visitors/SDLPrinter.cs index 02287876..cb74dfda 100644 --- a/src/GraphQLParser/Visitors/SDLPrinter.cs +++ b/src/GraphQLParser/Visitors/SDLPrinter.cs @@ -1213,7 +1213,7 @@ public DefaultPrintContext(TextWriter writer) public TextWriter Writer { get; } /// - public Stack Parents { get; init; } = new Stack(); + public Stack Parents { get; init; } = new(); /// public CancellationToken CancellationToken { get; init; }