@@ -517,8 +517,13 @@ func (p *printer) alignedItems(items []*ast.ObjectItem) []byte {
517517
518518// list returns the printable HCL form of an list type.
519519func (p * printer ) list (l * ast.ListType ) []byte {
520+ if p .isSingleLineList (l ) {
521+ return p .singleLineList (l )
522+ }
523+
520524 var buf bytes.Buffer
521525 buf .WriteString ("[" )
526+ buf .WriteByte (newline )
522527
523528 var longestLine int
524529 for _ , item := range l .List {
@@ -531,115 +536,112 @@ func (p *printer) list(l *ast.ListType) []byte {
531536 }
532537 }
533538
534- insertSpaceBeforeItem := false
535- lastHadLeadComment := false
539+ haveEmptyLine := false
536540 for i , item := range l .List {
537- // Keep track of whether this item is a heredoc since that has
538- // unique behavior.
539- heredoc := false
540- if lit , ok := item .(* ast.LiteralType ); ok && lit .Token .Type == token .HEREDOC {
541- heredoc = true
542- }
543-
544- if item .Pos ().Line != l .Lbrack .Line {
545- // multiline list, add newline before we add each item
546- buf .WriteByte (newline )
547- insertSpaceBeforeItem = false
548-
549- // If we have a lead comment, then we want to write that first
550- leadComment := false
551- if lit , ok := item .(* ast.LiteralType ); ok && lit .LeadComment != nil {
552- leadComment = true
553-
554- // If this isn't the first item and the previous element
555- // didn't have a lead comment, then we need to add an extra
556- // newline to properly space things out. If it did have a
557- // lead comment previously then this would be done
558- // automatically.
559- if i > 0 && ! lastHadLeadComment {
560- buf .WriteByte (newline )
561- }
562-
563- for _ , comment := range lit .LeadComment .List {
564- buf .Write (p .indent ([]byte (comment .Text )))
565- buf .WriteByte (newline )
566- }
541+ // If we have a lead comment, then we want to write that first
542+ leadComment := false
543+ if lit , ok := item .(* ast.LiteralType ); ok && lit .LeadComment != nil {
544+ leadComment = true
545+
546+ // Ensure an empty line before every element with a
547+ // lead comment (except the first item in a list).
548+ if ! haveEmptyLine && i != 0 {
549+ buf .WriteByte (newline )
567550 }
568551
569- // also indent each line
570- val := p .output (item )
571- curLen := len (val )
572- buf .Write (p .indent (val ))
573-
574- // if this item is a heredoc, then we output the comma on
575- // the next line. This is the only case this happens.
576- comma := []byte {',' }
577- if heredoc {
552+ for _ , comment := range lit .LeadComment .List {
553+ buf .Write (p .indent ([]byte (comment .Text )))
578554 buf .WriteByte (newline )
579- comma = p .indent (comma )
580555 }
556+ }
581557
582- buf .Write (comma )
558+ // also indent each line
559+ val := p .output (item )
560+ curLen := len (val )
561+ buf .Write (p .indent (val ))
583562
584- if lit , ok := item .(* ast.LiteralType ); ok && lit .LineComment != nil {
585- // if the next item doesn't have any comments, do not align
586- buf .WriteByte (blank ) // align one space
587- for i := 0 ; i < longestLine - curLen ; i ++ {
588- buf .WriteByte (blank )
589- }
563+ // if this item is a heredoc, then we output the comma on
564+ // the next line. This is the only case this happens.
565+ comma := []byte {',' }
566+ if lit , ok := item .(* ast.LiteralType ); ok && lit .Token .Type == token .HEREDOC {
567+ buf .WriteByte (newline )
568+ comma = p .indent (comma )
569+ }
590570
591- for _ , comment := range lit .LineComment .List {
592- buf .WriteString (comment .Text )
593- }
594- }
571+ buf .Write (comma )
595572
596- lastItem := i == len (l .List )- 1
597- if lastItem {
598- buf .WriteByte (newline )
573+ if lit , ok := item .(* ast.LiteralType ); ok && lit .LineComment != nil {
574+ // if the next item doesn't have any comments, do not align
575+ buf .WriteByte (blank ) // align one space
576+ for i := 0 ; i < longestLine - curLen ; i ++ {
577+ buf .WriteByte (blank )
599578 }
600579
601- if leadComment && ! lastItem {
602- buf .WriteByte ( newline )
580+ for _ , comment := range lit . LineComment . List {
581+ buf .WriteString ( comment . Text )
603582 }
583+ }
604584
605- lastHadLeadComment = leadComment
606- } else {
607- if insertSpaceBeforeItem {
608- buf .WriteByte (blank )
609- insertSpaceBeforeItem = false
610- }
585+ buf .WriteByte (newline )
611586
612- // Output the item itself
613- // also indent each line
614- val := p .output (item )
615- curLen := len (val )
616- buf .Write (val )
587+ // Ensure an empty line after every element with a
588+ // lead comment (except the first item in a list).
589+ haveEmptyLine = leadComment && i != len (l .List )- 1
590+ if haveEmptyLine {
591+ buf .WriteByte (newline )
592+ }
593+ }
617594
618- // If this is a heredoc item we always have to output a newline
619- // so that it parses properly.
620- if heredoc {
621- buf .WriteByte (newline )
622- }
595+ buf .WriteString ("]" )
596+ return buf .Bytes ()
597+ }
623598
624- // If this isn't the last element, write a comma.
625- if i != len (l .List )- 1 {
626- buf .WriteString ("," )
627- insertSpaceBeforeItem = true
628- }
599+ // isSingleLineList returns true if:
600+ // * they were previously formatted entirely on one line
601+ // * they consist entirely of literals
602+ // * there are either no heredoc strings or the list has exactly one element
603+ // * there are no line comments
604+ func (printer ) isSingleLineList (l * ast.ListType ) bool {
605+ for _ , item := range l .List {
606+ if item .Pos ().Line != l .Lbrack .Line {
607+ return false
608+ }
629609
630- if lit , ok := item .(* ast.LiteralType ); ok && lit .LineComment != nil {
631- // if the next item doesn't have any comments, do not align
632- buf .WriteByte (blank ) // align one space
633- for i := 0 ; i < longestLine - curLen ; i ++ {
634- buf .WriteByte (blank )
635- }
610+ lit , ok := item .(* ast.LiteralType )
611+ if ! ok {
612+ return false
613+ }
636614
637- for _ , comment := range lit .LineComment .List {
638- buf .WriteString (comment .Text )
639- }
640- }
615+ if lit .Token .Type == token .HEREDOC && len (l .List ) != 1 {
616+ return false
617+ }
618+
619+ if lit .LineComment != nil {
620+ return false
641621 }
622+ }
642623
624+ return true
625+ }
626+
627+ // singleLineList prints a simple single line list.
628+ // For a definition of "simple", see isSingleLineList above.
629+ func (p * printer ) singleLineList (l * ast.ListType ) []byte {
630+ buf := & bytes.Buffer {}
631+
632+ buf .WriteString ("[" )
633+ for i , item := range l .List {
634+ if i != 0 {
635+ buf .WriteString (", " )
636+ }
637+
638+ // Output the item itself
639+ buf .Write (p .output (item ))
640+
641+ // The heredoc marker needs to be at the end of line.
642+ if lit , ok := item .(* ast.LiteralType ); ok && lit .Token .Type == token .HEREDOC {
643+ buf .WriteByte (newline )
644+ }
643645 }
644646
645647 buf .WriteString ("]" )
0 commit comments