Skip to content

Commit c116bdc

Browse files
committed
formatter: remove sole-return block blanks
Remove existing blank lines before a sole return in control-statement bodies. This makes the blank-line rule idempotent for guard clauses whose wrapped return call is the only statement in the block. Keep the multiline function-signature exception intact by limiting the cleanup to if, for, and range bodies. Preserve leading-comment return separators and refresh self-formatting touched by the new rule.
1 parent 02a465e commit c116bdc

17 files changed

Lines changed: 65 additions & 46 deletions

dsl/action.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2885,7 +2885,6 @@ func callAlreadyAcceptableWithMultilineLiteralArg(ctx *Context,
28852885
return false
28862886
}
28872887
if !callHasDirectMultilineLiteralArg(ctx, call) {
2888-
28892888
return false
28902889
}
28912890

@@ -4855,7 +4854,6 @@ func (a *BreakInterfaceMethodAction) Execute(caps Captures, ctx *Context) (
48554854
method, indent, ctx.ColumnLimit, ctx.TabStop, a.FormatFunc,
48564855
func(signature, indent string, colLimit, tabStop int) (string,
48574856
bool) {
4858-
48594857
return formatMethodSimple(
48604858
signature, indent, colLimit, tabStop,
48614859
), false
@@ -5109,6 +5107,16 @@ func (c *blankLineBatchContext) inspectFile(file *ast.File) {
51095107
}
51105108

51115109
case *ast.ReturnStmt:
5110+
if onlyStmtInBlockWithoutLeadingComment(
5111+
c.ctx, n,
5112+
) {
5113+
5114+
start := c.ctx.Fset.Position(n.Pos()).Offset
5115+
c.maybeRemoveBlankBeforeLineStart(
5116+
lineStart(c.ctx.Source, start),
5117+
)
5118+
break
5119+
}
51125120
if c.returnCond.Eval(caps, c.ctx) {
51135121
c.maybeInsertBlankBefore(n)
51145122
}
@@ -5132,6 +5140,25 @@ func (c *blankLineBatchContext) inspectFile(file *ast.File) {
51325140
)
51335141
}
51345142

5143+
func (c *blankLineBatchContext) maybeRemoveBlankBeforeLineStart(
5144+
lineStartIdx int) {
5145+
5146+
if lineStartIdx <= 0 || lineStartIdx > len(c.ctx.Source) {
5147+
return
5148+
}
5149+
if !hasBlankLineBeforeLineStart(c.ctx.Source, lineStartIdx) {
5150+
return
5151+
}
5152+
5153+
prevLineEnd := lineStartIdx - 1
5154+
prevStart := lineStart(c.ctx.Source, prevLineEnd)
5155+
if prevStart < 0 || prevStart > lineStartIdx {
5156+
return
5157+
}
5158+
5159+
c.b.Delete(prevStart, lineStartIdx)
5160+
}
5161+
51355162
// parseCheckOK performs a defensive parse check on the output.
51365163
func parseCheckOK(out []byte) bool {
51375164
fset := token.NewFileSet()

dsl/composite_lit_expand_action.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ func (a *BreakCompositeKeyValueAction) Execute(caps Captures, ctx *Context) (
218218

219219
orig := string(ctx.Source[start:end])
220220
if orig == "" || hasLineComment(orig) || hasBlockComment(orig) {
221-
222221
return nil, false
223222
}
224223

dsl/condition.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,18 +2113,8 @@ func (c *IsReturnNeedingBlankCond) Eval(caps Captures, ctx *Context) bool {
21132113
if !ok {
21142114
return false
21152115
}
2116-
if block, ok := ctx.Parent(node).(*ast.BlockStmt); ok &&
2117-
block != nil && len(block.List) == 1 && block.List[0] == node {
2118-
2119-
brace := ctx.Fset.Position(block.Lbrace).Offset
2120-
returnStart := ctx.Fset.Position(node.Pos()).Offset
2121-
if brace >= 0 && brace+1 <= returnStart {
2122-
gap := string(ctx.Source[brace+1 : returnStart])
2123-
if !strings.Contains(gap, "//") &&
2124-
!strings.Contains(gap, "/*") {
2125-
return false
2126-
}
2127-
}
2116+
if onlyStmtInBlockWithoutLeadingComment(ctx, node) {
2117+
return false
21282118
}
21292119

21302120
pos := ctx.Fset.Position(node.Pos())
@@ -2175,6 +2165,30 @@ func (c *IsReturnNeedingBlankCond) Eval(caps Captures, ctx *Context) bool {
21752165
return true
21762166
}
21772167

2168+
func onlyStmtInBlockWithoutLeadingComment(ctx *Context, node ast.Node) bool {
2169+
block, ok := ctx.Parent(node).(*ast.BlockStmt)
2170+
if !ok || block == nil || len(block.List) != 1 ||
2171+
block.List[0] != node {
2172+
return false
2173+
}
2174+
switch ctx.Parent(block).(type) {
2175+
case *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt:
2176+
2177+
default:
2178+
return false
2179+
}
2180+
2181+
brace := ctx.Fset.Position(block.Lbrace).Offset
2182+
nodeStart := ctx.Fset.Position(node.Pos()).Offset
2183+
if brace < 0 || brace+1 > nodeStart {
2184+
return false
2185+
}
2186+
2187+
gap := string(ctx.Source[brace+1 : nodeStart])
2188+
2189+
return !strings.Contains(gap, "//") && !strings.Contains(gap, "/*")
2190+
}
2191+
21782192
// IsIfErrReturnNeedingBlankCond checks if an `if err != nil { return ... }`
21792193
// statement should be preceded by a blank line for readability.
21802194
//

dsl/edit.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ func ApplyEdits(src []byte, edits []Edit) ([]byte, error) {
5858
// single-span replacement case.
5959
func ApplySingleEdit(src []byte, start, end int,
6060
replace []byte) ([]byte, error) {
61-
6261
return ApplyEdits(
6362
src, []Edit{
6463
{Start: start, End: end, Replace: replace},

dsl/engine_edit_action_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ type replaceIdentEditAction struct {
2424

2525
func (a *replaceIdentEditAction) Execute(caps Captures, ctx *Context) ([]byte,
2626
bool) {
27-
2827
return nil, false
2928
}
3029

@@ -55,7 +54,6 @@ type overlappingEditAction struct{}
5554

5655
func (a *overlappingEditAction) Execute(caps Captures, ctx *Context) ([]byte,
5756
bool) {
58-
5957
return nil, false
6058
}
6159

dsl/engine_ownership_block_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ func (a fixedEditAction) Execute(caps Captures, ctx *Context) ([]byte, bool) {
2222

2323
func (a fixedEditAction) ExecuteEdits(caps Captures, ctx *Context) ([]Edit,
2424
bool, error) {
25-
2625
return []Edit{
2726
{
2827
Start: a.start,

dsl/layout/doc.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,15 @@ type IndentByCols struct {
9090
}
9191

9292
func (IndentByCols) isDoc() {}
93-
94-
func T(s string) Doc { return Text(s) }
95-
func L() Doc { return Line{} }
96-
func SL() Doc { return SoftLine{} }
97-
func FB() Doc { return ForceBreak{} }
98-
func G(d Doc) Doc { return Group{Doc: d} }
93+
func T(s string) Doc { return Text(s) }
94+
func L() Doc { return Line{} }
95+
func SL() Doc { return SoftLine{} }
96+
func FB() Doc { return ForceBreak{} }
97+
func G(d Doc) Doc { return Group{Doc: d} }
9998
func N(indent string, d Doc) Doc {
10099
return Nest{Indent: indent, Doc: d}
101100
}
102-
103-
func C(docs ...Doc) Doc { return Concat(docs) }
104-
101+
func C(docs ...Doc) Doc { return Concat(docs) }
105102
func IB(broken, flat Doc) Doc { return IfBreak{Broken: broken, Flat: flat} }
106103
func A(d Doc) Doc { return Align{Doc: d} }
107104
func I(cols int, d Doc) Doc { return IndentByCols{Cols: cols, Doc: d} }

dsl/rules.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,6 @@ func LegacyMultiLineScanRules(scanFunc LegacyMultiLineScanFunc) []Rule {
14991499
// LegacyMultiLineScanRules.
15001500
func LegacyMultiLineScanRulesWithOptions(opts MultiLineCallOptions,
15011501
scanFunc LegacyMultiLineScanFunc) []Rule {
1502-
15031502
return []Rule{
15041503
{
15051504
Name: "legacy_multiline_scan",
@@ -1540,7 +1539,6 @@ func LegacyCompactCallRules(formatFunc LegacyCompactCallFormatFunc) []Rule {
15401539
// LegacyCommentRules delegates comment formatting to a legacy formatter.
15411540
func LegacyCommentRules(formatFunc LegacyCommentFormatFunc,
15421541
moveInlineAbove bool) []Rule {
1543-
15441542
return []Rule{
15451543
{
15461544
Name: "legacy_comment_format",
@@ -1618,7 +1616,6 @@ func LegacyBlankLinesRules(formatFunc LegacyBlankLinesFormatFunc) []Rule {
16181616
// source cannot be parsed, or as a last resort after native DSL rules).
16191617
func LegacyBlankLinesFallbackRules(
16201618
formatFunc LegacyBlankLinesFormatFunc) []Rule {
1621-
16221619
return []Rule{
16231620
{
16241621
Name: "legacy_blank_lines_fallback",

dsl/types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ type Context struct {
108108
// NewContext creates a new formatting context.
109109
func NewContext(fset *token.FileSet, source []byte, columnLimit,
110110
tabStop int) *Context {
111-
112111
return &Context{
113112
Fset: fset,
114113
Source: source,

formatter/compact_call_formatter.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,7 +2195,6 @@ func isDirectCompositeLiteralExpr(expr ast.Expr) bool {
21952195
// at word boundaries when possible.
21962196
func buildSplitQuoted(text string, startCol int, contIndent string,
21972197
width int) string {
2198-
21992198
return buildSplitQuotedWithOptions(
22002199
text, startCol, contIndent, width, false,
22012200
)
@@ -2206,7 +2205,6 @@ func buildSplitQuoted(text string, startCol int, contIndent string,
22062205
// appears as a call argument that may have trailing arguments.
22072206
func buildSplitQuotedForCallArg(text string, startCol int, contIndent string,
22082207
width int, hasTrailingArgs bool) string {
2209-
22102208
return buildSplitQuotedWithOptions(
22112209
text, startCol, contIndent, width, hasTrailingArgs,
22122210
)
@@ -4023,7 +4021,6 @@ func FormatCallPackedMultiLine(call []byte, wsIndent string, colLimit,
40234021
// selected.
40244022
func FormatCallPackedMultiLineNext(call []byte, wsIndent string, colLimit,
40254023
ts int) string {
4026-
40274024
return FormatCallPackedMultiLineNextWithPrefix(
40284025
call, wsIndent, wsIndent, colLimit, ts,
40294026
)

0 commit comments

Comments
 (0)