Repository: openllb/hlb
Pull request #199 (2020-10-24 02:33:05)

Fix formatting for multi-line comments
Previously, a patch changed block formatting from handling newlines to delegating multi-line formatting to the underlying stmt unparsing, since with opts can now be plumbed down via `(parser.Node).Unparse(opts ...parser.UnparseOption)` for metadata like indentation.

However, comment groups didn't appropriately handle tabulation, so this PR fixes that issue and re-introduces comment groups to `FieldStmt`.


Patch:
diff --git a/mkdocs.hlb b/mkdocs.hlb
index 1a6b684..7db0f7e 100644
--- a/mkdocs.hlb
+++ b/mkdocs.hlb
@@ -159,8 +159,8 @@ fs _fetchGhPagesBranch() {
 				keepGitDir
 			}
 			# we have to recreate the .git/config because the one that 
-                        # comes from buildkit has invalid remote.origin.url and
-                        # no branch.master properties
+			# comes from buildkit has invalid remote.origin.url and
+			# no branch.master properties
 			mkfile ".git/config" 0o644 <<-EOM
 				[core]
 					repositoryformatversion = 0
diff --git a/parser/cst.go b/parser/cst.go
index 1f90c00..bb2162c 100644
--- a/parser/cst.go
+++ b/parser/cst.go
@@ -328,9 +328,9 @@ func (fl *FieldList) NumFields() int {
 // FieldStmt represents a statement in a list of fields.
 type FieldStmt struct {
 	Mixin
-	Field   *Field   `parser:"( @@ Delimit?"`
-	Newline *Newline `parser:"| @@"`
-	Comment *Comment `parser:"| @@ )"`
+	Field    *Field        `parser:"( @@ Delimit?"`
+	Newline  *Newline      `parser:"| @@"`
+	Comments *CommentGroup `parser:"| @@ )"`
 }
 
 // Field represents a parameter declaration in a signature.
diff --git a/parser/unparse.go b/parser/unparse.go
index db34dec..6ff8b78 100644
--- a/parser/unparse.go
+++ b/parser/unparse.go
@@ -188,8 +188,8 @@ func (fs *FieldStmt) Unparse(opts ...UnparseOption) string {
 		return fs.Field.Unparse(opts...)
 	case fs.Newline != nil:
 		return fs.Newline.Unparse(opts...)
-	case fs.Comment != nil:
-		return fs.Comment.Unparse(opts...)
+	case fs.Comments != nil:
+		return fs.Comments.Unparse(opts...)
 	}
 	return ""
 }
@@ -219,9 +219,7 @@ func (v *Variadic) Unparse(opts ...UnparseOption) string {
 func (bs *BlockStmt) String() string { return bs.Unparse() }
 
 func (bs *BlockStmt) Unparse(opts ...UnparseOption) string {
-	info := UnparseInfo{
-		Indent: 1,
-	}
+	var info UnparseInfo
 	for _, opt := range opts {
 		opt(&info)
 	}
@@ -253,7 +251,7 @@ func (bs *BlockStmt) Unparse(opts ...UnparseOption) string {
 		}
 		return fmt.Sprintf("{ %s }", strings.Join(stmts, "; "))
 	}
-	indent := strings.Repeat("\t", info.Indent)
+	indent := strings.Repeat("\t", info.Indent+1)
 	opts = append(opts, WithIndent(info.Indent+1))
 
 	skipNewlines := false
@@ -284,7 +282,7 @@ func (bs *BlockStmt) Unparse(opts ...UnparseOption) string {
 		}
 	}
 
-	return fmt.Sprintf("{%s\n%s}", strings.Join(stmts, "\n"), strings.Repeat("\t", info.Indent-1))
+	return fmt.Sprintf("{%s\n%s}", strings.Join(stmts, "\n"), strings.Repeat("\t", info.Indent))
 }
 
 func (s *Stmt) String() string { return s.Unparse() }
