Skip to content

Commit 20e9186

Browse files
authored
Fix some issues with indentation (#313)
1 parent bb6a168 commit 20e9186

File tree

2 files changed

+62
-25
lines changed

2 files changed

+62
-25
lines changed

src/GraphQLParser.Tests/Visitors/SDLPrinterFromParsedTextTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,49 @@ query Q {
790790
}
791791
}
792792
}
793+
""")]
794+
[InlineData(55,
795+
"""
796+
fragment f
797+
#comment
798+
on Person { name }
799+
""",
800+
"""
801+
fragment f
802+
#comment
803+
on Person {
804+
name
805+
}
806+
""")]
807+
[InlineData(56,
808+
"""
809+
type Person
810+
#comment
811+
implements Entity { name: String }
812+
""",
813+
"""
814+
type Person
815+
#comment
816+
implements Entity {
817+
name: String
818+
}
819+
""")]
820+
[InlineData(57,
821+
"""
822+
type Person
823+
#comment
824+
implements Entity &
825+
#comment
826+
Entity2 { name: String }
827+
""",
828+
"""
829+
type Person
830+
#comment
831+
implements Entity &
832+
#comment
833+
Entity2 {
834+
name: String
835+
}
793836
""")]
794837
public async Task SDLPrinter_Should_Print_Document(
795838
int number,

src/GraphQLParser/Visitors/SDLPrinter.cs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ protected override async ValueTask VisitFragmentDefinitionAsync(GraphQLFragmentD
158158
await VisitAsync(fragmentDefinition.Comments, context).ConfigureAwait(false);
159159
await VisitAsync(LiteralNode.Wrap("fragment "), context).ConfigureAwait(false);
160160
await VisitAsync(fragmentDefinition.FragmentName, context).ConfigureAwait(false);
161-
await context.WriteAsync(" ").ConfigureAwait(false);
162161
await VisitAsync(fragmentDefinition.TypeCondition, context).ConfigureAwait(false);
163162
await VisitAsync(fragmentDefinition.Directives, context).ConfigureAwait(false);
164163
await VisitAsync(fragmentDefinition.SelectionSet, context).ConfigureAwait(false);
@@ -177,7 +176,7 @@ protected override async ValueTask VisitFragmentSpreadAsync(GraphQLFragmentSprea
177176
protected override async ValueTask VisitInlineFragmentAsync(GraphQLInlineFragment inlineFragment, TContext context)
178177
{
179178
await VisitAsync(inlineFragment.Comments, context).ConfigureAwait(false);
180-
await VisitAsync(LiteralNode.Wrap("... "), context).ConfigureAwait(false);
179+
await VisitAsync(LiteralNode.Wrap("..."), context).ConfigureAwait(false);
181180
await VisitAsync(inlineFragment.TypeCondition, context).ConfigureAwait(false);
182181
await VisitAsync(inlineFragment.Directives, context).ConfigureAwait(false);
183182
await VisitAsync(inlineFragment.SelectionSet, context).ConfigureAwait(false);
@@ -187,21 +186,21 @@ protected override async ValueTask VisitInlineFragmentAsync(GraphQLInlineFragmen
187186
protected override async ValueTask VisitTypeConditionAsync(GraphQLTypeCondition typeCondition, TContext context)
188187
{
189188
await VisitAsync(typeCondition.Comments, context).ConfigureAwait(false);
190-
await context.WriteAsync("on ").ConfigureAwait(false);
189+
await VisitAsync(LiteralNode.Wrap(HasPrintableComments(typeCondition) ? "on " : " on "), context).ConfigureAwait(false);
191190
await VisitAsync(typeCondition.Type, context).ConfigureAwait(false);
192191
}
193192

194193
/// <inheritdoc/>
195194
protected override async ValueTask VisitImplementsInterfacesAsync(GraphQLImplementsInterfaces implementsInterfaces, TContext context)
196195
{
197196
await VisitAsync(implementsInterfaces.Comments, context).ConfigureAwait(false);
198-
await context.WriteAsync(" implements ").ConfigureAwait(false);
197+
await VisitAsync(LiteralNode.Wrap(HasPrintableComments(implementsInterfaces) ? "implements " : " implements "), context).ConfigureAwait(false);
199198

200199
for (int i = 0; i < implementsInterfaces.Items.Count; ++i)
201200
{
202201
await VisitAsync(implementsInterfaces.Items[i], context).ConfigureAwait(false);
203202
if (i < implementsInterfaces.Items.Count - 1)
204-
await context.WriteAsync(" & ").ConfigureAwait(false);
203+
await context.WriteAsync(HasPrintableComments(implementsInterfaces[i + 1]) ? " &" : " & ").ConfigureAwait(false);
205204
}
206205
}
207206

@@ -210,9 +209,8 @@ protected override async ValueTask VisitSelectionSetAsync(GraphQLSelectionSet se
210209
{
211210
await VisitAsync(selectionSet.Comments, context).ConfigureAwait(false);
212211

213-
bool freshLine = selectionSet.Comments != null && Options.PrintComments;
214212
bool hasParent = TryPeekParent(context, out var parent);
215-
if (!freshLine && hasParent && (parent is GraphQLOperationDefinition op && op.Name is not null || parent is not GraphQLOperationDefinition))
213+
if (!HasPrintableComments(selectionSet) && hasParent && (parent is GraphQLOperationDefinition op && op.Name is not null || parent is not GraphQLOperationDefinition))
216214
{
217215
await context.WriteAsync(" {").ConfigureAwait(false);
218216
}
@@ -385,8 +383,7 @@ protected override async ValueTask VisitSchemaExtensionAsync(GraphQLSchemaExtens
385383
//TODO: https://github.com/graphql/graphql-spec/issues/921
386384
if (schemaExtension.OperationTypes?.Count > 0)
387385
{
388-
//bool freshLine = schemaExtension.Comments != null && Options.PrintComments; always false
389-
await context.WriteAsync(/*freshLine ? "{" :*/" {").ConfigureAwait(false);
386+
await context.WriteAsync(/*HasPrintableComments(schemaExtension) ? "{" :*/" {").ConfigureAwait(false); // always false
390387
await context.WriteLineAsync().ConfigureAwait(false);
391388

392389
for (int i = 0; i < schemaExtension.OperationTypes.Count; ++i)
@@ -442,9 +439,7 @@ protected override async ValueTask VisitEnumValueDefinitionAsync(GraphQLEnumValu
442439
protected override async ValueTask VisitEnumValuesDefinitionAsync(GraphQLEnumValuesDefinition enumValuesDefinition, TContext context)
443440
{
444441
await VisitAsync(enumValuesDefinition.Comments, context).ConfigureAwait(false);
445-
446-
bool freshLine = enumValuesDefinition.Comments != null && Options.PrintComments;
447-
await VisitAsync(LiteralNode.Wrap(freshLine ? "{" : " {"), context).ConfigureAwait(false);
442+
await VisitAsync(LiteralNode.Wrap(HasPrintableComments(enumValuesDefinition) ? "{" : " {"), context).ConfigureAwait(false);
448443
await context.WriteLineAsync().ConfigureAwait(false);
449444

450445
if (enumValuesDefinition.Items?.Count > 0) // should always be true but may be negligently uninitialized
@@ -506,9 +501,7 @@ protected override async ValueTask VisitInputValueDefinitionAsync(GraphQLInputVa
506501
protected override async ValueTask VisitInputFieldsDefinitionAsync(GraphQLInputFieldsDefinition inputFieldsDefinition, TContext context)
507502
{
508503
await VisitAsync(inputFieldsDefinition.Comments, context).ConfigureAwait(false);
509-
510-
bool freshLine = inputFieldsDefinition.Comments != null && Options.PrintComments;
511-
await VisitAsync(LiteralNode.Wrap(freshLine ? "{" : " {"), context).ConfigureAwait(false);
504+
await VisitAsync(LiteralNode.Wrap(HasPrintableComments(inputFieldsDefinition) ? "{" : " {"), context).ConfigureAwait(false);
512505
await context.WriteLineAsync().ConfigureAwait(false);
513506

514507
if (inputFieldsDefinition.Items?.Count > 0) // should always be true but may be negligently uninitialized
@@ -585,9 +578,7 @@ protected override async ValueTask VisitFieldDefinitionAsync(GraphQLFieldDefinit
585578
protected override async ValueTask VisitFieldsDefinitionAsync(GraphQLFieldsDefinition fieldsDefinition, TContext context)
586579
{
587580
await VisitAsync(fieldsDefinition.Comments, context).ConfigureAwait(false);
588-
589-
bool freshLine = fieldsDefinition.Comments != null && Options.PrintComments;
590-
await VisitAsync(LiteralNode.Wrap(freshLine ? "{" : " {"), context).ConfigureAwait(false);
581+
await VisitAsync(LiteralNode.Wrap(HasPrintableComments(fieldsDefinition) ? "{" : " {"), context).ConfigureAwait(false);
591582
await context.WriteLineAsync().ConfigureAwait(false);
592583

593584
if (fieldsDefinition.Items?.Count > 0) // should always be true but may be negligently uninitialized
@@ -609,9 +600,7 @@ protected override async ValueTask VisitSchemaDefinitionAsync(GraphQLSchemaDefin
609600
await VisitAsync(schemaDefinition.Description, context).ConfigureAwait(false);
610601
await VisitAsync(LiteralNode.Wrap("schema"), context).ConfigureAwait(false);
611602
await VisitAsync(schemaDefinition.Directives, context).ConfigureAwait(false);
612-
613-
//bool freshLine = schemaDefinition.Comments != null && Options.PrintComments; always false
614-
await context.WriteAsync(/*freshLine? "{" : */" {").ConfigureAwait(false);
603+
await context.WriteAsync(/*HasPrintableComments(schemaDefinition) ? "{" : */" {").ConfigureAwait(false); // always false
615604
await context.WriteLineAsync().ConfigureAwait(false);
616605

617606
if (schemaDefinition.OperationTypes.Count > 0)
@@ -839,9 +828,10 @@ protected override async ValueTask VisitObjectFieldAsync(GraphQLObjectField obje
839828
}
840829

841830
/// <inheritdoc/>
842-
protected override ValueTask VisitNamedTypeAsync(GraphQLNamedType namedType, TContext context)
831+
protected override async ValueTask VisitNamedTypeAsync(GraphQLNamedType namedType, TContext context)
843832
{
844-
return base.VisitNamedTypeAsync(namedType, context);
833+
await VisitAsync(namedType.Comments, context).ConfigureAwait(false);
834+
await VisitAsync(namedType.Name, context).ConfigureAwait(false);
845835
}
846836

847837
/// <summary>
@@ -878,7 +868,7 @@ node is GraphQLEnumValueDefinition ||
878868
node is GraphQLRootOperationTypeDefinition ||
879869
node is GraphQLDirectiveLocations && Options.EachDirectiveLocationOnNewLine ||
880870
node is GraphQLUnionMemberTypes && Options.EachUnionMemberOnNewLine ||
881-
node is GraphQLArgumentsDefinition && node.Comments?.Count > 0
871+
node is GraphQLArgumentsDefinition && HasPrintableComments(node)
882872
)
883873
context.IndentLevel = 1; // fixed indentation of 1
884874
else if (
@@ -974,6 +964,8 @@ private async ValueTask WriteIndentAsync(TContext context)
974964
context.IndentPrinted = true;
975965
}
976966

967+
private bool HasPrintableComments(ASTNode node) => node.Comments?.Count > 0 && Options.PrintComments;
968+
977969
// Returns parent if called inside VisitXXX i.e. after context.Parents.Push(node);
978970
// Returns grand-parent if called inside VisitAsync i.e. before context.Parents.Push(node);
979971
private static bool TryPeekParent(TContext context, [NotNullWhen(true)] out ASTNode? node)
@@ -1139,7 +1131,9 @@ public class SDLPrinterOptions
11391131
}
11401132

11411133
/// <summary>
1142-
/// Preudo AST node to allow calls to <see cref="SDLPrinter{TContext}.VisitAsync(ASTNode?, TContext)"/> for indentation purposes.
1134+
/// Preudo AST node to allow calls to <see cref="SDLPrinter{TContext}.VisitAsync(ASTNode?, TContext)"/>
1135+
/// for indentation purposes. Any literal printed first after optional comment or description nodes in
1136+
/// any VisitXXX method should be wrapped into <see cref="LiteralNode"/> for proper indentation.
11431137
/// </summary>
11441138
internal class LiteralNode : ASTNode
11451139
{

0 commit comments

Comments
 (0)