diff --git a/parser/parser.go b/parser/parser.go index 37c0926..12772a5 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -585,6 +585,7 @@ func (p *parser) parse(isRoot bool) (result []*ast.Node, endPos ast.Position, er if p.config.infoLevel() { p.config.infof("blankLines: %v", blankLines) } + // Here we collapse the leading blank lines into one blank line. comments = append([]string{""}, comments...) } @@ -824,15 +825,21 @@ func (p *parser) readContinuousBlocksOfComments() []string { // skipWhiteSpaceAndReadComments has multiple cases: // - (1) reading a block of comments followed by a blank line // - (2) reading a block of comments followed by non-blank content -// - (3) reading the inline comments between the current char and the end of the -// current line +// - (3) reading one or more blank lines without any comment +// - (4) reading the inline comments between the current char and the end of +// the current line // -// Lines of comments and number of blank lines will be returned. +// In both cases (1) and (2), there can also be blank lines before the comment +// starts. +// +// Lines of comments and number of blank lines before the comment will be +// returned. If there is no comment, the returned slice will be empty. func (p *parser) skipWhiteSpaceAndReadComments(multiLine bool) ([]string, int) { i := p.index var foundComment, insideComment bool commentBegin := 0 var comments []string + // Number of blanks lines *before* the comment (if any) starts. blankLines := 0 for ; i < p.length; i++ { if p.in[i] == '#' && !insideComment { diff --git a/parser/parser_test.go b/parser/parser_test.go index 119753e..83504aa 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -1126,6 +1126,57 @@ presubmit: { prohibited_regexp: "UnsafeFunction" } } +`}, { + name: "blank lines before comment blocks are collapsed to one", + in: `# txtpbfmt: sort_repeated_fields_by_content +presubmit: { + check_contents: { + + + # Should go after ADD. + # And the empty lines above this are collapsed into one blank line. + operation: EDIT + operation: ADD + + + + operation: REMOVE + } +} +`, + out: `# txtpbfmt: sort_repeated_fields_by_content +presubmit: { + check_contents: { + operation: ADD + + # Should go after ADD. + # And the empty lines above this are collapsed into one blank line. + operation: EDIT + + operation: REMOVE + } +} +`}, { + name: "blank lines before comment blocks are collapsed to one", + in: `# txtpbfmt: sort_repeated_fields_by_content +presubmit: { + check_contents: { + # This comment is a separate node and does not move when the fields are sorted. + + operation: EDIT + operation: ADD + } +} +`, + out: `# txtpbfmt: sort_repeated_fields_by_content +presubmit: { + check_contents: { + # This comment is a separate node and does not move when the fields are sorted. + operation: ADD + + operation: EDIT + } +} `}, { name: "sort by subfield values", in: `# txtpbfmt: sort_repeated_fields_by_subfield=operation.name