@@ -520,7 +518,7 @@ func (h *Heredoc) Unparse(opts ...UnparseOption) string {
 	body := strings.TrimRight(strings.Join(fragments, ""), "\t")
 	// Insert a special unicode marker to avoid tabs being inserted by the parent
 	// block stmt unparser.
-	return fmt.Sprintf("%s%s%s%s", h.Start, body, strings.Repeat("\t", info.Indent-1), h.Terminate.Unparse(opts...))
+	return fmt.Sprintf("%s%s%s%s", h.Start, body, strings.Repeat("\t", info.Indent), h.Terminate.Unparse(opts...))
 }
 
 func (hf *HeredocFragment) String() string { return hf.Unparse() }
@@ -623,9 +621,19 @@ func (i *Ident) Unparse(opts ...UnparseOption) string {
 func (cg *CommentGroup) String() string { return cg.Unparse() }
 
 func (cg *CommentGroup) Unparse(opts ...UnparseOption) string {
+	var info UnparseInfo
+	for _, opt := range opts {
+		opt(&info)
+	}
 	var comments []string
-	for _, comment := range cg.List {
-		comments = append(comments, comment.Unparse(opts...))
+	for i, comment := range cg.List {
+		str := comment.Unparse(opts...)
+		// Only first line is tabulated by the parent block.
+		// Subsequent lines need to be tabulated by unparse options.
+		if i > 0 {
+			str = fmt.Sprintf("%s%s", strings.Repeat("\t", info.Indent), str)
+		}
+		comments = append(comments, str)
 	}
 	return strings.Join(comments, "")
 }
@@ -657,9 +665,7 @@ func (se *StmtEnd) Unparse(opts ...UnparseOption) string {
 }
 
 func unparseList(list []Node, opts ...UnparseOption) string {
-	info := UnparseInfo{
-		Indent: 1,
-	}
+	var info UnparseInfo
 	for _, opt := range opts {
 		opt(&info)
 	}
@@ -695,7 +701,7 @@ func unparseList(list []Node, opts ...UnparseOption) string {
 		}
 		return fmt.Sprintf("(%s)", strings.Join(stmts, ", "))
 	}
-	indent := strings.Repeat("\t", info.Indent)
+	indent := strings.Repeat("\t", info.Indent+1)
 	opts = append(opts, WithIndent(info.Indent+1))
 
 	skipNewlines := true
@@ -737,5 +743,5 @@ func unparseList(list []Node, opts ...UnparseOption) string {
 	}
 	stmts = stmts[:i+1]
 
-	return fmt.Sprintf("(\n%s\n%s)", strings.Join(stmts, ""), strings.Repeat("\t", info.Indent-1))
+	return fmt.Sprintf("(\n%s\n%s)", strings.Join(stmts, ""), strings.Repeat("\t", info.Indent))
 }
diff --git a/parser/walk.go b/parser/walk.go
index bfeb26c..ac0b39b 100644
--- a/parser/walk.go
+++ b/parser/walk.go
@@ -97,8 +97,8 @@ func (w *walker) walk(node Node, v Visitor) {
 		switch {
 		case n.Field != nil:
 			w.walk(n.Field, v)
-		case n.Comment != nil:
-			w.walk(n.Comment, v)
+		case n.Comments != nil:
+			w.walk(n.Comments, v)
 		}
 	case *Field:
 		if n.Modifier != nil {


Test patch:
diff --git a/unparse_test.go b/unparse_test.go
index ba66fbc..b79b7eb 100644
--- a/unparse_test.go
+++ b/unparse_test.go
@@ -446,9 +446,9 @@ func TestUnparse(t *testing.T) {
 			fs foo() { # comment
 
 
+				# multi-line
 				# comment
 
-
 				image "alpine" with option { # comment
 					resolve # comment
 				} # comment
@@ -464,6 +464,7 @@ func TestUnparse(t *testing.T) {
 			# comment
 			fs foo() { # comment
 
+				# multi-line
 				# comment
 
 				image "alpine" with option { # comment