diff options
author | Michael Muré <batolettre@gmail.com> | 2018-07-19 14:15:50 +0200 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-07-19 14:15:50 +0200 |
commit | a2a50f3de0c428c5a61e6a449191be3c4ded86ac (patch) | |
tree | 5ecf4f5f1f26933b42a606b741963fa5f66c85aa /vendor/github.com/graphql-go/graphql/language | |
parent | 25fb88d7497b00bbe3dda540efde22ffd3de6e49 (diff) | |
download | git-bug-a2a50f3de0c428c5a61e6a449191be3c4ded86ac.tar.gz |
webui: add a primitive graphql handler
Diffstat (limited to 'vendor/github.com/graphql-go/graphql/language')
19 files changed, 5637 insertions, 0 deletions
diff --git a/vendor/github.com/graphql-go/graphql/language/ast/arguments.go b/vendor/github.com/graphql-go/graphql/language/ast/arguments.go new file mode 100644 index 00000000..5f7ef0d2 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/arguments.go @@ -0,0 +1,33 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +// Argument implements Node +type Argument struct { + Kind string + Loc *Location + Name *Name + Value Value +} + +func NewArgument(arg *Argument) *Argument { + if arg == nil { + arg = &Argument{} + } + return &Argument{ + Kind: kinds.Argument, + Loc: arg.Loc, + Name: arg.Name, + Value: arg.Value, + } +} + +func (arg *Argument) GetKind() string { + return arg.Kind +} + +func (arg *Argument) GetLoc() *Location { + return arg.Loc +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/definitions.go b/vendor/github.com/graphql-go/graphql/language/ast/definitions.go new file mode 100644 index 00000000..cd527f0a --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/definitions.go @@ -0,0 +1,247 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +type Definition interface { + GetOperation() string + GetVariableDefinitions() []*VariableDefinition + GetSelectionSet() *SelectionSet + GetKind() string + GetLoc() *Location +} + +// Ensure that all definition types implements Definition interface +var _ Definition = (*OperationDefinition)(nil) +var _ Definition = (*FragmentDefinition)(nil) +var _ Definition = (TypeSystemDefinition)(nil) // experimental non-spec addition. + +// Note: subscription is an experimental non-spec addition. +const ( + OperationTypeQuery = "query" + OperationTypeMutation = "mutation" + OperationTypeSubscription = "subscription" +) + +// OperationDefinition implements Node, Definition +type OperationDefinition struct { + Kind string + Loc *Location + Operation string + Name *Name + VariableDefinitions []*VariableDefinition + Directives []*Directive + SelectionSet *SelectionSet +} + +func NewOperationDefinition(op *OperationDefinition) *OperationDefinition { + if op == nil { + op = &OperationDefinition{} + } + return &OperationDefinition{ + Kind: kinds.OperationDefinition, + Loc: op.Loc, + Operation: op.Operation, + Name: op.Name, + VariableDefinitions: op.VariableDefinitions, + Directives: op.Directives, + SelectionSet: op.SelectionSet, + } +} + +func (op *OperationDefinition) GetKind() string { + return op.Kind +} + +func (op *OperationDefinition) GetLoc() *Location { + return op.Loc +} + +func (op *OperationDefinition) GetOperation() string { + return op.Operation +} + +func (op *OperationDefinition) GetName() *Name { + return op.Name +} + +func (op *OperationDefinition) GetVariableDefinitions() []*VariableDefinition { + return op.VariableDefinitions +} + +func (op *OperationDefinition) GetDirectives() []*Directive { + return op.Directives +} + +func (op *OperationDefinition) GetSelectionSet() *SelectionSet { + return op.SelectionSet +} + +// FragmentDefinition implements Node, Definition +type FragmentDefinition struct { + Kind string + Loc *Location + Operation string + Name *Name + VariableDefinitions []*VariableDefinition + TypeCondition *Named + Directives []*Directive + SelectionSet *SelectionSet +} + +func NewFragmentDefinition(fd *FragmentDefinition) *FragmentDefinition { + if fd == nil { + fd = &FragmentDefinition{} + } + return &FragmentDefinition{ + Kind: kinds.FragmentDefinition, + Loc: fd.Loc, + Operation: fd.Operation, + Name: fd.Name, + VariableDefinitions: fd.VariableDefinitions, + TypeCondition: fd.TypeCondition, + Directives: fd.Directives, + SelectionSet: fd.SelectionSet, + } +} + +func (fd *FragmentDefinition) GetKind() string { + return fd.Kind +} + +func (fd *FragmentDefinition) GetLoc() *Location { + return fd.Loc +} + +func (fd *FragmentDefinition) GetOperation() string { + return fd.Operation +} + +func (fd *FragmentDefinition) GetName() *Name { + return fd.Name +} + +func (fd *FragmentDefinition) GetVariableDefinitions() []*VariableDefinition { + return fd.VariableDefinitions +} + +func (fd *FragmentDefinition) GetSelectionSet() *SelectionSet { + return fd.SelectionSet +} + +// VariableDefinition implements Node +type VariableDefinition struct { + Kind string + Loc *Location + Variable *Variable + Type Type + DefaultValue Value +} + +func NewVariableDefinition(vd *VariableDefinition) *VariableDefinition { + if vd == nil { + vd = &VariableDefinition{} + } + return &VariableDefinition{ + Kind: kinds.VariableDefinition, + Loc: vd.Loc, + Variable: vd.Variable, + Type: vd.Type, + DefaultValue: vd.DefaultValue, + } +} + +func (vd *VariableDefinition) GetKind() string { + return vd.Kind +} + +func (vd *VariableDefinition) GetLoc() *Location { + return vd.Loc +} + +// TypeExtensionDefinition implements Node, Definition +type TypeExtensionDefinition struct { + Kind string + Loc *Location + Definition *ObjectDefinition +} + +func NewTypeExtensionDefinition(def *TypeExtensionDefinition) *TypeExtensionDefinition { + if def == nil { + def = &TypeExtensionDefinition{} + } + return &TypeExtensionDefinition{ + Kind: kinds.TypeExtensionDefinition, + Loc: def.Loc, + Definition: def.Definition, + } +} + +func (def *TypeExtensionDefinition) GetKind() string { + return def.Kind +} + +func (def *TypeExtensionDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *TypeExtensionDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *TypeExtensionDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *TypeExtensionDefinition) GetOperation() string { + return "" +} + +// DirectiveDefinition implements Node, Definition +type DirectiveDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Arguments []*InputValueDefinition + Locations []*Name +} + +func NewDirectiveDefinition(def *DirectiveDefinition) *DirectiveDefinition { + if def == nil { + def = &DirectiveDefinition{} + } + return &DirectiveDefinition{ + Kind: kinds.DirectiveDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Arguments: def.Arguments, + Locations: def.Locations, + } +} + +func (def *DirectiveDefinition) GetKind() string { + return def.Kind +} + +func (def *DirectiveDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *DirectiveDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *DirectiveDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *DirectiveDefinition) GetOperation() string { + return "" +} + +func (def *DirectiveDefinition) GetDescription() *StringValue { + return def.Description +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/directives.go b/vendor/github.com/graphql-go/graphql/language/ast/directives.go new file mode 100644 index 00000000..0c8a8c0e --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/directives.go @@ -0,0 +1,33 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +// Directive implements Node +type Directive struct { + Kind string + Loc *Location + Name *Name + Arguments []*Argument +} + +func NewDirective(dir *Directive) *Directive { + if dir == nil { + dir = &Directive{} + } + return &Directive{ + Kind: kinds.Directive, + Loc: dir.Loc, + Name: dir.Name, + Arguments: dir.Arguments, + } +} + +func (dir *Directive) GetKind() string { + return dir.Kind +} + +func (dir *Directive) GetLoc() *Location { + return dir.Loc +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/document.go b/vendor/github.com/graphql-go/graphql/language/ast/document.go new file mode 100644 index 00000000..dcb67034 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/document.go @@ -0,0 +1,31 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +// Document implements Node +type Document struct { + Kind string + Loc *Location + Definitions []Node +} + +func NewDocument(d *Document) *Document { + if d == nil { + d = &Document{} + } + return &Document{ + Kind: kinds.Document, + Loc: d.Loc, + Definitions: d.Definitions, + } +} + +func (node *Document) GetKind() string { + return node.Kind +} + +func (node *Document) GetLoc() *Location { + return node.Loc +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/location.go b/vendor/github.com/graphql-go/graphql/language/ast/location.go new file mode 100644 index 00000000..266dc847 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/location.go @@ -0,0 +1,22 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/source" +) + +type Location struct { + Start int + End int + Source *source.Source +} + +func NewLocation(loc *Location) *Location { + if loc == nil { + loc = &Location{} + } + return &Location{ + Start: loc.Start, + End: loc.End, + Source: loc.Source, + } +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/name.go b/vendor/github.com/graphql-go/graphql/language/ast/name.go new file mode 100644 index 00000000..00fddbcd --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/name.go @@ -0,0 +1,31 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +// Name implements Node +type Name struct { + Kind string + Loc *Location + Value string +} + +func NewName(node *Name) *Name { + if node == nil { + node = &Name{} + } + return &Name{ + Kind: kinds.Name, + Value: node.Value, + Loc: node.Loc, + } +} + +func (node *Name) GetKind() string { + return node.Kind +} + +func (node *Name) GetLoc() *Location { + return node.Loc +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/node.go b/vendor/github.com/graphql-go/graphql/language/ast/node.go new file mode 100644 index 00000000..cd63a0fc --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/node.go @@ -0,0 +1,45 @@ +package ast + +type Node interface { + GetKind() string + GetLoc() *Location +} + +// The list of all possible AST node graphql. +// Ensure that all node types implements Node interface +var _ Node = (*Name)(nil) +var _ Node = (*Document)(nil) +var _ Node = (*OperationDefinition)(nil) +var _ Node = (*VariableDefinition)(nil) +var _ Node = (*Variable)(nil) +var _ Node = (*SelectionSet)(nil) +var _ Node = (*Field)(nil) +var _ Node = (*Argument)(nil) +var _ Node = (*FragmentSpread)(nil) +var _ Node = (*InlineFragment)(nil) +var _ Node = (*FragmentDefinition)(nil) +var _ Node = (*IntValue)(nil) +var _ Node = (*FloatValue)(nil) +var _ Node = (*StringValue)(nil) +var _ Node = (*BooleanValue)(nil) +var _ Node = (*EnumValue)(nil) +var _ Node = (*ListValue)(nil) +var _ Node = (*ObjectValue)(nil) +var _ Node = (*ObjectField)(nil) +var _ Node = (*Directive)(nil) +var _ Node = (*Named)(nil) +var _ Node = (*List)(nil) +var _ Node = (*NonNull)(nil) +var _ Node = (*SchemaDefinition)(nil) +var _ Node = (*OperationTypeDefinition)(nil) +var _ Node = (*ScalarDefinition)(nil) +var _ Node = (*ObjectDefinition)(nil) +var _ Node = (*FieldDefinition)(nil) +var _ Node = (*InputValueDefinition)(nil) +var _ Node = (*InterfaceDefinition)(nil) +var _ Node = (*UnionDefinition)(nil) +var _ Node = (*EnumDefinition)(nil) +var _ Node = (*EnumValueDefinition)(nil) +var _ Node = (*InputObjectDefinition)(nil) +var _ Node = (*TypeExtensionDefinition)(nil) +var _ Node = (*DirectiveDefinition)(nil) diff --git a/vendor/github.com/graphql-go/graphql/language/ast/selections.go b/vendor/github.com/graphql-go/graphql/language/ast/selections.go new file mode 100644 index 00000000..0dc0ea12 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/selections.go @@ -0,0 +1,144 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +type Selection interface { + GetSelectionSet() *SelectionSet +} + +// Ensure that all definition types implements Selection interface +var _ Selection = (*Field)(nil) +var _ Selection = (*FragmentSpread)(nil) +var _ Selection = (*InlineFragment)(nil) + +// Field implements Node, Selection +type Field struct { + Kind string + Loc *Location + Alias *Name + Name *Name + Arguments []*Argument + Directives []*Directive + SelectionSet *SelectionSet +} + +func NewField(f *Field) *Field { + if f == nil { + f = &Field{} + } + return &Field{ + Kind: kinds.Field, + Loc: f.Loc, + Alias: f.Alias, + Name: f.Name, + Arguments: f.Arguments, + Directives: f.Directives, + SelectionSet: f.SelectionSet, + } +} + +func (f *Field) GetKind() string { + return f.Kind +} + +func (f *Field) GetLoc() *Location { + return f.Loc +} + +func (f *Field) GetSelectionSet() *SelectionSet { + return f.SelectionSet +} + +// FragmentSpread implements Node, Selection +type FragmentSpread struct { + Kind string + Loc *Location + Name *Name + Directives []*Directive +} + +func NewFragmentSpread(fs *FragmentSpread) *FragmentSpread { + if fs == nil { + fs = &FragmentSpread{} + } + return &FragmentSpread{ + Kind: kinds.FragmentSpread, + Loc: fs.Loc, + Name: fs.Name, + Directives: fs.Directives, + } +} + +func (fs *FragmentSpread) GetKind() string { + return fs.Kind +} + +func (fs *FragmentSpread) GetLoc() *Location { + return fs.Loc +} + +func (fs *FragmentSpread) GetSelectionSet() *SelectionSet { + return nil +} + +// InlineFragment implements Node, Selection +type InlineFragment struct { + Kind string + Loc *Location + TypeCondition *Named + Directives []*Directive + SelectionSet *SelectionSet +} + +func NewInlineFragment(f *InlineFragment) *InlineFragment { + if f == nil { + f = &InlineFragment{} + } + return &InlineFragment{ + Kind: kinds.InlineFragment, + Loc: f.Loc, + TypeCondition: f.TypeCondition, + Directives: f.Directives, + SelectionSet: f.SelectionSet, + } +} + +func (f *InlineFragment) GetKind() string { + return f.Kind +} + +func (f *InlineFragment) GetLoc() *Location { + return f.Loc +} + +func (f *InlineFragment) GetSelectionSet() *SelectionSet { + return f.SelectionSet +} + +// SelectionSet implements Node +type SelectionSet struct { + Kind string + Loc *Location + Selections []Selection +} + +func NewSelectionSet(ss *SelectionSet) *SelectionSet { + if ss == nil { + ss = &SelectionSet{} + } + return &SelectionSet{ + Kind: kinds.SelectionSet, + Loc: ss.Loc, + Selections: ss.Selections, + } +} + +func (ss *SelectionSet) GetKind() string { + return ss.Kind +} + +func (ss *SelectionSet) GetLoc() *Location { + return ss.Loc +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/type_definitions.go b/vendor/github.com/graphql-go/graphql/language/ast/type_definitions.go new file mode 100644 index 00000000..aefa70ed --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/type_definitions.go @@ -0,0 +1,529 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +// DescribableNode are nodes that have descriptions associated with them. +type DescribableNode interface { + GetDescription() *StringValue +} + +type TypeDefinition interface { + DescribableNode + GetOperation() string + GetVariableDefinitions() []*VariableDefinition + GetSelectionSet() *SelectionSet + GetKind() string + GetLoc() *Location +} + +var _ TypeDefinition = (*ScalarDefinition)(nil) +var _ TypeDefinition = (*ObjectDefinition)(nil) +var _ TypeDefinition = (*InterfaceDefinition)(nil) +var _ TypeDefinition = (*UnionDefinition)(nil) +var _ TypeDefinition = (*EnumDefinition)(nil) +var _ TypeDefinition = (*InputObjectDefinition)(nil) + +type TypeSystemDefinition interface { + GetOperation() string + GetVariableDefinitions() []*VariableDefinition + GetSelectionSet() *SelectionSet + GetKind() string + GetLoc() *Location +} + +var _ TypeSystemDefinition = (*SchemaDefinition)(nil) +var _ TypeSystemDefinition = (TypeDefinition)(nil) +var _ TypeSystemDefinition = (*TypeExtensionDefinition)(nil) +var _ TypeSystemDefinition = (*DirectiveDefinition)(nil) + +// SchemaDefinition implements Node, Definition +type SchemaDefinition struct { + Kind string + Loc *Location + Directives []*Directive + OperationTypes []*OperationTypeDefinition +} + +func NewSchemaDefinition(def *SchemaDefinition) *SchemaDefinition { + if def == nil { + def = &SchemaDefinition{} + } + return &SchemaDefinition{ + Kind: kinds.SchemaDefinition, + Loc: def.Loc, + Directives: def.Directives, + OperationTypes: def.OperationTypes, + } +} + +func (def *SchemaDefinition) GetKind() string { + return def.Kind +} + +func (def *SchemaDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *SchemaDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *SchemaDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *SchemaDefinition) GetOperation() string { + return "" +} + +// OperationTypeDefinition implements Node, Definition +type OperationTypeDefinition struct { + Kind string + Loc *Location + Operation string + Type *Named +} + +func NewOperationTypeDefinition(def *OperationTypeDefinition) *OperationTypeDefinition { + if def == nil { + def = &OperationTypeDefinition{} + } + return &OperationTypeDefinition{ + Kind: kinds.OperationTypeDefinition, + Loc: def.Loc, + Operation: def.Operation, + Type: def.Type, + } +} + +func (def *OperationTypeDefinition) GetKind() string { + return def.Kind +} + +func (def *OperationTypeDefinition) GetLoc() *Location { + return def.Loc +} + +// ScalarDefinition implements Node, Definition +type ScalarDefinition struct { + Kind string + Loc *Location + Description *StringValue + Name *Name + Directives []*Directive +} + +func NewScalarDefinition(def *ScalarDefinition) *ScalarDefinition { + if def == nil { + def = &ScalarDefinition{} + } + return &ScalarDefinition{ + Kind: kinds.ScalarDefinition, + Loc: def.Loc, + Description: def.Description, + Name: def.Name, + Directives: def.Directives, + } +} + +func (def *ScalarDefinition) GetKind() string { + return def.Kind +} + +func (def *ScalarDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *ScalarDefinition) GetName() *Name { + return def.Name +} + +func (def *ScalarDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *ScalarDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *ScalarDefinition) GetOperation() string { + return "" +} + +func (def *ScalarDefinition) GetDescription() *StringValue { + return def.Description +} + +// ObjectDefinition implements Node, Definition +type ObjectDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Interfaces []*Named + Directives []*Directive + Fields []*FieldDefinition +} + +func NewObjectDefinition(def *ObjectDefinition) *ObjectDefinition { + if def == nil { + def = &ObjectDefinition{} + } + return &ObjectDefinition{ + Kind: kinds.ObjectDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Interfaces: def.Interfaces, + Directives: def.Directives, + Fields: def.Fields, + } +} + +func (def *ObjectDefinition) GetKind() string { + return def.Kind +} + +func (def *ObjectDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *ObjectDefinition) GetName() *Name { + return def.Name +} + +func (def *ObjectDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *ObjectDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *ObjectDefinition) GetOperation() string { + return "" +} + +func (def *ObjectDefinition) GetDescription() *StringValue { + return def.Description +} + +// FieldDefinition implements Node +type FieldDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Arguments []*InputValueDefinition + Type Type + Directives []*Directive +} + +func NewFieldDefinition(def *FieldDefinition) *FieldDefinition { + if def == nil { + def = &FieldDefinition{} + } + return &FieldDefinition{ + Kind: kinds.FieldDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Arguments: def.Arguments, + Type: def.Type, + Directives: def.Directives, + } +} + +func (def *FieldDefinition) GetKind() string { + return def.Kind +} + +func (def *FieldDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *FieldDefinition) GetDescription() *StringValue { + return def.Description +} + +// InputValueDefinition implements Node +type InputValueDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Type Type + DefaultValue Value + Directives []*Directive +} + +func NewInputValueDefinition(def *InputValueDefinition) *InputValueDefinition { + if def == nil { + def = &InputValueDefinition{} + } + return &InputValueDefinition{ + Kind: kinds.InputValueDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Type: def.Type, + DefaultValue: def.DefaultValue, + Directives: def.Directives, + } +} + +func (def *InputValueDefinition) GetKind() string { + return def.Kind +} + +func (def *InputValueDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *InputValueDefinition) GetDescription() *StringValue { + return def.Description +} + +// InterfaceDefinition implements Node, Definition +type InterfaceDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Directives []*Directive + Fields []*FieldDefinition +} + +func NewInterfaceDefinition(def *InterfaceDefinition) *InterfaceDefinition { + if def == nil { + def = &InterfaceDefinition{} + } + return &InterfaceDefinition{ + Kind: kinds.InterfaceDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Directives: def.Directives, + Fields: def.Fields, + } +} + +func (def *InterfaceDefinition) GetKind() string { + return def.Kind +} + +func (def *InterfaceDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *InterfaceDefinition) GetName() *Name { + return def.Name +} + +func (def *InterfaceDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *InterfaceDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *InterfaceDefinition) GetOperation() string { + return "" +} + +func (def *InterfaceDefinition) GetDescription() *StringValue { + return def.Description +} + +// UnionDefinition implements Node, Definition +type UnionDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Directives []*Directive + Types []*Named +} + +func NewUnionDefinition(def *UnionDefinition) *UnionDefinition { + if def == nil { + def = &UnionDefinition{} + } + return &UnionDefinition{ + Kind: kinds.UnionDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Directives: def.Directives, + Types: def.Types, + } +} + +func (def *UnionDefinition) GetKind() string { + return def.Kind +} + +func (def *UnionDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *UnionDefinition) GetName() *Name { + return def.Name +} + +func (def *UnionDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *UnionDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *UnionDefinition) GetOperation() string { + return "" +} + +func (def *UnionDefinition) GetDescription() *StringValue { + return def.Description +} + +// EnumDefinition implements Node, Definition +type EnumDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Directives []*Directive + Values []*EnumValueDefinition +} + +func NewEnumDefinition(def *EnumDefinition) *EnumDefinition { + if def == nil { + def = &EnumDefinition{} + } + return &EnumDefinition{ + Kind: kinds.EnumDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Directives: def.Directives, + Values: def.Values, + } +} + +func (def *EnumDefinition) GetKind() string { + return def.Kind +} + +func (def *EnumDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *EnumDefinition) GetName() *Name { + return def.Name +} + +func (def *EnumDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *EnumDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *EnumDefinition) GetOperation() string { + return "" +} + +func (def *EnumDefinition) GetDescription() *StringValue { + return def.Description +} + +// EnumValueDefinition implements Node, Definition +type EnumValueDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Directives []*Directive +} + +func NewEnumValueDefinition(def *EnumValueDefinition) *EnumValueDefinition { + if def == nil { + def = &EnumValueDefinition{} + } + return &EnumValueDefinition{ + Kind: kinds.EnumValueDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Directives: def.Directives, + } +} + +func (def *EnumValueDefinition) GetKind() string { + return def.Kind +} + +func (def *EnumValueDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *EnumValueDefinition) GetDescription() *StringValue { + return def.Description +} + +// InputObjectDefinition implements Node, Definition +type InputObjectDefinition struct { + Kind string + Loc *Location + Name *Name + Description *StringValue + Directives []*Directive + Fields []*InputValueDefinition +} + +func NewInputObjectDefinition(def *InputObjectDefinition) *InputObjectDefinition { + if def == nil { + def = &InputObjectDefinition{} + } + return &InputObjectDefinition{ + Kind: kinds.InputObjectDefinition, + Loc: def.Loc, + Name: def.Name, + Description: def.Description, + Directives: def.Directives, + Fields: def.Fields, + } +} + +func (def *InputObjectDefinition) GetKind() string { + return def.Kind +} + +func (def *InputObjectDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *InputObjectDefinition) GetName() *Name { + return def.Name +} + +func (def *InputObjectDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *InputObjectDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *InputObjectDefinition) GetOperation() string { + return "" +} + +func (def *InputObjectDefinition) GetDescription() *StringValue { + return def.Description +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/types.go b/vendor/github.com/graphql-go/graphql/language/ast/types.go new file mode 100644 index 00000000..27f00997 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/types.go @@ -0,0 +1,106 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +type Type interface { + GetKind() string + GetLoc() *Location + String() string +} + +// Ensure that all value types implements Value interface +var _ Type = (*Named)(nil) +var _ Type = (*List)(nil) +var _ Type = (*NonNull)(nil) + +// Named implements Node, Type +type Named struct { + Kind string + Loc *Location + Name *Name +} + +func NewNamed(t *Named) *Named { + if t == nil { + t = &Named{} + } + return &Named{ + Kind: kinds.Named, + Loc: t.Loc, + Name: t.Name, + } +} + +func (t *Named) GetKind() string { + return t.Kind +} + +func (t *Named) GetLoc() *Location { + return t.Loc +} + +func (t *Named) String() string { + return t.GetKind() +} + +// List implements Node, Type +type List struct { + Kind string + Loc *Location + Type Type +} + +func NewList(t *List) *List { + if t == nil { + t = &List{} + } + return &List{ + Kind: kinds.List, + Loc: t.Loc, + Type: t.Type, + } +} + +func (t *List) GetKind() string { + return t.Kind +} + +func (t *List) GetLoc() *Location { + return t.Loc +} + +func (t *List) String() string { + return t.GetKind() +} + +// NonNull implements Node, Type +type NonNull struct { + Kind string + Loc *Location + Type Type +} + +func NewNonNull(t *NonNull) *NonNull { + if t == nil { + t = &NonNull{} + } + return &NonNull{ + Kind: kinds.NonNull, + Loc: t.Loc, + Type: t.Type, + } +} + +func (t *NonNull) GetKind() string { + return t.Kind +} + +func (t *NonNull) GetLoc() *Location { + return t.Loc +} + +func (t *NonNull) String() string { + return t.GetKind() +} diff --git a/vendor/github.com/graphql-go/graphql/language/ast/values.go b/vendor/github.com/graphql-go/graphql/language/ast/values.go new file mode 100644 index 00000000..67912bdc --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/ast/values.go @@ -0,0 +1,305 @@ +package ast + +import ( + "github.com/graphql-go/graphql/language/kinds" +) + +type Value interface { + GetValue() interface{} + GetKind() string + GetLoc() *Location +} + +// Ensure that all value types implements Value interface +var _ Value = (*Variable)(nil) +var _ Value = (*IntValue)(nil) +var _ Value = (*FloatValue)(nil) +var _ Value = (*StringValue)(nil) +var _ Value = (*BooleanValue)(nil) +var _ Value = (*EnumValue)(nil) +var _ Value = (*ListValue)(nil) +var _ Value = (*ObjectValue)(nil) + +// Variable implements Node, Value +type Variable struct { + Kind string + Loc *Location + Name *Name +} + +func NewVariable(v *Variable) *Variable { + if v == nil { + v = &Variable{} + } + return &Variable{ + Kind: kinds.Variable, + Loc: v.Loc, + Name: v.Name, + } +} + +func (v *Variable) GetKind() string { + return v.Kind +} + +func (v *Variable) GetLoc() *Location { + return v.Loc +} + +// GetValue alias to Variable.GetName() +func (v *Variable) GetValue() interface{} { + return v.GetName() +} + +func (v *Variable) GetName() interface{} { + return v.Name +} + +// IntValue implements Node, Value +type IntValue struct { + Kind string + Loc *Location + Value string +} + +func NewIntValue(v *IntValue) *IntValue { + if v == nil { + v = &IntValue{} + } + return &IntValue{ + Kind: kinds.IntValue, + Loc: v.Loc, + Value: v.Value, + } +} + +func (v *IntValue) GetKind() string { + return v.Kind +} + +func (v *IntValue) GetLoc() *Location { + return v.Loc +} + +func (v *IntValue) GetValue() interface{} { + return v.Value +} + +// FloatValue implements Node, Value +type FloatValue struct { + Kind string + Loc *Location + Value string +} + +func NewFloatValue(v *FloatValue) *FloatValue { + if v == nil { + v = &FloatValue{} + } + return &FloatValue{ + Kind: kinds.FloatValue, + Loc: v.Loc, + Value: v.Value, + } +} + +func (v *FloatValue) GetKind() string { + return v.Kind +} + +func (v *FloatValue) GetLoc() *Location { + return v.Loc +} + +func (v *FloatValue) GetValue() interface{} { + return v.Value +} + +// StringValue implements Node, Value +type StringValue struct { + Kind string + Loc *Location + Value string +} + +func NewStringValue(v *StringValue) *StringValue { + if v == nil { + v = &StringValue{} + } + return &StringValue{ + Kind: kinds.StringValue, + Loc: v.Loc, + Value: v.Value, + } +} + +func (v *StringValue) GetKind() string { + return v.Kind +} + +func (v *StringValue) GetLoc() *Location { + return v.Loc +} + +func (v *StringValue) GetValue() interface{} { + return v.Value +} + +// BooleanValue implements Node, Value +type BooleanValue struct { + Kind string + Loc *Location + Value bool +} + +func NewBooleanValue(v *BooleanValue) *BooleanValue { + if v == nil { + v = &BooleanValue{} + } + return &BooleanValue{ + Kind: kinds.BooleanValue, + Loc: v.Loc, + Value: v.Value, + } +} + +func (v *BooleanValue) GetKind() string { + return v.Kind +} + +func (v *BooleanValue) GetLoc() *Location { + return v.Loc +} + +func (v *BooleanValue) GetValue() interface{} { + return v.Value +} + +// EnumValue implements Node, Value +type EnumValue struct { + Kind string + Loc *Location + Value string +} + +func NewEnumValue(v *EnumValue) *EnumValue { + if v == nil { + v = &EnumValue{} + } + return &EnumValue{ + Kind: kinds.EnumValue, + Loc: v.Loc, + Value: v.Value, + } +} + +func (v *EnumValue) GetKind() string { + return v.Kind +} + +func (v *EnumValue) GetLoc() *Location { + return v.Loc +} + +func (v *EnumValue) GetValue() interface{} { + return v.Value +} + +// ListValue implements Node, Value +type ListValue struct { + Kind string + Loc *Location + Values []Value +} + +func NewListValue(v *ListValue) *ListValue { + if v == nil { + v = &ListValue{} + } + return &ListValue{ + Kind: kinds.ListValue, + Loc: v.Loc, + Values: v.Values, + } +} + +func (v *ListValue) GetKind() string { + return v.Kind +} + +func (v *ListValue) GetLoc() *Location { + return v.Loc +} + +// GetValue alias to ListValue.GetValues() +func (v *ListValue) GetValue() interface{} { + return v.GetValues() +} + +func (v *ListValue) GetValues() interface{} { + // TODO: verify ObjectValue.GetValue() + return v.Values +} + +// ObjectValue implements Node, Value +type ObjectValue struct { + Kind string + Loc *Location + Fields []*ObjectField +} + +func NewObjectValue(v *ObjectValue) *ObjectValue { + if v == nil { + v = &ObjectValue{} + } + return &ObjectValue{ + Kind: kinds.ObjectValue, + Loc: v.Loc, + Fields: v.Fields, + } +} + +func (v *ObjectValue) GetKind() string { + return v.Kind +} + +func (v *ObjectValue) GetLoc() *Location { + return v.Loc +} + +func (v *ObjectValue) GetValue() interface{} { + // TODO: verify ObjectValue.GetValue() + return v.Fields +} + +// ObjectField implements Node, Value +type ObjectField struct { + Kind string + Name *Name + Loc *Location + Value Value +} + +func NewObjectField(f *ObjectField) *ObjectField { + if f == nil { + f = &ObjectField{} + } + return &ObjectField{ + Kind: kinds.ObjectField, + Loc: f.Loc, + Name: f.Name, + Value: f.Value, + } +} + +func (f *ObjectField) GetKind() string { + return f.Kind +} + +func (f *ObjectField) GetLoc() *Location { + return f.Loc +} + +func (f *ObjectField) GetValue() interface{} { + return f.Value +} diff --git a/vendor/github.com/graphql-go/graphql/language/kinds/kinds.go b/vendor/github.com/graphql-go/graphql/language/kinds/kinds.go new file mode 100644 index 00000000..40bc994e --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/kinds/kinds.go @@ -0,0 +1,59 @@ +package kinds + +const ( + // Name + Name = "Name" + + // Document + Document = "Document" + OperationDefinition = "OperationDefinition" + VariableDefinition = "VariableDefinition" + Variable = "Variable" + SelectionSet = "SelectionSet" + Field = "Field" + Argument = "Argument" + + // Fragments + FragmentSpread = "FragmentSpread" + InlineFragment = "InlineFragment" + FragmentDefinition = "FragmentDefinition" + + // Values + IntValue = "IntValue" + FloatValue = "FloatValue" + StringValue = "StringValue" + BooleanValue = "BooleanValue" + EnumValue = "EnumValue" + ListValue = "ListValue" + ObjectValue = "ObjectValue" + ObjectField = "ObjectField" + + // Directives + Directive = "Directive" + + // Types + Named = "Named" // previously NamedType + List = "List" // previously ListType + NonNull = "NonNull" // previously NonNull + + // Type System Definitions + SchemaDefinition = "SchemaDefinition" + OperationTypeDefinition = "OperationTypeDefinition" + + // Types Definitions + ScalarDefinition = "ScalarDefinition" // previously ScalarTypeDefinition + ObjectDefinition = "ObjectDefinition" // previously ObjectTypeDefinition + FieldDefinition = "FieldDefinition" + InputValueDefinition = "InputValueDefinition" + InterfaceDefinition = "InterfaceDefinition" // previously InterfaceTypeDefinition + UnionDefinition = "UnionDefinition" // previously UnionTypeDefinition + EnumDefinition = "EnumDefinition" // previously EnumTypeDefinition + EnumValueDefinition = "EnumValueDefinition" + InputObjectDefinition = "InputObjectDefinition" // previously InputObjectTypeDefinition + + // Types Extensions + TypeExtensionDefinition = "TypeExtensionDefinition" + + // Directive Definitions + DirectiveDefinition = "DirectiveDefinition" +) diff --git a/vendor/github.com/graphql-go/graphql/language/lexer/lexer.go b/vendor/github.com/graphql-go/graphql/language/lexer/lexer.go new file mode 100644 index 00000000..62589f4e --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/lexer/lexer.go @@ -0,0 +1,656 @@ +package lexer + +import ( + "bytes" + "fmt" + "regexp" + "strings" + "unicode/utf8" + + "github.com/graphql-go/graphql/gqlerrors" + "github.com/graphql-go/graphql/language/source" +) + +const ( + EOF = iota + 1 + BANG + DOLLAR + PAREN_L + PAREN_R + SPREAD + COLON + EQUALS + AT + BRACKET_L + BRACKET_R + BRACE_L + PIPE + BRACE_R + NAME + INT + FLOAT + STRING + BLOCK_STRING +) + +var TokenKind map[int]int +var tokenDescription map[int]string + +func init() { + TokenKind = make(map[int]int) + tokenDescription = make(map[int]string) + TokenKind[EOF] = EOF + TokenKind[BANG] = BANG + TokenKind[DOLLAR] = DOLLAR + TokenKind[PAREN_L] = PAREN_L + TokenKind[PAREN_R] = PAREN_R + TokenKind[SPREAD] = SPREAD + TokenKind[COLON] = COLON + TokenKind[EQUALS] = EQUALS + TokenKind[AT] = AT + TokenKind[BRACKET_L] = BRACKET_L + TokenKind[BRACKET_R] = BRACKET_R + TokenKind[BRACE_L] = BRACE_L + TokenKind[PIPE] = PIPE + TokenKind[BRACE_R] = BRACE_R + TokenKind[NAME] = NAME + TokenKind[INT] = INT + TokenKind[FLOAT] = FLOAT + TokenKind[STRING] = STRING + TokenKind[BLOCK_STRING] = BLOCK_STRING + tokenDescription[TokenKind[EOF]] = "EOF" + tokenDescription[TokenKind[BANG]] = "!" + tokenDescription[TokenKind[DOLLAR]] = "$" + tokenDescription[TokenKind[PAREN_L]] = "(" + tokenDescription[TokenKind[PAREN_R]] = ")" + tokenDescription[TokenKind[SPREAD]] = "..." + tokenDescription[TokenKind[COLON]] = ":" + tokenDescription[TokenKind[EQUALS]] = "=" + tokenDescription[TokenKind[AT]] = "@" + tokenDescription[TokenKind[BRACKET_L]] = "[" + tokenDescription[TokenKind[BRACKET_R]] = "]" + tokenDescription[TokenKind[BRACE_L]] = "{" + tokenDescription[TokenKind[PIPE]] = "|" + tokenDescription[TokenKind[BRACE_R]] = "}" + tokenDescription[TokenKind[NAME]] = "Name" + tokenDescription[TokenKind[INT]] = "Int" + tokenDescription[TokenKind[FLOAT]] = "Float" + tokenDescription[TokenKind[STRING]] = "String" + tokenDescription[TokenKind[BLOCK_STRING]] = "BlockString" +} + +// Token is a representation of a lexed Token. Value only appears for non-punctuation +// tokens: NAME, INT, FLOAT, and STRING. +type Token struct { + Kind int + Start int + End int + Value string +} + +type Lexer func(resetPosition int) (Token, error) + +func Lex(s *source.Source) Lexer { + var prevPosition int + return func(resetPosition int) (Token, error) { + if resetPosition == 0 { + resetPosition = prevPosition + } + token, err := readToken(s, resetPosition) + if err != nil { + return token, err + } + prevPosition = token.End + return token, nil + } +} + +// Reads an alphanumeric + underscore name from the source. +// [_A-Za-z][_0-9A-Za-z]* +// position: Points to the byte position in the byte array +// runePosition: Points to the rune position in the byte array +func readName(source *source.Source, position, runePosition int) Token { + body := source.Body + bodyLength := len(body) + endByte := position + 1 + endRune := runePosition + 1 + for { + code, _ := runeAt(body, endByte) + if (endByte != bodyLength) && + (code == '_' || // _ + code >= '0' && code <= '9' || // 0-9 + code >= 'A' && code <= 'Z' || // A-Z + code >= 'a' && code <= 'z') { // a-z + endByte++ + endRune++ + continue + } else { + break + } + } + return makeToken(TokenKind[NAME], runePosition, endRune, string(body[position:endByte])) +} + +// Reads a number token from the source file, either a float +// or an int depending on whether a decimal point appears. +// Int: -?(0|[1-9][0-9]*) +// Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)? +func readNumber(s *source.Source, start int, firstCode rune, codeLength int) (Token, error) { + code := firstCode + body := s.Body + position := start + isFloat := false + if code == '-' { // - + position += codeLength + code, codeLength = runeAt(body, position) + } + if code == '0' { // 0 + position += codeLength + code, codeLength = runeAt(body, position) + if code >= '0' && code <= '9' { + description := fmt.Sprintf("Invalid number, unexpected digit after 0: %v.", printCharCode(code)) + return Token{}, gqlerrors.NewSyntaxError(s, position, description) + } + } else { + p, err := readDigits(s, position, code, codeLength) + if err != nil { + return Token{}, err + } + position = p + code, codeLength = runeAt(body, position) + } + if code == '.' { // . + isFloat = true + position += codeLength + code, codeLength = runeAt(body, position) + p, err := readDigits(s, position, code, codeLength) + if err != nil { + return Token{}, err + } + position = p + code, codeLength = runeAt(body, position) + } + if code == 'E' || code == 'e' { // E e + isFloat = true + position += codeLength + code, codeLength = runeAt(body, position) + if code == '+' || code == '-' { // + - + position += codeLength + code, codeLength = runeAt(body, position) + } + p, err := readDigits(s, position, code, codeLength) + if err != nil { + return Token{}, err + } + position = p + } + kind := TokenKind[INT] + if isFloat { + kind = TokenKind[FLOAT] + } + + return makeToken(kind, start, position, string(body[start:position])), nil +} + +// Returns the new position in the source after reading digits. +func readDigits(s *source.Source, start int, firstCode rune, codeLength int) (int, error) { + body := s.Body + position := start + code := firstCode + if code >= '0' && code <= '9' { // 0 - 9 + for { + if code >= '0' && code <= '9' { // 0 - 9 + position += codeLength + code, codeLength = runeAt(body, position) + continue + } else { + break + } + } + return position, nil + } + var description string + description = fmt.Sprintf("Invalid number, expected digit but got: %v.", printCharCode(code)) + return position, gqlerrors.NewSyntaxError(s, position, description) +} + +func readString(s *source.Source, start int) (Token, error) { + body := s.Body + position := start + 1 + runePosition := start + 1 + chunkStart := position + var code rune + var n int + var valueBuffer bytes.Buffer + for { + code, n = runeAt(body, position) + if position < len(body) && + // not LineTerminator + code != 0x000A && code != 0x000D && + // not Quote (") + code != '"' { + + // SourceCharacter + if code < 0x0020 && code != 0x0009 { + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, fmt.Sprintf(`Invalid character within String: %v.`, printCharCode(code))) + } + position += n + runePosition++ + if code == '\\' { // \ + valueBuffer.Write(body[chunkStart : position-1]) + code, n = runeAt(body, position) + switch code { + case '"': + valueBuffer.WriteRune('"') + break + case '/': + valueBuffer.WriteRune('/') + break + case '\\': + valueBuffer.WriteRune('\\') + break + case 'b': + valueBuffer.WriteRune('\b') + break + case 'f': + valueBuffer.WriteRune('\f') + break + case 'n': + valueBuffer.WriteRune('\n') + break + case 'r': + valueBuffer.WriteRune('\r') + break + case 't': + valueBuffer.WriteRune('\t') + break + case 'u': + // Check if there are at least 4 bytes available + if len(body) <= position+4 { + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, + fmt.Sprintf("Invalid character escape sequence: "+ + "\\u%v", string(body[position+1:]))) + } + charCode := uniCharCode( + rune(body[position+1]), + rune(body[position+2]), + rune(body[position+3]), + rune(body[position+4]), + ) + if charCode < 0 { + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, + fmt.Sprintf("Invalid character escape sequence: "+ + "\\u%v", string(body[position+1:position+5]))) + } + valueBuffer.WriteRune(charCode) + position += 4 + runePosition += 4 + break + default: + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, + fmt.Sprintf(`Invalid character escape sequence: \\%c.`, code)) + } + position += n + runePosition++ + chunkStart = position + } + continue + } else { + break + } + } + if code != '"' { // quote (") + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, "Unterminated string.") + } + stringContent := body[chunkStart:position] + valueBuffer.Write(stringContent) + value := valueBuffer.String() + return makeToken(TokenKind[STRING], start, position+1, value), nil +} + +// readBlockString reads a block string token from the source file. +// +// """("?"?(\\"""|\\(?!=""")|[^"\\]))*""" +func readBlockString(s *source.Source, start int) (Token, error) { + body := s.Body + position := start + 3 + runePosition := start + 3 + chunkStart := position + var valueBuffer bytes.Buffer + + for { + // Stop if we've reached the end of the buffer + if position >= len(body) { + break + } + + code, n := runeAt(body, position) + + // Closing Triple-Quote (""") + if code == '"' { + x, _ := runeAt(body, position+1) + y, _ := runeAt(body, position+2) + if x == '"' && y == '"' { + stringContent := body[chunkStart:position] + valueBuffer.Write(stringContent) + value := blockStringValue(valueBuffer.String()) + return makeToken(TokenKind[BLOCK_STRING], start, position+3, value), nil + } + } + + // SourceCharacter + if code < 0x0020 && + code != 0x0009 && + code != 0x000a && + code != 0x000d { + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, fmt.Sprintf(`Invalid character within String: %v.`, printCharCode(code))) + } + + // Escape Triple-Quote (\""") + if code == '\\' { // \ + x, _ := runeAt(body, position+1) + y, _ := runeAt(body, position+2) + z, _ := runeAt(body, position+3) + if x == '"' && y == '"' && z == '"' { + stringContent := append(body[chunkStart:position], []byte(`"""`)...) + valueBuffer.Write(stringContent) + position += 4 // account for `"""` characters + runePosition += 4 // " " " " + chunkStart = position + continue + } + } + + position += n + runePosition++ + } + + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, "Unterminated string.") +} + +var splitLinesRegex = regexp.MustCompile("\r\n|[\n\r]") + +// This implements the GraphQL spec's BlockStringValue() static algorithm. +// +// Produces the value of a block string from its parsed raw value, similar to +// Coffeescript's block string, Python's docstring trim or Ruby's strip_heredoc. +// +// Spec: http://facebook.github.io/graphql/draft/#BlockStringValue() +// Heavily borrows from: https://github.com/graphql/graphql-js/blob/8e0c599ceccfa8c40d6edf3b72ee2a71490b10e0/src/language/blockStringValue.js +func blockStringValue(in string) string { + // Expand a block string's raw value into independent lines. + lines := splitLinesRegex.Split(in, -1) + + // Remove common indentation from all lines but first + commonIndent := -1 + for i := 1; i < len(lines); i++ { + line := lines[i] + indent := leadingWhitespaceLen(line) + if indent < len(line) && (commonIndent == -1 || indent < commonIndent) { + commonIndent = indent + if commonIndent == 0 { + break + } + } + } + if commonIndent > 0 { + for i, line := range lines { + if commonIndent > len(line) { + continue + } + lines[i] = line[commonIndent:] + } + } + + // Remove leading blank lines. + for { + if isBlank := lineIsBlank(lines[0]); !isBlank { + break + } + lines = lines[1:] + } + + // Remove trailing blank lines. + for { + i := len(lines) - 1 + if isBlank := lineIsBlank(lines[i]); !isBlank { + break + } + lines = append(lines[:i], lines[i+1:]...) + } + + // Return a string of the lines joined with U+000A. + return strings.Join(lines, "\n") +} + +// leadingWhitespaceLen returns count of whitespace characters on given line. +func leadingWhitespaceLen(in string) (n int) { + for _, ch := range in { + if ch == ' ' || ch == '\t' { + n++ + } else { + break + } + } + return +} + +// lineIsBlank returns true when given line has no content. +func lineIsBlank(in string) bool { + return leadingWhitespaceLen(in) == len(in) +} + +// Converts four hexidecimal chars to the integer that the +// string represents. For example, uniCharCode('0','0','0','f') +// will return 15, and uniCharCode('0','0','f','f') returns 255. +// Returns a negative number on error, if a char was invalid. +// This is implemented by noting that char2hex() returns -1 on error, +// which means the result of ORing the char2hex() will also be negative. +func uniCharCode(a, b, c, d rune) rune { + return rune(char2hex(a)<<12 | char2hex(b)<<8 | char2hex(c)<<4 | char2hex(d)) +} + +// Converts a hex character to its integer value. +// '0' becomes 0, '9' becomes 9 +// 'A' becomes 10, 'F' becomes 15 +// 'a' becomes 10, 'f' becomes 15 +// Returns -1 on error. +func char2hex(a rune) int { + if a >= 48 && a <= 57 { // 0-9 + return int(a) - 48 + } else if a >= 65 && a <= 70 { // A-F + return int(a) - 55 + } else if a >= 97 && a <= 102 { + // a-f + return int(a) - 87 + } + return -1 +} + +func makeToken(kind int, start int, end int, value string) Token { + return Token{Kind: kind, Start: start, End: end, Value: value} +} + +func printCharCode(code rune) string { + // NaN/undefined represents access beyond the end of the file. + if code < 0 { + return "<EOF>" + } + // print as ASCII for printable range + if code >= 0x0020 && code < 0x007F { + return fmt.Sprintf(`"%c"`, code) + } + // Otherwise print the escaped form. e.g. `"\\u0007"` + return fmt.Sprintf(`"\\u%04X"`, code) +} + +func readToken(s *source.Source, fromPosition int) (Token, error) { + body := s.Body + bodyLength := len(body) + position, runePosition := positionAfterWhitespace(body, fromPosition) + if position >= bodyLength { + return makeToken(TokenKind[EOF], position, position, ""), nil + } + code, codeLength := runeAt(body, position) + + // SourceCharacter + if code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D { + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, fmt.Sprintf(`Invalid character %v`, printCharCode(code))) + } + + switch code { + // ! + case '!': + return makeToken(TokenKind[BANG], position, position+1, ""), nil + // $ + case '$': + return makeToken(TokenKind[DOLLAR], position, position+1, ""), nil + // ( + case '(': + return makeToken(TokenKind[PAREN_L], position, position+1, ""), nil + // ) + case ')': + return makeToken(TokenKind[PAREN_R], position, position+1, ""), nil + // . + case '.': + next1, _ := runeAt(body, position+1) + next2, _ := runeAt(body, position+2) + if next1 == '.' && next2 == '.' { + return makeToken(TokenKind[SPREAD], position, position+3, ""), nil + } + break + // : + case ':': + return makeToken(TokenKind[COLON], position, position+1, ""), nil + // = + case '=': + return makeToken(TokenKind[EQUALS], position, position+1, ""), nil + // @ + case '@': + return makeToken(TokenKind[AT], position, position+1, ""), nil + // [ + case '[': + return makeToken(TokenKind[BRACKET_L], position, position+1, ""), nil + // ] + case ']': + return makeToken(TokenKind[BRACKET_R], position, position+1, ""), nil + // { + case '{': + return makeToken(TokenKind[BRACE_L], position, position+1, ""), nil + // | + case '|': + return makeToken(TokenKind[PIPE], position, position+1, ""), nil + // } + case '}': + return makeToken(TokenKind[BRACE_R], position, position+1, ""), nil + // A-Z + case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z': + return readName(s, position, runePosition), nil + // _ + // a-z + case '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z': + return readName(s, position, runePosition), nil + // - + // 0-9 + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + token, err := readNumber(s, position, code, codeLength) + if err != nil { + return token, err + } + return token, nil + // " + case '"': + var token Token + var err error + x, _ := runeAt(body, position+1) + y, _ := runeAt(body, position+2) + if x == '"' && y == '"' { + token, err = readBlockString(s, position) + } else { + token, err = readString(s, position) + } + return token, err + } + description := fmt.Sprintf("Unexpected character %v.", printCharCode(code)) + return Token{}, gqlerrors.NewSyntaxError(s, runePosition, description) +} + +// Gets the rune from the byte array at given byte position and it's width in bytes +func runeAt(body []byte, position int) (code rune, charWidth int) { + if len(body) <= position { + // <EOF> + return -1, utf8.RuneError + } + + c := body[position] + if c < utf8.RuneSelf { + return rune(c), 1 + } + + r, n := utf8.DecodeRune(body[position:]) + return r, n +} + +// Reads from body starting at startPosition until it finds a non-whitespace +// or commented character, then returns the position of that character for lexing. +// lexing. +// Returns both byte positions and rune position +func positionAfterWhitespace(body []byte, startPosition int) (position int, runePosition int) { + bodyLength := len(body) + position = startPosition + runePosition = startPosition + for { + if position < bodyLength { + code, n := runeAt(body, position) + + // Skip Ignored + if code == 0xFEFF || // BOM + // White Space + code == 0x0009 || // tab + code == 0x0020 || // space + // Line Terminator + code == 0x000A || // new line + code == 0x000D || // carriage return + // Comma + code == 0x002C { + position += n + runePosition++ + } else if code == 35 { // # + position += n + runePosition++ + for { + code, n := runeAt(body, position) + if position < bodyLength && + code != 0 && + // SourceCharacter but not LineTerminator + (code > 0x001F || code == 0x0009) && code != 0x000A && code != 0x000D { + position += n + runePosition++ + continue + } else { + break + } + } + } else { + break + } + continue + } else { + break + } + } + return position, runePosition +} + +func GetTokenDesc(token Token) string { + if token.Value == "" { + return GetTokenKindDesc(token.Kind) + } + return fmt.Sprintf("%s \"%s\"", GetTokenKindDesc(token.Kind), token.Value) +} + +func GetTokenKindDesc(kind int) string { + return tokenDescription[kind] +} diff --git a/vendor/github.com/graphql-go/graphql/language/location/location.go b/vendor/github.com/graphql-go/graphql/language/location/location.go new file mode 100644 index 00000000..04bbde6e --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/location/location.go @@ -0,0 +1,35 @@ +package location + +import ( + "regexp" + + "github.com/graphql-go/graphql/language/source" +) + +type SourceLocation struct { + Line int `json:"line"` + Column int `json:"column"` +} + +func GetLocation(s *source.Source, position int) SourceLocation { + body := []byte{} + if s != nil { + body = s.Body + } + line := 1 + column := position + 1 + lineRegexp := regexp.MustCompile("\r\n|[\n\r]") + matches := lineRegexp.FindAllIndex(body, -1) + for _, match := range matches { + matchIndex := match[0] + if matchIndex < position { + line++ + l := len(s.Body[match[0]:match[1]]) + column = position + 1 - (matchIndex + l) + continue + } else { + break + } + } + return SourceLocation{Line: line, Column: column} +} diff --git a/vendor/github.com/graphql-go/graphql/language/parser/parser.go b/vendor/github.com/graphql-go/graphql/language/parser/parser.go new file mode 100644 index 00000000..32beef37 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/parser/parser.go @@ -0,0 +1,1636 @@ +package parser + +import ( + "fmt" + + "github.com/graphql-go/graphql/gqlerrors" + "github.com/graphql-go/graphql/language/ast" + "github.com/graphql-go/graphql/language/lexer" + "github.com/graphql-go/graphql/language/source" +) + +type parseFn func(parser *Parser) (interface{}, error) + +type ParseOptions struct { + NoLocation bool + NoSource bool +} + +type ParseParams struct { + Source interface{} + Options ParseOptions +} + +type Parser struct { + LexToken lexer.Lexer + Source *source.Source + Options ParseOptions + PrevEnd int + Token lexer.Token +} + +func Parse(p ParseParams) (*ast.Document, error) { + var sourceObj *source.Source + switch p.Source.(type) { + case *source.Source: + sourceObj = p.Source.(*source.Source) + default: + body, _ := p.Source.(string) + sourceObj = source.NewSource(&source.Source{Body: []byte(body)}) + } + parser, err := makeParser(sourceObj, p.Options) + if err != nil { + return nil, err + } + doc, err := parseDocument(parser) + if err != nil { + return nil, err + } + return doc, nil +} + +// TODO: test and expose parseValue as a public +func parseValue(p ParseParams) (ast.Value, error) { + var value ast.Value + var sourceObj *source.Source + switch p.Source.(type) { + case *source.Source: + sourceObj = p.Source.(*source.Source) + default: + body, _ := p.Source.(string) + sourceObj = source.NewSource(&source.Source{Body: []byte(body)}) + } + parser, err := makeParser(sourceObj, p.Options) + if err != nil { + return value, err + } + value, err = parseValueLiteral(parser, false) + if err != nil { + return value, err + } + return value, nil +} + +// Converts a name lex token into a name parse node. +func parseName(parser *Parser) (*ast.Name, error) { + token, err := expect(parser, lexer.TokenKind[lexer.NAME]) + if err != nil { + return nil, err + } + return ast.NewName(&ast.Name{ + Value: token.Value, + Loc: loc(parser, token.Start), + }), nil +} + +func makeParser(s *source.Source, opts ParseOptions) (*Parser, error) { + lexToken := lexer.Lex(s) + token, err := lexToken(0) + if err != nil { + return &Parser{}, err + } + return &Parser{ + LexToken: lexToken, + Source: s, + Options: opts, + PrevEnd: 0, + Token: token, + }, nil +} + +/* Implements the parsing rules in the Document section. */ + +func parseDocument(parser *Parser) (*ast.Document, error) { + start := parser.Token.Start + var nodes []ast.Node + for { + if skp, err := skip(parser, lexer.TokenKind[lexer.EOF]); err != nil { + return nil, err + } else if skp { + break + } + if peek(parser, lexer.TokenKind[lexer.BRACE_L]) { + node, err := parseOperationDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + } else if peek(parser, lexer.TokenKind[lexer.NAME]) { + switch parser.Token.Value { + case "query": + fallthrough + case "mutation": + fallthrough + case "subscription": // Note: subscription is an experimental non-spec addition. + node, err := parseOperationDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + case "fragment": + node, err := parseFragmentDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + + // Note: the Type System IDL is an experimental non-spec addition. + case "schema": + fallthrough + case "scalar": + fallthrough + case "type": + fallthrough + case "interface": + fallthrough + case "union": + fallthrough + case "enum": + fallthrough + case "input": + fallthrough + case "extend": + fallthrough + case "directive": + node, err := parseTypeSystemDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + default: + if err := unexpected(parser, lexer.Token{}); err != nil { + return nil, err + } + } + } else if peekDescription(parser) { + node, err := parseTypeSystemDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + } else { + if err := unexpected(parser, lexer.Token{}); err != nil { + return nil, err + } + } + } + return ast.NewDocument(&ast.Document{ + Loc: loc(parser, start), + Definitions: nodes, + }), nil +} + +/* Implements the parsing rules in the Operations section. */ + +/** + * OperationDefinition : + * - SelectionSet + * - OperationType Name? VariableDefinitions? Directives? SelectionSet + */ +func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error) { + start := parser.Token.Start + if peek(parser, lexer.TokenKind[lexer.BRACE_L]) { + selectionSet, err := parseSelectionSet(parser) + if err != nil { + return nil, err + } + return ast.NewOperationDefinition(&ast.OperationDefinition{ + Operation: ast.OperationTypeQuery, + Directives: []*ast.Directive{}, + SelectionSet: selectionSet, + Loc: loc(parser, start), + }), nil + } + operation, err := parseOperationType(parser) + if err != nil { + return nil, err + } + + var name *ast.Name + if peek(parser, lexer.TokenKind[lexer.NAME]) { + name, err = parseName(parser) + } + variableDefinitions, err := parseVariableDefinitions(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + selectionSet, err := parseSelectionSet(parser) + if err != nil { + return nil, err + } + return ast.NewOperationDefinition(&ast.OperationDefinition{ + Operation: operation, + Name: name, + VariableDefinitions: variableDefinitions, + Directives: directives, + SelectionSet: selectionSet, + Loc: loc(parser, start), + }), nil +} + +/** + * OperationType : one of query mutation subscription + */ +func parseOperationType(parser *Parser) (string, error) { + operationToken, err := expect(parser, lexer.TokenKind[lexer.NAME]) + if err != nil { + return "", err + } + switch operationToken.Value { + case ast.OperationTypeQuery: + return operationToken.Value, nil + case ast.OperationTypeMutation: + return operationToken.Value, nil + case ast.OperationTypeSubscription: + return operationToken.Value, nil + default: + return "", unexpected(parser, operationToken) + } +} + +/** + * VariableDefinitions : ( VariableDefinition+ ) + */ +func parseVariableDefinitions(parser *Parser) ([]*ast.VariableDefinition, error) { + variableDefinitions := []*ast.VariableDefinition{} + if peek(parser, lexer.TokenKind[lexer.PAREN_L]) { + vdefs, err := many(parser, lexer.TokenKind[lexer.PAREN_L], parseVariableDefinition, lexer.TokenKind[lexer.PAREN_R]) + for _, vdef := range vdefs { + if vdef != nil { + variableDefinitions = append(variableDefinitions, vdef.(*ast.VariableDefinition)) + } + } + if err != nil { + return variableDefinitions, err + } + return variableDefinitions, nil + } + return variableDefinitions, nil +} + +/** + * VariableDefinition : Variable : Type DefaultValue? + */ +func parseVariableDefinition(parser *Parser) (interface{}, error) { + start := parser.Token.Start + variable, err := parseVariable(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + ttype, err := parseType(parser) + if err != nil { + return nil, err + } + var defaultValue ast.Value + if skp, err := skip(parser, lexer.TokenKind[lexer.EQUALS]); err != nil { + return nil, err + } else if skp { + dv, err := parseValueLiteral(parser, true) + if err != nil { + return nil, err + } + defaultValue = dv + } + return ast.NewVariableDefinition(&ast.VariableDefinition{ + Variable: variable, + Type: ttype, + DefaultValue: defaultValue, + Loc: loc(parser, start), + }), nil +} + +/** + * Variable : $ Name + */ +func parseVariable(parser *Parser) (*ast.Variable, error) { + start := parser.Token.Start + _, err := expect(parser, lexer.TokenKind[lexer.DOLLAR]) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + return ast.NewVariable(&ast.Variable{ + Name: name, + Loc: loc(parser, start), + }), nil +} + +/** + * SelectionSet : { Selection+ } + */ +func parseSelectionSet(parser *Parser) (*ast.SelectionSet, error) { + start := parser.Token.Start + iSelections, err := many(parser, lexer.TokenKind[lexer.BRACE_L], parseSelection, lexer.TokenKind[lexer.BRACE_R]) + if err != nil { + return nil, err + } + selections := []ast.Selection{} + for _, iSelection := range iSelections { + if iSelection != nil { + // type assert interface{} into Selection interface + selections = append(selections, iSelection.(ast.Selection)) + } + } + + return ast.NewSelectionSet(&ast.SelectionSet{ + Selections: selections, + Loc: loc(parser, start), + }), nil +} + +/** + * Selection : + * - Field + * - FragmentSpread + * - InlineFragment + */ +func parseSelection(parser *Parser) (interface{}, error) { + if peek(parser, lexer.TokenKind[lexer.SPREAD]) { + r, err := parseFragment(parser) + return r, err + } + return parseField(parser) +} + +/** + * Field : Alias? Name Arguments? Directives? SelectionSet? + * + * Alias : Name : + */ +func parseField(parser *Parser) (*ast.Field, error) { + start := parser.Token.Start + nameOrAlias, err := parseName(parser) + if err != nil { + return nil, err + } + var ( + name *ast.Name + alias *ast.Name + ) + if skp, err := skip(parser, lexer.TokenKind[lexer.COLON]); err != nil { + return nil, err + } else if skp { + alias = nameOrAlias + n, err := parseName(parser) + if err != nil { + return nil, err + } + name = n + } else { + name = nameOrAlias + } + arguments, err := parseArguments(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + var selectionSet *ast.SelectionSet + if peek(parser, lexer.TokenKind[lexer.BRACE_L]) { + sSet, err := parseSelectionSet(parser) + if err != nil { + return nil, err + } + selectionSet = sSet + } + return ast.NewField(&ast.Field{ + Alias: alias, + Name: name, + Arguments: arguments, + Directives: directives, + SelectionSet: selectionSet, + Loc: loc(parser, start), + }), nil +} + +/** + * Arguments : ( Argument+ ) + */ +func parseArguments(parser *Parser) ([]*ast.Argument, error) { + arguments := []*ast.Argument{} + if peek(parser, lexer.TokenKind[lexer.PAREN_L]) { + iArguments, err := many(parser, lexer.TokenKind[lexer.PAREN_L], parseArgument, lexer.TokenKind[lexer.PAREN_R]) + if err != nil { + return arguments, err + } + for _, iArgument := range iArguments { + if iArgument != nil { + arguments = append(arguments, iArgument.(*ast.Argument)) + } + } + return arguments, nil + } + return arguments, nil +} + +/** + * Argument : Name : Value + */ +func parseArgument(parser *Parser) (interface{}, error) { + start := parser.Token.Start + name, err := parseName(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + value, err := parseValueLiteral(parser, false) + if err != nil { + return nil, err + } + return ast.NewArgument(&ast.Argument{ + Name: name, + Value: value, + Loc: loc(parser, start), + }), nil +} + +/* Implements the parsing rules in the Fragments section. */ + +/** + * Corresponds to both FragmentSpread and InlineFragment in the spec. + * + * FragmentSpread : ... FragmentName Directives? + * + * InlineFragment : ... TypeCondition? Directives? SelectionSet + */ +func parseFragment(parser *Parser) (interface{}, error) { + start := parser.Token.Start + _, err := expect(parser, lexer.TokenKind[lexer.SPREAD]) + if err != nil { + return nil, err + } + if peek(parser, lexer.TokenKind[lexer.NAME]) && parser.Token.Value != "on" { + name, err := parseFragmentName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + return ast.NewFragmentSpread(&ast.FragmentSpread{ + Name: name, + Directives: directives, + Loc: loc(parser, start), + }), nil + } + var typeCondition *ast.Named + if parser.Token.Value == "on" { + if err := advance(parser); err != nil { + return nil, err + } + name, err := parseNamed(parser) + if err != nil { + return nil, err + } + typeCondition = name + + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + selectionSet, err := parseSelectionSet(parser) + if err != nil { + return nil, err + } + return ast.NewInlineFragment(&ast.InlineFragment{ + TypeCondition: typeCondition, + Directives: directives, + SelectionSet: selectionSet, + Loc: loc(parser, start), + }), nil +} + +/** + * FragmentDefinition : + * - fragment FragmentName on TypeCondition Directives? SelectionSet + * + * TypeCondition : NamedType + */ +func parseFragmentDefinition(parser *Parser) (*ast.FragmentDefinition, error) { + start := parser.Token.Start + _, err := expectKeyWord(parser, "fragment") + if err != nil { + return nil, err + } + name, err := parseFragmentName(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "on") + if err != nil { + return nil, err + } + typeCondition, err := parseNamed(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + selectionSet, err := parseSelectionSet(parser) + if err != nil { + return nil, err + } + return ast.NewFragmentDefinition(&ast.FragmentDefinition{ + Name: name, + TypeCondition: typeCondition, + Directives: directives, + SelectionSet: selectionSet, + Loc: loc(parser, start), + }), nil +} + +/** + * FragmentName : Name but not `on` + */ +func parseFragmentName(parser *Parser) (*ast.Name, error) { + if parser.Token.Value == "on" { + return nil, unexpected(parser, lexer.Token{}) + } + return parseName(parser) +} + +/* Implements the parsing rules in the Values section. */ + +/** + * Value[Const] : + * - [~Const] Variable + * - IntValue + * - FloatValue + * - StringValue + * - BooleanValue + * - EnumValue + * - ListValue[?Const] + * - ObjectValue[?Const] + * + * BooleanValue : one of `true` `false` + * + * EnumValue : Name but not `true`, `false` or `null` + */ +func parseValueLiteral(parser *Parser, isConst bool) (ast.Value, error) { + token := parser.Token + switch token.Kind { + case lexer.TokenKind[lexer.BRACKET_L]: + return parseList(parser, isConst) + case lexer.TokenKind[lexer.BRACE_L]: + return parseObject(parser, isConst) + case lexer.TokenKind[lexer.INT]: + if err := advance(parser); err != nil { + return nil, err + } + return ast.NewIntValue(&ast.IntValue{ + Value: token.Value, + Loc: loc(parser, token.Start), + }), nil + case lexer.TokenKind[lexer.FLOAT]: + if err := advance(parser); err != nil { + return nil, err + } + return ast.NewFloatValue(&ast.FloatValue{ + Value: token.Value, + Loc: loc(parser, token.Start), + }), nil + case lexer.TokenKind[lexer.BLOCK_STRING]: + fallthrough + case lexer.TokenKind[lexer.STRING]: + return parseStringLiteral(parser) + case lexer.TokenKind[lexer.NAME]: + if token.Value == "true" || token.Value == "false" { + if err := advance(parser); err != nil { + return nil, err + } + value := true + if token.Value == "false" { + value = false + } + return ast.NewBooleanValue(&ast.BooleanValue{ + Value: value, + Loc: loc(parser, token.Start), + }), nil + } else if token.Value != "null" { + if err := advance(parser); err != nil { + return nil, err + } + return ast.NewEnumValue(&ast.EnumValue{ + Value: token.Value, + Loc: loc(parser, token.Start), + }), nil + } + case lexer.TokenKind[lexer.DOLLAR]: + if !isConst { + return parseVariable(parser) + } + } + if err := unexpected(parser, lexer.Token{}); err != nil { + return nil, err + } + return nil, nil +} + +func parseConstValue(parser *Parser) (interface{}, error) { + value, err := parseValueLiteral(parser, true) + if err != nil { + return value, err + } + return value, nil +} + +func parseValueValue(parser *Parser) (interface{}, error) { + return parseValueLiteral(parser, false) +} + +/** + * ListValue[Const] : + * - [ ] + * - [ Value[?Const]+ ] + */ +func parseList(parser *Parser, isConst bool) (*ast.ListValue, error) { + start := parser.Token.Start + var item parseFn + if isConst { + item = parseConstValue + } else { + item = parseValueValue + } + iValues, err := any(parser, lexer.TokenKind[lexer.BRACKET_L], item, lexer.TokenKind[lexer.BRACKET_R]) + if err != nil { + return nil, err + } + values := []ast.Value{} + for _, iValue := range iValues { + values = append(values, iValue.(ast.Value)) + } + return ast.NewListValue(&ast.ListValue{ + Values: values, + Loc: loc(parser, start), + }), nil +} + +/** + * ObjectValue[Const] : + * - { } + * - { ObjectField[?Const]+ } + */ +func parseObject(parser *Parser, isConst bool) (*ast.ObjectValue, error) { + start := parser.Token.Start + _, err := expect(parser, lexer.TokenKind[lexer.BRACE_L]) + if err != nil { + return nil, err + } + fields := []*ast.ObjectField{} + for { + if skp, err := skip(parser, lexer.TokenKind[lexer.BRACE_R]); err != nil { + return nil, err + } else if skp { + break + } + field, err := parseObjectField(parser, isConst) + if err != nil { + return nil, err + } + fields = append(fields, field) + } + return ast.NewObjectValue(&ast.ObjectValue{ + Fields: fields, + Loc: loc(parser, start), + }), nil +} + +/** + * ObjectField[Const] : Name : Value[?Const] + */ +func parseObjectField(parser *Parser, isConst bool) (*ast.ObjectField, error) { + start := parser.Token.Start + name, err := parseName(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + value, err := parseValueLiteral(parser, isConst) + if err != nil { + return nil, err + } + return ast.NewObjectField(&ast.ObjectField{ + Name: name, + Value: value, + Loc: loc(parser, start), + }), nil +} + +/* Implements the parsing rules in the Directives section. */ + +/** + * Directives : Directive+ + */ +func parseDirectives(parser *Parser) ([]*ast.Directive, error) { + directives := []*ast.Directive{} + for { + if !peek(parser, lexer.TokenKind[lexer.AT]) { + break + } + directive, err := parseDirective(parser) + if err != nil { + return directives, err + } + directives = append(directives, directive) + } + return directives, nil +} + +/** + * Directive : @ Name Arguments? + */ +func parseDirective(parser *Parser) (*ast.Directive, error) { + start := parser.Token.Start + _, err := expect(parser, lexer.TokenKind[lexer.AT]) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + args, err := parseArguments(parser) + if err != nil { + return nil, err + } + return ast.NewDirective(&ast.Directive{ + Name: name, + Arguments: args, + Loc: loc(parser, start), + }), nil +} + +/* Implements the parsing rules in the Types section. */ + +/** + * Type : + * - NamedType + * - ListType + * - NonNullType + */ +func parseType(parser *Parser) (ast.Type, error) { + start := parser.Token.Start + var ttype ast.Type + if skp, err := skip(parser, lexer.TokenKind[lexer.BRACKET_L]); err != nil { + return nil, err + } else if skp { + t, err := parseType(parser) + if err != nil { + return t, err + } + ttype = t + _, err = expect(parser, lexer.TokenKind[lexer.BRACKET_R]) + if err != nil { + return ttype, err + } + ttype = ast.NewList(&ast.List{ + Type: ttype, + Loc: loc(parser, start), + }) + } else { + name, err := parseNamed(parser) + if err != nil { + return ttype, err + } + ttype = name + } + if skp, err := skip(parser, lexer.TokenKind[lexer.BANG]); err != nil { + return nil, err + } else if skp { + ttype = ast.NewNonNull(&ast.NonNull{ + Type: ttype, + Loc: loc(parser, start), + }) + return ttype, nil + } + return ttype, nil +} + +/** + * NamedType : Name + */ +func parseNamed(parser *Parser) (*ast.Named, error) { + start := parser.Token.Start + name, err := parseName(parser) + if err != nil { + return nil, err + } + return ast.NewNamed(&ast.Named{ + Name: name, + Loc: loc(parser, start), + }), nil +} + +/* Implements the parsing rules in the Type Definition section. */ + +/** + * TypeSystemDefinition : + * - SchemaDefinition + * - TypeDefinition + * - TypeExtension + * - DirectiveDefinition + * + * TypeDefinition : + * - ScalarTypeDefinition + * - ObjectTypeDefinition + * - InterfaceTypeDefinition + * - UnionTypeDefinition + * - EnumTypeDefinition + * - InputObjectTypeDefinition + */ +func parseTypeSystemDefinition(parser *Parser) (ast.Node, error) { + var err error + + // Many definitions begin with a description and require a lookahead. + keywordToken := parser.Token + if peekDescription(parser) { + keywordToken, err = lookahead(parser) + if err != nil { + return nil, err + } + } + + if keywordToken.Kind == lexer.NAME { + switch keywordToken.Value { + case "schema": + return parseSchemaDefinition(parser) + case "scalar": + return parseScalarTypeDefinition(parser) + case "type": + return parseObjectTypeDefinition(parser) + case "interface": + return parseInterfaceTypeDefinition(parser) + case "union": + return parseUnionTypeDefinition(parser) + case "enum": + return parseEnumTypeDefinition(parser) + case "input": + return parseInputObjectTypeDefinition(parser) + case "extend": + return parseTypeExtensionDefinition(parser) + case "directive": + return parseDirectiveDefinition(parser) + } + } + + return nil, unexpected(parser, keywordToken) +} + +/** + * SchemaDefinition : schema Directives? { OperationTypeDefinition+ } + * + * OperationTypeDefinition : OperationType : NamedType + */ +func parseSchemaDefinition(parser *Parser) (*ast.SchemaDefinition, error) { + start := parser.Token.Start + _, err := expectKeyWord(parser, "schema") + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + operationTypesI, err := many( + parser, + lexer.TokenKind[lexer.BRACE_L], + parseOperationTypeDefinition, + lexer.TokenKind[lexer.BRACE_R], + ) + if err != nil { + return nil, err + } + operationTypes := []*ast.OperationTypeDefinition{} + for _, op := range operationTypesI { + if op, ok := op.(*ast.OperationTypeDefinition); ok { + operationTypes = append(operationTypes, op) + } + } + return ast.NewSchemaDefinition(&ast.SchemaDefinition{ + OperationTypes: operationTypes, + Directives: directives, + Loc: loc(parser, start), + }), nil +} + +func parseOperationTypeDefinition(parser *Parser) (interface{}, error) { + start := parser.Token.Start + operation, err := parseOperationType(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + ttype, err := parseNamed(parser) + if err != nil { + return nil, err + } + return ast.NewOperationTypeDefinition(&ast.OperationTypeDefinition{ + Operation: operation, + Type: ttype, + Loc: loc(parser, start), + }), nil +} + +/** + * ScalarTypeDefinition : Description? scalar Name Directives? + */ +func parseScalarTypeDefinition(parser *Parser) (*ast.ScalarDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "scalar") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + def := ast.NewScalarDefinition(&ast.ScalarDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + }) + return def, nil +} + +/** + * ObjectTypeDefinition : + * Description? + * type Name ImplementsInterfaces? Directives? { FieldDefinition+ } + */ +func parseObjectTypeDefinition(parser *Parser) (*ast.ObjectDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "type") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + interfaces, err := parseImplementsInterfaces(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + iFields, err := any(parser, lexer.TokenKind[lexer.BRACE_L], parseFieldDefinition, lexer.TokenKind[lexer.BRACE_R]) + if err != nil { + return nil, err + } + fields := []*ast.FieldDefinition{} + for _, iField := range iFields { + if iField != nil { + fields = append(fields, iField.(*ast.FieldDefinition)) + } + } + return ast.NewObjectDefinition(&ast.ObjectDefinition{ + Name: name, + Description: description, + Loc: loc(parser, start), + Interfaces: interfaces, + Directives: directives, + Fields: fields, + }), nil +} + +/** + * ImplementsInterfaces : implements NamedType+ + */ +func parseImplementsInterfaces(parser *Parser) ([]*ast.Named, error) { + types := []*ast.Named{} + if parser.Token.Value == "implements" { + if err := advance(parser); err != nil { + return nil, err + } + for { + ttype, err := parseNamed(parser) + if err != nil { + return types, err + } + types = append(types, ttype) + if !peek(parser, lexer.TokenKind[lexer.NAME]) { + break + } + } + } + return types, nil +} + +/** + * FieldDefinition : Description? Name ArgumentsDefinition? : Type Directives? + */ +func parseFieldDefinition(parser *Parser) (interface{}, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + args, err := parseArgumentDefs(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + ttype, err := parseType(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + return ast.NewFieldDefinition(&ast.FieldDefinition{ + Name: name, + Description: description, + Arguments: args, + Type: ttype, + Directives: directives, + Loc: loc(parser, start), + }), nil +} + +/** + * ArgumentsDefinition : ( InputValueDefinition+ ) + */ +func parseArgumentDefs(parser *Parser) ([]*ast.InputValueDefinition, error) { + inputValueDefinitions := []*ast.InputValueDefinition{} + + if !peek(parser, lexer.TokenKind[lexer.PAREN_L]) { + return inputValueDefinitions, nil + } + iInputValueDefinitions, err := many(parser, lexer.TokenKind[lexer.PAREN_L], parseInputValueDef, lexer.TokenKind[lexer.PAREN_R]) + if err != nil { + return inputValueDefinitions, err + } + for _, iInputValueDefinition := range iInputValueDefinitions { + if iInputValueDefinition != nil { + inputValueDefinitions = append(inputValueDefinitions, iInputValueDefinition.(*ast.InputValueDefinition)) + } + } + return inputValueDefinitions, err +} + +/** + * InputValueDefinition : Description? Name : Type DefaultValue? Directives? + */ +func parseInputValueDef(parser *Parser) (interface{}, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + ttype, err := parseType(parser) + if err != nil { + return nil, err + } + var defaultValue ast.Value + if skp, err := skip(parser, lexer.TokenKind[lexer.EQUALS]); err != nil { + return nil, err + } else if skp { + val, err := parseConstValue(parser) + if err != nil { + return nil, err + } + if val, ok := val.(ast.Value); ok { + defaultValue = val + } + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + return ast.NewInputValueDefinition(&ast.InputValueDefinition{ + Name: name, + Description: description, + Type: ttype, + DefaultValue: defaultValue, + Directives: directives, + Loc: loc(parser, start), + }), nil +} + +/** + * InterfaceTypeDefinition : + * Description? + * interface Name Directives? { FieldDefinition+ } + */ +func parseInterfaceTypeDefinition(parser *Parser) (*ast.InterfaceDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "interface") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + iFields, err := any(parser, lexer.TokenKind[lexer.BRACE_L], parseFieldDefinition, lexer.TokenKind[lexer.BRACE_R]) + if err != nil { + return nil, err + } + fields := []*ast.FieldDefinition{} + for _, iField := range iFields { + if iField != nil { + fields = append(fields, iField.(*ast.FieldDefinition)) + } + } + return ast.NewInterfaceDefinition(&ast.InterfaceDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + Fields: fields, + }), nil +} + +/** + * UnionTypeDefinition : Description? union Name Directives? = UnionMembers + */ +func parseUnionTypeDefinition(parser *Parser) (*ast.UnionDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "union") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.EQUALS]) + if err != nil { + return nil, err + } + types, err := parseUnionMembers(parser) + if err != nil { + return nil, err + } + return ast.NewUnionDefinition(&ast.UnionDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + Types: types, + }), nil +} + +/** + * UnionMembers : + * - NamedType + * - UnionMembers | NamedType + */ +func parseUnionMembers(parser *Parser) ([]*ast.Named, error) { + members := []*ast.Named{} + for { + member, err := parseNamed(parser) + if err != nil { + return members, err + } + members = append(members, member) + if skp, err := skip(parser, lexer.TokenKind[lexer.PIPE]); err != nil { + return nil, err + } else if !skp { + break + } + } + return members, nil +} + +/** + * EnumTypeDefinition : Description? enum Name Directives? { EnumValueDefinition+ } + */ +func parseEnumTypeDefinition(parser *Parser) (*ast.EnumDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "enum") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + iEnumValueDefs, err := any(parser, lexer.TokenKind[lexer.BRACE_L], parseEnumValueDefinition, lexer.TokenKind[lexer.BRACE_R]) + if err != nil { + return nil, err + } + values := []*ast.EnumValueDefinition{} + for _, iEnumValueDef := range iEnumValueDefs { + if iEnumValueDef != nil { + values = append(values, iEnumValueDef.(*ast.EnumValueDefinition)) + } + } + return ast.NewEnumDefinition(&ast.EnumDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + Values: values, + }), nil +} + +/** + * EnumValueDefinition : Description? EnumValue Directives? + * + * EnumValue : Name + */ +func parseEnumValueDefinition(parser *Parser) (interface{}, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + return ast.NewEnumValueDefinition(&ast.EnumValueDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + }), nil +} + +/** + * InputObjectTypeDefinition : + * - Description? input Name Directives? { InputValueDefinition+ } + */ +func parseInputObjectTypeDefinition(parser *Parser) (*ast.InputObjectDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "input") + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + directives, err := parseDirectives(parser) + if err != nil { + return nil, err + } + iInputValueDefinitions, err := any(parser, lexer.TokenKind[lexer.BRACE_L], parseInputValueDef, lexer.TokenKind[lexer.BRACE_R]) + if err != nil { + return nil, err + } + fields := []*ast.InputValueDefinition{} + for _, iInputValueDefinition := range iInputValueDefinitions { + if iInputValueDefinition != nil { + fields = append(fields, iInputValueDefinition.(*ast.InputValueDefinition)) + } + } + return ast.NewInputObjectDefinition(&ast.InputObjectDefinition{ + Name: name, + Description: description, + Directives: directives, + Loc: loc(parser, start), + Fields: fields, + }), nil +} + +/** + * TypeExtensionDefinition : extend ObjectTypeDefinition + */ +func parseTypeExtensionDefinition(parser *Parser) (*ast.TypeExtensionDefinition, error) { + start := parser.Token.Start + _, err := expectKeyWord(parser, "extend") + if err != nil { + return nil, err + } + + definition, err := parseObjectTypeDefinition(parser) + if err != nil { + return nil, err + } + return ast.NewTypeExtensionDefinition(&ast.TypeExtensionDefinition{ + Loc: loc(parser, start), + Definition: definition, + }), nil +} + +/** + * DirectiveDefinition : + * - directive @ Name ArgumentsDefinition? on DirectiveLocations + */ +func parseDirectiveDefinition(parser *Parser) (*ast.DirectiveDefinition, error) { + start := parser.Token.Start + description, err := parseDescription(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "directive") + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.AT]) + if err != nil { + return nil, err + } + name, err := parseName(parser) + if err != nil { + return nil, err + } + args, err := parseArgumentDefs(parser) + if err != nil { + return nil, err + } + _, err = expectKeyWord(parser, "on") + if err != nil { + return nil, err + } + locations, err := parseDirectiveLocations(parser) + if err != nil { + return nil, err + } + + return ast.NewDirectiveDefinition(&ast.DirectiveDefinition{ + Loc: loc(parser, start), + Name: name, + Description: description, + Arguments: args, + Locations: locations, + }), nil +} + +/** + * DirectiveLocations : + * - Name + * - DirectiveLocations | Name + */ +func parseDirectiveLocations(parser *Parser) ([]*ast.Name, error) { + locations := []*ast.Name{} + for { + name, err := parseName(parser) + if err != nil { + return locations, err + } + locations = append(locations, name) + + hasPipe, err := skip(parser, lexer.TokenKind[lexer.PIPE]) + if err != nil { + return locations, err + } + if !hasPipe { + break + } + } + return locations, nil +} + +func parseStringLiteral(parser *Parser) (*ast.StringValue, error) { + token := parser.Token + if err := advance(parser); err != nil { + return nil, err + } + return ast.NewStringValue(&ast.StringValue{ + Value: token.Value, + Loc: loc(parser, token.Start), + }), nil +} + +/** + * Description : StringValue + */ +func parseDescription(parser *Parser) (*ast.StringValue, error) { + if peekDescription(parser) { + return parseStringLiteral(parser) + } + return nil, nil +} + +/* Core parsing utility functions */ + +// Returns a location object, used to identify the place in +// the source that created a given parsed object. +func loc(parser *Parser, start int) *ast.Location { + if parser.Options.NoLocation { + return nil + } + if parser.Options.NoSource { + return ast.NewLocation(&ast.Location{ + Start: start, + End: parser.PrevEnd, + }) + } + return ast.NewLocation(&ast.Location{ + Start: start, + End: parser.PrevEnd, + Source: parser.Source, + }) +} + +// Moves the internal parser object to the next lexed token. +func advance(parser *Parser) error { + prevEnd := parser.Token.End + parser.PrevEnd = prevEnd + token, err := parser.LexToken(prevEnd) + if err != nil { + return err + } + parser.Token = token + return nil +} + +// lookahead retrieves the next token +func lookahead(parser *Parser) (lexer.Token, error) { + prevEnd := parser.Token.End + return parser.LexToken(prevEnd) +} + +// Determines if the next token is of a given kind +func peek(parser *Parser, Kind int) bool { + return parser.Token.Kind == Kind +} + +// peekDescription determines if the next token is a string value +func peekDescription(parser *Parser) bool { + return peek(parser, lexer.STRING) || peek(parser, lexer.BLOCK_STRING) +} + +// If the next token is of the given kind, return true after advancing +// the parser. Otherwise, do not change the parser state and return false. +func skip(parser *Parser, Kind int) (bool, error) { + if parser.Token.Kind == Kind { + err := advance(parser) + return true, err + } + return false, nil +} + +// If the next token is of the given kind, return that token after advancing +// the parser. Otherwise, do not change the parser state and return error. +func expect(parser *Parser, kind int) (lexer.Token, error) { + token := parser.Token + if token.Kind == kind { + err := advance(parser) + return token, err + } + descp := fmt.Sprintf("Expected %s, found %s", lexer.GetTokenKindDesc(kind), lexer.GetTokenDesc(token)) + return token, gqlerrors.NewSyntaxError(parser.Source, token.Start, descp) +} + +// If the next token is a keyword with the given value, return that token after +// advancing the parser. Otherwise, do not change the parser state and return false. +func expectKeyWord(parser *Parser, value string) (lexer.Token, error) { + token := parser.Token + if token.Kind == lexer.TokenKind[lexer.NAME] && token.Value == value { + err := advance(parser) + return token, err + } + descp := fmt.Sprintf("Expected \"%s\", found %s", value, lexer.GetTokenDesc(token)) + return token, gqlerrors.NewSyntaxError(parser.Source, token.Start, descp) +} + +// Helper function for creating an error when an unexpected lexed token +// is encountered. +func unexpected(parser *Parser, atToken lexer.Token) error { + var token lexer.Token + if (atToken == lexer.Token{}) { + token = parser.Token + } else { + token = parser.Token + } + description := fmt.Sprintf("Unexpected %v", lexer.GetTokenDesc(token)) + return gqlerrors.NewSyntaxError(parser.Source, token.Start, description) +} + +// Returns a possibly empty list of parse nodes, determined by +// the parseFn. This list begins with a lex token of openKind +// and ends with a lex token of closeKind. Advances the parser +// to the next lex token after the closing token. +func any(parser *Parser, openKind int, parseFn parseFn, closeKind int) ([]interface{}, error) { + var nodes []interface{} + _, err := expect(parser, openKind) + if err != nil { + return nodes, nil + } + for { + if skp, err := skip(parser, closeKind); err != nil { + return nil, err + } else if skp { + break + } + n, err := parseFn(parser) + if err != nil { + return nodes, err + } + nodes = append(nodes, n) + } + return nodes, nil +} + +// Returns a non-empty list of parse nodes, determined by +// the parseFn. This list begins with a lex token of openKind +// and ends with a lex token of closeKind. Advances the parser +// to the next lex token after the closing token. +func many(parser *Parser, openKind int, parseFn parseFn, closeKind int) ([]interface{}, error) { + _, err := expect(parser, openKind) + if err != nil { + return nil, err + } + var nodes []interface{} + node, err := parseFn(parser) + if err != nil { + return nodes, err + } + nodes = append(nodes, node) + for { + if skp, err := skip(parser, closeKind); err != nil { + return nil, err + } else if skp { + break + } + node, err := parseFn(parser) + if err != nil { + return nodes, err + } + nodes = append(nodes, node) + } + return nodes, nil +} diff --git a/vendor/github.com/graphql-go/graphql/language/printer/printer.go b/vendor/github.com/graphql-go/graphql/language/printer/printer.go new file mode 100644 index 00000000..3add3852 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/printer/printer.go @@ -0,0 +1,821 @@ +package printer + +import ( + "fmt" + "strings" + + "github.com/graphql-go/graphql/language/ast" + "github.com/graphql-go/graphql/language/visitor" + "reflect" +) + +func getMapValue(m map[string]interface{}, key string) interface{} { + tokens := strings.Split(key, ".") + valMap := m + for _, token := range tokens { + v, ok := valMap[token] + if !ok { + return nil + } + switch v := v.(type) { + case []interface{}: + return v + case map[string]interface{}: + valMap = v + continue + default: + return v + } + } + return valMap +} +func getMapSliceValue(m map[string]interface{}, key string) []interface{} { + tokens := strings.Split(key, ".") + valMap := m + for _, token := range tokens { + v, ok := valMap[token] + if !ok { + return []interface{}{} + } + switch v := v.(type) { + case []interface{}: + return v + default: + return []interface{}{} + } + } + return []interface{}{} +} +func getMapValueString(m map[string]interface{}, key string) string { + tokens := strings.Split(key, ".") + valMap := m + for _, token := range tokens { + v, ok := valMap[token] + if !ok { + return "" + } + if v == nil { + return "" + } + switch v := v.(type) { + case map[string]interface{}: + valMap = v + continue + case string: + return v + default: + return fmt.Sprintf("%v", v) + } + } + return "" +} + +func toSliceString(slice interface{}) []string { + if slice == nil { + return []string{} + } + res := []string{} + switch reflect.TypeOf(slice).Kind() { + case reflect.Slice: + s := reflect.ValueOf(slice) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + elemInterface := elem.Interface() + if elem, ok := elemInterface.(string); ok { + res = append(res, elem) + } + } + return res + default: + return res + } +} + +func join(str []string, sep string) string { + ss := []string{} + // filter out empty strings + for _, s := range str { + if s == "" { + continue + } + ss = append(ss, s) + } + return strings.Join(ss, sep) +} + +func wrap(start, maybeString, end string) string { + if maybeString == "" { + return maybeString + } + return start + maybeString + end +} + +// Given array, print each item on its own line, wrapped in an indented "{ }" block. +func block(maybeArray interface{}) string { + s := toSliceString(maybeArray) + if len(s) == 0 { + return "{}" + } + return indent("{\n"+join(s, "\n")) + "\n}" +} + +func indent(maybeString interface{}) string { + if maybeString == nil { + return "" + } + switch str := maybeString.(type) { + case string: + return strings.Replace(str, "\n", "\n ", -1) + } + return "" +} + +var printDocASTReducer = map[string]visitor.VisitFunc{ + "Name": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Name: + return visitor.ActionUpdate, node.Value + case map[string]interface{}: + return visitor.ActionUpdate, getMapValue(node, "Value") + } + return visitor.ActionNoChange, nil + }, + "Variable": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Variable: + return visitor.ActionUpdate, fmt.Sprintf("$%v", node.Name) + case map[string]interface{}: + return visitor.ActionUpdate, "$" + getMapValueString(node, "Name") + } + return visitor.ActionNoChange, nil + }, + + // Document + "Document": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Document: + definitions := toSliceString(node.Definitions) + return visitor.ActionUpdate, join(definitions, "\n\n") + "\n" + case map[string]interface{}: + definitions := toSliceString(getMapValue(node, "Definitions")) + return visitor.ActionUpdate, join(definitions, "\n\n") + "\n" + } + return visitor.ActionNoChange, nil + }, + "OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.OperationDefinition: + op := string(node.Operation) + name := fmt.Sprintf("%v", node.Name) + + varDefs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")") + directives := join(toSliceString(node.Directives), " ") + selectionSet := fmt.Sprintf("%v", node.SelectionSet) + // Anonymous queries with no directives or variable definitions can use + // the query short form. + str := "" + if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery { + str = selectionSet + } else { + str = join([]string{ + op, + join([]string{name, varDefs}, ""), + directives, + selectionSet, + }, " ") + } + return visitor.ActionUpdate, str + case map[string]interface{}: + + op := getMapValueString(node, "Operation") + name := getMapValueString(node, "Name") + + varDefs := wrap("(", join(toSliceString(getMapValue(node, "VariableDefinitions")), ", "), ")") + directives := join(toSliceString(getMapValue(node, "Directives")), " ") + selectionSet := getMapValueString(node, "SelectionSet") + str := "" + if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery { + str = selectionSet + } else { + str = join([]string{ + op, + join([]string{name, varDefs}, ""), + directives, + selectionSet, + }, " ") + } + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "VariableDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.VariableDefinition: + variable := fmt.Sprintf("%v", node.Variable) + ttype := fmt.Sprintf("%v", node.Type) + defaultValue := fmt.Sprintf("%v", node.DefaultValue) + + return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "") + case map[string]interface{}: + + variable := getMapValueString(node, "Variable") + ttype := getMapValueString(node, "Type") + defaultValue := getMapValueString(node, "DefaultValue") + + return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "") + + } + return visitor.ActionNoChange, nil + }, + "SelectionSet": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.SelectionSet: + str := block(node.Selections) + return visitor.ActionUpdate, str + case map[string]interface{}: + selections := getMapValue(node, "Selections") + str := block(selections) + return visitor.ActionUpdate, str + + } + return visitor.ActionNoChange, nil + }, + "Field": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Argument: + name := fmt.Sprintf("%v", node.Name) + value := fmt.Sprintf("%v", node.Value) + return visitor.ActionUpdate, name + ": " + value + case map[string]interface{}: + + alias := getMapValueString(node, "Alias") + name := getMapValueString(node, "Name") + args := toSliceString(getMapValue(node, "Arguments")) + directives := toSliceString(getMapValue(node, "Directives")) + selectionSet := getMapValueString(node, "SelectionSet") + + str := join( + []string{ + wrap("", alias, ": ") + name + wrap("(", join(args, ", "), ")"), + join(directives, " "), + selectionSet, + }, + " ", + ) + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "Argument": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.FragmentSpread: + name := fmt.Sprintf("%v", node.Name) + directives := toSliceString(node.Directives) + return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "") + case map[string]interface{}: + name := getMapValueString(node, "Name") + value := getMapValueString(node, "Value") + return visitor.ActionUpdate, name + ": " + value + } + return visitor.ActionNoChange, nil + }, + + // Fragments + "FragmentSpread": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.InlineFragment: + typeCondition := fmt.Sprintf("%v", node.TypeCondition) + directives := toSliceString(node.Directives) + selectionSet := fmt.Sprintf("%v", node.SelectionSet) + return visitor.ActionUpdate, "... on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet + case map[string]interface{}: + name := getMapValueString(node, "Name") + directives := toSliceString(getMapValue(node, "Directives")) + return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "") + } + return visitor.ActionNoChange, nil + }, + "InlineFragment": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case map[string]interface{}: + typeCondition := getMapValueString(node, "TypeCondition") + directives := toSliceString(getMapValue(node, "Directives")) + selectionSet := getMapValueString(node, "SelectionSet") + return visitor.ActionUpdate, + join([]string{ + "...", + wrap("on ", typeCondition, ""), + join(directives, " "), + selectionSet, + }, " ") + } + return visitor.ActionNoChange, nil + }, + "FragmentDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.FragmentDefinition: + name := fmt.Sprintf("%v", node.Name) + typeCondition := fmt.Sprintf("%v", node.TypeCondition) + directives := toSliceString(node.Directives) + selectionSet := fmt.Sprintf("%v", node.SelectionSet) + return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet + case map[string]interface{}: + name := getMapValueString(node, "Name") + typeCondition := getMapValueString(node, "TypeCondition") + directives := toSliceString(getMapValue(node, "Directives")) + selectionSet := getMapValueString(node, "SelectionSet") + return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet + } + return visitor.ActionNoChange, nil + }, + + // Value + "IntValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.IntValue: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Value") + } + return visitor.ActionNoChange, nil + }, + "FloatValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.FloatValue: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Value") + } + return visitor.ActionNoChange, nil + }, + "StringValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.StringValue: + return visitor.ActionUpdate, `"` + fmt.Sprintf("%v", node.Value) + `"` + case map[string]interface{}: + return visitor.ActionUpdate, `"` + getMapValueString(node, "Value") + `"` + } + return visitor.ActionNoChange, nil + }, + "BooleanValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.BooleanValue: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Value") + } + return visitor.ActionNoChange, nil + }, + "EnumValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.EnumValue: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Value") + } + return visitor.ActionNoChange, nil + }, + "ListValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.ListValue: + return visitor.ActionUpdate, "[" + join(toSliceString(node.Values), ", ") + "]" + case map[string]interface{}: + return visitor.ActionUpdate, "[" + join(toSliceString(getMapValue(node, "Values")), ", ") + "]" + } + return visitor.ActionNoChange, nil + }, + "ObjectValue": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.ObjectValue: + return visitor.ActionUpdate, "{" + join(toSliceString(node.Fields), ", ") + "}" + case map[string]interface{}: + return visitor.ActionUpdate, "{" + join(toSliceString(getMapValue(node, "Fields")), ", ") + "}" + } + return visitor.ActionNoChange, nil + }, + "ObjectField": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.ObjectField: + name := fmt.Sprintf("%v", node.Name) + value := fmt.Sprintf("%v", node.Value) + return visitor.ActionUpdate, name + ": " + value + case map[string]interface{}: + name := getMapValueString(node, "Name") + value := getMapValueString(node, "Value") + return visitor.ActionUpdate, name + ": " + value + } + return visitor.ActionNoChange, nil + }, + + // Directive + "Directive": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Directive: + name := fmt.Sprintf("%v", node.Name) + args := toSliceString(node.Arguments) + return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")") + case map[string]interface{}: + name := getMapValueString(node, "Name") + args := toSliceString(getMapValue(node, "Arguments")) + return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")") + } + return visitor.ActionNoChange, nil + }, + + // Type + "Named": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.Named: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Name) + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Name") + } + return visitor.ActionNoChange, nil + }, + "List": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.List: + return visitor.ActionUpdate, "[" + fmt.Sprintf("%v", node.Type) + "]" + case map[string]interface{}: + return visitor.ActionUpdate, "[" + getMapValueString(node, "Type") + "]" + } + return visitor.ActionNoChange, nil + }, + "NonNull": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.NonNull: + return visitor.ActionUpdate, fmt.Sprintf("%v", node.Type) + "!" + case map[string]interface{}: + return visitor.ActionUpdate, getMapValueString(node, "Type") + "!" + } + return visitor.ActionNoChange, nil + }, + + // Type System Definitions + "SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.SchemaDefinition: + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "schema", + join(directives, " "), + block(node.OperationTypes), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + operationTypes := toSliceString(getMapValue(node, "OperationTypes")) + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "schema", + join(directives, " "), + block(operationTypes), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "OperationTypeDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.OperationTypeDefinition: + str := fmt.Sprintf("%v: %v", node.Operation, node.Type) + return visitor.ActionUpdate, str + case map[string]interface{}: + operation := getMapValueString(node, "Operation") + ttype := getMapValueString(node, "Type") + str := fmt.Sprintf("%v: %v", operation, ttype) + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.ScalarDefinition: + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "scalar", + fmt.Sprintf("%v", node.Name), + join(directives, " "), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "scalar", + name, + join(directives, " "), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "ObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.ObjectDefinition: + name := fmt.Sprintf("%v", node.Name) + interfaces := toSliceString(node.Interfaces) + fields := node.Fields + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "type", + name, + wrap("implements ", join(interfaces, ", "), ""), + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + interfaces := toSliceString(getMapValue(node, "Interfaces")) + fields := getMapValue(node, "Fields") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "type", + name, + wrap("implements ", join(interfaces, ", "), ""), + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "FieldDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.FieldDefinition: + name := fmt.Sprintf("%v", node.Name) + ttype := fmt.Sprintf("%v", node.Type) + args := toSliceString(node.Arguments) + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := name + wrap("(", join(args, ", "), ")") + ": " + ttype + wrap(" ", join(directives, " "), "") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + ttype := getMapValueString(node, "Type") + args := toSliceString(getMapValue(node, "Arguments")) + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := name + wrap("(", join(args, ", "), ")") + ": " + ttype + wrap(" ", join(directives, " "), "") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "InputValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.InputValueDefinition: + name := fmt.Sprintf("%v", node.Name) + ttype := fmt.Sprintf("%v", node.Type) + defaultValue := fmt.Sprintf("%v", node.DefaultValue) + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + name + ": " + ttype, + wrap("= ", defaultValue, ""), + join(directives, " "), + }, " ") + + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + ttype := getMapValueString(node, "Type") + defaultValue := getMapValueString(node, "DefaultValue") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + name + ": " + ttype, + wrap("= ", defaultValue, ""), + join(directives, " "), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "InterfaceDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.InterfaceDefinition: + name := fmt.Sprintf("%v", node.Name) + fields := node.Fields + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "interface", + name, + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + fields := getMapValue(node, "Fields") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "interface", + name, + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "UnionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.UnionDefinition: + name := fmt.Sprintf("%v", node.Name) + types := toSliceString(node.Types) + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "union", + name, + join(directives, " "), + "= " + join(types, " | "), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + types := toSliceString(getMapValue(node, "Types")) + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "union", + name, + join(directives, " "), + "= " + join(types, " | "), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "EnumDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.EnumDefinition: + name := fmt.Sprintf("%v", node.Name) + values := node.Values + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "enum", + name, + join(directives, " "), + block(values), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + values := getMapValue(node, "Values") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "enum", + name, + join(directives, " "), + block(values), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "EnumValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.EnumValueDefinition: + name := fmt.Sprintf("%v", node.Name) + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + name, + join(directives, " "), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + name, + join(directives, " "), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "InputObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.InputObjectDefinition: + name := fmt.Sprintf("%v", node.Name) + fields := node.Fields + directives := []string{} + for _, directive := range node.Directives { + directives = append(directives, fmt.Sprintf("%v", directive.Name)) + } + str := join([]string{ + "input", + name, + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + fields := getMapValue(node, "Fields") + directives := []string{} + for _, directive := range getMapSliceValue(node, "Directives") { + directives = append(directives, fmt.Sprintf("%v", directive)) + } + str := join([]string{ + "input", + name, + join(directives, " "), + block(fields), + }, " ") + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "TypeExtensionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.TypeExtensionDefinition: + definition := fmt.Sprintf("%v", node.Definition) + str := "extend " + definition + return visitor.ActionUpdate, str + case map[string]interface{}: + definition := getMapValueString(node, "Definition") + str := "extend " + definition + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "DirectiveDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + switch node := p.Node.(type) { + case *ast.DirectiveDefinition: + args := wrap("(", join(toSliceString(node.Arguments), ", "), ")") + str := fmt.Sprintf("directive @%v%v on %v", node.Name, args, join(toSliceString(node.Locations), " | ")) + return visitor.ActionUpdate, str + case map[string]interface{}: + name := getMapValueString(node, "Name") + locations := toSliceString(getMapValue(node, "Locations")) + args := toSliceString(getMapValue(node, "Arguments")) + argsStr := wrap("(", join(args, ", "), ")") + str := fmt.Sprintf("directive @%v%v on %v", name, argsStr, join(locations, " | ")) + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, +} + +func Print(astNode ast.Node) (printed interface{}) { + defer func() interface{} { + if r := recover(); r != nil { + return fmt.Sprintf("%v", astNode) + } + return printed + }() + printed = visitor.Visit(astNode, &visitor.VisitorOptions{ + LeaveKindMap: printDocASTReducer, + }, nil) + return printed +} diff --git a/vendor/github.com/graphql-go/graphql/language/source/source.go b/vendor/github.com/graphql-go/graphql/language/source/source.go new file mode 100644 index 00000000..f14af003 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/source/source.go @@ -0,0 +1,20 @@ +package source + +const ( + name = "GraphQL" +) + +type Source struct { + Body []byte + Name string +} + +func NewSource(s *Source) *Source { + if s == nil { + s = &Source{Name: name} + } + if s.Name == "" { + s.Name = name + } + return s +} diff --git a/vendor/github.com/graphql-go/graphql/language/typeInfo/type_info.go b/vendor/github.com/graphql-go/graphql/language/typeInfo/type_info.go new file mode 100644 index 00000000..e012ee02 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/typeInfo/type_info.go @@ -0,0 +1,11 @@ +package typeInfo + +import ( + "github.com/graphql-go/graphql/language/ast" +) + +// TypeInfoI defines the interface for TypeInfo Implementation +type TypeInfoI interface { + Enter(node ast.Node) + Leave(node ast.Node) +} diff --git a/vendor/github.com/graphql-go/graphql/language/visitor/visitor.go b/vendor/github.com/graphql-go/graphql/language/visitor/visitor.go new file mode 100644 index 00000000..9a1c2ac2 --- /dev/null +++ b/vendor/github.com/graphql-go/graphql/language/visitor/visitor.go @@ -0,0 +1,873 @@ +package visitor + +import ( + "encoding/json" + "fmt" + "github.com/graphql-go/graphql/language/ast" + "github.com/graphql-go/graphql/language/typeInfo" + "reflect" +) + +const ( + ActionNoChange = "" + ActionBreak = "BREAK" + ActionSkip = "SKIP" + ActionUpdate = "UPDATE" +) + +type KeyMap map[string][]string + +// note that the keys are in Capital letters, equivalent to the ast.Node field Names +var QueryDocumentKeys = KeyMap{ + "Name": []string{}, + "Document": []string{"Definitions"}, + "OperationDefinition": []string{ + "Name", + "VariableDefinitions", + "Directives", + "SelectionSet", + }, + "VariableDefinition": []string{ + "Variable", + "Type", + "DefaultValue", + }, + "Variable": []string{"Name"}, + "SelectionSet": []string{"Selections"}, + "Field": []string{ + "Alias", + "Name", + "Arguments", + "Directives", + "SelectionSet", + }, + "Argument": []string{ + "Name", + "Value", + }, + + "FragmentSpread": []string{ + "Name", + "Directives", + }, + "InlineFragment": []string{ + "TypeCondition", + "Directives", + "SelectionSet", + }, + "FragmentDefinition": []string{ + "Name", + "TypeCondition", + "Directives", + "SelectionSet", + }, + + "IntValue": []string{}, + "FloatValue": []string{}, + "StringValue": []string{}, + "BooleanValue": []string{}, + "EnumValue": []string{}, + "ListValue": []string{"Values"}, + "ObjectValue": []string{"Fields"}, + "ObjectField": []string{ + "Name", + "Value", + }, + + "Directive": []string{ + "Name", + "Arguments", + }, + + "Named": []string{"Name"}, + "List": []string{"Type"}, + "NonNull": []string{"Type"}, + + "SchemaDefinition": []string{ + "Directives", + "OperationTypes", + }, + "OperationTypeDefinition": []string{"Type"}, + + "ScalarDefinition": []string{ + "Name", + "Directives", + }, + "ObjectDefinition": []string{ + "Name", + "Interfaces", + "Directives", + "Fields", + }, + "FieldDefinition": []string{ + "Name", + "Arguments", + "Type", + "Directives", + }, + "InputValueDefinition": []string{ + "Name", + "Type", + "DefaultValue", + "Directives", + }, + "InterfaceDefinition": []string{ + "Name", + "Directives", + "Fields", + }, + "UnionDefinition": []string{ + "Name", + "Directives", + "Types", + }, + "EnumDefinition": []string{ + "Name", + "Directives", + "Values", + }, + "EnumValueDefinition": []string{ + "Name", + "Directives", + }, + "InputObjectDefinition": []string{ + "Name", + "Directives", + "Fields", + }, + + "TypeExtensionDefinition": []string{"Definition"}, + + "DirectiveDefinition": []string{"Name", "Arguments", "Locations"}, +} + +type stack struct { + Index int + Keys []interface{} + Edits []*edit + inSlice bool + Prev *stack +} +type edit struct { + Key interface{} + Value interface{} +} + +type VisitFuncParams struct { + Node interface{} + Key interface{} + Parent ast.Node + Path []interface{} + Ancestors []ast.Node +} + +type VisitFunc func(p VisitFuncParams) (string, interface{}) + +type NamedVisitFuncs struct { + Kind VisitFunc // 1) Named visitors triggered when entering a node a specific kind. + Leave VisitFunc // 2) Named visitors that trigger upon entering and leaving a node of + Enter VisitFunc // 2) Named visitors that trigger upon entering and leaving a node of +} + +type VisitorOptions struct { + KindFuncMap map[string]NamedVisitFuncs + Enter VisitFunc // 3) Generic visitors that trigger upon entering and leaving any node. + Leave VisitFunc // 3) Generic visitors that trigger upon entering and leaving any node. + + EnterKindMap map[string]VisitFunc // 4) Parallel visitors for entering and leaving nodes of a specific kind + LeaveKindMap map[string]VisitFunc // 4) Parallel visitors for entering and leaving nodes of a specific kind +} + +func Visit(root ast.Node, visitorOpts *VisitorOptions, keyMap KeyMap) interface{} { + visitorKeys := keyMap + if visitorKeys == nil { + visitorKeys = QueryDocumentKeys + } + + var result interface{} + var newRoot = root + var sstack *stack + var parent interface{} + var parentSlice []interface{} + inSlice := false + prevInSlice := false + keys := []interface{}{newRoot} + index := -1 + edits := []*edit{} + path := []interface{}{} + ancestors := []interface{}{} + ancestorsSlice := [][]interface{}{} +Loop: + for { + index = index + 1 + + isLeaving := (len(keys) == index) + var key interface{} // string for structs or int for slices + var node interface{} // ast.Node or can be anything + var nodeSlice []interface{} + isEdited := (isLeaving && len(edits) != 0) + + if isLeaving { + if !inSlice { + if len(ancestors) == 0 { + key = nil + } else { + key, path = pop(path) + } + } else { + if len(ancestorsSlice) == 0 { + key = nil + } else { + key, path = pop(path) + } + } + + node = parent + parent, ancestors = pop(ancestors) + nodeSlice = parentSlice + parentSlice, ancestorsSlice = popNodeSlice(ancestorsSlice) + + if isEdited { + prevInSlice = inSlice + editOffset := 0 + for _, edit := range edits { + arrayEditKey := 0 + if inSlice { + keyInt := edit.Key.(int) + edit.Key = keyInt - editOffset + arrayEditKey = edit.Key.(int) + } + if inSlice && isNilNode(edit.Value) { + nodeSlice = spliceNode(nodeSlice, arrayEditKey) + editOffset = editOffset + 1 + } else { + if inSlice { + nodeSlice[arrayEditKey] = edit.Value + } else { + key, _ := edit.Key.(string) + + var updatedNode interface{} + if !isSlice(edit.Value) { + if isStructNode(edit.Value) { + updatedNode = updateNodeField(node, key, edit.Value) + } else { + var todoNode map[string]interface{} + b, err := json.Marshal(node) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node: %v", root)) + } + err = json.Unmarshal(b, &todoNode) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node (2): %v", root)) + } + todoNode[key] = edit.Value + updatedNode = todoNode + } + } else { + isSliceOfNodes := true + + // check if edit.value slice is ast.nodes + switch reflect.TypeOf(edit.Value).Kind() { + case reflect.Slice: + s := reflect.ValueOf(edit.Value) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + if !isStructNode(elem.Interface()) { + isSliceOfNodes = false + } + } + } + + // is a slice of real nodes + if isSliceOfNodes { + // the node we are writing to is an ast.Node + updatedNode = updateNodeField(node, key, edit.Value) + } else { + var todoNode map[string]interface{} + b, err := json.Marshal(node) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node: %v", root)) + } + err = json.Unmarshal(b, &todoNode) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node (2): %v", root)) + } + todoNode[key] = edit.Value + updatedNode = todoNode + } + + } + node = updatedNode + } + } + } + } + index = sstack.Index + keys = sstack.Keys + edits = sstack.Edits + inSlice = sstack.inSlice + sstack = sstack.Prev + } else { + // get key + if !inSlice { + if !isNilNode(parent) { + key = getFieldValue(keys, index) + } else { + // initial conditions + key = nil + } + } else { + key = index + } + // get node + if !inSlice { + if !isNilNode(parent) { + fieldValue := getFieldValue(parent, key) + if isNode(fieldValue) { + node = fieldValue.(ast.Node) + } + if isSlice(fieldValue) { + nodeSlice = toSliceInterfaces(fieldValue) + } + } else { + // initial conditions + node = newRoot + } + } else { + if len(parentSlice) != 0 { + fieldValue := getFieldValue(parentSlice, key) + if isNode(fieldValue) { + node = fieldValue.(ast.Node) + } + if isSlice(fieldValue) { + nodeSlice = toSliceInterfaces(fieldValue) + } + } else { + // initial conditions + nodeSlice = []interface{}{} + } + } + + if isNilNode(node) && len(nodeSlice) == 0 { + continue + } + + if !inSlice { + if !isNilNode(parent) { + path = append(path, key) + } + } else { + if len(parentSlice) != 0 { + path = append(path, key) + } + } + } + + // get result from visitFn for a node if set + var result interface{} + resultIsUndefined := true + if !isNilNode(node) { + if !isNode(node) { // is node-ish. + panic(fmt.Sprintf("Invalid AST Node (4): %v", node)) + } + + // Try to pass in current node as ast.Node + // Note that since user can potentially return a non-ast.Node from visit functions. + // In that case, we try to unmarshal map[string]interface{} into ast.Node + var nodeIn interface{} + if _, ok := node.(map[string]interface{}); ok { + b, err := json.Marshal(node) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node: %v", root)) + } + err = json.Unmarshal(b, &nodeIn) + if err != nil { + panic(fmt.Sprintf("Invalid root AST Node (2a): %v", root)) + } + } else { + nodeIn = node + } + parentConcrete, _ := parent.(ast.Node) + // ancestorsConcrete slice may contain nil values + ancestorsConcrete := []ast.Node{} + for _, ancestor := range ancestors { + if ancestorConcrete, ok := ancestor.(ast.Node); ok { + ancestorsConcrete = append(ancestorsConcrete, ancestorConcrete) + } else { + ancestorsConcrete = append(ancestorsConcrete, nil) + } + } + + kind := "" + if node, ok := node.(map[string]interface{}); ok { + kind, _ = node["Kind"].(string) + } + if node, ok := node.(ast.Node); ok { + kind = node.GetKind() + } + + visitFn := GetVisitFn(visitorOpts, kind, isLeaving) + if visitFn != nil { + p := VisitFuncParams{ + Node: nodeIn, + Key: key, + Parent: parentConcrete, + Path: path, + Ancestors: ancestorsConcrete, + } + action := ActionUpdate + action, result = visitFn(p) + if action == ActionBreak { + break Loop + } + if action == ActionSkip { + if !isLeaving { + _, path = pop(path) + continue + } + } + if action != ActionNoChange { + resultIsUndefined = false + edits = append(edits, &edit{ + Key: key, + Value: result, + }) + if !isLeaving { + if isNode(result) { + node = result + } else { + _, path = pop(path) + continue + } + } + } else { + resultIsUndefined = true + } + } + + } + + // collect back edits on the way out + if resultIsUndefined && isEdited { + if !prevInSlice { + edits = append(edits, &edit{ + Key: key, + Value: node, + }) + } else { + edits = append(edits, &edit{ + Key: key, + Value: nodeSlice, + }) + } + } + if !isLeaving { + + // add to stack + prevStack := sstack + sstack = &stack{ + inSlice: inSlice, + Index: index, + Keys: keys, + Edits: edits, + Prev: prevStack, + } + + // replace keys + inSlice = false + if len(nodeSlice) > 0 { + inSlice = true + } + keys = []interface{}{} + + if inSlice { + // get keys + for _, m := range nodeSlice { + keys = append(keys, m) + } + } else { + if !isNilNode(node) { + if node, ok := node.(ast.Node); ok { + kind := node.GetKind() + if n, ok := visitorKeys[kind]; ok { + for _, m := range n { + keys = append(keys, m) + } + } + } + + } + + } + index = -1 + edits = []*edit{} + + ancestors = append(ancestors, parent) + parent = node + ancestorsSlice = append(ancestorsSlice, parentSlice) + parentSlice = nodeSlice + + } + + // loop guard + if sstack == nil { + break Loop + } + } + if len(edits) != 0 { + result = edits[len(edits)-1].Value + } + return result +} + +func pop(a []interface{}) (x interface{}, aa []interface{}) { + if len(a) == 0 { + return x, aa + } + x, aa = a[len(a)-1], a[:len(a)-1] + return x, aa +} +func popNodeSlice(a [][]interface{}) (x []interface{}, aa [][]interface{}) { + if len(a) == 0 { + return x, aa + } + x, aa = a[len(a)-1], a[:len(a)-1] + return x, aa +} +func spliceNode(a interface{}, i int) (result []interface{}) { + if i < 0 { + return result + } + typeOf := reflect.TypeOf(a) + if typeOf == nil { + return result + } + switch typeOf.Kind() { + case reflect.Slice: + s := reflect.ValueOf(a) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + elemInterface := elem.Interface() + result = append(result, elemInterface) + } + if i >= s.Len() { + return result + } + return append(result[:i], result[i+1:]...) + default: + return result + } +} + +func getFieldValue(obj interface{}, key interface{}) interface{} { + val := reflect.ValueOf(obj) + if val.Type().Kind() == reflect.Ptr { + val = val.Elem() + } + if val.Type().Kind() == reflect.Struct { + key, ok := key.(string) + if !ok { + return nil + } + valField := val.FieldByName(key) + if valField.IsValid() { + return valField.Interface() + } + return nil + } + if val.Type().Kind() == reflect.Slice { + key, ok := key.(int) + if !ok { + return nil + } + if key >= val.Len() { + return nil + } + valField := val.Index(key) + if valField.IsValid() { + return valField.Interface() + } + return nil + } + if val.Type().Kind() == reflect.Map { + keyVal := reflect.ValueOf(key) + valField := val.MapIndex(keyVal) + if valField.IsValid() { + return valField.Interface() + } + return nil + } + return nil +} + +func updateNodeField(value interface{}, fieldName string, fieldValue interface{}) (retVal interface{}) { + retVal = value + val := reflect.ValueOf(value) + + isPtr := false + if val.IsValid() && val.Type().Kind() == reflect.Ptr { + val = val.Elem() + isPtr = true + } + if !val.IsValid() { + return retVal + } + if val.Type().Kind() == reflect.Struct { + for i := 0; i < val.NumField(); i++ { + valueField := val.Field(i) + typeField := val.Type().Field(i) + + // try matching the field name + if typeField.Name == fieldName { + fieldValueVal := reflect.ValueOf(fieldValue) + if valueField.CanSet() { + + if fieldValueVal.IsValid() { + if valueField.Type().Kind() == fieldValueVal.Type().Kind() { + if fieldValueVal.Type().Kind() == reflect.Slice { + newSliceValue := reflect.MakeSlice(reflect.TypeOf(valueField.Interface()), fieldValueVal.Len(), fieldValueVal.Len()) + for i := 0; i < newSliceValue.Len(); i++ { + dst := newSliceValue.Index(i) + src := fieldValueVal.Index(i) + srcValue := reflect.ValueOf(src.Interface()) + if dst.CanSet() { + dst.Set(srcValue) + } + } + valueField.Set(newSliceValue) + + } else { + valueField.Set(fieldValueVal) + } + } + } else { + valueField.Set(reflect.New(valueField.Type()).Elem()) + } + if isPtr == true { + retVal = val.Addr().Interface() + return retVal + } + retVal = val.Interface() + return retVal + + } + } + } + } + return retVal +} +func toSliceInterfaces(slice interface{}) (result []interface{}) { + switch reflect.TypeOf(slice).Kind() { + case reflect.Slice: + s := reflect.ValueOf(slice) + for i := 0; i < s.Len(); i++ { + elem := s.Index(i) + elemInterface := elem.Interface() + if elem, ok := elemInterface.(ast.Node); ok { + result = append(result, elem) + } + } + return result + default: + return result + } +} + +func isSlice(value interface{}) bool { + val := reflect.ValueOf(value) + if val.IsValid() && val.Type().Kind() == reflect.Slice { + return true + } + return false +} +func isNode(node interface{}) bool { + val := reflect.ValueOf(node) + if val.IsValid() && val.Type().Kind() == reflect.Ptr { + val = val.Elem() + } + if !val.IsValid() { + return false + } + if val.Type().Kind() == reflect.Map { + keyVal := reflect.ValueOf("Kind") + valField := val.MapIndex(keyVal) + return valField.IsValid() + } + if val.Type().Kind() == reflect.Struct { + valField := val.FieldByName("Kind") + return valField.IsValid() + } + return false +} +func isStructNode(node interface{}) bool { + val := reflect.ValueOf(node) + if val.IsValid() && val.Type().Kind() == reflect.Ptr { + val = val.Elem() + } + if !val.IsValid() { + return false + } + if val.Type().Kind() == reflect.Struct { + valField := val.FieldByName("Kind") + return valField.IsValid() + } + return false +} + +func isNilNode(node interface{}) bool { + val := reflect.ValueOf(node) + if !val.IsValid() { + return true + } + if val.Type().Kind() == reflect.Ptr { + return val.IsNil() + } + if val.Type().Kind() == reflect.Slice { + return val.Len() == 0 + } + if val.Type().Kind() == reflect.Map { + return val.Len() == 0 + } + if val.Type().Kind() == reflect.Bool { + return val.Interface().(bool) + } + return val.Interface() == nil +} + +// VisitInParallel Creates a new visitor instance which delegates to many visitors to run in +// parallel. Each visitor will be visited for each node before moving on. +// +// If a prior visitor edits a node, no following visitors will see that node. +func VisitInParallel(visitorOptsSlice ...*VisitorOptions) *VisitorOptions { + skipping := map[int]interface{}{} + + return &VisitorOptions{ + Enter: func(p VisitFuncParams) (string, interface{}) { + for i, visitorOpts := range visitorOptsSlice { + if _, ok := skipping[i]; !ok { + switch node := p.Node.(type) { + case ast.Node: + kind := node.GetKind() + fn := GetVisitFn(visitorOpts, kind, false) + if fn != nil { + action, result := fn(p) + if action == ActionSkip { + skipping[i] = node + } else if action == ActionBreak { + skipping[i] = ActionBreak + } else if action == ActionUpdate { + return ActionUpdate, result + } + } + } + } + } + return ActionNoChange, nil + }, + Leave: func(p VisitFuncParams) (string, interface{}) { + for i, visitorOpts := range visitorOptsSlice { + skippedNode, ok := skipping[i] + if !ok { + switch node := p.Node.(type) { + case ast.Node: + kind := node.GetKind() + fn := GetVisitFn(visitorOpts, kind, true) + if fn != nil { + action, result := fn(p) + if action == ActionBreak { + skipping[i] = ActionBreak + } else if action == ActionUpdate { + return ActionUpdate, result + } + } + } + } else if skippedNode == p.Node { + delete(skipping, i) + } + } + return ActionNoChange, nil + }, + } +} + +// VisitWithTypeInfo Creates a new visitor instance which maintains a provided TypeInfo instance +// along with visiting visitor. +func VisitWithTypeInfo(ttypeInfo typeInfo.TypeInfoI, visitorOpts *VisitorOptions) *VisitorOptions { + return &VisitorOptions{ + Enter: func(p VisitFuncParams) (string, interface{}) { + if node, ok := p.Node.(ast.Node); ok { + ttypeInfo.Enter(node) + fn := GetVisitFn(visitorOpts, node.GetKind(), false) + if fn != nil { + action, result := fn(p) + if action == ActionUpdate { + ttypeInfo.Leave(node) + if isNode(result) { + if result, ok := result.(ast.Node); ok { + ttypeInfo.Enter(result) + } + } + } + return action, result + } + } + return ActionNoChange, nil + }, + Leave: func(p VisitFuncParams) (string, interface{}) { + action := ActionNoChange + var result interface{} + if node, ok := p.Node.(ast.Node); ok { + fn := GetVisitFn(visitorOpts, node.GetKind(), true) + if fn != nil { + action, result = fn(p) + } + ttypeInfo.Leave(node) + } + return action, result + }, + } +} + +// GetVisitFn Given a visitor instance, if it is leaving or not, and a node kind, return +// the function the visitor runtime should call. +func GetVisitFn(visitorOpts *VisitorOptions, kind string, isLeaving bool) VisitFunc { + if visitorOpts == nil { + return nil + } + kindVisitor, ok := visitorOpts.KindFuncMap[kind] + if ok { + if !isLeaving && kindVisitor.Kind != nil { + // { Kind() {} } + return kindVisitor.Kind + } + if isLeaving { + // { Kind: { leave() {} } } + return kindVisitor.Leave + } + // { Kind: { enter() {} } } + return kindVisitor.Enter + + } + if isLeaving { + // { enter() {} } + specificVisitor := visitorOpts.Leave + if specificVisitor != nil { + return specificVisitor + } + if specificKindVisitor, ok := visitorOpts.LeaveKindMap[kind]; ok { + // { leave: { Kind() {} } } + return specificKindVisitor + } + + } + // { leave() {} } + specificVisitor := visitorOpts.Enter + if specificVisitor != nil { + return specificVisitor + } + if specificKindVisitor, ok := visitorOpts.EnterKindMap[kind]; ok { + // { enter: { Kind() {} } } + return specificKindVisitor + } + return nil +} |