@@ -971,7 +971,7 @@ func formatCallPackedMultiLine(call []byte, wsIndent, fullPrefix string,
971971 // []string{" in Configure)
972972 shouldBreakAfterCall := seenMultilineCall
973973 shouldBreakAfterComposite := seenMultilineComposite &&
974- ! seenMultilineCall && ! argIsMultiline
974+ ! seenMultilineCall
975975 shouldBreak := curLen + need > lineWidth || forcedBreak ||
976976 shouldBreakAfterCall || shouldBreakAfterComposite
977977 if shouldBreak {
@@ -1531,13 +1531,14 @@ func formatCallPackedMultiLineNext(call []byte, wsIndent, fullPrefix string,
15311531
15321532 // Handle call expression arguments with potential nesting.
15331533 callState := & callExprArgNextState {
1534- b : & b ,
1535- contIndent : contIndent ,
1536- contIndentLen : contIndentLen ,
1537- lineWidth : lineWidth ,
1538- curLen : curLen ,
1539- first : first ,
1540- forcedBreak : forcedBreak ,
1534+ b : & b ,
1535+ contIndent : contIndent ,
1536+ contIndentLen : contIndentLen ,
1537+ lineWidth : lineWidth ,
1538+ curLen : curLen ,
1539+ first : first ,
1540+ forcedBreak : forcedBreak || (! first &&
1541+ (seenMultilineCall || seenMultilineComposite )),
15411542 seenMultilineCall : seenMultilineCall ,
15421543 seenMultilineComposite : seenMultilineComposite ,
15431544 }
@@ -1955,6 +1956,10 @@ func (s *callExprArgNextState) writeArgSimple(a string) {
19551956 s .b .WriteString (s .contIndent )
19561957 s .b .WriteString (a )
19571958 s .curLen = s .contIndentLen + firstLineLen (a )
1959+ if strings .Contains (a , "\n " ) {
1960+ s .curLen = lastLineLen (a )
1961+ s .seenMultilineCall = true
1962+ }
19581963 s .first = false
19591964
19601965 return
@@ -1970,6 +1975,10 @@ func (s *callExprArgNextState) writeArgSimple(a string) {
19701975 }
19711976 s .b .WriteString (a )
19721977 s .curLen = advanceCols (s .curLen + 2 , a )
1978+ if strings .Contains (a , "\n " ) {
1979+ s .curLen = lastLineLen (a )
1980+ s .seenMultilineCall = true
1981+ }
19731982}
19741983
19751984func formatSelectorCallArgIfOverflowsNext (arg , contIndent string ,
@@ -2421,7 +2430,7 @@ func formatCallGreedyWithOptions(call []byte, wsIndent string, baseLen int,
24212430
24222431 // No pre-scan; we will attach leading comments of the next arg (// or
24232432 // /* */) to the previous argument inline when emitting.
2424- rawArgs := scanner .SplitTopLevel (argsBody )
2433+ rawArgs := scanner .SplitTopLevelAny (argsBody )
24252434 hasInlineComment := strings .Contains (argsBody , "/*" ) ||
24262435 strings .Contains (argsBody , "//" )
24272436 normArgs := normalizeCallArgs (rawArgs , opts )
@@ -2432,6 +2441,15 @@ func formatCallGreedyWithOptions(call []byte, wsIndent string, baseLen int,
24322441 b .WriteByte ('(' )
24332442 curLen := baseLen + visualLen (head ) + 1
24342443 contIndent := wsIndent + "\t "
2444+ prevArgMultiline := false
2445+
2446+ if len (normArgs ) == 1 && normArgs [0 ].kind == argText {
2447+ q := quoteGoString (normArgs [0 ].text )
2448+ candidate := head + "(" + q + ")"
2449+ if advanceCols (baseLen , candidate ) <= width {
2450+ return candidate
2451+ }
2452+ }
24352453
24362454 writeSplit := func (seg string , hasTrailingArgs bool ) {
24372455 q := quoteGoString (seg )
@@ -2474,7 +2492,12 @@ func formatCallGreedyWithOptions(call []byte, wsIndent string, baseLen int,
24742492 a .expr ,
24752493 )
24762494 }
2477- if hasInlineComment {
2495+ if prevArgMultiline {
2496+ curLen = emitBreakWithComments (
2497+ & b , prefixes , contIndent ,
2498+ )
2499+ justBroke = true
2500+ } else if hasInlineComment {
24782501 // Separator on same line; attach trailing line
24792502 // comment to previous arg, then place any block
24802503 // comment before next arg.
@@ -2541,10 +2564,19 @@ func formatCallGreedyWithOptions(call []byte, wsIndent string, baseLen int,
25412564 curLen = writeExprArg (
25422565 & b , a .expr , wsIndent , curLen , opts ,
25432566 )
2567+ prevArgMultiline = strings .Contains (a .expr , "\n " )
25442568 continue
25452569 }
25462570
25472571 // String arg: split greedily
2572+ if shouldPreserveExplicitStringConcat (a , contIndent , width ) {
2573+ b .WriteString (a .raw )
2574+ curLen = advanceCols (curLen , a .raw )
2575+ prevArgMultiline = strings .Contains (a .raw , "\n " )
2576+
2577+ continue
2578+ }
2579+
25482580 rest := a .text
25492581 hasTrailingArgs := i < len (normArgs )- 1
25502582 avoidTinyVerbTail := opts .AvoidTinyFormatVerbTail &&
@@ -2746,6 +2778,7 @@ func formatCallGreedyWithOptions(call []byte, wsIndent string, baseLen int,
27462778 writeSplit (seg , hasTrailingArgs )
27472779 rest = rest [cut + 1 :]
27482780 }
2781+ prevArgMultiline = false
27492782 }
27502783 b .WriteByte (')' )
27512784
@@ -2827,13 +2860,32 @@ func normalizeCallArg(trimmed string, argIndex int, rawCount int,
28272860 }
28282861
28292862 return arg {
2830- kind : argText ,
2831- text : str ,
2832- raw : trimmed ,
2833- containsFormatVerb : containsFormatVerb (str ),
2863+ kind : argText ,
2864+ text : str ,
2865+ raw : trimmed ,
2866+ containsFormatVerb : containsFormatVerb (str ),
2867+ explicitStringConcat : ! isBasicStringLitExpr (e ),
28342868 }
28352869}
28362870
2871+ func shouldPreserveExplicitStringConcat (a arg , contIndent string ,
2872+ width int ) bool {
2873+
2874+ if ! a .explicitStringConcat {
2875+ return false
2876+ }
2877+ if strings .Contains (a .text , "\n " ) {
2878+ return true
2879+ }
2880+
2881+ // Deeply indented calls can leave too little room for useful word
2882+ // splits. In that case, keep the author's concatenation boundaries
2883+ // instead of hard-cutting tiny string fragments.
2884+ const minUsefulTextCols = 24
2885+
2886+ return width - visualLen (contIndent )- 4 < minUsefulTextCols
2887+ }
2888+
28372889type argKind int
28382890
28392891const (
@@ -2847,7 +2899,8 @@ type arg struct {
28472899 text string
28482900 raw string
28492901
2850- containsFormatVerb bool
2902+ containsFormatVerb bool
2903+ explicitStringConcat bool
28512904}
28522905
28532906// commentPrefixes holds extracted comment prefixes from an argument.
@@ -3162,6 +3215,14 @@ func tryMoveStringToCont(b *strings.Builder, q, contIndent string, curLen *int,
31623215func writeExprArg (b * strings.Builder , expr , wsIndent string , curLen int ,
31633216 opts greedyCallOptions ) int {
31643217
3218+ if formatted , ok := FormatCompositeLiteralArg (
3219+ expr , wsIndent + "\t " ,
3220+ ); ok && strings .Contains (formatted , "\n " ) {
3221+
3222+ b .WriteString (formatted )
3223+
3224+ return lastLineLen (formatted )
3225+ }
31653226 if isTargetedCallStart (expr ) {
31663227 formatted := formatCallGreedyWithOptions (
31673228 []byte (expr ), wsIndent , curLen , opts ,
0 commit comments