...

Source file src/github.com/vektah/gqlparser/formatter/formatter.go

Documentation: github.com/vektah/gqlparser/formatter

     1  package formatter
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/vektah/gqlparser/ast"
    10  )
    11  
    12  type Formatter interface {
    13  	FormatSchema(schema *ast.Schema)
    14  	FormatSchemaDocument(doc *ast.SchemaDocument)
    15  	FormatQueryDocument(doc *ast.QueryDocument)
    16  }
    17  
    18  func NewFormatter(w io.Writer) Formatter {
    19  	return &formatter{writer: w}
    20  }
    21  
    22  type formatter struct {
    23  	writer io.Writer
    24  
    25  	indent      int
    26  	emitBuiltin bool
    27  
    28  	padNext  bool
    29  	lineHead bool
    30  }
    31  
    32  func (f *formatter) writeString(s string) {
    33  	_, _ = f.writer.Write([]byte(s))
    34  }
    35  
    36  func (f *formatter) writeIndent() *formatter {
    37  	if f.lineHead {
    38  		f.writeString(strings.Repeat("\t", f.indent))
    39  	}
    40  	f.lineHead = false
    41  	f.padNext = false
    42  
    43  	return f
    44  }
    45  
    46  func (f *formatter) WriteNewline() *formatter {
    47  	f.writeString("\n")
    48  	f.lineHead = true
    49  	f.padNext = false
    50  
    51  	return f
    52  }
    53  
    54  func (f *formatter) WriteWord(word string) *formatter {
    55  	if f.lineHead {
    56  		f.writeIndent()
    57  	}
    58  	if f.padNext {
    59  		f.writeString(" ")
    60  	}
    61  	f.writeString(strings.TrimSpace(word))
    62  	f.padNext = true
    63  
    64  	return f
    65  }
    66  
    67  func (f *formatter) WriteString(s string) *formatter {
    68  	if f.lineHead {
    69  		f.writeIndent()
    70  	}
    71  	if f.padNext {
    72  		f.writeString(" ")
    73  	}
    74  	f.writeString(s)
    75  	f.padNext = false
    76  
    77  	return f
    78  }
    79  
    80  func (f *formatter) WriteDescription(s string) *formatter {
    81  	if s == "" {
    82  		return f
    83  	}
    84  
    85  	f.WriteString(`"""`).WriteNewline()
    86  
    87  	ss := strings.Split(s, "\n")
    88  	for _, s := range ss {
    89  		f.WriteString(s).WriteNewline()
    90  	}
    91  
    92  	f.WriteString(`"""`).WriteNewline()
    93  
    94  	return f
    95  }
    96  
    97  func (f *formatter) IncrementIndent() {
    98  	f.indent++
    99  }
   100  
   101  func (f *formatter) DecrementIndent() {
   102  	f.indent--
   103  }
   104  
   105  func (f *formatter) NoPadding() *formatter {
   106  	f.padNext = false
   107  
   108  	return f
   109  }
   110  
   111  func (f *formatter) NeedPadding() *formatter {
   112  	f.padNext = true
   113  
   114  	return f
   115  }
   116  
   117  func (f *formatter) FormatSchema(schema *ast.Schema) {
   118  	if schema == nil {
   119  		return
   120  	}
   121  
   122  	var inSchema bool
   123  	startSchema := func() {
   124  		if !inSchema {
   125  			inSchema = true
   126  
   127  			f.WriteWord("schema").WriteString("{").WriteNewline()
   128  			f.IncrementIndent()
   129  		}
   130  	}
   131  	if schema.Query != nil && schema.Query.Name != "Query" {
   132  		startSchema()
   133  		f.WriteWord("query").NoPadding().WriteString(":").NeedPadding()
   134  		f.WriteWord(schema.Query.Name).WriteNewline()
   135  	}
   136  	if schema.Mutation != nil && schema.Mutation.Name != "Mutation" {
   137  		startSchema()
   138  		f.WriteWord("mutation").NoPadding().WriteString(":").NeedPadding()
   139  		f.WriteWord(schema.Mutation.Name).WriteNewline()
   140  	}
   141  	if schema.Subscription != nil && schema.Subscription.Name != "Subscription" {
   142  		startSchema()
   143  		f.WriteWord("subscription").NoPadding().WriteString(":").NeedPadding()
   144  		f.WriteWord(schema.Subscription.Name).WriteNewline()
   145  	}
   146  	if inSchema {
   147  		f.DecrementIndent()
   148  		f.WriteString("}").WriteNewline()
   149  	}
   150  
   151  	directiveNames := make([]string, 0, len(schema.Directives))
   152  	for name := range schema.Directives {
   153  		directiveNames = append(directiveNames, name)
   154  	}
   155  	sort.Strings(directiveNames)
   156  	for _, name := range directiveNames {
   157  		f.FormatDirectiveDefinition(schema.Directives[name])
   158  	}
   159  
   160  	typeNames := make([]string, 0, len(schema.Types))
   161  	for name := range schema.Types {
   162  		typeNames = append(typeNames, name)
   163  	}
   164  	sort.Strings(typeNames)
   165  	for _, name := range typeNames {
   166  		f.FormatDefinition(schema.Types[name], false)
   167  	}
   168  }
   169  
   170  func (f *formatter) FormatSchemaDocument(doc *ast.SchemaDocument) {
   171  	// TODO emit by position based order
   172  
   173  	if doc == nil {
   174  		return
   175  	}
   176  
   177  	f.FormatSchemaDefinitionList(doc.Schema, false)
   178  	f.FormatSchemaDefinitionList(doc.SchemaExtension, true)
   179  
   180  	f.FormatDirectiveDefinitionList(doc.Directives)
   181  
   182  	f.FormatDefinitionList(doc.Definitions, false)
   183  	f.FormatDefinitionList(doc.Extensions, true)
   184  }
   185  
   186  func (f *formatter) FormatQueryDocument(doc *ast.QueryDocument) {
   187  	// TODO emit by position based order
   188  
   189  	if doc == nil {
   190  		return
   191  	}
   192  
   193  	f.FormatOperationList(doc.Operations)
   194  	f.FormatFragmentDefinitionList(doc.Fragments)
   195  }
   196  
   197  func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, extension bool) {
   198  	if len(lists) == 0 {
   199  		return
   200  	}
   201  
   202  	if extension {
   203  		f.WriteWord("extend")
   204  	}
   205  	f.WriteWord("schema").WriteString("{").WriteNewline()
   206  	f.IncrementIndent()
   207  
   208  	for _, def := range lists {
   209  		f.FormatSchemaDefinition(def)
   210  	}
   211  
   212  	f.DecrementIndent()
   213  	f.WriteString("}").WriteNewline()
   214  }
   215  
   216  func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) {
   217  	f.WriteDescription(def.Description)
   218  
   219  	f.FormatDirectiveList(def.Directives)
   220  
   221  	f.FormatOperationTypeDefinitionList(def.OperationTypes)
   222  }
   223  
   224  func (f *formatter) FormatOperationTypeDefinitionList(lists ast.OperationTypeDefinitionList) {
   225  	for _, def := range lists {
   226  		f.FormatOperationTypeDefinition(def)
   227  	}
   228  }
   229  
   230  func (f *formatter) FormatOperationTypeDefinition(def *ast.OperationTypeDefinition) {
   231  	f.WriteWord(string(def.Operation)).NoPadding().WriteString(":").NeedPadding()
   232  	f.WriteWord(def.Type)
   233  	f.WriteNewline()
   234  }
   235  
   236  func (f *formatter) FormatFieldList(fieldList ast.FieldList) {
   237  	if len(fieldList) == 0 {
   238  		return
   239  	}
   240  
   241  	f.WriteString("{").WriteNewline()
   242  	f.IncrementIndent()
   243  
   244  	for _, field := range fieldList {
   245  		f.FormatFieldDefinition(field)
   246  	}
   247  
   248  	f.DecrementIndent()
   249  	f.WriteString("}")
   250  }
   251  
   252  func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) {
   253  	if !f.emitBuiltin && strings.HasPrefix(field.Name, "__") {
   254  		return
   255  	}
   256  
   257  	f.WriteDescription(field.Description)
   258  
   259  	f.WriteWord(field.Name).NoPadding()
   260  	f.FormatArgumentDefinitionList(field.Arguments)
   261  	f.NoPadding().WriteString(":").NeedPadding()
   262  	f.FormatType(field.Type)
   263  
   264  	if field.DefaultValue != nil {
   265  		f.WriteWord("=")
   266  		f.FormatValue(field.DefaultValue)
   267  	}
   268  
   269  	f.FormatDirectiveList(field.Directives)
   270  
   271  	f.WriteNewline()
   272  }
   273  
   274  func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionList) {
   275  	if len(lists) == 0 {
   276  		return
   277  	}
   278  
   279  	f.WriteString("(")
   280  	for idx, arg := range lists {
   281  		f.FormatArgumentDefinition(arg)
   282  
   283  		if idx != len(lists)-1 {
   284  			f.NoPadding().WriteWord(",")
   285  		}
   286  	}
   287  	f.NoPadding().WriteString(")").NeedPadding()
   288  }
   289  
   290  func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) {
   291  	f.WriteDescription(def.Description)
   292  
   293  	f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding()
   294  	f.FormatType(def.Type)
   295  
   296  	if def.DefaultValue != nil {
   297  		f.WriteWord("=")
   298  		f.FormatValue(def.DefaultValue)
   299  	}
   300  }
   301  
   302  func (f *formatter) FormatDirectiveLocation(location ast.DirectiveLocation) {
   303  	f.WriteWord(string(location))
   304  }
   305  
   306  func (f *formatter) FormatDirectiveDefinitionList(lists ast.DirectiveDefinitionList) {
   307  	if len(lists) == 0 {
   308  		return
   309  	}
   310  
   311  	for _, dec := range lists {
   312  		f.FormatDirectiveDefinition(dec)
   313  	}
   314  }
   315  
   316  func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) {
   317  	if !f.emitBuiltin {
   318  		if def.Position.Src.BuiltIn {
   319  			return
   320  		}
   321  	}
   322  
   323  	f.WriteDescription(def.Description)
   324  	f.WriteWord("directive").WriteString("@").WriteWord(def.Name)
   325  
   326  	if len(def.Arguments) != 0 {
   327  		f.NoPadding()
   328  		f.FormatArgumentDefinitionList(def.Arguments)
   329  	}
   330  
   331  	if len(def.Locations) != 0 {
   332  		f.WriteWord("on")
   333  
   334  		for idx, dirLoc := range def.Locations {
   335  			f.FormatDirectiveLocation(dirLoc)
   336  
   337  			if idx != len(def.Locations)-1 {
   338  				f.WriteWord("|")
   339  			}
   340  		}
   341  	}
   342  
   343  	f.WriteNewline()
   344  }
   345  
   346  func (f *formatter) FormatDefinitionList(lists ast.DefinitionList, extend bool) {
   347  	if len(lists) == 0 {
   348  		return
   349  	}
   350  
   351  	for _, dec := range lists {
   352  		f.FormatDefinition(dec, extend)
   353  	}
   354  }
   355  
   356  func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) {
   357  	if !f.emitBuiltin && def.BuiltIn {
   358  		return
   359  	}
   360  
   361  	f.WriteDescription(def.Description)
   362  
   363  	if extend {
   364  		f.WriteWord("extend")
   365  	}
   366  
   367  	switch def.Kind {
   368  	case ast.Scalar:
   369  		f.WriteWord("scalar").WriteWord(def.Name)
   370  
   371  	case ast.Object:
   372  		f.WriteWord("type").WriteWord(def.Name)
   373  
   374  	case ast.Interface:
   375  		f.WriteWord("interface").WriteWord(def.Name)
   376  
   377  	case ast.Union:
   378  		f.WriteWord("union").WriteWord(def.Name)
   379  
   380  	case ast.Enum:
   381  		f.WriteWord("enum").WriteWord(def.Name)
   382  
   383  	case ast.InputObject:
   384  		f.WriteWord("input").WriteWord(def.Name)
   385  	}
   386  
   387  	if len(def.Interfaces) != 0 {
   388  		f.WriteWord("implements").WriteWord(strings.Join(def.Interfaces, " & "))
   389  	}
   390  
   391  	f.FormatDirectiveList(def.Directives)
   392  
   393  	if len(def.Types) != 0 {
   394  		f.WriteWord("=").WriteWord(strings.Join(def.Types, " | "))
   395  	}
   396  
   397  	f.FormatFieldList(def.Fields)
   398  
   399  	f.FormatEnumValueList(def.EnumValues)
   400  
   401  	f.WriteNewline()
   402  }
   403  
   404  func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) {
   405  	if len(lists) == 0 {
   406  		return
   407  	}
   408  
   409  	f.WriteString("{").WriteNewline()
   410  	f.IncrementIndent()
   411  
   412  	for _, v := range lists {
   413  		f.FormatEnumValueDefinition(v)
   414  	}
   415  
   416  	f.DecrementIndent()
   417  	f.WriteString("}")
   418  }
   419  
   420  func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) {
   421  	f.WriteDescription(def.Description)
   422  
   423  	f.WriteWord(def.Name)
   424  	f.FormatDirectiveList(def.Directives)
   425  
   426  	f.WriteNewline()
   427  }
   428  
   429  func (f *formatter) FormatOperationList(lists ast.OperationList) {
   430  	for _, def := range lists {
   431  		f.FormatOperationDefinition(def)
   432  	}
   433  }
   434  
   435  func (f *formatter) FormatOperationDefinition(def *ast.OperationDefinition) {
   436  	f.WriteWord(string(def.Operation))
   437  	if def.Name != "" {
   438  		f.WriteWord(def.Name)
   439  	}
   440  	f.FormatVariableDefinitionList(def.VariableDefinitions)
   441  	f.FormatDirectiveList(def.Directives)
   442  
   443  	if len(def.SelectionSet) != 0 {
   444  		f.FormatSelectionSet(def.SelectionSet)
   445  		f.WriteNewline()
   446  	}
   447  }
   448  
   449  func (f *formatter) FormatDirectiveList(lists ast.DirectiveList) {
   450  	if len(lists) == 0 {
   451  		return
   452  	}
   453  
   454  	for _, dir := range lists {
   455  		f.FormatDirective(dir)
   456  	}
   457  }
   458  
   459  func (f *formatter) FormatDirective(dir *ast.Directive) {
   460  	f.WriteString("@").WriteWord(dir.Name)
   461  	f.FormatArgumentList(dir.Arguments)
   462  }
   463  
   464  func (f *formatter) FormatArgumentList(lists ast.ArgumentList) {
   465  	if len(lists) == 0 {
   466  		return
   467  	}
   468  	f.NoPadding().WriteString("(")
   469  	for idx, arg := range lists {
   470  		f.FormatArgument(arg)
   471  
   472  		if idx != len(lists)-1 {
   473  			f.NoPadding().WriteWord(",")
   474  		}
   475  	}
   476  	f.WriteString(")").NeedPadding()
   477  }
   478  
   479  func (f *formatter) FormatArgument(arg *ast.Argument) {
   480  	f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding()
   481  	f.WriteString(arg.Value.String())
   482  }
   483  
   484  func (f *formatter) FormatFragmentDefinitionList(lists ast.FragmentDefinitionList) {
   485  	for _, def := range lists {
   486  		f.FormatFragmentDefinition(def)
   487  	}
   488  }
   489  
   490  func (f *formatter) FormatFragmentDefinition(def *ast.FragmentDefinition) {
   491  	f.WriteWord("fragment").WriteWord(def.Name)
   492  	f.FormatVariableDefinitionList(def.VariableDefinition)
   493  	f.WriteWord("on").WriteWord(def.TypeCondition)
   494  	f.FormatDirectiveList(def.Directives)
   495  
   496  	if len(def.SelectionSet) != 0 {
   497  		f.FormatSelectionSet(def.SelectionSet)
   498  		f.WriteNewline()
   499  	}
   500  }
   501  
   502  func (f *formatter) FormatVariableDefinitionList(lists ast.VariableDefinitionList) {
   503  	if len(lists) == 0 {
   504  		return
   505  	}
   506  
   507  	f.WriteString("(")
   508  	for idx, def := range lists {
   509  		f.FormatVariableDefinition(def)
   510  
   511  		if idx != len(lists)-1 {
   512  			f.NoPadding().WriteWord(",")
   513  		}
   514  	}
   515  	f.NoPadding().WriteString(")").NeedPadding()
   516  }
   517  
   518  func (f *formatter) FormatVariableDefinition(def *ast.VariableDefinition) {
   519  	f.WriteString("$").WriteWord(def.Variable).NoPadding().WriteString(":").NeedPadding()
   520  	f.FormatType(def.Type)
   521  
   522  	if def.DefaultValue != nil {
   523  		f.WriteWord("=")
   524  		f.FormatValue(def.DefaultValue)
   525  	}
   526  
   527  	// TODO https://github.com/vektah/gqlparser/issues/102
   528  	//   VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
   529  }
   530  
   531  func (f *formatter) FormatSelectionSet(sets ast.SelectionSet) {
   532  	if len(sets) == 0 {
   533  		return
   534  	}
   535  
   536  	f.WriteString("{").WriteNewline()
   537  	f.IncrementIndent()
   538  
   539  	for _, sel := range sets {
   540  		f.FormatSelection(sel)
   541  	}
   542  
   543  	f.DecrementIndent()
   544  	f.WriteString("}")
   545  }
   546  
   547  func (f *formatter) FormatSelection(selection ast.Selection) {
   548  	switch v := selection.(type) {
   549  	case *ast.Field:
   550  		f.FormatField(v)
   551  
   552  	case *ast.FragmentSpread:
   553  		f.FormatFragmentSpread(v)
   554  
   555  	case *ast.InlineFragment:
   556  		f.FormatInlineFragment(v)
   557  
   558  	default:
   559  		panic(fmt.Errorf("unknown Selection type: %T", selection))
   560  	}
   561  
   562  	f.WriteNewline()
   563  }
   564  
   565  func (f *formatter) FormatField(field *ast.Field) {
   566  	if field.Alias != "" && field.Alias != field.Name {
   567  		f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding()
   568  	}
   569  	f.WriteWord(field.Name)
   570  
   571  	if len(field.Arguments) != 0 {
   572  		f.NoPadding()
   573  		f.FormatArgumentList(field.Arguments)
   574  		f.NeedPadding()
   575  	}
   576  
   577  	f.FormatDirectiveList(field.Directives)
   578  
   579  	f.FormatSelectionSet(field.SelectionSet)
   580  }
   581  
   582  func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) {
   583  	f.WriteWord("...").WriteWord(spread.Name)
   584  
   585  	f.FormatDirectiveList(spread.Directives)
   586  }
   587  
   588  func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) {
   589  	f.WriteWord("...")
   590  	if inline.TypeCondition != "" {
   591  		f.WriteWord("on").WriteWord(inline.TypeCondition)
   592  	}
   593  
   594  	f.FormatDirectiveList(inline.Directives)
   595  
   596  	f.FormatSelectionSet(inline.SelectionSet)
   597  }
   598  
   599  func (f *formatter) FormatType(t *ast.Type) {
   600  	f.WriteWord(t.String())
   601  }
   602  
   603  func (f *formatter) FormatValue(value *ast.Value) {
   604  	f.WriteString(value.String())
   605  }
   606  

View as plain text