...

Source file src/github.com/vektah/gqlparser/parser/schema.go

Documentation: github.com/vektah/gqlparser/parser

     1  package parser
     2  
     3  import (
     4  	. "github.com/vektah/gqlparser/ast"
     5  	"github.com/vektah/gqlparser/gqlerror"
     6  	"github.com/vektah/gqlparser/lexer"
     7  )
     8  
     9  func ParseSchema(source *Source) (*SchemaDocument, *gqlerror.Error) {
    10  	p := parser{
    11  		lexer: lexer.New(source),
    12  	}
    13  	ast, err := p.parseSchemaDocument(), p.err
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  
    18  	for _, def := range ast.Definitions {
    19  		def.BuiltIn = source.BuiltIn
    20  	}
    21  	for _, def := range ast.Extensions {
    22  		def.BuiltIn = source.BuiltIn
    23  	}
    24  
    25  	return ast, nil
    26  }
    27  
    28  func ParseSchemas(inputs ...*Source) (*SchemaDocument, *gqlerror.Error) {
    29  	ast := &SchemaDocument{}
    30  	for _, input := range inputs {
    31  		inputAst, err := ParseSchema(input)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  		ast.Merge(inputAst)
    36  	}
    37  	return ast, nil
    38  }
    39  
    40  func (p *parser) parseSchemaDocument() *SchemaDocument {
    41  	var doc SchemaDocument
    42  	doc.Position = p.peekPos()
    43  	for p.peek().Kind != lexer.EOF {
    44  		if p.err != nil {
    45  			return nil
    46  		}
    47  
    48  		var description string
    49  		if p.peek().Kind == lexer.BlockString || p.peek().Kind == lexer.String {
    50  			description = p.parseDescription()
    51  		}
    52  
    53  		if p.peek().Kind != lexer.Name {
    54  			p.unexpectedError()
    55  			break
    56  		}
    57  
    58  		switch p.peek().Value {
    59  		case "scalar", "type", "interface", "union", "enum", "input":
    60  			doc.Definitions = append(doc.Definitions, p.parseTypeSystemDefinition(description))
    61  		case "schema":
    62  			doc.Schema = append(doc.Schema, p.parseSchemaDefinition(description))
    63  		case "directive":
    64  			doc.Directives = append(doc.Directives, p.parseDirectiveDefinition(description))
    65  		case "extend":
    66  			if description != "" {
    67  				p.unexpectedToken(p.prev)
    68  			}
    69  			p.parseTypeSystemExtension(&doc)
    70  		default:
    71  			p.unexpectedError()
    72  			return nil
    73  		}
    74  	}
    75  
    76  	return &doc
    77  }
    78  
    79  func (p *parser) parseDescription() string {
    80  	token := p.peek()
    81  
    82  	if token.Kind != lexer.BlockString && token.Kind != lexer.String {
    83  		return ""
    84  	}
    85  
    86  	return p.next().Value
    87  }
    88  
    89  func (p *parser) parseTypeSystemDefinition(description string) *Definition {
    90  	tok := p.peek()
    91  	if tok.Kind != lexer.Name {
    92  		p.unexpectedError()
    93  		return nil
    94  	}
    95  
    96  	switch tok.Value {
    97  	case "scalar":
    98  		return p.parseScalarTypeDefinition(description)
    99  	case "type":
   100  		return p.parseObjectTypeDefinition(description)
   101  	case "interface":
   102  		return p.parseInterfaceTypeDefinition(description)
   103  	case "union":
   104  		return p.parseUnionTypeDefinition(description)
   105  	case "enum":
   106  		return p.parseEnumTypeDefinition(description)
   107  	case "input":
   108  		return p.parseInputObjectTypeDefinition(description)
   109  	default:
   110  		p.unexpectedError()
   111  		return nil
   112  	}
   113  }
   114  
   115  func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition {
   116  	p.expectKeyword("schema")
   117  
   118  	def := SchemaDefinition{Description: description}
   119  	def.Position = p.peekPos()
   120  	def.Description = description
   121  	def.Directives = p.parseDirectives(true)
   122  
   123  	p.some(lexer.BraceL, lexer.BraceR, func() {
   124  		def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition())
   125  	})
   126  	return &def
   127  }
   128  
   129  func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition {
   130  	var op OperationTypeDefinition
   131  	op.Position = p.peekPos()
   132  	op.Operation = p.parseOperationType()
   133  	p.expect(lexer.Colon)
   134  	op.Type = p.parseName()
   135  	return &op
   136  }
   137  
   138  func (p *parser) parseScalarTypeDefinition(description string) *Definition {
   139  	p.expectKeyword("scalar")
   140  
   141  	var def Definition
   142  	def.Position = p.peekPos()
   143  	def.Kind = Scalar
   144  	def.Description = description
   145  	def.Name = p.parseName()
   146  	def.Directives = p.parseDirectives(true)
   147  	return &def
   148  }
   149  
   150  func (p *parser) parseObjectTypeDefinition(description string) *Definition {
   151  	p.expectKeyword("type")
   152  
   153  	var def Definition
   154  	def.Position = p.peekPos()
   155  	def.Kind = Object
   156  	def.Description = description
   157  	def.Name = p.parseName()
   158  	def.Interfaces = p.parseImplementsInterfaces()
   159  	def.Directives = p.parseDirectives(true)
   160  	def.Fields = p.parseFieldsDefinition()
   161  	return &def
   162  }
   163  
   164  func (p *parser) parseImplementsInterfaces() []string {
   165  	var types []string
   166  	if p.peek().Value == "implements" {
   167  		p.next()
   168  		// optional leading ampersand
   169  		p.skip(lexer.Amp)
   170  
   171  		types = append(types, p.parseName())
   172  		for p.skip(lexer.Amp) && p.err == nil {
   173  			types = append(types, p.parseName())
   174  		}
   175  	}
   176  	return types
   177  }
   178  
   179  func (p *parser) parseFieldsDefinition() FieldList {
   180  	var defs FieldList
   181  	p.some(lexer.BraceL, lexer.BraceR, func() {
   182  		defs = append(defs, p.parseFieldDefinition())
   183  	})
   184  	return defs
   185  }
   186  
   187  func (p *parser) parseFieldDefinition() *FieldDefinition {
   188  	var def FieldDefinition
   189  	def.Position = p.peekPos()
   190  	def.Description = p.parseDescription()
   191  	def.Name = p.parseName()
   192  	def.Arguments = p.parseArgumentDefs()
   193  	p.expect(lexer.Colon)
   194  	def.Type = p.parseTypeReference()
   195  	def.Directives = p.parseDirectives(true)
   196  
   197  	return &def
   198  }
   199  
   200  func (p *parser) parseArgumentDefs() ArgumentDefinitionList {
   201  	var args ArgumentDefinitionList
   202  	p.some(lexer.ParenL, lexer.ParenR, func() {
   203  		args = append(args, p.parseArgumentDef())
   204  	})
   205  	return args
   206  }
   207  
   208  func (p *parser) parseArgumentDef() *ArgumentDefinition {
   209  	var def ArgumentDefinition
   210  	def.Position = p.peekPos()
   211  	def.Description = p.parseDescription()
   212  	def.Name = p.parseName()
   213  	p.expect(lexer.Colon)
   214  	def.Type = p.parseTypeReference()
   215  	if p.skip(lexer.Equals) {
   216  		def.DefaultValue = p.parseValueLiteral(true)
   217  	}
   218  	def.Directives = p.parseDirectives(true)
   219  	return &def
   220  }
   221  
   222  func (p *parser) parseInputValueDef() *FieldDefinition {
   223  	var def FieldDefinition
   224  	def.Position = p.peekPos()
   225  	def.Description = p.parseDescription()
   226  	def.Name = p.parseName()
   227  	p.expect(lexer.Colon)
   228  	def.Type = p.parseTypeReference()
   229  	if p.skip(lexer.Equals) {
   230  		def.DefaultValue = p.parseValueLiteral(true)
   231  	}
   232  	def.Directives = p.parseDirectives(true)
   233  	return &def
   234  }
   235  
   236  func (p *parser) parseInterfaceTypeDefinition(description string) *Definition {
   237  	p.expectKeyword("interface")
   238  
   239  	var def Definition
   240  	def.Position = p.peekPos()
   241  	def.Kind = Interface
   242  	def.Description = description
   243  	def.Name = p.parseName()
   244  	def.Directives = p.parseDirectives(true)
   245  	def.Fields = p.parseFieldsDefinition()
   246  	return &def
   247  }
   248  
   249  func (p *parser) parseUnionTypeDefinition(description string) *Definition {
   250  	p.expectKeyword("union")
   251  
   252  	var def Definition
   253  	def.Position = p.peekPos()
   254  	def.Kind = Union
   255  	def.Description = description
   256  	def.Name = p.parseName()
   257  	def.Directives = p.parseDirectives(true)
   258  	def.Types = p.parseUnionMemberTypes()
   259  	return &def
   260  }
   261  
   262  func (p *parser) parseUnionMemberTypes() []string {
   263  	var types []string
   264  	if p.skip(lexer.Equals) {
   265  		// optional leading pipe
   266  		p.skip(lexer.Pipe)
   267  
   268  		types = append(types, p.parseName())
   269  		for p.skip(lexer.Pipe) && p.err == nil {
   270  			types = append(types, p.parseName())
   271  		}
   272  	}
   273  	return types
   274  }
   275  
   276  func (p *parser) parseEnumTypeDefinition(description string) *Definition {
   277  	p.expectKeyword("enum")
   278  
   279  	var def Definition
   280  	def.Position = p.peekPos()
   281  	def.Kind = Enum
   282  	def.Description = description
   283  	def.Name = p.parseName()
   284  	def.Directives = p.parseDirectives(true)
   285  	def.EnumValues = p.parseEnumValuesDefinition()
   286  	return &def
   287  }
   288  
   289  func (p *parser) parseEnumValuesDefinition() EnumValueList {
   290  	var values EnumValueList
   291  	p.some(lexer.BraceL, lexer.BraceR, func() {
   292  		values = append(values, p.parseEnumValueDefinition())
   293  	})
   294  	return values
   295  }
   296  
   297  func (p *parser) parseEnumValueDefinition() *EnumValueDefinition {
   298  	return &EnumValueDefinition{
   299  		Position:    p.peekPos(),
   300  		Description: p.parseDescription(),
   301  		Name:        p.parseName(),
   302  		Directives:  p.parseDirectives(true),
   303  	}
   304  }
   305  
   306  func (p *parser) parseInputObjectTypeDefinition(description string) *Definition {
   307  	p.expectKeyword("input")
   308  
   309  	var def Definition
   310  	def.Position = p.peekPos()
   311  	def.Kind = InputObject
   312  	def.Description = description
   313  	def.Name = p.parseName()
   314  	def.Directives = p.parseDirectives(true)
   315  	def.Fields = p.parseInputFieldsDefinition()
   316  	return &def
   317  }
   318  
   319  func (p *parser) parseInputFieldsDefinition() FieldList {
   320  	var values FieldList
   321  	p.some(lexer.BraceL, lexer.BraceR, func() {
   322  		values = append(values, p.parseInputValueDef())
   323  	})
   324  	return values
   325  }
   326  
   327  func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) {
   328  	p.expectKeyword("extend")
   329  
   330  	switch p.peek().Value {
   331  	case "schema":
   332  		doc.SchemaExtension = append(doc.SchemaExtension, p.parseSchemaExtension())
   333  	case "scalar":
   334  		doc.Extensions = append(doc.Extensions, p.parseScalarTypeExtension())
   335  	case "type":
   336  		doc.Extensions = append(doc.Extensions, p.parseObjectTypeExtension())
   337  	case "interface":
   338  		doc.Extensions = append(doc.Extensions, p.parseInterfaceTypeExtension())
   339  	case "union":
   340  		doc.Extensions = append(doc.Extensions, p.parseUnionTypeExtension())
   341  	case "enum":
   342  		doc.Extensions = append(doc.Extensions, p.parseEnumTypeExtension())
   343  	case "input":
   344  		doc.Extensions = append(doc.Extensions, p.parseInputObjectTypeExtension())
   345  	default:
   346  		p.unexpectedError()
   347  	}
   348  }
   349  
   350  func (p *parser) parseSchemaExtension() *SchemaDefinition {
   351  	p.expectKeyword("schema")
   352  
   353  	var def SchemaDefinition
   354  	def.Position = p.peekPos()
   355  	def.Directives = p.parseDirectives(true)
   356  	p.some(lexer.BraceL, lexer.BraceR, func() {
   357  		def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition())
   358  	})
   359  	if len(def.Directives) == 0 && len(def.OperationTypes) == 0 {
   360  		p.unexpectedError()
   361  	}
   362  	return &def
   363  }
   364  
   365  func (p *parser) parseScalarTypeExtension() *Definition {
   366  	p.expectKeyword("scalar")
   367  
   368  	var def Definition
   369  	def.Position = p.peekPos()
   370  	def.Kind = Scalar
   371  	def.Name = p.parseName()
   372  	def.Directives = p.parseDirectives(true)
   373  	if len(def.Directives) == 0 {
   374  		p.unexpectedError()
   375  	}
   376  	return &def
   377  }
   378  
   379  func (p *parser) parseObjectTypeExtension() *Definition {
   380  	p.expectKeyword("type")
   381  
   382  	var def Definition
   383  	def.Position = p.peekPos()
   384  	def.Kind = Object
   385  	def.Name = p.parseName()
   386  	def.Interfaces = p.parseImplementsInterfaces()
   387  	def.Directives = p.parseDirectives(true)
   388  	def.Fields = p.parseFieldsDefinition()
   389  	if len(def.Interfaces) == 0 && len(def.Directives) == 0 && len(def.Fields) == 0 {
   390  		p.unexpectedError()
   391  	}
   392  	return &def
   393  }
   394  
   395  func (p *parser) parseInterfaceTypeExtension() *Definition {
   396  	p.expectKeyword("interface")
   397  
   398  	var def Definition
   399  	def.Position = p.peekPos()
   400  	def.Kind = Interface
   401  	def.Name = p.parseName()
   402  	def.Directives = p.parseDirectives(true)
   403  	def.Fields = p.parseFieldsDefinition()
   404  	if len(def.Directives) == 0 && len(def.Fields) == 0 {
   405  		p.unexpectedError()
   406  	}
   407  	return &def
   408  }
   409  
   410  func (p *parser) parseUnionTypeExtension() *Definition {
   411  	p.expectKeyword("union")
   412  
   413  	var def Definition
   414  	def.Position = p.peekPos()
   415  	def.Kind = Union
   416  	def.Name = p.parseName()
   417  	def.Directives = p.parseDirectives(true)
   418  	def.Types = p.parseUnionMemberTypes()
   419  
   420  	if len(def.Directives) == 0 && len(def.Types) == 0 {
   421  		p.unexpectedError()
   422  	}
   423  	return &def
   424  }
   425  
   426  func (p *parser) parseEnumTypeExtension() *Definition {
   427  	p.expectKeyword("enum")
   428  
   429  	var def Definition
   430  	def.Position = p.peekPos()
   431  	def.Kind = Enum
   432  	def.Name = p.parseName()
   433  	def.Directives = p.parseDirectives(true)
   434  	def.EnumValues = p.parseEnumValuesDefinition()
   435  	if len(def.Directives) == 0 && len(def.EnumValues) == 0 {
   436  		p.unexpectedError()
   437  	}
   438  	return &def
   439  }
   440  
   441  func (p *parser) parseInputObjectTypeExtension() *Definition {
   442  	p.expectKeyword("input")
   443  
   444  	var def Definition
   445  	def.Position = p.peekPos()
   446  	def.Kind = InputObject
   447  	def.Name = p.parseName()
   448  	def.Directives = p.parseDirectives(false)
   449  	def.Fields = p.parseInputFieldsDefinition()
   450  	if len(def.Directives) == 0 && len(def.Fields) == 0 {
   451  		p.unexpectedError()
   452  	}
   453  	return &def
   454  }
   455  
   456  func (p *parser) parseDirectiveDefinition(description string) *DirectiveDefinition {
   457  	p.expectKeyword("directive")
   458  	p.expect(lexer.At)
   459  
   460  	var def DirectiveDefinition
   461  	def.Position = p.peekPos()
   462  	def.Description = description
   463  	def.Name = p.parseName()
   464  	def.Arguments = p.parseArgumentDefs()
   465  
   466  	p.expectKeyword("on")
   467  	def.Locations = p.parseDirectiveLocations()
   468  	return &def
   469  }
   470  
   471  func (p *parser) parseDirectiveLocations() []DirectiveLocation {
   472  	p.skip(lexer.Pipe)
   473  
   474  	locations := []DirectiveLocation{p.parseDirectiveLocation()}
   475  
   476  	for p.skip(lexer.Pipe) && p.err == nil {
   477  		locations = append(locations, p.parseDirectiveLocation())
   478  	}
   479  
   480  	return locations
   481  }
   482  
   483  func (p *parser) parseDirectiveLocation() DirectiveLocation {
   484  	name := p.expect(lexer.Name)
   485  
   486  	switch name.Value {
   487  	case `QUERY`:
   488  		return LocationQuery
   489  	case `MUTATION`:
   490  		return LocationMutation
   491  	case `SUBSCRIPTION`:
   492  		return LocationSubscription
   493  	case `FIELD`:
   494  		return LocationField
   495  	case `FRAGMENT_DEFINITION`:
   496  		return LocationFragmentDefinition
   497  	case `FRAGMENT_SPREAD`:
   498  		return LocationFragmentSpread
   499  	case `INLINE_FRAGMENT`:
   500  		return LocationInlineFragment
   501  	case `SCHEMA`:
   502  		return LocationSchema
   503  	case `SCALAR`:
   504  		return LocationScalar
   505  	case `OBJECT`:
   506  		return LocationObject
   507  	case `FIELD_DEFINITION`:
   508  		return LocationFieldDefinition
   509  	case `ARGUMENT_DEFINITION`:
   510  		return LocationArgumentDefinition
   511  	case `INTERFACE`:
   512  		return LocationInterface
   513  	case `UNION`:
   514  		return LocationUnion
   515  	case `ENUM`:
   516  		return LocationEnum
   517  	case `ENUM_VALUE`:
   518  		return LocationEnumValue
   519  	case `INPUT_OBJECT`:
   520  		return LocationInputObject
   521  	case `INPUT_FIELD_DEFINITION`:
   522  		return LocationInputFieldDefinition
   523  	}
   524  
   525  	p.unexpectedToken(name)
   526  	return ""
   527  }
   528  

View as plain text