...

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

Documentation: github.com/vektah/gqlparser/v2/formatter

     1  package formatter
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/vektah/gqlparser/v2/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  //nolint:revive // Ignore "stuttering" name format.FormatterOption
    19  type FormatterOption func(*formatter)
    20  
    21  // WithIndent uses the given string for indenting block bodies in the output,
    22  // instead of the default, `"\t"`.
    23  func WithIndent(indent string) FormatterOption {
    24  	return func(f *formatter) {
    25  		f.indent = indent
    26  	}
    27  }
    28  
    29  // WithComments includes comments from the source/AST in the formatted output.
    30  func WithComments() FormatterOption {
    31  	return func(f *formatter) {
    32  		f.emitComments = true
    33  	}
    34  }
    35  
    36  func NewFormatter(w io.Writer, options ...FormatterOption) Formatter {
    37  	f := &formatter{
    38  		indent: "\t",
    39  		writer: w,
    40  	}
    41  	for _, opt := range options {
    42  		opt(f)
    43  	}
    44  	return f
    45  }
    46  
    47  type formatter struct {
    48  	writer io.Writer
    49  
    50  	indent       string
    51  	indentSize   int
    52  	emitBuiltin  bool
    53  	emitComments bool
    54  
    55  	padNext  bool
    56  	lineHead bool
    57  }
    58  
    59  func (f *formatter) writeString(s string) {
    60  	_, _ = f.writer.Write([]byte(s))
    61  }
    62  
    63  func (f *formatter) writeIndent() *formatter {
    64  	if f.lineHead {
    65  		f.writeString(strings.Repeat(f.indent, f.indentSize))
    66  	}
    67  	f.lineHead = false
    68  	f.padNext = false
    69  
    70  	return f
    71  }
    72  
    73  func (f *formatter) WriteNewline() *formatter {
    74  	f.writeString("\n")
    75  	f.lineHead = true
    76  	f.padNext = false
    77  
    78  	return f
    79  }
    80  
    81  func (f *formatter) WriteWord(word string) *formatter {
    82  	if f.lineHead {
    83  		f.writeIndent()
    84  	}
    85  	if f.padNext {
    86  		f.writeString(" ")
    87  	}
    88  	f.writeString(strings.TrimSpace(word))
    89  	f.padNext = true
    90  
    91  	return f
    92  }
    93  
    94  func (f *formatter) WriteString(s string) *formatter {
    95  	if f.lineHead {
    96  		f.writeIndent()
    97  	}
    98  	if f.padNext {
    99  		f.writeString(" ")
   100  	}
   101  	f.writeString(s)
   102  	f.padNext = false
   103  
   104  	return f
   105  }
   106  
   107  func (f *formatter) WriteDescription(s string) *formatter {
   108  	if s == "" {
   109  		return f
   110  	}
   111  
   112  	f.WriteString(`"""`)
   113  	ss := strings.Split(s, "\n")
   114  	f.WriteNewline()
   115  	for _, s := range ss {
   116  		f.WriteString(s).WriteNewline()
   117  	}
   118  
   119  	f.WriteString(`"""`).WriteNewline()
   120  
   121  	return f
   122  }
   123  
   124  func (f *formatter) IncrementIndent() {
   125  	f.indentSize++
   126  }
   127  
   128  func (f *formatter) DecrementIndent() {
   129  	f.indentSize--
   130  }
   131  
   132  func (f *formatter) NoPadding() *formatter {
   133  	f.padNext = false
   134  
   135  	return f
   136  }
   137  
   138  func (f *formatter) NeedPadding() *formatter {
   139  	f.padNext = true
   140  
   141  	return f
   142  }
   143  
   144  func (f *formatter) FormatSchema(schema *ast.Schema) {
   145  	if schema == nil {
   146  		return
   147  	}
   148  
   149  	f.FormatCommentGroup(schema.Comment)
   150  
   151  	var inSchema bool
   152  	startSchema := func() {
   153  		if !inSchema {
   154  			inSchema = true
   155  
   156  			f.WriteWord("schema").WriteString("{").WriteNewline()
   157  			f.IncrementIndent()
   158  		}
   159  	}
   160  	if schema.Query != nil && schema.Query.Name != "Query" {
   161  		startSchema()
   162  		f.WriteWord("query").NoPadding().WriteString(":").NeedPadding()
   163  		f.WriteWord(schema.Query.Name).WriteNewline()
   164  	}
   165  	if schema.Mutation != nil && schema.Mutation.Name != "Mutation" {
   166  		startSchema()
   167  		f.WriteWord("mutation").NoPadding().WriteString(":").NeedPadding()
   168  		f.WriteWord(schema.Mutation.Name).WriteNewline()
   169  	}
   170  	if schema.Subscription != nil && schema.Subscription.Name != "Subscription" {
   171  		startSchema()
   172  		f.WriteWord("subscription").NoPadding().WriteString(":").NeedPadding()
   173  		f.WriteWord(schema.Subscription.Name).WriteNewline()
   174  	}
   175  	if inSchema {
   176  		f.DecrementIndent()
   177  		f.WriteString("}").WriteNewline()
   178  	}
   179  
   180  	directiveNames := make([]string, 0, len(schema.Directives))
   181  	for name := range schema.Directives {
   182  		directiveNames = append(directiveNames, name)
   183  	}
   184  	sort.Strings(directiveNames)
   185  	for _, name := range directiveNames {
   186  		f.FormatDirectiveDefinition(schema.Directives[name])
   187  	}
   188  
   189  	typeNames := make([]string, 0, len(schema.Types))
   190  	for name := range schema.Types {
   191  		typeNames = append(typeNames, name)
   192  	}
   193  	sort.Strings(typeNames)
   194  	for _, name := range typeNames {
   195  		f.FormatDefinition(schema.Types[name], false)
   196  	}
   197  }
   198  
   199  func (f *formatter) FormatSchemaDocument(doc *ast.SchemaDocument) {
   200  	// TODO emit by position based order
   201  
   202  	if doc == nil {
   203  		return
   204  	}
   205  
   206  	f.FormatSchemaDefinitionList(doc.Schema, false)
   207  	f.FormatSchemaDefinitionList(doc.SchemaExtension, true)
   208  
   209  	f.FormatDirectiveDefinitionList(doc.Directives)
   210  
   211  	f.FormatDefinitionList(doc.Definitions, false)
   212  	f.FormatDefinitionList(doc.Extensions, true)
   213  
   214  	// doc.Comment is end of file comment, so emit last
   215  	f.FormatCommentGroup(doc.Comment)
   216  }
   217  
   218  func (f *formatter) FormatQueryDocument(doc *ast.QueryDocument) {
   219  	// TODO emit by position based order
   220  
   221  	if doc == nil {
   222  		return
   223  	}
   224  
   225  	f.FormatCommentGroup(doc.Comment)
   226  
   227  	f.FormatOperationList(doc.Operations)
   228  	f.FormatFragmentDefinitionList(doc.Fragments)
   229  }
   230  
   231  func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, extension bool) {
   232  	if len(lists) == 0 {
   233  		return
   234  	}
   235  
   236  	var (
   237  		beforeDescComment      = new(ast.CommentGroup)
   238  		afterDescComment       = new(ast.CommentGroup)
   239  		endOfDefinitionComment = new(ast.CommentGroup)
   240  		description            string
   241  	)
   242  
   243  	for _, def := range lists {
   244  		if def.BeforeDescriptionComment != nil {
   245  			beforeDescComment.List = append(beforeDescComment.List, def.BeforeDescriptionComment.List...)
   246  		}
   247  		if def.AfterDescriptionComment != nil {
   248  			afterDescComment.List = append(afterDescComment.List, def.AfterDescriptionComment.List...)
   249  		}
   250  		if def.EndOfDefinitionComment != nil {
   251  			endOfDefinitionComment.List = append(endOfDefinitionComment.List, def.EndOfDefinitionComment.List...)
   252  		}
   253  		description += def.Description
   254  	}
   255  
   256  	f.FormatCommentGroup(beforeDescComment)
   257  	f.WriteDescription(description)
   258  	f.FormatCommentGroup(afterDescComment)
   259  
   260  	if extension {
   261  		f.WriteWord("extend")
   262  	}
   263  	f.WriteWord("schema").WriteString("{").WriteNewline()
   264  	f.IncrementIndent()
   265  
   266  	for _, def := range lists {
   267  		f.FormatSchemaDefinition(def)
   268  	}
   269  
   270  	f.FormatCommentGroup(endOfDefinitionComment)
   271  
   272  	f.DecrementIndent()
   273  	f.WriteString("}").WriteNewline()
   274  }
   275  
   276  func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) {
   277  	f.FormatDirectiveList(def.Directives)
   278  
   279  	f.FormatOperationTypeDefinitionList(def.OperationTypes)
   280  }
   281  
   282  func (f *formatter) FormatOperationTypeDefinitionList(lists ast.OperationTypeDefinitionList) {
   283  	for _, def := range lists {
   284  		f.FormatOperationTypeDefinition(def)
   285  	}
   286  }
   287  
   288  func (f *formatter) FormatOperationTypeDefinition(def *ast.OperationTypeDefinition) {
   289  	f.FormatCommentGroup(def.Comment)
   290  	f.WriteWord(string(def.Operation)).NoPadding().WriteString(":").NeedPadding()
   291  	f.WriteWord(def.Type)
   292  	f.WriteNewline()
   293  }
   294  
   295  func (f *formatter) FormatFieldList(fieldList ast.FieldList, endOfDefComment *ast.CommentGroup) {
   296  	if len(fieldList) == 0 {
   297  		return
   298  	}
   299  
   300  	f.WriteString("{").WriteNewline()
   301  	f.IncrementIndent()
   302  
   303  	for _, field := range fieldList {
   304  		f.FormatFieldDefinition(field)
   305  	}
   306  
   307  	f.FormatCommentGroup(endOfDefComment)
   308  
   309  	f.DecrementIndent()
   310  	f.WriteString("}")
   311  }
   312  
   313  func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) {
   314  	if !f.emitBuiltin && strings.HasPrefix(field.Name, "__") {
   315  		return
   316  	}
   317  
   318  	f.FormatCommentGroup(field.BeforeDescriptionComment)
   319  
   320  	f.WriteDescription(field.Description)
   321  
   322  	f.FormatCommentGroup(field.AfterDescriptionComment)
   323  
   324  	f.WriteWord(field.Name).NoPadding()
   325  	f.FormatArgumentDefinitionList(field.Arguments)
   326  	f.NoPadding().WriteString(":").NeedPadding()
   327  	f.FormatType(field.Type)
   328  
   329  	if field.DefaultValue != nil {
   330  		f.WriteWord("=")
   331  		f.FormatValue(field.DefaultValue)
   332  	}
   333  
   334  	f.FormatDirectiveList(field.Directives)
   335  
   336  	f.WriteNewline()
   337  }
   338  
   339  func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionList) {
   340  	if len(lists) == 0 {
   341  		return
   342  	}
   343  
   344  	f.WriteString("(")
   345  	for idx, arg := range lists {
   346  		f.FormatArgumentDefinition(arg)
   347  
   348  		// Skip emitting (insignificant) comma in case it is the
   349  		// last argument, or we printed a new line in its definition.
   350  		if idx != len(lists)-1 && arg.Description == "" {
   351  			f.NoPadding().WriteWord(",")
   352  		}
   353  	}
   354  	f.NoPadding().WriteString(")").NeedPadding()
   355  }
   356  
   357  func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) {
   358  	f.FormatCommentGroup(def.BeforeDescriptionComment)
   359  
   360  	if def.Description != "" {
   361  		f.WriteNewline().IncrementIndent()
   362  		f.WriteDescription(def.Description)
   363  	}
   364  
   365  	f.FormatCommentGroup(def.AfterDescriptionComment)
   366  
   367  	f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding()
   368  	f.FormatType(def.Type)
   369  
   370  	if def.DefaultValue != nil {
   371  		f.WriteWord("=")
   372  		f.FormatValue(def.DefaultValue)
   373  	}
   374  
   375  	f.NeedPadding().FormatDirectiveList(def.Directives)
   376  
   377  	if def.Description != "" {
   378  		f.DecrementIndent()
   379  		f.WriteNewline()
   380  	}
   381  }
   382  
   383  func (f *formatter) FormatDirectiveLocation(location ast.DirectiveLocation) {
   384  	f.WriteWord(string(location))
   385  }
   386  
   387  func (f *formatter) FormatDirectiveDefinitionList(lists ast.DirectiveDefinitionList) {
   388  	if len(lists) == 0 {
   389  		return
   390  	}
   391  
   392  	for _, dec := range lists {
   393  		f.FormatDirectiveDefinition(dec)
   394  	}
   395  }
   396  
   397  func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) {
   398  	if !f.emitBuiltin {
   399  		if def.Position.Src.BuiltIn {
   400  			return
   401  		}
   402  	}
   403  
   404  	f.FormatCommentGroup(def.BeforeDescriptionComment)
   405  
   406  	f.WriteDescription(def.Description)
   407  
   408  	f.FormatCommentGroup(def.AfterDescriptionComment)
   409  
   410  	f.WriteWord("directive").WriteString("@").WriteWord(def.Name)
   411  
   412  	if len(def.Arguments) != 0 {
   413  		f.NoPadding()
   414  		f.FormatArgumentDefinitionList(def.Arguments)
   415  	}
   416  
   417  	if def.IsRepeatable {
   418  		f.WriteWord("repeatable")
   419  	}
   420  
   421  	if len(def.Locations) != 0 {
   422  		f.WriteWord("on")
   423  
   424  		for idx, dirLoc := range def.Locations {
   425  			f.FormatDirectiveLocation(dirLoc)
   426  
   427  			if idx != len(def.Locations)-1 {
   428  				f.WriteWord("|")
   429  			}
   430  		}
   431  	}
   432  
   433  	f.WriteNewline()
   434  }
   435  
   436  func (f *formatter) FormatDefinitionList(lists ast.DefinitionList, extend bool) {
   437  	if len(lists) == 0 {
   438  		return
   439  	}
   440  
   441  	for _, dec := range lists {
   442  		f.FormatDefinition(dec, extend)
   443  	}
   444  }
   445  
   446  func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) {
   447  	if !f.emitBuiltin && def.BuiltIn {
   448  		return
   449  	}
   450  
   451  	f.FormatCommentGroup(def.BeforeDescriptionComment)
   452  
   453  	f.WriteDescription(def.Description)
   454  
   455  	f.FormatCommentGroup(def.AfterDescriptionComment)
   456  
   457  	if extend {
   458  		f.WriteWord("extend")
   459  	}
   460  
   461  	switch def.Kind {
   462  	case ast.Scalar:
   463  		f.WriteWord("scalar").WriteWord(def.Name)
   464  
   465  	case ast.Object:
   466  		f.WriteWord("type").WriteWord(def.Name)
   467  
   468  	case ast.Interface:
   469  		f.WriteWord("interface").WriteWord(def.Name)
   470  
   471  	case ast.Union:
   472  		f.WriteWord("union").WriteWord(def.Name)
   473  
   474  	case ast.Enum:
   475  		f.WriteWord("enum").WriteWord(def.Name)
   476  
   477  	case ast.InputObject:
   478  		f.WriteWord("input").WriteWord(def.Name)
   479  	}
   480  
   481  	if len(def.Interfaces) != 0 {
   482  		f.WriteWord("implements").WriteWord(strings.Join(def.Interfaces, " & "))
   483  	}
   484  
   485  	f.FormatDirectiveList(def.Directives)
   486  
   487  	if len(def.Types) != 0 {
   488  		f.WriteWord("=").WriteWord(strings.Join(def.Types, " | "))
   489  	}
   490  
   491  	f.FormatFieldList(def.Fields, def.EndOfDefinitionComment)
   492  
   493  	f.FormatEnumValueList(def.EnumValues, def.EndOfDefinitionComment)
   494  
   495  	f.WriteNewline()
   496  }
   497  
   498  func (f *formatter) FormatEnumValueList(lists ast.EnumValueList, endOfDefComment *ast.CommentGroup) {
   499  	if len(lists) == 0 {
   500  		return
   501  	}
   502  
   503  	f.WriteString("{").WriteNewline()
   504  	f.IncrementIndent()
   505  
   506  	for _, v := range lists {
   507  		f.FormatEnumValueDefinition(v)
   508  	}
   509  
   510  	f.FormatCommentGroup(endOfDefComment)
   511  
   512  	f.DecrementIndent()
   513  	f.WriteString("}")
   514  }
   515  
   516  func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) {
   517  	f.FormatCommentGroup(def.BeforeDescriptionComment)
   518  
   519  	f.WriteDescription(def.Description)
   520  
   521  	f.FormatCommentGroup(def.AfterDescriptionComment)
   522  
   523  	f.WriteWord(def.Name)
   524  	f.FormatDirectiveList(def.Directives)
   525  
   526  	f.WriteNewline()
   527  }
   528  
   529  func (f *formatter) FormatOperationList(lists ast.OperationList) {
   530  	for _, def := range lists {
   531  		f.FormatOperationDefinition(def)
   532  	}
   533  }
   534  
   535  func (f *formatter) FormatOperationDefinition(def *ast.OperationDefinition) {
   536  	f.FormatCommentGroup(def.Comment)
   537  
   538  	f.WriteWord(string(def.Operation))
   539  	if def.Name != "" {
   540  		f.WriteWord(def.Name)
   541  	}
   542  	f.FormatVariableDefinitionList(def.VariableDefinitions)
   543  	f.FormatDirectiveList(def.Directives)
   544  
   545  	if len(def.SelectionSet) != 0 {
   546  		f.FormatSelectionSet(def.SelectionSet)
   547  		f.WriteNewline()
   548  	}
   549  }
   550  
   551  func (f *formatter) FormatDirectiveList(lists ast.DirectiveList) {
   552  	if len(lists) == 0 {
   553  		return
   554  	}
   555  
   556  	for _, dir := range lists {
   557  		f.FormatDirective(dir)
   558  	}
   559  }
   560  
   561  func (f *formatter) FormatDirective(dir *ast.Directive) {
   562  	f.WriteString("@").WriteWord(dir.Name)
   563  	f.FormatArgumentList(dir.Arguments)
   564  }
   565  
   566  func (f *formatter) FormatArgumentList(lists ast.ArgumentList) {
   567  	if len(lists) == 0 {
   568  		return
   569  	}
   570  	f.NoPadding().WriteString("(")
   571  	for idx, arg := range lists {
   572  		f.FormatArgument(arg)
   573  
   574  		if idx != len(lists)-1 {
   575  			f.NoPadding().WriteWord(",")
   576  		}
   577  	}
   578  	f.WriteString(")").NeedPadding()
   579  }
   580  
   581  func (f *formatter) FormatArgument(arg *ast.Argument) {
   582  	f.FormatCommentGroup(arg.Comment)
   583  
   584  	f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding()
   585  	f.WriteString(arg.Value.String())
   586  }
   587  
   588  func (f *formatter) FormatFragmentDefinitionList(lists ast.FragmentDefinitionList) {
   589  	for _, def := range lists {
   590  		f.FormatFragmentDefinition(def)
   591  	}
   592  }
   593  
   594  func (f *formatter) FormatFragmentDefinition(def *ast.FragmentDefinition) {
   595  	f.FormatCommentGroup(def.Comment)
   596  
   597  	f.WriteWord("fragment").WriteWord(def.Name)
   598  	f.FormatVariableDefinitionList(def.VariableDefinition)
   599  	f.WriteWord("on").WriteWord(def.TypeCondition)
   600  	f.FormatDirectiveList(def.Directives)
   601  
   602  	if len(def.SelectionSet) != 0 {
   603  		f.FormatSelectionSet(def.SelectionSet)
   604  		f.WriteNewline()
   605  	}
   606  }
   607  
   608  func (f *formatter) FormatVariableDefinitionList(lists ast.VariableDefinitionList) {
   609  	if len(lists) == 0 {
   610  		return
   611  	}
   612  
   613  	f.WriteString("(")
   614  	for idx, def := range lists {
   615  		f.FormatVariableDefinition(def)
   616  
   617  		if idx != len(lists)-1 {
   618  			f.NoPadding().WriteWord(",")
   619  		}
   620  	}
   621  	f.NoPadding().WriteString(")").NeedPadding()
   622  }
   623  
   624  func (f *formatter) FormatVariableDefinition(def *ast.VariableDefinition) {
   625  	f.FormatCommentGroup(def.Comment)
   626  
   627  	f.WriteString("$").WriteWord(def.Variable).NoPadding().WriteString(":").NeedPadding()
   628  	f.FormatType(def.Type)
   629  
   630  	if def.DefaultValue != nil {
   631  		f.WriteWord("=")
   632  		f.FormatValue(def.DefaultValue)
   633  	}
   634  
   635  	// TODO https://github.com/vektah/gqlparser/v2/issues/102
   636  	//   VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
   637  }
   638  
   639  func (f *formatter) FormatSelectionSet(sets ast.SelectionSet) {
   640  	if len(sets) == 0 {
   641  		return
   642  	}
   643  
   644  	f.WriteString("{").WriteNewline()
   645  	f.IncrementIndent()
   646  
   647  	for _, sel := range sets {
   648  		f.FormatSelection(sel)
   649  	}
   650  
   651  	f.DecrementIndent()
   652  	f.WriteString("}")
   653  }
   654  
   655  func (f *formatter) FormatSelection(selection ast.Selection) {
   656  	switch v := selection.(type) {
   657  	case *ast.Field:
   658  		f.FormatField(v)
   659  
   660  	case *ast.FragmentSpread:
   661  		f.FormatFragmentSpread(v)
   662  
   663  	case *ast.InlineFragment:
   664  		f.FormatInlineFragment(v)
   665  
   666  	default:
   667  		panic(fmt.Errorf("unknown Selection type: %T", selection))
   668  	}
   669  
   670  	f.WriteNewline()
   671  }
   672  
   673  func (f *formatter) FormatField(field *ast.Field) {
   674  	f.FormatCommentGroup(field.Comment)
   675  
   676  	if field.Alias != "" && field.Alias != field.Name {
   677  		f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding()
   678  	}
   679  	f.WriteWord(field.Name)
   680  
   681  	if len(field.Arguments) != 0 {
   682  		f.NoPadding()
   683  		f.FormatArgumentList(field.Arguments)
   684  		f.NeedPadding()
   685  	}
   686  
   687  	f.FormatDirectiveList(field.Directives)
   688  
   689  	f.FormatSelectionSet(field.SelectionSet)
   690  }
   691  
   692  func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) {
   693  	f.FormatCommentGroup(spread.Comment)
   694  
   695  	f.WriteWord("...").WriteWord(spread.Name)
   696  
   697  	f.FormatDirectiveList(spread.Directives)
   698  }
   699  
   700  func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) {
   701  	f.FormatCommentGroup(inline.Comment)
   702  
   703  	f.WriteWord("...")
   704  	if inline.TypeCondition != "" {
   705  		f.WriteWord("on").WriteWord(inline.TypeCondition)
   706  	}
   707  
   708  	f.FormatDirectiveList(inline.Directives)
   709  
   710  	f.FormatSelectionSet(inline.SelectionSet)
   711  }
   712  
   713  func (f *formatter) FormatType(t *ast.Type) {
   714  	f.WriteWord(t.String())
   715  }
   716  
   717  func (f *formatter) FormatValue(value *ast.Value) {
   718  	f.FormatCommentGroup(value.Comment)
   719  
   720  	f.WriteString(value.String())
   721  }
   722  
   723  func (f *formatter) FormatCommentGroup(group *ast.CommentGroup) {
   724  	if !f.emitComments || group == nil {
   725  		return
   726  	}
   727  	for _, comment := range group.List {
   728  		f.FormatComment(comment)
   729  	}
   730  }
   731  
   732  func (f *formatter) FormatComment(comment *ast.Comment) {
   733  	if !f.emitComments || comment == nil {
   734  		return
   735  	}
   736  	f.WriteString("#").WriteString(comment.Text()).WriteNewline()
   737  }
   738  

View as plain text