diff --git a/gqlyzer.go b/gqlyzer.go index d55b6aa..50ed3ff 100644 --- a/gqlyzer.go +++ b/gqlyzer.go @@ -1,5 +1,7 @@ package gqlyzer +import "github.com/kumparan/gqlyzer/token" + // Lexer definition type Lexer struct { input string @@ -22,3 +24,8 @@ func (l *Lexer) Reset() { l.parseStack = []rune{} l.cursor = 0 } + +// Parse operation without variable +func (l *Lexer) Parse() (token.Operation, error) { + return l.parseOperation() +} diff --git a/parse_operation.go b/parse_operation.go new file mode 100644 index 0000000..0ee7d44 --- /dev/null +++ b/parse_operation.go @@ -0,0 +1,66 @@ +package gqlyzer + +import ( + "errors" + + "github.com/kumparan/gqlyzer/token" + "github.com/kumparan/gqlyzer/token/operation" +) + +func (l *Lexer) parseOperation() (op token.Operation, err error) { + l.consumeWhitespace() + l.pushFlush() + // parse "query" keyword + var ( + isQuery bool + isMutation bool + ) + + c, err := l.read() + if err != nil { + return + } + switch c { + case 'q': + if err = l.parseKeyword("query"); err != nil { + return + } + isQuery = true + l.cursor++ + case 'm': + if err = l.parseKeyword("mutation"); err != nil { + return + } + isMutation = true + l.cursor++ + case '{': + break + default: + err = errors.New("unknown definition") + return + } + + if isQuery { + op.Type = operation.Query + } else if isMutation { + op.Type = operation.Mutation + } + + // get name of named operation + if isQuery || isMutation { + op.Name, err = l.parseName() + if err != nil { + return + } + l.pushString(op.Name) + } else { + op.Type = operation.Query + } + + op.Selections, err = l.parseSelectionSet() + if err != nil { + return + } + + return +} diff --git a/parse_operation_test.go b/parse_operation_test.go new file mode 100644 index 0000000..b71a2a3 --- /dev/null +++ b/parse_operation_test.go @@ -0,0 +1,29 @@ +package gqlyzer + +import ( + "testing" + + "github.com/kumparan/gqlyzer/token/operation" + "github.com/stretchr/testify/assert" +) + +func TestParseOperation(t *testing.T) { + t.Run("with anonymous operation", func(t *testing.T) { + l := Lexer{input: `{ + SomeQuery(id: 123) { + subQuery + } + }`} + l.Reset() + l.push('\\') + + s, err := l.parseOperation() + assert.NoError(t, err) + assert.Equal(t, operation.Query, s.Type) + assert.Equal(t, "", s.Name) + assert.Equal(t, "SomeQuery", s.Selections["SomeQuery"].Name) + assert.Equal(t, "id", s.Selections["SomeQuery"].Arguments["id"].Key) + assert.Equal(t, "123", s.Selections["SomeQuery"].Arguments["id"].Value) + assert.Equal(t, "subQuery", s.Selections["SomeQuery"].InnerSelection["subQuery"].Name) + }) +} diff --git a/parse_selection.go b/parse_selection.go index bd6c2f0..5005eb7 100644 --- a/parse_selection.go +++ b/parse_selection.go @@ -2,7 +2,6 @@ package gqlyzer import ( "errors" - "fmt" "github.com/kumparan/gqlyzer/token" ) @@ -21,7 +20,6 @@ func (l *Lexer) parseSelection() (newSelection token.Selection, err error) { arguments, argErr := l.parseArgumentSet() if argErr == nil && len(arguments) > 0 { newSelection.Arguments = arguments - fmt.Println("<><><><>", arguments) l.cursor++ l.consumeWhitespace() } diff --git a/parse_selection_test.go b/parse_selection_test.go index 6f48715..85080c1 100644 --- a/parse_selection_test.go +++ b/parse_selection_test.go @@ -73,4 +73,22 @@ func TestParseSelectionSet(t *testing.T) { assert.Error(t, err) }) + t.Run("with nested value", func(t *testing.T) { + l := Lexer{input: `{ + query1(id: 123) { + query3 + }, + query2 + }`} + l.Reset() + + s, err := l.parseSelectionSet() + + assert.NoError(t, err) + assert.Equal(t, "query1", s["query1"].Name) + assert.Equal(t, "query3", s["query1"].InnerSelection["query3"].Name) + assert.Equal(t, "id", s["query1"].Arguments["id"].Key) + assert.Equal(t, "query2", s["query2"].Name) + }) + }