<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/105974>105974</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Inconsistent precedence for empty lines in clang-format related to dependence on MaxEmptyLinesToKeep
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          jtmedley
      </td>
    </tr>
</table>

<pre>
    `EmptyLineAfterAccessModifier` and its `Before` pair have additive and subtractive options, but the additive behavior is limited to adding exactly one line only. When set to `Never`, it removes empty lines that might otherwise be left in by `MaxEmptyLinesToKeep`. When set to `Always`, it will add one empty line before/after access modifiers whenever there are none, but it will allow multiple lines between definition blocks if they already exist. 

These settings allow for 0 lines (`Never`) or min(max(1,`MaxEmptyLinesToKeep`), max(1,number of existing lines)) lines (`Always`). Even if `MaxEmptyLinesToKeep` is 0, it will still add empty lines before/after access modifiers. It takes precedence over `MaxEmptyLinesToKeep` in either case. 

Then there's `SeparateDefinitionBlocks`. Like `EmptyLineAfterAccessModifier`, it has additive and subtractive options and the additive behavior is limited to adding exactly one line only. Like `EmptyLineAfterAccessModifier`, when set to `Never`, it removes empty lines that might otherwise be left in by `MaxEmptyLinesToKeep`. And when set to `Always`, it will add one empty line between definition blocks whenever there are none, and it will allow multiple lines between definition blocks if they already exist. 

These settings allow for 0 lines (`Never`) or min(`MaxEmptyLinesToKeep`, max(1,number of existing lines)) lines (`Always`). This setting does NOT override `MaxEmptyLinesToKeep`. If `MaxEmptyLinesToKeep` is 0, this setting does nothing. So when set to `Never`, `SeparateDefinitionBlocks` takes precedence over `MaxEmptyLinesToKeep`, but when set to `Always`, the reverse happens. 

`KeepEmptyLines` behaves differently than either of the above, in that it defines areas for `MaxEmptyLinesToKeep` to ignore, rather than defining any behavior of its own. 

At the very least, `SeparateDefinitionBlocks` should have an internal consistency, either taking precedence over `MaxEmptyLinesToKeep` or not. Currently it seems to do both. I would expect that its behavior should mirror that of `EmptyLineAfterAccessModifier`, which would be to take precedence over `MaxEmptyLinesToKeep`. That's the bug fix in my view. 

(( As a separate feature request, there really should be a more unified way to handle empty lines - one that gets rid of each individual setting interacting with `MaxEmptyLinesToKeep` in a slightly different way. One way to fix that would be a setting like this: 

`EmptyLines:`
`  BetweenDefinitionBlocks: #`
`  AfterAccessModifier: #`
`  BeforeAccessModifier: #`
` EndOfFile: #`
`  BeginningOfFile: #`
`  EndOfBlock: #`

In this example, they're all numbers. Unset means `MaxEmptyLinesToKeep` affects them as normal. -1 means leave them as is, `MaxEmptyLinesToKeep` ignores them. All other numbers enforce an actual number of empty lines, taking precedence over `MaxEmptyLinesToKeep`. That makes 0 equivalent to the expected behavior of `Never`. And with this you could easily disable part or all of the empty line settings to let `MaxEmptyLinesToKeep` have full control again, for example in the case where you want to remove all empty lines via `MaxEmptyLinesToKeep` = 0. ))
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV0tv20wS_DXUpWGCpt4HHWQ7Boz9vuQQL_bcJJtkx8MZZmYomf9-0UPqFceyg10s9qJE4rAf1VXVY3SOK020ieZ30fxhgp2vjd388A0VivpJZop-Ey2SL03r-79Y07b0ZLd5Ts79bQoumWy0SAB1AewdRIvkjkpjSX5skS3UuCPAomDP8h9dgOsybzEP303r2WgXpfeQdR58fXY2oxp3bCywA8UNeyrAm_BcV0CvmHvVg9EEijWB0aqP4V81aXDk5WS0SL7SLhQoCdiDpcbsyAFJO-E1B75GDw1XtQfja7J7dpIbFJUeWEPWS6C_8fWIgXs2_yBqo0XyJt9W7bF3p4R7VkoqDmWeskI2gJQ-ouAJGACFZkTUwb4mLaULIpYALYE2mg44HSMrZfbQdMpzq2hsKCO_J9JQUMmaBV_IlMlfHHAp8XpAZQmLHuiVnY8hSh6iZDt8PtfkSBryrCs3JiiNhWSMHqWrC1zXYCw0rKN01eBrlK5uo_T-XcCidC09nE7qrsnIgimHYmSyIU84uL7IeYbtOoYvO9LS0LuphDYXY3D-MIzz8X8wiRiePHh8IQetpZwK0jmBkdFcyayBWCYHOTp6A7AephqlyyCY79SiRU8Px3ndhXEFfv3FLwQfC3Dss0b3odbC7_-50P6gsP3_WJNbXfya8_O6fE87VxQ5mN__oyKv6PC_IsLnmt2hNCgMOfj67Tmow3JB12b09Bnl-jfhtfE16yqG7-Yara6r6k_1fHDda5wSQVmpwBHU2Lak3eUYo0Ui4U7hpZCgPHJQcFmSJS068zUe7cOUg1IzswtMYz1Ig_3AJXJCRHSBD-_j6Q1wpYPN3YPFEDqkGQipK0Ddn2zAlGGXm72-bGE7LOgd2R4UofOfgNrVplPFeAvQwNqT1aggN9qx86TzXqKM_Xp8kWo-77TGCiViuO_sCB97cESNk6YLA5nxdQxPsA9l0GtLuT9g6E4tj2U2bK2xw3NTftreOK_HBBlJXuHX55sQGaEP20DgzboKSn6VWTc97Jj2vxApXUXpCrYOENyIPJSEvrNCwZ8dDYMZfMoSKtUf-ssIEBpjCTotLRSwx14qrlEXii48-CZ4Y4CiIu_AchEcAvMaWBe846JDdZRnmKxsGl3Bnn19fT0iOCX2rvoT96WWGL5pOhQlKIT8-1Pxh3RK1o_4QzTd_qqzM41N5fvxAcDd4MRvmCpB0unl2d9N_Hfnhgvvxwe_6OJb-ciK3olSsRYtXjkTIoSK3zwOn096sEx6xaZVNLKgj9KlbCylYDB6F8M_tfhYQ6jdlUFhWVLuAy0bQHFf26CK4eZ2fFWR6PrwmN1oCO_NPXjQEC6GrVLDcj9UBaRLY_PgE5h7IdfZYjoxM7T1h0YxaAyaYPwJ0M-Od6iEdCLXmkZnoOLCBc-2ynirEGIHiHvTQT54CjoONHaYKYIWrRdbErhH-z67XxzXuDegyF8BKzhm2algld4aBVihLPX7YPbjiIeNQOGeKfvJUqhsj0Nnw90q1HIu7R3jlczR9AGSGIblPyk202I9XeOENrfLdDZfpNP1fFJvVtP1MsNlMp8RZbQu8myRz5HmWXF7u6R0NeFNmqSzZJXOk3mymM7j-TK7zYrZarXO5uV6lkazhBpkFSu1a2Jjqwk719HmNpmvl7OJwoyUO_xhajdy6ibrKhfNEsXOu9N7nr2izZM-LhV_zowA11n3rCFXqKubUugsF1CF45W3oJb0yCcNv8Fn0lm1qb1vg7Wkj1H6WLGvuyzOTROlj1LS-M9Na80Pyn2UPoa-XJQ-jq3tNum_AwAA__-5P0GO">