Skip to content

Commit 6fb78ac

Browse files
authored
[Fusion] FieldSelectionMapParser support for Path.SelectedObjectValue (#8203)
1 parent c4dcfea commit 6fb78ac

File tree

5 files changed

+76
-7
lines changed

5 files changed

+76
-7
lines changed

src/HotChocolate/Fusion-vnext/src/Fusion.Language/Parsers/FieldSelectionMapParser.cs

+12-3
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,17 @@ private SelectedValueEntryNode ParseSelectedValueEntry()
9797
case TokenKind.LeftAngleBracket: // For a <TypeName>.
9898
path = ParsePath();
9999

100-
if (_reader.TokenKind == TokenKind.LeftSquareBracket)
100+
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
101+
switch (_reader.TokenKind)
101102
{
102-
selectedListValue = ParseSelectedListValue();
103+
case TokenKind.Period:
104+
MoveNext(); // skip "."
105+
selectedObjectValue = ParseSelectedObjectValue();
106+
break;
107+
108+
case TokenKind.LeftSquareBracket:
109+
selectedListValue = ParseSelectedListValue();
110+
break;
103111
}
104112

105113
break;
@@ -202,7 +210,8 @@ private PathSegmentNode ParsePathSegment()
202210
Expect(TokenKind.Period);
203211
pathSegment = ParsePathSegment();
204212
}
205-
else if (_reader.TokenKind == TokenKind.Period)
213+
else if (_reader.TokenKind == TokenKind.Period
214+
&& _reader.GetNextTokenKind() != TokenKind.LeftBrace)
206215
{
207216
MoveNext(); // skip "."
208217
pathSegment = ParsePathSegment();

src/HotChocolate/Fusion-vnext/src/Fusion.Language/Readers/FieldSelectionMapReader.cs

+46-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,46 @@ public bool Read()
124124
throw new FieldSelectionMapSyntaxException(this, UnexpectedCharacter, code);
125125
}
126126

127+
public readonly TokenKind GetNextTokenKind()
128+
{
129+
if (Position >= _length)
130+
{
131+
return TokenKind.EndOfFile;
132+
}
133+
134+
var position = Position;
135+
var code = _sourceText[position];
136+
137+
// Skip insignificant characters.
138+
while (position < _length - 1)
139+
{
140+
if (code
141+
is CharConstants.Space
142+
or CharConstants.LineFeed
143+
or CharConstants.Return
144+
or CharConstants.HorizontalTab
145+
or CharConstants.Comma)
146+
{
147+
code = _sourceText[++position];
148+
continue;
149+
}
150+
151+
break;
152+
}
153+
154+
if (code.IsPunctuator())
155+
{
156+
return GetPunctuatorTokenKind(code);
157+
}
158+
159+
if (code.IsLetterOrUnderscore())
160+
{
161+
return TokenKind.Name;
162+
}
163+
164+
throw new FieldSelectionMapSyntaxException(this, UnexpectedCharacter, code);
165+
}
166+
127167
[MethodImpl(MethodImplOptions.AggressiveInlining)]
128168
public bool Skip(TokenKind tokenKind)
129169
{
@@ -219,8 +259,13 @@ private void ReadPunctuatorToken(char code)
219259
Start = Position;
220260
End = ++Position;
221261
Value = null;
262+
TokenKind = GetPunctuatorTokenKind(code);
263+
}
222264

223-
TokenKind = code switch
265+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
266+
private static TokenKind GetPunctuatorTokenKind(char code)
267+
{
268+
return code switch
224269
{
225270
CharConstants.Colon => TokenKind.Colon,
226271
CharConstants.LeftAngleBracket => TokenKind.LeftAngleBracket,

src/HotChocolate/Fusion-vnext/src/Fusion.Language/SyntaxSerializers/FieldSelectionMapSyntaxSerializer.cs

+5
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ protected override ISyntaxVisitorAction Enter(
146146
if (node.Path is not null)
147147
{
148148
Visit(node.Path, writer);
149+
150+
if (node.SelectedObjectValue is not null)
151+
{
152+
writer.Write(Period);
153+
}
149154
}
150155

151156
if (node.SelectedObjectValue is not null)

src/HotChocolate/Fusion-vnext/test/Fusion.Language.Tests/FieldSelectionMapParserTests.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,7 @@ public void Parse_SelectedObjectValueMultipleFieldsNoSelectedValue_MatchesSnapsh
187187

188188
[Theory]
189189
// https://graphql.github.io/composite-schemas-spec/draft/#sec-SelectedObjectValue
190-
// TODO: Enable this test when the parser supports it.
191-
[InlineData("dimension.{ size weight }", Skip = "Not yet supported by parser")]
190+
[InlineData("dimension.{ size weight }")]
192191
[InlineData("{ size: dimensions.size weight: dimensions.weight }")]
193192
public void ParseAndPrint_SelectedObjectValueValidExamples_Matches(string sourceText)
194193
{

src/HotChocolate/Fusion-vnext/test/Fusion.Utilities.Tests/Rewriters/SelectedValueToSelectionSetRewriterTests.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,18 @@ ... on Book {
6060
}
6161
"""
6262
},
63-
// TODO: Test "dimension.{ size weight }" (not yet supported by parser).
63+
{
64+
"Product",
65+
"dimensions.{ size weight }",
66+
"""
67+
{
68+
dimensions {
69+
size
70+
weight
71+
}
72+
}
73+
"""
74+
},
6475
{
6576
"Product",
6677
"{ size: dimensions.size weight: dimensions.weight }",

0 commit comments

Comments
 (0)