From f4b5c535dafa6132284e0cb9432e0df710fd57e0 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 12:37:36 +0900 Subject: [PATCH 01/21] feat(ast): add comment fields --- ast/comment.go | 36 ++++++++++++++++++++++++++++++++++++ ast/definition.go | 4 ++++ ast/document.go | 6 ++++++ ast/fragment.go | 3 +++ ast/operation.go | 2 ++ ast/selection.go | 2 ++ ast/value.go | 2 ++ 7 files changed, 55 insertions(+) create mode 100644 ast/comment.go diff --git a/ast/comment.go b/ast/comment.go new file mode 100644 index 00000000..22dbfd1b --- /dev/null +++ b/ast/comment.go @@ -0,0 +1,36 @@ +package ast + +import "strings" + +type Comment struct { + Text string + Position *Position +} +type CommentGroup struct { + List []*Comment +} + +func (c *CommentGroup) Start() int { + if len(c.List) == 0 { + return 0 + } + return c.List[0].Position.Start +} + +func (c *CommentGroup) End() int { + if len(c.List) == 0 { + return 0 + } + return c.List[len(c.List)-1].Position.End +} + +func (c *CommentGroup) Text() string { + if len(c.List) == 0 { + return "" + } + var builder strings.Builder + for _, comment := range c.List { + builder.WriteString(comment.Text) + } + return builder.String() +} diff --git a/ast/definition.go b/ast/definition.go index d2039081..4d7b014a 100644 --- a/ast/definition.go +++ b/ast/definition.go @@ -66,6 +66,7 @@ type FieldDefinition struct { Type *Type Directives DirectiveList Position *Position `dump:"-"` + Comment *CommentGroup } type ArgumentDefinition struct { @@ -75,6 +76,7 @@ type ArgumentDefinition struct { Type *Type Directives DirectiveList Position *Position `dump:"-"` + Comment *CommentGroup } type EnumValueDefinition struct { @@ -82,6 +84,7 @@ type EnumValueDefinition struct { Name string Directives DirectiveList Position *Position `dump:"-"` + Comment *CommentGroup } type DirectiveDefinition struct { @@ -91,4 +94,5 @@ type DirectiveDefinition struct { Locations []DirectiveLocation IsRepeatable bool Position *Position `dump:"-"` + Comment *CommentGroup } diff --git a/ast/document.go b/ast/document.go index 43bfb54f..2a309d29 100644 --- a/ast/document.go +++ b/ast/document.go @@ -4,6 +4,7 @@ type QueryDocument struct { Operations OperationList Fragments FragmentDefinitionList Position *Position `dump:"-"` + Comment *CommentGroup } type SchemaDocument struct { @@ -13,6 +14,7 @@ type SchemaDocument struct { Definitions DefinitionList Extensions DefinitionList Position *Position `dump:"-"` + Comment *CommentGroup } func (d *SchemaDocument) Merge(other *SchemaDocument) { @@ -35,6 +37,8 @@ type Schema struct { Implements map[string][]*Definition Description string + + Comment *CommentGroup } // AddTypes is the helper to add types definition to the schema @@ -70,10 +74,12 @@ type SchemaDefinition struct { Directives DirectiveList OperationTypes OperationTypeDefinitionList Position *Position `dump:"-"` + Comment *CommentGroup } type OperationTypeDefinition struct { Operation Operation Type string Position *Position `dump:"-"` + Comment *CommentGroup } diff --git a/ast/fragment.go b/ast/fragment.go index 57ab56c7..7bd7dbce 100644 --- a/ast/fragment.go +++ b/ast/fragment.go @@ -9,6 +9,7 @@ type FragmentSpread struct { Definition *FragmentDefinition Position *Position `dump:"-"` + Comment *CommentGroup } type InlineFragment struct { @@ -20,6 +21,7 @@ type InlineFragment struct { ObjectDefinition *Definition Position *Position `dump:"-"` + Comment *CommentGroup } type FragmentDefinition struct { @@ -35,4 +37,5 @@ type FragmentDefinition struct { Definition *Definition Position *Position `dump:"-"` + Comment *CommentGroup } diff --git a/ast/operation.go b/ast/operation.go index 3b37f81b..16ee064d 100644 --- a/ast/operation.go +++ b/ast/operation.go @@ -15,6 +15,7 @@ type OperationDefinition struct { Directives DirectiveList SelectionSet SelectionSet Position *Position `dump:"-"` + Comment *CommentGroup } type VariableDefinition struct { @@ -23,6 +24,7 @@ type VariableDefinition struct { DefaultValue *Value Directives DirectiveList Position *Position `dump:"-"` + Comment *CommentGroup // Requires validation Definition *Definition diff --git a/ast/selection.go b/ast/selection.go index 5ef26c6a..b93558e5 100644 --- a/ast/selection.go +++ b/ast/selection.go @@ -22,6 +22,7 @@ type Field struct { Directives DirectiveList SelectionSet SelectionSet Position *Position `dump:"-"` + Comment *CommentGroup // Require validation Definition *FieldDefinition @@ -32,6 +33,7 @@ type Argument struct { Name string Value *Value Position *Position `dump:"-"` + Comment *CommentGroup } func (s *Field) ArgumentMap(vars map[string]interface{}) map[string]interface{} { diff --git a/ast/value.go b/ast/value.go index c25ef150..10f7b1cc 100644 --- a/ast/value.go +++ b/ast/value.go @@ -26,6 +26,7 @@ type Value struct { Children ChildValueList Kind ValueKind Position *Position `dump:"-"` + Comment *CommentGroup // Require validation Definition *Definition @@ -37,6 +38,7 @@ type ChildValue struct { Name string Value *Value Position *Position `dump:"-"` + Comment *CommentGroup } func (v *Value) Value(vars map[string]interface{}) (interface{}, error) { From 35ed8ee75ffa792106ab27fa4d1c8e0e1d3ae306 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 12:45:56 +0900 Subject: [PATCH 02/21] feat(formatter): implement getComment --- formatter/comment.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 formatter/comment.go diff --git a/formatter/comment.go b/formatter/comment.go new file mode 100644 index 00000000..13afb7bf --- /dev/null +++ b/formatter/comment.go @@ -0,0 +1,37 @@ +package formatter + +import "github.com/vektah/gqlparser/v2/ast" + +func getComment(node interface{}) *ast.CommentGroup { + switch n := node.(type) { + case *ast.Field: + return n.Comment + case *ast.Argument: + return n.Comment + case *ast.QueryDocument: + return n.Comment + case *ast.SchemaDocument: + return n.Comment + case *ast.FragmentSpread: + return n.Comment + case *ast.InlineFragment: + return n.Comment + case *ast.OperationDefinition: + return n.Comment + case *ast.VariableDefinition: + return n.Comment + case *ast.Value: + return n.Comment + case *ast.ChildValue: + return n.Comment + case *ast.FieldDefinition: + return n.Comment + case *ast.ArgumentDefinition: + return n.Comment + case *ast.EnumValueDefinition: + return n.Comment + case *ast.DirectiveDefinition: + return n.Comment + } + return nil +} From ce9d2640471353f15ccc02e31c40b85d4b5f8123 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 12:58:56 +0900 Subject: [PATCH 03/21] feat(parser): store comments in parser --- parser/parser.go | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 765d0bee..67b8510c 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -17,6 +17,39 @@ type parser struct { peekError error prev lexer.Token + + comment *ast.CommentGroup +} + +func (p *parser) consumeComment() (*ast.Comment, bool) { + if p.err != nil { + return nil, false + } + tok := p.peek() + if tok.Kind != lexer.Comment { + return nil, false + } + p.next() + return &ast.Comment{ + Text: tok.Value, + Position: &tok.Pos, + }, true +} + +func (p *parser) consumeCommentGroup() { + if p.err != nil { + return + } + var comments []*ast.Comment + for { + comment, ok := p.consumeComment() + if !ok { + break + } + comments = append(comments, comment) + } + + p.comment = &ast.CommentGroup{List: comments} } func (p *parser) peekPos() *ast.Position { @@ -35,10 +68,10 @@ func (p *parser) peek() lexer.Token { if !p.peeked { p.peekToken, p.peekError = p.lexer.ReadToken() + p.peeked = true if p.peekToken.Kind == lexer.Comment { - return p.peek() + p.consumeCommentGroup() } - p.peeked = true } return p.peekToken @@ -57,11 +90,12 @@ func (p *parser) next() lexer.Token { } if p.peeked { p.peeked = false + p.comment = nil p.prev, p.err = p.peekToken, p.peekError } else { p.prev, p.err = p.lexer.ReadToken() if p.prev.Kind == lexer.Comment { - return p.next() + p.consumeCommentGroup() } } return p.prev From f2e44ce4b7cc7537ab032a9fc860b58d65acfb7f Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 13:13:20 +0900 Subject: [PATCH 04/21] feat(ast): add Comment field for Definition --- ast/definition.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ast/definition.go b/ast/definition.go index 4d7b014a..a408377d 100644 --- a/ast/definition.go +++ b/ast/definition.go @@ -30,7 +30,8 @@ type Definition struct { EnumValues EnumValueList // enum Position *Position `dump:"-"` - BuiltIn bool `dump:"-"` + Comment *CommentGroup + BuiltIn bool `dump:"-"` } func (d *Definition) IsLeafType() bool { From 3b9fe64c2677c5a9a07c026010cc23b43680a305 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 13:36:46 +0900 Subject: [PATCH 05/21] feat(ast): implement Dumper interface for CommentGroup --- ast/comment.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ast/comment.go b/ast/comment.go index 22dbfd1b..b0f2e9c0 100644 --- a/ast/comment.go +++ b/ast/comment.go @@ -34,3 +34,7 @@ func (c *CommentGroup) Text() string { } return builder.String() } + +func (c *CommentGroup) Dump() string { + return c.Text() +} From d8f4b5333e774d15be836fc5eea9aa907672a236 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 13:37:06 +0900 Subject: [PATCH 06/21] feat(parser): add comment support for schema parsing --- parser/parser.go | 14 +++++++----- parser/parser_test.go | 7 ++++-- parser/query.go | 2 +- parser/schema.go | 52 +++++++++++++++++++++++++++++------------- parser/schema_test.yml | 21 +++++++++++++++++ 5 files changed, 71 insertions(+), 25 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 67b8510c..928560a4 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -101,24 +101,26 @@ func (p *parser) next() lexer.Token { return p.prev } -func (p *parser) expectKeyword(value string) lexer.Token { +func (p *parser) expectKeyword(value string) (lexer.Token, *ast.CommentGroup) { tok := p.peek() + comment := p.comment if tok.Kind == lexer.Name && tok.Value == value { - return p.next() + return p.next(), comment } p.error(tok, "Expected %s, found %s", strconv.Quote(value), tok.String()) - return tok + return tok, comment } -func (p *parser) expect(kind lexer.Type) lexer.Token { +func (p *parser) expect(kind lexer.Type) (lexer.Token, *ast.CommentGroup) { tok := p.peek() + comment := p.comment if tok.Kind == kind { - return p.next() + return p.next(), comment } p.error(tok, "Expected %s, found %s", kind, tok.Kind.String()) - return tok + return tok, comment } func (p *parser) skip(kind lexer.Type) bool { diff --git a/parser/parser_test.go b/parser/parser_test.go index 02ff41fe..16eb0308 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -12,13 +12,16 @@ func TestParserUtils(t *testing.T) { t.Run("test lookaround", func(t *testing.T) { p := newParser("asdf 1.0 turtles") require.Equal(t, "asdf", p.peek().Value) - require.Equal(t, "asdf", p.expectKeyword("asdf").Value) + + tok, _ := p.expectKeyword("asdf") + require.Equal(t, "asdf", tok.Value) require.Equal(t, "asdf", p.prev.Value) require.Nil(t, p.err) require.Equal(t, "1.0", p.peek().Value) require.Equal(t, "1.0", p.peek().Value) - require.Equal(t, "1.0", p.expect(lexer.Float).Value) + tok, _ = p.expect(lexer.Float) + require.Equal(t, "1.0", tok.Value) require.Equal(t, "1.0", p.prev.Value) require.Nil(t, p.err) diff --git a/parser/query.go b/parser/query.go index 123423bb..b4efb302 100644 --- a/parser/query.go +++ b/parser/query.go @@ -343,7 +343,7 @@ func (p *parser) parseTypeReference() *Type { } func (p *parser) parseName() string { - token := p.expect(lexer.Name) + token, _ := p.expect(lexer.Name) return token.Value } diff --git a/parser/schema.go b/parser/schema.go index 9656bcca..ed784366 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -113,11 +113,12 @@ func (p *parser) parseTypeSystemDefinition(description string) *Definition { } func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition { - p.expectKeyword("schema") + _, comment := p.expectKeyword("schema") def := SchemaDefinition{Description: description} def.Position = p.peekPos() def.Description = description + def.Comment = comment def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { @@ -129,6 +130,7 @@ func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition { func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition { var op OperationTypeDefinition op.Position = p.peekPos() + op.Comment = p.comment op.Operation = p.parseOperationType() p.expect(lexer.Colon) op.Type = p.parseName() @@ -136,10 +138,11 @@ func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition { } func (p *parser) parseScalarTypeDefinition(description string) *Definition { - p.expectKeyword("scalar") + _, comment := p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Scalar def.Description = description def.Name = p.parseName() @@ -148,12 +151,13 @@ func (p *parser) parseScalarTypeDefinition(description string) *Definition { } func (p *parser) parseObjectTypeDefinition(description string) *Definition { - p.expectKeyword("type") + _, comment := p.expectKeyword("type") var def Definition def.Position = p.peekPos() def.Kind = Object def.Description = description + def.Comment = comment def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) @@ -187,6 +191,7 @@ func (p *parser) parseFieldsDefinition() FieldList { func (p *parser) parseFieldDefinition() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() + def.Comment = p.comment def.Description = p.parseDescription() def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() @@ -208,6 +213,7 @@ func (p *parser) parseArgumentDefs() ArgumentDefinitionList { func (p *parser) parseArgumentDef() *ArgumentDefinition { var def ArgumentDefinition def.Position = p.peekPos() + def.Comment = p.comment def.Description = p.parseDescription() def.Name = p.parseName() p.expect(lexer.Colon) @@ -222,6 +228,7 @@ func (p *parser) parseArgumentDef() *ArgumentDefinition { func (p *parser) parseInputValueDef() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() + def.Comment = p.comment def.Description = p.parseDescription() def.Name = p.parseName() p.expect(lexer.Colon) @@ -234,11 +241,13 @@ func (p *parser) parseInputValueDef() *FieldDefinition { } func (p *parser) parseInterfaceTypeDefinition(description string) *Definition { - p.expectKeyword("interface") + _, comment := p.expectKeyword("interface") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Interface + def.Comment = p.comment def.Description = description def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() @@ -248,10 +257,11 @@ func (p *parser) parseInterfaceTypeDefinition(description string) *Definition { } func (p *parser) parseUnionTypeDefinition(description string) *Definition { - p.expectKeyword("union") + _, comment := p.expectKeyword("union") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Union def.Description = description def.Name = p.parseName() @@ -275,11 +285,12 @@ func (p *parser) parseUnionMemberTypes() []string { } func (p *parser) parseEnumTypeDefinition(description string) *Definition { - p.expectKeyword("enum") + _, comment := p.expectKeyword("enum") var def Definition def.Position = p.peekPos() def.Kind = Enum + def.Comment = comment def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -305,11 +316,12 @@ func (p *parser) parseEnumValueDefinition() *EnumValueDefinition { } func (p *parser) parseInputObjectTypeDefinition(description string) *Definition { - p.expectKeyword("input") + _, comment := p.expectKeyword("input") var def Definition def.Position = p.peekPos() def.Kind = InputObject + def.Comment = comment def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -349,10 +361,11 @@ func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) { } func (p *parser) parseSchemaExtension() *SchemaDefinition { - p.expectKeyword("schema") + _, comment := p.expectKeyword("schema") var def SchemaDefinition def.Position = p.peekPos() + def.Comment = comment def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition()) @@ -364,10 +377,11 @@ func (p *parser) parseSchemaExtension() *SchemaDefinition { } func (p *parser) parseScalarTypeExtension() *Definition { - p.expectKeyword("scalar") + _, comment := p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Scalar def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -378,10 +392,11 @@ func (p *parser) parseScalarTypeExtension() *Definition { } func (p *parser) parseObjectTypeExtension() *Definition { - p.expectKeyword("type") + _, comment := p.expectKeyword("type") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Object def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() @@ -394,10 +409,11 @@ func (p *parser) parseObjectTypeExtension() *Definition { } func (p *parser) parseInterfaceTypeExtension() *Definition { - p.expectKeyword("interface") + _, comment := p.expectKeyword("interface") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Interface def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -409,10 +425,11 @@ func (p *parser) parseInterfaceTypeExtension() *Definition { } func (p *parser) parseUnionTypeExtension() *Definition { - p.expectKeyword("union") + _, comment := p.expectKeyword("union") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Union def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -425,10 +442,11 @@ func (p *parser) parseUnionTypeExtension() *Definition { } func (p *parser) parseEnumTypeExtension() *Definition { - p.expectKeyword("enum") + _, comment := p.expectKeyword("enum") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = Enum def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -440,10 +458,11 @@ func (p *parser) parseEnumTypeExtension() *Definition { } func (p *parser) parseInputObjectTypeExtension() *Definition { - p.expectKeyword("input") + _, comment := p.expectKeyword("input") var def Definition def.Position = p.peekPos() + def.Comment = comment def.Kind = InputObject def.Name = p.parseName() def.Directives = p.parseDirectives(false) @@ -455,11 +474,12 @@ func (p *parser) parseInputObjectTypeExtension() *Definition { } func (p *parser) parseDirectiveDefinition(description string) *DirectiveDefinition { - p.expectKeyword("directive") + _, comment := p.expectKeyword("directive") p.expect(lexer.At) var def DirectiveDefinition def.Position = p.peekPos() + def.Comment = comment def.Description = description def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() @@ -487,7 +507,7 @@ func (p *parser) parseDirectiveLocations() []DirectiveLocation { } func (p *parser) parseDirectiveLocation() DirectiveLocation { - name := p.expect(lexer.Name) + name, _ := p.expect(lexer.Name) switch name.Value { case `QUERY`: diff --git a/parser/schema_test.yml b/parser/schema_test.yml index 8b6a5d0c..8a59fce6 100644 --- a/parser/schema_test.yml +++ b/parser/schema_test.yml @@ -15,6 +15,26 @@ object types: Name: "world" Type: String + - name: with comments + input: | + # Hello + type Hello { + # World + world: String + } + ast: | + + Definitions: [Definition] + - + Kind: DefinitionKind("OBJECT") + Name: "Hello" + Fields: [FieldDefinition] + - + Name: "world" + Type: String + Comment: # World + Comment: # Hello + - name: with description input: | "Description" @@ -53,6 +73,7 @@ object types: - Name: "world" Type: String + Comment: # Even with comments between them - name: with field arg input: | type Hello { From 4a1d175495005d15a135c8ce23d483ecee8e3017 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 13:42:44 +0900 Subject: [PATCH 07/21] fix(parser): add comments to schema extensions --- parser/schema.go | 45 +++++++++++++++++++++--------------------- parser/schema_test.yml | 2 ++ 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/parser/schema.go b/parser/schema.go index ed784366..1f9ffeec 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -2,6 +2,7 @@ package parser import ( //nolint:revive + "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" ) @@ -338,30 +339,30 @@ func (p *parser) parseInputFieldsDefinition() FieldList { } func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) { - p.expectKeyword("extend") + _, comment := p.expectKeyword("extend") switch p.peek().Value { case "schema": - doc.SchemaExtension = append(doc.SchemaExtension, p.parseSchemaExtension()) + doc.SchemaExtension = append(doc.SchemaExtension, p.parseSchemaExtension(comment)) case "scalar": - doc.Extensions = append(doc.Extensions, p.parseScalarTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseScalarTypeExtension(comment)) case "type": - doc.Extensions = append(doc.Extensions, p.parseObjectTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseObjectTypeExtension(comment)) case "interface": - doc.Extensions = append(doc.Extensions, p.parseInterfaceTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseInterfaceTypeExtension(comment)) case "union": - doc.Extensions = append(doc.Extensions, p.parseUnionTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseUnionTypeExtension(comment)) case "enum": - doc.Extensions = append(doc.Extensions, p.parseEnumTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseEnumTypeExtension(comment)) case "input": - doc.Extensions = append(doc.Extensions, p.parseInputObjectTypeExtension()) + doc.Extensions = append(doc.Extensions, p.parseInputObjectTypeExtension(comment)) default: p.unexpectedError() } } -func (p *parser) parseSchemaExtension() *SchemaDefinition { - _, comment := p.expectKeyword("schema") +func (p *parser) parseSchemaExtension(comment *ast.CommentGroup) *SchemaDefinition { + p.expectKeyword("schema") var def SchemaDefinition def.Position = p.peekPos() @@ -376,8 +377,8 @@ func (p *parser) parseSchemaExtension() *SchemaDefinition { return &def } -func (p *parser) parseScalarTypeExtension() *Definition { - _, comment := p.expectKeyword("scalar") +func (p *parser) parseScalarTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() @@ -391,8 +392,8 @@ func (p *parser) parseScalarTypeExtension() *Definition { return &def } -func (p *parser) parseObjectTypeExtension() *Definition { - _, comment := p.expectKeyword("type") +func (p *parser) parseObjectTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("type") var def Definition def.Position = p.peekPos() @@ -408,8 +409,8 @@ func (p *parser) parseObjectTypeExtension() *Definition { return &def } -func (p *parser) parseInterfaceTypeExtension() *Definition { - _, comment := p.expectKeyword("interface") +func (p *parser) parseInterfaceTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("interface") var def Definition def.Position = p.peekPos() @@ -424,8 +425,8 @@ func (p *parser) parseInterfaceTypeExtension() *Definition { return &def } -func (p *parser) parseUnionTypeExtension() *Definition { - _, comment := p.expectKeyword("union") +func (p *parser) parseUnionTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("union") var def Definition def.Position = p.peekPos() @@ -441,8 +442,8 @@ func (p *parser) parseUnionTypeExtension() *Definition { return &def } -func (p *parser) parseEnumTypeExtension() *Definition { - _, comment := p.expectKeyword("enum") +func (p *parser) parseEnumTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("enum") var def Definition def.Position = p.peekPos() @@ -457,8 +458,8 @@ func (p *parser) parseEnumTypeExtension() *Definition { return &def } -func (p *parser) parseInputObjectTypeExtension() *Definition { - _, comment := p.expectKeyword("input") +func (p *parser) parseInputObjectTypeExtension(comment *ast.CommentGroup) *Definition { + p.expectKeyword("input") var def Definition def.Position = p.peekPos() diff --git a/parser/schema_test.yml b/parser/schema_test.yml index 8a59fce6..74e36f13 100644 --- a/parser/schema_test.yml +++ b/parser/schema_test.yml @@ -167,6 +167,7 @@ object types: type extensions: - name: Object extension input: | + # comment extend type Hello { world: String } @@ -180,6 +181,7 @@ type extensions: - Name: "world" Type: String + Comment: # comment - name: without any fields input: "extend type Hello implements Greeting" From 88539b64b4116ff22f7a2e14a47ac5285c0a902e Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 13:48:02 +0900 Subject: [PATCH 08/21] test(formatter): add comments for schema test --- .../FormatSchemaDocument/definition.graphql | 17 +++++++++++++++++ .../testdata/source/schema/definition.graphql | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql index 2eb48e32..edde31cd 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql @@ -1,24 +1,41 @@ +# Cat0 comment scalar Cat0 +# Cat1 comment type Cat1 { + # Cat1 name comment name: String } +# Cat2 comment interface Cat2 { + # Cat2 name comment name: String } +# Cat3_0 comment type Cat3_0 { + # Cat3_0 name comment name: String } +# Cat3_1 comment type Cat3_1 { + # Cat3_1 name comment name: String } +# Cat3_2 comment type Cat3_2 { + # Cat3_2 name comment name: String } +# Cat3 comment union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 +# Cat4 comment enum Cat4 { + # Cat4 NFC comment NFC + # Cat4 MAINECOON comment MAINECOON } +# Cat5 comment input Cat5 { + # Cat5 name comment name: String } diff --git a/formatter/testdata/source/schema/definition.graphql b/formatter/testdata/source/schema/definition.graphql index 349d72f3..d97bc9c5 100644 --- a/formatter/testdata/source/schema/definition.graphql +++ b/formatter/testdata/source/schema/definition.graphql @@ -1,25 +1,42 @@ +# Cat0 comment scalar Cat0 +# Cat1 comment type Cat1 { + # Cat1 name comment name: String } +# Cat2 comment interface Cat2 { + # Cat2 name comment name: String } +# Cat3_0 comment type Cat3_0 { + # Cat3_0 name comment name: String } +# Cat3_1 comment type Cat3_1 { + # Cat3_1 name comment name: String } +# Cat3_2 comment type Cat3_2 { + # Cat3_2 name comment name: String } +# Cat3 comment union Cat3 = Cat3_0|Cat3_1|Cat3_2 +# Cat4 comment enum Cat4 { + # Cat4 NFC comment NFC + # Cat4 MAINECOON comment MAINECOON } +# Cat5 comment input Cat5 { + # Cat5 name comment name: String } From 50d27ff03f9512e6c41cb0882eed8bad34e4bea5 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:03:31 +0900 Subject: [PATCH 09/21] fix(ast,parser): treat multiline comments --- ast/comment.go | 27 ++++++++++++++++++++++----- parser/parser.go | 11 +++++++++-- parser/schema_test.yml | 10 ++++++---- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/ast/comment.go b/ast/comment.go index b0f2e9c0..5b36036a 100644 --- a/ast/comment.go +++ b/ast/comment.go @@ -1,11 +1,19 @@ package ast -import "strings" +import ( + "strconv" + "strings" +) type Comment struct { - Text string + Value string Position *Position } + +func (c *Comment) Text() string { + return strings.TrimSpace(strings.TrimPrefix(c.Value, "#")) +} + type CommentGroup struct { List []*Comment } @@ -25,16 +33,25 @@ func (c *CommentGroup) End() int { } func (c *CommentGroup) Text() string { - if len(c.List) == 0 { + if c == nil || len(c.List) == 0 { return "" } var builder strings.Builder for _, comment := range c.List { - builder.WriteString(comment.Text) + builder.WriteString(comment.Text()) + builder.WriteString("\n") } return builder.String() } func (c *CommentGroup) Dump() string { - return c.Text() + if len(c.List) == 0 { + return "" + } + var builder strings.Builder + for _, comment := range c.List { + builder.WriteString(comment.Value) + builder.WriteString("\n") + } + return strconv.Quote(builder.String()) } diff --git a/parser/parser.go b/parser/parser.go index 928560a4..40e3cc68 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -18,7 +18,8 @@ type parser struct { prev lexer.Token - comment *ast.CommentGroup + comment *ast.CommentGroup + commentConsuming bool } func (p *parser) consumeComment() (*ast.Comment, bool) { @@ -31,7 +32,7 @@ func (p *parser) consumeComment() (*ast.Comment, bool) { } p.next() return &ast.Comment{ - Text: tok.Value, + Value: tok.Value, Position: &tok.Pos, }, true } @@ -40,6 +41,11 @@ func (p *parser) consumeCommentGroup() { if p.err != nil { return } + if p.commentConsuming { + return + } + p.commentConsuming = true + var comments []*ast.Comment for { comment, ok := p.consumeComment() @@ -50,6 +56,7 @@ func (p *parser) consumeCommentGroup() { } p.comment = &ast.CommentGroup{List: comments} + p.commentConsuming = false } func (p *parser) peekPos() *ast.Position { diff --git a/parser/schema_test.yml b/parser/schema_test.yml index 74e36f13..93ef042a 100644 --- a/parser/schema_test.yml +++ b/parser/schema_test.yml @@ -18,8 +18,10 @@ object types: - name: with comments input: | # Hello + # Hello another type Hello { # World + # World another world: String } ast: | @@ -32,8 +34,8 @@ object types: - Name: "world" Type: String - Comment: # World - Comment: # Hello + Comment: "# World\n# World another\n" + Comment: "# Hello\n# Hello another\n" - name: with description input: | @@ -73,7 +75,7 @@ object types: - Name: "world" Type: String - Comment: # Even with comments between them + Comment: "# Even with comments between them\n" - name: with field arg input: | type Hello { @@ -181,7 +183,7 @@ type extensions: - Name: "world" Type: String - Comment: # comment + Comment: "# comment\n" - name: without any fields input: "extend type Hello implements Greeting" From 33e71958a6ac7457e4dd9216b41b448d7f5e5396 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:04:14 +0900 Subject: [PATCH 10/21] feat(formatter): format schema comments --- formatter/formatter.go | 51 +++++++++++++++++++ .../baseline/FormatSchema/definition.graphql | 15 ++++++ .../baseline/FormatSchema/swapi.graphql | 48 +++++++++++++++++ .../FormatSchemaDocument/definition.graphql | 16 +++--- .../FormatSchemaDocument/swapi.graphql | 48 +++++++++++++++++ .../testdata/source/schema/definition.graphql | 1 + 6 files changed, 170 insertions(+), 9 deletions(-) diff --git a/formatter/formatter.go b/formatter/formatter.go index 01980052..5010ef3c 100644 --- a/formatter/formatter.go +++ b/formatter/formatter.go @@ -139,6 +139,8 @@ func (f *formatter) FormatSchema(schema *ast.Schema) { return } + f.FormatCommentGroup(schema.Comment) + var inSchema bool startSchema := func() { if !inSchema { @@ -194,6 +196,8 @@ func (f *formatter) FormatSchemaDocument(doc *ast.SchemaDocument) { return } + f.FormatCommentGroup(doc.Comment) + f.FormatSchemaDefinitionList(doc.Schema, false) f.FormatSchemaDefinitionList(doc.SchemaExtension, true) @@ -210,6 +214,8 @@ func (f *formatter) FormatQueryDocument(doc *ast.QueryDocument) { return } + f.FormatCommentGroup(doc.Comment) + f.FormatOperationList(doc.Operations) f.FormatFragmentDefinitionList(doc.Fragments) } @@ -234,6 +240,8 @@ func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, e } func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) { + f.FormatCommentGroup(def.Comment) + f.WriteDescription(def.Description) f.FormatDirectiveList(def.Directives) @@ -248,6 +256,7 @@ func (f *formatter) FormatOperationTypeDefinitionList(lists ast.OperationTypeDef } func (f *formatter) FormatOperationTypeDefinition(def *ast.OperationTypeDefinition) { + f.FormatCommentGroup(def.Comment) f.WriteWord(string(def.Operation)).NoPadding().WriteString(":").NeedPadding() f.WriteWord(def.Type) f.WriteNewline() @@ -274,6 +283,8 @@ func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) { return } + f.FormatCommentGroup(field.Comment) + f.WriteDescription(field.Description) f.WriteWord(field.Name).NoPadding() @@ -310,6 +321,8 @@ func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionLis } func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) { + f.FormatCommentGroup(def.Comment) + if def.Description != "" { f.WriteNewline().IncrementIndent() f.WriteDescription(def.Description) @@ -352,6 +365,8 @@ func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) { } } + f.FormatCommentGroup(def.Comment) + f.WriteDescription(def.Description) f.WriteWord("directive").WriteString("@").WriteWord(def.Name) @@ -394,6 +409,8 @@ func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) { return } + f.FormatCommentGroup(def.Comment) + f.WriteDescription(def.Description) if extend { @@ -454,6 +471,8 @@ func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) { } func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) { + f.FormatCommentGroup(def.Comment) + f.WriteDescription(def.Description) f.WriteWord(def.Name) @@ -469,6 +488,8 @@ func (f *formatter) FormatOperationList(lists ast.OperationList) { } func (f *formatter) FormatOperationDefinition(def *ast.OperationDefinition) { + f.FormatCommentGroup(def.Comment) + f.WriteWord(string(def.Operation)) if def.Name != "" { f.WriteWord(def.Name) @@ -513,6 +534,8 @@ func (f *formatter) FormatArgumentList(lists ast.ArgumentList) { } func (f *formatter) FormatArgument(arg *ast.Argument) { + f.FormatCommentGroup(arg.Comment) + f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding() f.WriteString(arg.Value.String()) } @@ -524,6 +547,8 @@ func (f *formatter) FormatFragmentDefinitionList(lists ast.FragmentDefinitionLis } func (f *formatter) FormatFragmentDefinition(def *ast.FragmentDefinition) { + f.FormatCommentGroup(def.Comment) + f.WriteWord("fragment").WriteWord(def.Name) f.FormatVariableDefinitionList(def.VariableDefinition) f.WriteWord("on").WriteWord(def.TypeCondition) @@ -552,6 +577,8 @@ func (f *formatter) FormatVariableDefinitionList(lists ast.VariableDefinitionLis } func (f *formatter) FormatVariableDefinition(def *ast.VariableDefinition) { + f.FormatCommentGroup(def.Comment) + f.WriteString("$").WriteWord(def.Variable).NoPadding().WriteString(":").NeedPadding() f.FormatType(def.Type) @@ -599,6 +626,8 @@ func (f *formatter) FormatSelection(selection ast.Selection) { } func (f *formatter) FormatField(field *ast.Field) { + f.FormatCommentGroup(field.Comment) + if field.Alias != "" && field.Alias != field.Name { f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding() } @@ -616,12 +645,16 @@ func (f *formatter) FormatField(field *ast.Field) { } func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) { + f.FormatCommentGroup(spread.Comment) + f.WriteWord("...").WriteWord(spread.Name) f.FormatDirectiveList(spread.Directives) } func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) { + f.FormatCommentGroup(inline.Comment) + f.WriteWord("...") if inline.TypeCondition != "" { f.WriteWord("on").WriteWord(inline.TypeCondition) @@ -637,5 +670,23 @@ func (f *formatter) FormatType(t *ast.Type) { } func (f *formatter) FormatValue(value *ast.Value) { + f.FormatCommentGroup(value.Comment) + f.WriteString(value.String()) } + +func (f *formatter) FormatCommentGroup(group *ast.CommentGroup) { + if group == nil { + return + } + for _, comment := range group.List { + f.FormatComment(comment) + } +} + +func (f *formatter) FormatComment(comment *ast.Comment) { + if comment == nil { + return + } + f.WriteString("# ").WriteString(comment.Text()).WriteNewline() +} diff --git a/formatter/testdata/baseline/FormatSchema/definition.graphql b/formatter/testdata/baseline/FormatSchema/definition.graphql index ac651492..28f9b01a 100644 --- a/formatter/testdata/baseline/FormatSchema/definition.graphql +++ b/formatter/testdata/baseline/FormatSchema/definition.graphql @@ -1,24 +1,39 @@ +# Cat0 comment +# Cat0 comment 2 scalar Cat0 +# Cat1 comment type Cat1 { + # Cat1 name comment name: String } interface Cat2 { + # Cat2 name comment name: String } +# Cat3 comment union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 +# Cat3_0 comment type Cat3_0 { + # Cat3_0 name comment name: String } +# Cat3_1 comment type Cat3_1 { + # Cat3_1 name comment name: String } +# Cat3_2 comment type Cat3_2 { + # Cat3_2 name comment name: String } +# Cat4 comment enum Cat4 { NFC MAINECOON } +# Cat5 comment input Cat5 { + # Cat5 name comment name: String } diff --git a/formatter/testdata/baseline/FormatSchema/swapi.graphql b/formatter/testdata/baseline/FormatSchema/swapi.graphql index f2c1aea3..cec9a93a 100644 --- a/formatter/testdata/baseline/FormatSchema/swapi.graphql +++ b/formatter/testdata/baseline/FormatSchema/swapi.graphql @@ -1,61 +1,97 @@ interface Character { + # The ID of the character id: ID! + # The name of the character name: String! + # The friends of the character, or an empty list if they have none friends: [Character] + # The friends of the character exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this character appears in appearsIn: [Episode]! } +# The input object sent when passing in a color input ColorInput { red: Int! green: Int! blue: Int! } +# An autonomous mechanical character in the Star Wars universe type Droid implements Character { + # The ID of the droid id: ID! + # What others call this droid name: String! + # This droid's friends, or an empty list if they have none friends: [Character] + # The friends of the droid exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this droid appears in appearsIn: [Episode]! + # This droid's primary function primaryFunction: String } +# The episodes in the Star Wars trilogy enum Episode { NEWHOPE EMPIRE JEDI } +# A connection object for a character's friends type FriendsConnection { + # The total number of friends totalCount: Int + # The edges for each of the character's friends. edges: [FriendsEdge] + # A list of the friends, as a convenience when edges are not needed. friends: [Character] + # Information for paginating this connection pageInfo: PageInfo! } +# An edge object for a character's friends type FriendsEdge { + # A cursor used for pagination cursor: ID! + # The character represented by this friendship edge node: Character } +# A humanoid creature from the Star Wars universe type Human implements Character { + # The ID of the human id: ID! + # What this human calls themselves name: String! + # The home planet of the human, or null if unknown homePlanet: String + # Height in the preferred unit, default is meters height(unit: LengthUnit = METER): Float + # Mass in kilograms, or null if unknown mass: Float + # This human's friends, or an empty list if they have none friends: [Character] + # The friends of the human exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this human appears in appearsIn: [Episode]! + # A list of starships this person has piloted, or an empty list if none starships: [Starship] } +# Units of height enum LengthUnit { METER FOOT } +# The mutation type, represents all updates we can make to our data type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } +# Information for paginating this connection type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } +# The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] @@ -65,23 +101,35 @@ type Query { human(id: ID!): Human starship(id: ID!): Starship } +# Represents a review for a movie type Review { + # The movie episode: Episode + # The number of stars this review gave, 1-5 stars: Int! + # Comment about the movie commentary: String } +# The input object sent when someone is creating a new review input ReviewInput { + # 0-5 stars stars: Int! + # Comment about the movie, optional commentary: String + # Favorite color, optional favorite_color: ColorInput } union SearchResult = Human | Droid | Starship type Starship { + # The ID of the starship id: ID! + # The name of the starship name: String! + # Length of the starship, along the longest axis length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } +# The subscription type, represents all subscriptions we can make to our data type Subscription { reviewAdded(episode: Episode): Review } diff --git a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql index edde31cd..9c8a394c 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql @@ -1,41 +1,39 @@ # Cat0 comment +# Cat0 comment 2 scalar Cat0 # Cat1 comment type Cat1 { - # Cat1 name comment + # Cat1 name comment name: String } -# Cat2 comment interface Cat2 { - # Cat2 name comment + # Cat2 name comment name: String } # Cat3_0 comment type Cat3_0 { - # Cat3_0 name comment + # Cat3_0 name comment name: String } # Cat3_1 comment type Cat3_1 { - # Cat3_1 name comment + # Cat3_1 name comment name: String } # Cat3_2 comment type Cat3_2 { - # Cat3_2 name comment + # Cat3_2 name comment name: String } # Cat3 comment union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 # Cat4 comment enum Cat4 { - # Cat4 NFC comment NFC - # Cat4 MAINECOON comment MAINECOON } # Cat5 comment input Cat5 { - # Cat5 name comment + # Cat5 name comment name: String } diff --git a/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql b/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql index 357f8f57..f2e01c6f 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql @@ -3,6 +3,7 @@ schema { mutation: Mutation subscription: Subscription } +# The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] @@ -12,80 +13,127 @@ type Query { human(id: ID!): Human starship(id: ID!): Starship } +# The mutation type, represents all updates we can make to our data type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } +# The subscription type, represents all subscriptions we can make to our data type Subscription { reviewAdded(episode: Episode): Review } +# The episodes in the Star Wars trilogy enum Episode { NEWHOPE EMPIRE JEDI } interface Character { + # The ID of the character id: ID! + # The name of the character name: String! + # The friends of the character, or an empty list if they have none friends: [Character] + # The friends of the character exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this character appears in appearsIn: [Episode]! } +# Units of height enum LengthUnit { METER FOOT } +# A humanoid creature from the Star Wars universe type Human implements Character { + # The ID of the human id: ID! + # What this human calls themselves name: String! + # The home planet of the human, or null if unknown homePlanet: String + # Height in the preferred unit, default is meters height(unit: LengthUnit = METER): Float + # Mass in kilograms, or null if unknown mass: Float + # This human's friends, or an empty list if they have none friends: [Character] + # The friends of the human exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this human appears in appearsIn: [Episode]! + # A list of starships this person has piloted, or an empty list if none starships: [Starship] } +# An autonomous mechanical character in the Star Wars universe type Droid implements Character { + # The ID of the droid id: ID! + # What others call this droid name: String! + # This droid's friends, or an empty list if they have none friends: [Character] + # The friends of the droid exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! + # The movies this droid appears in appearsIn: [Episode]! + # This droid's primary function primaryFunction: String } +# A connection object for a character's friends type FriendsConnection { + # The total number of friends totalCount: Int + # The edges for each of the character's friends. edges: [FriendsEdge] + # A list of the friends, as a convenience when edges are not needed. friends: [Character] + # Information for paginating this connection pageInfo: PageInfo! } +# An edge object for a character's friends type FriendsEdge { + # A cursor used for pagination cursor: ID! + # The character represented by this friendship edge node: Character } +# Information for paginating this connection type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } +# Represents a review for a movie type Review { + # The movie episode: Episode + # The number of stars this review gave, 1-5 stars: Int! + # Comment about the movie commentary: String } +# The input object sent when someone is creating a new review input ReviewInput { + # 0-5 stars stars: Int! + # Comment about the movie, optional commentary: String + # Favorite color, optional favorite_color: ColorInput } +# The input object sent when passing in a color input ColorInput { red: Int! green: Int! blue: Int! } type Starship { + # The ID of the starship id: ID! + # The name of the starship name: String! + # Length of the starship, along the longest axis length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } diff --git a/formatter/testdata/source/schema/definition.graphql b/formatter/testdata/source/schema/definition.graphql index d97bc9c5..e36297a1 100644 --- a/formatter/testdata/source/schema/definition.graphql +++ b/formatter/testdata/source/schema/definition.graphql @@ -1,4 +1,5 @@ # Cat0 comment +# Cat0 comment 2 scalar Cat0 # Cat1 comment type Cat1 { From 7915f5c1d4462ed36e3ea27f2cf31ef68c4efe5b Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:12:07 +0900 Subject: [PATCH 11/21] test(formatter): update golden --- .../baseline/FormatSchema/extensions.graphql | 12 ++++++++++++ .../FormatSchemaDocument/extensions.graphql | 15 +++++++++++++++ .../testdata/source/schema/extensions.graphql | 17 ++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/formatter/testdata/baseline/FormatSchema/extensions.graphql b/formatter/testdata/baseline/FormatSchema/extensions.graphql index 813b4d03..534fcd2d 100644 --- a/formatter/testdata/baseline/FormatSchema/extensions.graphql +++ b/formatter/testdata/baseline/FormatSchema/extensions.graphql @@ -1,16 +1,28 @@ +# directive @extends comment directive @extends on OBJECT +# directive @key comment directive @key(fields: String!) on OBJECT | INTERFACE +# directive @persmission comment directive @permission(permission: String!) on FIELD_DEFINITION +# Dog comment type Dog { + # Dog name comment name: String! + # Dog owner comment owner: Person! @permission(permission: "admin") } +# Person comment type Person @key(fields: "name") { + # Person name comment name: String! } +# query extends comment type Query @extends { + # dogs comment dogs: [Dog!]! } +# subscription comment type Subscription { + # dogEvents comment dogEvents: [Dog!]! } diff --git a/formatter/testdata/baseline/FormatSchemaDocument/extensions.graphql b/formatter/testdata/baseline/FormatSchemaDocument/extensions.graphql index 225694f8..7af0a72d 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/extensions.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/extensions.graphql @@ -1,24 +1,39 @@ schema { + # query comment query: Query } extend schema { + # subscription comment subscription: Subscription } +# directive @persmission comment directive @permission(permission: String!) on FIELD_DEFINITION +# directive @extends comment directive @extends on OBJECT +# directive @key comment directive @key(fields: String!) on OBJECT | INTERFACE +# query extends comment type Query @extends { + # dogs comment dogs: [Dog!]! } +# subscription comment type Subscription { + # dogEvents comment dogEvents: [Dog!]! } +# Dog comment type Dog { + # Dog name comment name: String! } +# Person comment type Person @key(fields: "name") { + # Person name comment name: String! } +# extend type Dog comment extend type Dog { + # Dog owner comment owner: Person! @permission(permission: "admin") } diff --git a/formatter/testdata/source/schema/extensions.graphql b/formatter/testdata/source/schema/extensions.graphql index d6ee0ceb..af4a12fd 100644 --- a/formatter/testdata/source/schema/extensions.graphql +++ b/formatter/testdata/source/schema/extensions.graphql @@ -1,31 +1,46 @@ schema { + # query comment query: Query } extend schema { + # subscription comment subscription: Subscription } +# query extends comment type Query @extends { + # dogs comment dogs: [Dog!]! } +# subscription comment type Subscription { + # dogEvents comment dogEvents: [Dog!]! } +# Dog comment type Dog { + # Dog name comment name: String! } +# Person comment type Person @key(fields: "name") { + # Person name comment name: String! } +# extend type Dog comment extend type Dog { + # Dog owner comment owner: Person! @permission(permission: "admin") } +# directive @persmission comment directive @permission(permission: String!) on FIELD_DEFINITION +# directive @extends comment directive @extends on OBJECT -directive @key(fields: String!) on OBJECT | INTERFACE \ No newline at end of file +# directive @key comment +directive @key(fields: String!) on OBJECT | INTERFACE From 84fb6108a1f496851f51494da0214be902b332a0 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:22:09 +0900 Subject: [PATCH 12/21] feat(parser): implement comment parsing --- parser/query.go | 21 ++++++++++++++++----- parser/query_test.yml | 1 + 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/parser/query.go b/parser/query.go index b4efb302..9d378fe7 100644 --- a/parser/query.go +++ b/parser/query.go @@ -45,6 +45,7 @@ func (p *parser) parseOperationDefinition() *OperationDefinition { if p.peek().Kind == lexer.BraceL { return &OperationDefinition{ Position: p.peekPos(), + Comment: p.comment, Operation: Query, SelectionSet: p.parseRequiredSelectionSet(), } @@ -52,6 +53,7 @@ func (p *parser) parseOperationDefinition() *OperationDefinition { var od OperationDefinition od.Position = p.peekPos() + od.Comment = p.comment od.Operation = p.parseOperationType() if p.peek().Kind == lexer.Name { @@ -91,6 +93,7 @@ func (p *parser) parseVariableDefinitions() VariableDefinitionList { func (p *parser) parseVariableDefinition() *VariableDefinition { var def VariableDefinition def.Position = p.peekPos() + def.Comment = p.comment def.Variable = p.parseVariable() p.expect(lexer.Colon) @@ -144,6 +147,7 @@ func (p *parser) parseSelection() Selection { func (p *parser) parseField() *Field { var field Field field.Position = p.peekPos() + field.Comment = p.comment field.Alias = p.parseName() if p.skip(lexer.Colon) { @@ -173,6 +177,7 @@ func (p *parser) parseArguments(isConst bool) ArgumentList { func (p *parser) parseArgument(isConst bool) *Argument { arg := Argument{} arg.Position = p.peekPos() + arg.Comment = p.comment arg.Name = p.parseName() p.expect(lexer.Colon) @@ -181,11 +186,12 @@ func (p *parser) parseArgument(isConst bool) *Argument { } func (p *parser) parseFragment() Selection { - p.expect(lexer.Spread) + _, comment := p.expect(lexer.Spread) if peek := p.peek(); peek.Kind == lexer.Name && peek.Value != "on" { return &FragmentSpread{ Position: p.peekPos(), + Comment: comment, Name: p.parseFragmentName(), Directives: p.parseDirectives(false), } @@ -193,6 +199,7 @@ func (p *parser) parseFragment() Selection { var def InlineFragment def.Position = p.peekPos() + def.Comment = comment if p.peek().Value == "on" { p.next() // "on" @@ -207,6 +214,7 @@ func (p *parser) parseFragment() Selection { func (p *parser) parseFragmentDefinition() *FragmentDefinition { var def FragmentDefinition def.Position = p.peekPos() + def.Comment = p.comment p.expectKeyword("fragment") def.Name = p.parseFragmentName() @@ -243,7 +251,7 @@ func (p *parser) parseValueLiteral(isConst bool) *Value { p.unexpectedError() return nil } - return &Value{Position: &token.Pos, Raw: p.parseVariable(), Kind: Variable} + return &Value{Position: &token.Pos, Comment: p.comment, Raw: p.parseVariable(), Kind: Variable} case lexer.Int: kind = IntValue case lexer.Float: @@ -268,32 +276,35 @@ func (p *parser) parseValueLiteral(isConst bool) *Value { p.next() - return &Value{Position: &token.Pos, Raw: token.Value, Kind: kind} + return &Value{Position: &token.Pos, Comment: p.comment, Raw: token.Value, Kind: kind} } func (p *parser) parseList(isConst bool) *Value { var values ChildValueList pos := p.peekPos() + comment := p.comment p.many(lexer.BracketL, lexer.BracketR, func() { values = append(values, &ChildValue{Value: p.parseValueLiteral(isConst)}) }) - return &Value{Children: values, Kind: ListValue, Position: pos} + return &Value{Children: values, Kind: ListValue, Position: pos, Comment: comment} } func (p *parser) parseObject(isConst bool) *Value { var fields ChildValueList pos := p.peekPos() + comment := p.comment p.many(lexer.BraceL, lexer.BraceR, func() { fields = append(fields, p.parseObjectField(isConst)) }) - return &Value{Children: fields, Kind: ObjectValue, Position: pos} + return &Value{Children: fields, Kind: ObjectValue, Position: pos, Comment: comment} } func (p *parser) parseObjectField(isConst bool) *ChildValue { field := ChildValue{} field.Position = p.peekPos() + field.Comment = p.comment field.Name = p.parseName() p.expect(lexer.Colon) diff --git a/parser/query_test.yml b/parser/query_test.yml index a46a01e7..ec0580f5 100644 --- a/parser/query_test.yml +++ b/parser/query_test.yml @@ -436,6 +436,7 @@ large queries: - Alias: "id" Name: "id" + Comment: "# Copyright (c) 2015-present, Facebook, Inc.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n" - Operation: Operation("mutation") Name: "likeStory" From 666777f93d092c1cc007383290d206aeb25e373a Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:26:31 +0900 Subject: [PATCH 13/21] test(formatter): add query comment tests --- .../baseline/FormatQueryDocument/basic.graphql | 4 ++++ .../baseline/FormatQueryDocument/field.graphql | 1 + .../baseline/FormatQueryDocument/fragment.graphql | 12 ++++++++++++ .../baseline/FormatQueryDocument/variable.graphql | 5 +++++ formatter/testdata/source/query/basic.graphql | 4 ++++ formatter/testdata/source/query/field.graphql | 1 + formatter/testdata/source/query/fragment.graphql | 12 ++++++++++++ formatter/testdata/source/query/variable.graphql | 5 +++++ 8 files changed, 44 insertions(+) diff --git a/formatter/testdata/baseline/FormatQueryDocument/basic.graphql b/formatter/testdata/baseline/FormatQueryDocument/basic.graphql index 238d422e..71ee82bb 100644 --- a/formatter/testdata/baseline/FormatQueryDocument/basic.graphql +++ b/formatter/testdata/baseline/FormatQueryDocument/basic.graphql @@ -1,6 +1,10 @@ +# FooBarQuery comment query FooBarQuery ($after: String!) { + # fizzList comment fizzList(first: 100, after: $after) { + # nodes comment nodes { + # id comment id } } diff --git a/formatter/testdata/baseline/FormatQueryDocument/field.graphql b/formatter/testdata/baseline/FormatQueryDocument/field.graphql index 7614c27e..b3445cef 100644 --- a/formatter/testdata/baseline/FormatQueryDocument/field.graphql +++ b/formatter/testdata/baseline/FormatQueryDocument/field.graphql @@ -1,3 +1,4 @@ query { + # bar: foo comment bar: foo } diff --git a/formatter/testdata/baseline/FormatQueryDocument/fragment.graphql b/formatter/testdata/baseline/FormatQueryDocument/fragment.graphql index 6ecda709..d5b3b472 100644 --- a/formatter/testdata/baseline/FormatQueryDocument/fragment.graphql +++ b/formatter/testdata/baseline/FormatQueryDocument/fragment.graphql @@ -1,18 +1,30 @@ +# FooBarQuery comment query FooBarQuery ($after: String!) { + # fizzList comment fizzList(first: 100, after: $after) { + # nodes comment nodes { + # id comment id + # FooFragment comment ... FooFragment + # on Foo comment ... on Foo { + # on Foo id comment id } + # anonymous Fragment comment ... { + # anonymous Fragment id comment id } + # name comment name } } } +# fragment FooFragment comment fragment FooFragment on Foo { + # id comment id } diff --git a/formatter/testdata/baseline/FormatQueryDocument/variable.graphql b/formatter/testdata/baseline/FormatQueryDocument/variable.graphql index 3eeec53b..71690103 100644 --- a/formatter/testdata/baseline/FormatQueryDocument/variable.graphql +++ b/formatter/testdata/baseline/FormatQueryDocument/variable.graphql @@ -1,7 +1,12 @@ +# query root comment query ($first: Int = 30, $after: String!) { + # searchCats comment searchCats(first: $first, after: $after) { + # nodes comment nodes { + # id comment id + # name comment name } } diff --git a/formatter/testdata/source/query/basic.graphql b/formatter/testdata/source/query/basic.graphql index 658ddf0b..a9c3cc03 100644 --- a/formatter/testdata/source/query/basic.graphql +++ b/formatter/testdata/source/query/basic.graphql @@ -1,6 +1,10 @@ +# FooBarQuery comment query FooBarQuery ($after: String!) { + # fizzList comment fizzList(first: 100, after: $after) { + # nodes comment nodes { + # id comment id } } diff --git a/formatter/testdata/source/query/field.graphql b/formatter/testdata/source/query/field.graphql index 7ac16091..051e1917 100644 --- a/formatter/testdata/source/query/field.graphql +++ b/formatter/testdata/source/query/field.graphql @@ -1,3 +1,4 @@ { + # bar: foo comment bar: foo } diff --git a/formatter/testdata/source/query/fragment.graphql b/formatter/testdata/source/query/fragment.graphql index 48fdc929..fa09a321 100644 --- a/formatter/testdata/source/query/fragment.graphql +++ b/formatter/testdata/source/query/fragment.graphql @@ -1,19 +1,31 @@ +# FooBarQuery comment query FooBarQuery ($after: String!) { + # fizzList comment fizzList(first: 100, after: $after) { + # nodes comment nodes { + # id comment id + # FooFragment comment ... FooFragment + # on Foo comment ... on Foo { + # on Foo id comment id } + # anonymous Fragment comment ... { + # anonymous Fragment id comment id } + # name comment name } } } +# fragment FooFragment comment fragment FooFragment on Foo { + # id comment id } diff --git a/formatter/testdata/source/query/variable.graphql b/formatter/testdata/source/query/variable.graphql index ccea84aa..66a51bcc 100644 --- a/formatter/testdata/source/query/variable.graphql +++ b/formatter/testdata/source/query/variable.graphql @@ -1,7 +1,12 @@ +# query root comment query ($first: Int = 30, $after: String!) { + # searchCats comment searchCats(first: $first, after: $after) { + # nodes comment nodes { + # id comment id + # name comment name } } From 90752bd983a2081c2502e116b64964b7f5b015ba Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:27:50 +0900 Subject: [PATCH 14/21] refactor(formatter): remove unused function --- formatter/comment.go | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 formatter/comment.go diff --git a/formatter/comment.go b/formatter/comment.go deleted file mode 100644 index 13afb7bf..00000000 --- a/formatter/comment.go +++ /dev/null @@ -1,37 +0,0 @@ -package formatter - -import "github.com/vektah/gqlparser/v2/ast" - -func getComment(node interface{}) *ast.CommentGroup { - switch n := node.(type) { - case *ast.Field: - return n.Comment - case *ast.Argument: - return n.Comment - case *ast.QueryDocument: - return n.Comment - case *ast.SchemaDocument: - return n.Comment - case *ast.FragmentSpread: - return n.Comment - case *ast.InlineFragment: - return n.Comment - case *ast.OperationDefinition: - return n.Comment - case *ast.VariableDefinition: - return n.Comment - case *ast.Value: - return n.Comment - case *ast.ChildValue: - return n.Comment - case *ast.FieldDefinition: - return n.Comment - case *ast.ArgumentDefinition: - return n.Comment - case *ast.EnumValueDefinition: - return n.Comment - case *ast.DirectiveDefinition: - return n.Comment - } - return nil -} From f9db37815a6ee2e295d17a06b3389243d9cc4be4 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 15:32:16 +0900 Subject: [PATCH 15/21] refactor(parser): use dot import --- parser/schema.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/parser/schema.go b/parser/schema.go index 1f9ffeec..839c8d25 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -2,7 +2,6 @@ package parser import ( //nolint:revive - "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" ) @@ -361,7 +360,7 @@ func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) { } } -func (p *parser) parseSchemaExtension(comment *ast.CommentGroup) *SchemaDefinition { +func (p *parser) parseSchemaExtension(comment *CommentGroup) *SchemaDefinition { p.expectKeyword("schema") var def SchemaDefinition @@ -377,7 +376,7 @@ func (p *parser) parseSchemaExtension(comment *ast.CommentGroup) *SchemaDefiniti return &def } -func (p *parser) parseScalarTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseScalarTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("scalar") var def Definition @@ -392,7 +391,7 @@ func (p *parser) parseScalarTypeExtension(comment *ast.CommentGroup) *Definition return &def } -func (p *parser) parseObjectTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseObjectTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("type") var def Definition @@ -409,7 +408,7 @@ func (p *parser) parseObjectTypeExtension(comment *ast.CommentGroup) *Definition return &def } -func (p *parser) parseInterfaceTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseInterfaceTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("interface") var def Definition @@ -425,7 +424,7 @@ func (p *parser) parseInterfaceTypeExtension(comment *ast.CommentGroup) *Definit return &def } -func (p *parser) parseUnionTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseUnionTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("union") var def Definition @@ -442,7 +441,7 @@ func (p *parser) parseUnionTypeExtension(comment *ast.CommentGroup) *Definition return &def } -func (p *parser) parseEnumTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseEnumTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("enum") var def Definition @@ -458,7 +457,7 @@ func (p *parser) parseEnumTypeExtension(comment *ast.CommentGroup) *Definition { return &def } -func (p *parser) parseInputObjectTypeExtension(comment *ast.CommentGroup) *Definition { +func (p *parser) parseInputObjectTypeExtension(comment *CommentGroup) *Definition { p.expectKeyword("input") var def Definition From 176f77a5931d9cd5aa5a147e7699247b4c2c1c80 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 17:20:43 +0900 Subject: [PATCH 16/21] refactor(ast): remove unused methods --- ast/comment.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/ast/comment.go b/ast/comment.go index 5b36036a..8c554080 100644 --- a/ast/comment.go +++ b/ast/comment.go @@ -18,32 +18,6 @@ type CommentGroup struct { List []*Comment } -func (c *CommentGroup) Start() int { - if len(c.List) == 0 { - return 0 - } - return c.List[0].Position.Start -} - -func (c *CommentGroup) End() int { - if len(c.List) == 0 { - return 0 - } - return c.List[len(c.List)-1].Position.End -} - -func (c *CommentGroup) Text() string { - if c == nil || len(c.List) == 0 { - return "" - } - var builder strings.Builder - for _, comment := range c.List { - builder.WriteString(comment.Text()) - builder.WriteString("\n") - } - return builder.String() -} - func (c *CommentGroup) Dump() string { if len(c.List) == 0 { return "" From 08607831d24718a557479e7ab712ee5b629a4c65 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 19:07:13 +0900 Subject: [PATCH 17/21] fix: support comments before and after description --- ast/definition.go | 22 ++- ast/document.go | 4 +- formatter/formatter.go | 25 +++- .../baseline/FormatSchema/definition.graphql | 3 + .../baseline/FormatSchema/description.graphql | 3 + .../baseline/FormatSchema/swapi.graphql | 6 + .../FormatSchemaDocument/definition.graphql | 3 + .../FormatSchemaDocument/description.graphql | 3 + .../FormatSchemaDocument/swapi.graphql | 6 + .../source/schema/description.graphql | 4 + parser/schema.go | 141 +++++++++++------- parser/schema_test.yml | 10 +- 12 files changed, 163 insertions(+), 67 deletions(-) diff --git a/ast/definition.go b/ast/definition.go index a408377d..cd9c0883 100644 --- a/ast/definition.go +++ b/ast/definition.go @@ -30,8 +30,10 @@ type Definition struct { EnumValues EnumValueList // enum Position *Position `dump:"-"` - Comment *CommentGroup - BuiltIn bool `dump:"-"` + BuiltIn bool `dump:"-"` + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } func (d *Definition) IsLeafType() bool { @@ -67,7 +69,9 @@ type FieldDefinition struct { Type *Type Directives DirectiveList Position *Position `dump:"-"` - Comment *CommentGroup + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } type ArgumentDefinition struct { @@ -77,7 +81,9 @@ type ArgumentDefinition struct { Type *Type Directives DirectiveList Position *Position `dump:"-"` - Comment *CommentGroup + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } type EnumValueDefinition struct { @@ -85,7 +91,9 @@ type EnumValueDefinition struct { Name string Directives DirectiveList Position *Position `dump:"-"` - Comment *CommentGroup + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } type DirectiveDefinition struct { @@ -95,5 +103,7 @@ type DirectiveDefinition struct { Locations []DirectiveLocation IsRepeatable bool Position *Position `dump:"-"` - Comment *CommentGroup + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } diff --git a/ast/document.go b/ast/document.go index 2a309d29..5efa8fc4 100644 --- a/ast/document.go +++ b/ast/document.go @@ -74,7 +74,9 @@ type SchemaDefinition struct { Directives DirectiveList OperationTypes OperationTypeDefinitionList Position *Position `dump:"-"` - Comment *CommentGroup + + BeforeDescriptionComment *CommentGroup + AfterDescriptionComment *CommentGroup } type OperationTypeDefinition struct { diff --git a/formatter/formatter.go b/formatter/formatter.go index 5010ef3c..41166288 100644 --- a/formatter/formatter.go +++ b/formatter/formatter.go @@ -240,10 +240,12 @@ func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, e } func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) { - f.FormatCommentGroup(def.Comment) + f.FormatCommentGroup(def.BeforeDescriptionComment) f.WriteDescription(def.Description) + f.FormatCommentGroup(def.AfterDescriptionComment) + f.FormatDirectiveList(def.Directives) f.FormatOperationTypeDefinitionList(def.OperationTypes) @@ -283,10 +285,12 @@ func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) { return } - f.FormatCommentGroup(field.Comment) + f.FormatCommentGroup(field.BeforeDescriptionComment) f.WriteDescription(field.Description) + f.FormatCommentGroup(field.AfterDescriptionComment) + f.WriteWord(field.Name).NoPadding() f.FormatArgumentDefinitionList(field.Arguments) f.NoPadding().WriteString(":").NeedPadding() @@ -321,13 +325,15 @@ func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionLis } func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) { - f.FormatCommentGroup(def.Comment) + f.FormatCommentGroup(def.BeforeDescriptionComment) if def.Description != "" { f.WriteNewline().IncrementIndent() f.WriteDescription(def.Description) } + f.FormatCommentGroup(def.AfterDescriptionComment) + f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding() f.FormatType(def.Type) @@ -365,9 +371,12 @@ func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) { } } - f.FormatCommentGroup(def.Comment) + f.FormatCommentGroup(def.BeforeDescriptionComment) f.WriteDescription(def.Description) + + f.FormatCommentGroup(def.AfterDescriptionComment) + f.WriteWord("directive").WriteString("@").WriteWord(def.Name) if len(def.Arguments) != 0 { @@ -409,10 +418,12 @@ func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) { return } - f.FormatCommentGroup(def.Comment) + f.FormatCommentGroup(def.BeforeDescriptionComment) f.WriteDescription(def.Description) + f.FormatCommentGroup(def.AfterDescriptionComment) + if extend { f.WriteWord("extend") } @@ -471,10 +482,12 @@ func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) { } func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) { - f.FormatCommentGroup(def.Comment) + f.FormatCommentGroup(def.BeforeDescriptionComment) f.WriteDescription(def.Description) + f.FormatCommentGroup(def.AfterDescriptionComment) + f.WriteWord(def.Name) f.FormatDirectiveList(def.Directives) diff --git a/formatter/testdata/baseline/FormatSchema/definition.graphql b/formatter/testdata/baseline/FormatSchema/definition.graphql index 28f9b01a..ff36f471 100644 --- a/formatter/testdata/baseline/FormatSchema/definition.graphql +++ b/formatter/testdata/baseline/FormatSchema/definition.graphql @@ -6,6 +6,7 @@ type Cat1 { # Cat1 name comment name: String } +# Cat2 comment interface Cat2 { # Cat2 name comment name: String @@ -29,7 +30,9 @@ type Cat3_2 { } # Cat4 comment enum Cat4 { + # Cat4 NFC comment NFC + # Cat4 MAINECOON comment MAINECOON } # Cat5 comment diff --git a/formatter/testdata/baseline/FormatSchema/description.graphql b/formatter/testdata/baseline/FormatSchema/description.graphql index a4dca23f..bab1bc16 100644 --- a/formatter/testdata/baseline/FormatSchema/description.graphql +++ b/formatter/testdata/baseline/FormatSchema/description.graphql @@ -1,8 +1,11 @@ +# description comment """ Cat is best kawaii animal in the world. meow! """ +# type comment type Cat { + # field description comment """Shiny brillian name.""" name: String } diff --git a/formatter/testdata/baseline/FormatSchema/swapi.graphql b/formatter/testdata/baseline/FormatSchema/swapi.graphql index cec9a93a..654cb6ad 100644 --- a/formatter/testdata/baseline/FormatSchema/swapi.graphql +++ b/formatter/testdata/baseline/FormatSchema/swapi.graphql @@ -1,3 +1,4 @@ +# A character from the Star Wars universe interface Character { # The ID of the character id: ID! @@ -33,8 +34,11 @@ type Droid implements Character { } # The episodes in the Star Wars trilogy enum Episode { + # Star Wars Episode IV: A New Hope, released in 1977. NEWHOPE + # Star Wars Episode V: The Empire Strikes Back, released in 1980. EMPIRE + # Star Wars Episode VI: Return of the Jedi, released in 1983. JEDI } # A connection object for a character's friends @@ -78,7 +82,9 @@ type Human implements Character { } # Units of height enum LengthUnit { + # The standard unit around the world METER + # Primarily used in the United States FOOT } # The mutation type, represents all updates we can make to our data diff --git a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql index 9c8a394c..239f7e1d 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql @@ -6,6 +6,7 @@ type Cat1 { # Cat1 name comment name: String } +# Cat2 comment interface Cat2 { # Cat2 name comment name: String @@ -29,7 +30,9 @@ type Cat3_2 { union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 # Cat4 comment enum Cat4 { + # Cat4 NFC comment NFC + # Cat4 MAINECOON comment MAINECOON } # Cat5 comment diff --git a/formatter/testdata/baseline/FormatSchemaDocument/description.graphql b/formatter/testdata/baseline/FormatSchemaDocument/description.graphql index a4dca23f..bab1bc16 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/description.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/description.graphql @@ -1,8 +1,11 @@ +# description comment """ Cat is best kawaii animal in the world. meow! """ +# type comment type Cat { + # field description comment """Shiny brillian name.""" name: String } diff --git a/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql b/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql index f2e01c6f..d2f1eeb2 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql @@ -23,10 +23,14 @@ type Subscription { } # The episodes in the Star Wars trilogy enum Episode { + # Star Wars Episode IV: A New Hope, released in 1977. NEWHOPE + # Star Wars Episode V: The Empire Strikes Back, released in 1980. EMPIRE + # Star Wars Episode VI: Return of the Jedi, released in 1983. JEDI } +# A character from the Star Wars universe interface Character { # The ID of the character id: ID! @@ -41,7 +45,9 @@ interface Character { } # Units of height enum LengthUnit { + # The standard unit around the world METER + # Primarily used in the United States FOOT } # A humanoid creature from the Star Wars universe diff --git a/formatter/testdata/source/schema/description.graphql b/formatter/testdata/source/schema/description.graphql index d25aff86..f522d41d 100644 --- a/formatter/testdata/source/schema/description.graphql +++ b/formatter/testdata/source/schema/description.graphql @@ -1,8 +1,12 @@ +# description comment """ Cat is best kawaii animal in the world. meow! """ +# type comment type Cat { + # field description comment """Shiny brillian name.""" + # field comment name: String } diff --git a/parser/schema.go b/parser/schema.go index 839c8d25..9a00cf12 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -45,7 +45,7 @@ func (p *parser) parseSchemaDocument() *SchemaDocument { return nil } - var description string + var description descriptionWithComment if p.peek().Kind == lexer.BlockString || p.peek().Kind == lexer.String { description = p.parseDescription() } @@ -63,7 +63,7 @@ func (p *parser) parseSchemaDocument() *SchemaDocument { case "directive": doc.Directives = append(doc.Directives, p.parseDirectiveDefinition(description)) case "extend": - if description != "" { + if description.text != "" { p.unexpectedToken(p.prev) } p.parseTypeSystemExtension(&doc) @@ -76,17 +76,20 @@ func (p *parser) parseSchemaDocument() *SchemaDocument { return &doc } -func (p *parser) parseDescription() string { +func (p *parser) parseDescription() descriptionWithComment { token := p.peek() + var desc descriptionWithComment if token.Kind != lexer.BlockString && token.Kind != lexer.String { - return "" + return desc } - return p.next().Value + desc.comment = p.comment + desc.text = p.next().Value + return desc } -func (p *parser) parseTypeSystemDefinition(description string) *Definition { +func (p *parser) parseTypeSystemDefinition(description descriptionWithComment) *Definition { tok := p.peek() if tok.Kind != lexer.Name { p.unexpectedError() @@ -112,13 +115,14 @@ func (p *parser) parseTypeSystemDefinition(description string) *Definition { } } -func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition { +func (p *parser) parseSchemaDefinition(description descriptionWithComment) *SchemaDefinition { _, comment := p.expectKeyword("schema") - def := SchemaDefinition{Description: description} + def := SchemaDefinition{} def.Position = p.peekPos() - def.Description = description - def.Comment = comment + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { @@ -137,27 +141,29 @@ func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition { return &op } -func (p *parser) parseScalarTypeDefinition(description string) *Definition { +func (p *parser) parseScalarTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() - def.Comment = comment + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Kind = Scalar - def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) return &def } -func (p *parser) parseObjectTypeDefinition(description string) *Definition { +func (p *parser) parseObjectTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("type") var def Definition def.Position = p.peekPos() def.Kind = Object - def.Description = description - def.Comment = comment + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) @@ -191,8 +197,14 @@ func (p *parser) parseFieldsDefinition() FieldList { func (p *parser) parseFieldDefinition() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() - def.Comment = p.comment - def.Description = p.parseDescription() + + desc := p.parseDescription() + if desc.text != "" { + def.BeforeDescriptionComment = desc.comment + def.Description = desc.text + } + + def.AfterDescriptionComment = p.comment def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() p.expect(lexer.Colon) @@ -213,8 +225,14 @@ func (p *parser) parseArgumentDefs() ArgumentDefinitionList { func (p *parser) parseArgumentDef() *ArgumentDefinition { var def ArgumentDefinition def.Position = p.peekPos() - def.Comment = p.comment - def.Description = p.parseDescription() + + desc := p.parseDescription() + if desc.text != "" { + def.BeforeDescriptionComment = desc.comment + def.Description = desc.text + } + + def.AfterDescriptionComment = p.comment def.Name = p.parseName() p.expect(lexer.Colon) def.Type = p.parseTypeReference() @@ -228,8 +246,14 @@ func (p *parser) parseArgumentDef() *ArgumentDefinition { func (p *parser) parseInputValueDef() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() - def.Comment = p.comment - def.Description = p.parseDescription() + + desc := p.parseDescription() + if desc.text != "" { + def.BeforeDescriptionComment = desc.comment + def.Description = desc.text + } + + def.AfterDescriptionComment = p.comment def.Name = p.parseName() p.expect(lexer.Colon) def.Type = p.parseTypeReference() @@ -240,15 +264,15 @@ func (p *parser) parseInputValueDef() *FieldDefinition { return &def } -func (p *parser) parseInterfaceTypeDefinition(description string) *Definition { +func (p *parser) parseInterfaceTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("interface") var def Definition def.Position = p.peekPos() - def.Comment = comment def.Kind = Interface - def.Comment = p.comment - def.Description = description + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) @@ -256,14 +280,15 @@ func (p *parser) parseInterfaceTypeDefinition(description string) *Definition { return &def } -func (p *parser) parseUnionTypeDefinition(description string) *Definition { +func (p *parser) parseUnionTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("union") var def Definition def.Position = p.peekPos() - def.Comment = comment def.Kind = Union - def.Description = description + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Types = p.parseUnionMemberTypes() @@ -284,14 +309,15 @@ func (p *parser) parseUnionMemberTypes() []string { return types } -func (p *parser) parseEnumTypeDefinition(description string) *Definition { +func (p *parser) parseEnumTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("enum") var def Definition def.Position = p.peekPos() def.Kind = Enum - def.Comment = comment - def.Description = description + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.EnumValues = p.parseEnumValuesDefinition() @@ -307,22 +333,31 @@ func (p *parser) parseEnumValuesDefinition() EnumValueList { } func (p *parser) parseEnumValueDefinition() *EnumValueDefinition { - return &EnumValueDefinition{ - Position: p.peekPos(), - Description: p.parseDescription(), - Name: p.parseName(), - Directives: p.parseDirectives(true), + var def EnumValueDefinition + def.Position = p.peekPos() + desc := p.parseDescription() + if desc.text != "" { + def.BeforeDescriptionComment = desc.comment + def.Description = desc.text } + + def.AfterDescriptionComment = p.comment + + def.Name = p.parseName() + def.Directives = p.parseDirectives(true) + + return &def } -func (p *parser) parseInputObjectTypeDefinition(description string) *Definition { +func (p *parser) parseInputObjectTypeDefinition(description descriptionWithComment) *Definition { _, comment := p.expectKeyword("input") var def Definition def.Position = p.peekPos() def.Kind = InputObject - def.Comment = comment - def.Description = description + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Fields = p.parseInputFieldsDefinition() @@ -365,7 +400,7 @@ func (p *parser) parseSchemaExtension(comment *CommentGroup) *SchemaDefinition { var def SchemaDefinition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition()) @@ -381,7 +416,7 @@ func (p *parser) parseScalarTypeExtension(comment *CommentGroup) *Definition { var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = Scalar def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -396,7 +431,7 @@ func (p *parser) parseObjectTypeExtension(comment *CommentGroup) *Definition { var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = Object def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() @@ -413,7 +448,7 @@ func (p *parser) parseInterfaceTypeExtension(comment *CommentGroup) *Definition var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = Interface def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -429,7 +464,7 @@ func (p *parser) parseUnionTypeExtension(comment *CommentGroup) *Definition { var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = Union def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -446,7 +481,7 @@ func (p *parser) parseEnumTypeExtension(comment *CommentGroup) *Definition { var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = Enum def.Name = p.parseName() def.Directives = p.parseDirectives(true) @@ -462,7 +497,7 @@ func (p *parser) parseInputObjectTypeExtension(comment *CommentGroup) *Definitio var def Definition def.Position = p.peekPos() - def.Comment = comment + def.AfterDescriptionComment = comment def.Kind = InputObject def.Name = p.parseName() def.Directives = p.parseDirectives(false) @@ -473,14 +508,15 @@ func (p *parser) parseInputObjectTypeExtension(comment *CommentGroup) *Definitio return &def } -func (p *parser) parseDirectiveDefinition(description string) *DirectiveDefinition { +func (p *parser) parseDirectiveDefinition(description descriptionWithComment) *DirectiveDefinition { _, comment := p.expectKeyword("directive") p.expect(lexer.At) var def DirectiveDefinition def.Position = p.peekPos() - def.Comment = comment - def.Description = description + def.BeforeDescriptionComment = description.comment + def.Description = description.text + def.AfterDescriptionComment = comment def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() @@ -553,3 +589,8 @@ func (p *parser) parseDirectiveLocation() DirectiveLocation { p.unexpectedToken(name) return "" } + +type descriptionWithComment struct { + text string + comment *CommentGroup +} diff --git a/parser/schema_test.yml b/parser/schema_test.yml index 93ef042a..98574ab8 100644 --- a/parser/schema_test.yml +++ b/parser/schema_test.yml @@ -34,8 +34,8 @@ object types: - Name: "world" Type: String - Comment: "# World\n# World another\n" - Comment: "# Hello\n# Hello another\n" + AfterDescriptionComment: "# World\n# World another\n" + AfterDescriptionComment: "# Hello\n# Hello another\n" - name: with description input: | @@ -57,6 +57,7 @@ object types: - name: with block description input: | + # Before description comment """ Description """ @@ -75,7 +76,8 @@ object types: - Name: "world" Type: String - Comment: "# Even with comments between them\n" + BeforeDescriptionComment: "# Before description comment\n" + AfterDescriptionComment: "# Even with comments between them\n" - name: with field arg input: | type Hello { @@ -183,7 +185,7 @@ type extensions: - Name: "world" Type: String - Comment: "# comment\n" + AfterDescriptionComment: "# comment\n" - name: without any fields input: "extend type Hello implements Greeting" From dbc6f0396dd7f35a81dbd8fc900f66430b16e155 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 19:20:32 +0900 Subject: [PATCH 18/21] test(parser): add test case with comments and descriptions --- parser/schema_test.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/parser/schema_test.yml b/parser/schema_test.yml index 98574ab8..3130138b 100644 --- a/parser/schema_test.yml +++ b/parser/schema_test.yml @@ -37,6 +37,38 @@ object types: AfterDescriptionComment: "# World\n# World another\n" AfterDescriptionComment: "# Hello\n# Hello another\n" + - name: with comments and description + input: | + # Hello + # Hello another + "type description" + # Hello after description + # Hello after description another + type Hello { + # World + # World another + "field description" + # World after description + # World after description another + world: String + } + ast: | + + Definitions: [Definition] + - + Kind: DefinitionKind("OBJECT") + Description: "type description" + Name: "Hello" + Fields: [FieldDefinition] + - + Description: "field description" + Name: "world" + Type: String + BeforeDescriptionComment: "# World\n# World another\n" + AfterDescriptionComment: "# World after description\n# World after description another\n" + BeforeDescriptionComment: "# Hello\n# Hello another\n" + AfterDescriptionComment: "# Hello after description\n# Hello after description another\n" + - name: with description input: | "Description" From 03b382f3e47cdb4832e8f6ba4274afd3729b7cb7 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 19:28:34 +0900 Subject: [PATCH 19/21] fix: fix lost of comments after desription --- formatter/testdata/baseline/FormatSchema/description.graphql | 1 + .../baseline/FormatSchemaDocument/description.graphql | 1 + parser/schema.go | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/formatter/testdata/baseline/FormatSchema/description.graphql b/formatter/testdata/baseline/FormatSchema/description.graphql index bab1bc16..f03c67cd 100644 --- a/formatter/testdata/baseline/FormatSchema/description.graphql +++ b/formatter/testdata/baseline/FormatSchema/description.graphql @@ -7,5 +7,6 @@ meow! type Cat { # field description comment """Shiny brillian name.""" + # field comment name: String } diff --git a/formatter/testdata/baseline/FormatSchemaDocument/description.graphql b/formatter/testdata/baseline/FormatSchemaDocument/description.graphql index bab1bc16..f03c67cd 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/description.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/description.graphql @@ -7,5 +7,6 @@ meow! type Cat { # field description comment """Shiny brillian name.""" + # field comment name: String } diff --git a/parser/schema.go b/parser/schema.go index 9a00cf12..67691d04 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -2,6 +2,7 @@ package parser import ( //nolint:revive + . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" ) @@ -204,6 +205,7 @@ func (p *parser) parseFieldDefinition() *FieldDefinition { def.Description = desc.text } + p.peek() // peek to set p.comment def.AfterDescriptionComment = p.comment def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() @@ -232,6 +234,7 @@ func (p *parser) parseArgumentDef() *ArgumentDefinition { def.Description = desc.text } + p.peek() // peek to set p.comment def.AfterDescriptionComment = p.comment def.Name = p.parseName() p.expect(lexer.Colon) @@ -253,6 +256,7 @@ func (p *parser) parseInputValueDef() *FieldDefinition { def.Description = desc.text } + p.peek() // peek to set p.comment def.AfterDescriptionComment = p.comment def.Name = p.parseName() p.expect(lexer.Colon) @@ -341,6 +345,7 @@ func (p *parser) parseEnumValueDefinition() *EnumValueDefinition { def.Description = desc.text } + p.peek() // peek to set p.comment def.AfterDescriptionComment = p.comment def.Name = p.parseName() From 29ff36b779596fef23986ac179f6c9031ecb29cf Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 19:34:25 +0900 Subject: [PATCH 20/21] test(formatter): add description to scalar test case --- formatter/testdata/baseline/FormatSchema/definition.graphql | 1 + .../testdata/baseline/FormatSchemaDocument/definition.graphql | 1 + formatter/testdata/source/schema/definition.graphql | 1 + 3 files changed, 3 insertions(+) diff --git a/formatter/testdata/baseline/FormatSchema/definition.graphql b/formatter/testdata/baseline/FormatSchema/definition.graphql index ff36f471..8c0b0cce 100644 --- a/formatter/testdata/baseline/FormatSchema/definition.graphql +++ b/formatter/testdata/baseline/FormatSchema/definition.graphql @@ -1,5 +1,6 @@ # Cat0 comment # Cat0 comment 2 +"""Cat0 description""" scalar Cat0 # Cat1 comment type Cat1 { diff --git a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql index 239f7e1d..86a6b795 100644 --- a/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql +++ b/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql @@ -1,5 +1,6 @@ # Cat0 comment # Cat0 comment 2 +"""Cat0 description""" scalar Cat0 # Cat1 comment type Cat1 { diff --git a/formatter/testdata/source/schema/definition.graphql b/formatter/testdata/source/schema/definition.graphql index e36297a1..8b51a277 100644 --- a/formatter/testdata/source/schema/definition.graphql +++ b/formatter/testdata/source/schema/definition.graphql @@ -1,5 +1,6 @@ # Cat0 comment # Cat0 comment 2 +"""Cat0 description""" scalar Cat0 # Cat1 comment type Cat1 { From 8e4c68cbc18238ba7fc98226477fde9305b98c94 Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada <6warashi9@gmail.com> Date: Sat, 24 Jun 2023 19:51:53 +0900 Subject: [PATCH 21/21] fix(parser): remove empty line --- parser/schema.go | 1 - 1 file changed, 1 deletion(-) diff --git a/parser/schema.go b/parser/schema.go index 67691d04..5329de84 100644 --- a/parser/schema.go +++ b/parser/schema.go @@ -2,7 +2,6 @@ package parser import ( //nolint:revive - . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" )