diff --git a/CHANGELOG.md b/CHANGELOG.md index 63ca8bcfb..6c6ea6184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This release drops support for Go 1.17 and includes many features and fixes. - Simplify `${name:-}` to the equivalent `${name-}` - [#849] - Don't print trailing whitespaces on nested subshells - [#814] - Don't print extra newlines in some case clauses - [#779] + - Don't indent comments preceding case clause items - [#917] - Allow escaped newlines before unquoted words again - [#873] - Parse a redirections edge case without spaces - [#879] - Give a helpful error when `<<<` is used in POSIX mode - [#881] @@ -672,6 +673,7 @@ Initial release. [#886]: https://github.com/mvdan/sh/issues/886 [#892]: https://github.com/mvdan/sh/issues/892 [#900]: https://github.com/mvdan/sh/pull/900 +[#917]: https://github.com/mvdan/sh/pull/917 [#928]: https://github.com/mvdan/sh/issues/928 [#929]: https://github.com/mvdan/sh/pull/929 diff --git a/syntax/parser.go b/syntax/parser.go index 4ea0b1cda..86e7274c2 100644 --- a/syntax/parser.go +++ b/syntax/parser.go @@ -2112,18 +2112,28 @@ func (p *Parser) caseItems(stop string) (items []*CaseItem) { ci.Op = CaseOperator(p.tok) p.next() p.got(_Newl) + + // Split the comments: + // + // case x in + // a) + // foo + // ;; + // # comment for a + // # comment for b + // b) + // [...] split := len(p.accComs) - if p.tok == _LitWord && p.val != stop { - for i := len(p.accComs) - 1; i >= 0; i-- { - c := p.accComs[i] - if c.Pos().Col() != p.pos.Col() { - break - } - split = i + for i := len(p.accComs) - 1; i >= 0; i-- { + c := p.accComs[i] + if c.Pos().Col() != p.pos.Col() { + break } + split = i } ci.Comments = append(ci.Comments, p.accComs[:split]...) p.accComs = p.accComs[split:] + items = append(items, ci) } return diff --git a/syntax/printer.go b/syntax/printer.go index 1944ba838..6626b3639 100644 --- a/syntax/printer.go +++ b/syntax/printer.go @@ -313,8 +313,10 @@ func (p *Printer) wantsNewline(pos Pos) bool { // We must have a newline here. return true } - if p.singleLine { - // The newline is optional, and singleLine turns it off. + if p.singleLine && len(p.pendingComments) == 0 { + // The newline is optional, and singleLine skips it. + // Don't skip if there are any pending comments, + // as that might move them further down to the wrong place. return false } // THe newline is optional, and we want it via either wantNewline or via diff --git a/syntax/printer_test.go b/syntax/printer_test.go index afba67eab..4b31971d7 100644 --- a/syntax/printer_test.go +++ b/syntax/printer_test.go @@ -405,6 +405,7 @@ var printTests = []printCase{ samePrint("case $i in\n#foo\nesac"), samePrint("case $i in\n#before\n1) ;;\nesac"), samePrint("case $i in\n#bef\n1) ;; #inl\nesac"), + samePrint("case $i in\n#before1\n'1') ;;\n#before2\n'2') ;;\nesac"), samePrint("case $i in\n1) ;; #inl1\n2) ;; #inl2\nesac"), samePrint("case $i in\n#bef\n1) #inl\n\tfoo\n\t;;\nesac"), samePrint("case $i in\n1) #inl\n\t;;\nesac"),