[clang] [clang-format] Add per-operator granularity for BreakBinaryOperations (PR #181051)

Sergey Subbotin via cfe-commits cfe-commits at lists.llvm.org
Sun Feb 15 14:23:06 PST 2026


================
@@ -144,14 +144,50 @@ static bool startsNextOperand(const FormatToken &Current) {
   return isAlignableBinaryOperator(Previous) && !Current.isTrailingComment();
 }
 
+// Returns the number of operators in the chain containing \c Op.
+static unsigned getChainLength(const FormatToken &Op) {
+  const FormatToken *Last = &Op;
+  while (Last->NextOperator)
+    Last = Last->NextOperator;
+  return Last->OperatorIndex + 1;
+}
+
 // Returns \c true if \c Current is a binary operation that must break.
 static bool mustBreakBinaryOperation(const FormatToken &Current,
                                      const FormatStyle &Style) {
-  return Style.BreakBinaryOperations != FormatStyle::BBO_Never &&
-         Current.CanBreakBefore &&
-         (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None
-              ? startsNextOperand
-              : isAlignableBinaryOperator)(Current);
+  if (!Current.CanBreakBefore)
+    return false;
+
+  // Determine the operator token: when breaking after the operator,
+  // it is Current.Previous; when breaking before, it is Current itself.
+  bool BreakBefore = Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
+  const FormatToken *OpToken = BreakBefore ? &Current : Current.Previous;
+
+  if (!OpToken)
+    return false;
+
+  // Check that this is an alignable binary operator.
+  if (BreakBefore) {
+    if (!isAlignableBinaryOperator(Current))
+      return false;
+  } else {
+    if (!startsNextOperand(Current))
+      return false;
+  }
+
+  // Look up per-operator rule or fall back to Default.
+  auto EffStyle =
+      Style.BreakBinaryOperations.getStyleForOperator(OpToken->TokenText);
+  if (EffStyle == FormatStyle::BBO_Never)
+    return false;
+
+  // Check MinChainLength: if the chain is too short, don't force a break.
+  unsigned MinChain = Style.BreakBinaryOperations.getMinChainLengthForOperator(
+      OpToken->TokenText);
+  if (MinChain > 0 && getChainLength(*OpToken) < MinChain)
+    return false;
+
+  return true;
----------------
ssubbotin wrote:

Done in commit 258f4f3. Simplified to a single return expression. I used `>=` rather than `>` because in commit 84d65fb I changed `getChainLength` to count operands instead of operators (so `a && b && c` = chain length 3, which is more intuitive for users configuring `MinChainLength: 3`):

```cpp
return MinChain == 0 || getChainLength(*OpToken) >= MinChain;
```

https://github.com/llvm/llvm-project/pull/181051


More information about the cfe-commits mailing list