This is an archive of the discontinued LLVM Phabricator instance.

clang-format: Add AlignConsecutiveShortCaseStatements
ClosedPublic

Authored by galenelias on May 30 2023, 4:01 PM.

Details

Summary

This resolves https://github.com/llvm/llvm-project/issues/55475.

This adds a new AlignConsecutiveShortCaseStatements option in line with the existing AlignConsecutive* options , which when AllowShortCaseLabelsOnASingleLine is enabled will align the tokens after the case statement's colon. This also adds a AlignCaseColons option to allow aligning the case label colon itself rather than the token after it.

For the implementation, I tried re-using AlignTokens, however went with a custom alignment method instead since consecutive case labels require traversing scopes (which AlignTokens doesn't allow). Additionally, special casing was required to allow empty case labels to not break the alignment sequence.

Diff Detail

Event Timeline

galenelias created this revision.May 30 2023, 4:01 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptMay 30 2023, 4:01 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
galenelias requested review of this revision.May 30 2023, 4:01 PM

When I read the title I thought "Yay, some one is doing what I want and don't find the time.", but (for me) sadly you're not.
I'd like to align the colon (and thus the statement behind that). Do you think you can add that option too?

clang/include/clang/Format/Format.h
308

We need another name, you're not aligning the label, but the statement.

clang/unittests/Format/FormatTest.cpp
19258
19259

There is a verifyFormat overload which takes 2 strings, please use that.

19307

Add a test with AcrossEmptyLines and AcrossComments.

19308

Also add tests with SpaceBeforeCaseColon.

When I read the title I thought "Yay, some one is doing what I want and don't find the time.", but (for me) sadly you're not.
I'd like to align the colon (and thus the statement behind that). Do you think you can add that option too?

Hmm, it had not occurred to me that there are folks who would want to insert the spaces after the 'case'. I can think about how that might be accomplished, but it doesn't seem straightforward given the current alignment infrastructure since the token you want to align (the colon) isn't the token which should be padded (the token after the case keyword). I think I'd have to write custom alignment code to allow for the separation of these two.

clang/include/clang/Format/Format.h
308

I was taking the name from the GitHub issue, which while I agree is a slight misnomer seemed to yield what I assumed most people would expect. I guess AlignConsecutiveStatementsAfterShortCaseLabels is more correct, but is also getting pretty verbose.

MyDeveloperDay added inline comments.May 31 2023, 3:19 PM
clang/docs/ClangFormatStyleOptions.rst
790

Did you generate this by hand or run the dump_format_style.py function? Format.h and the rst look out of sync

galenelias added inline comments.May 31 2023, 9:44 PM
clang/docs/ClangFormatStyleOptions.rst
790

This was generated from dump_format_style.py. What looks out of sync? My guess is the confusing thing is all the styles which use AlignConsecutiveStyle get the same documentation pasted for them which specifically references AlignConsecutiveMacros and makes it look like it's for the wrong option.

clang/unittests/Format/FormatTest.cpp
19307

There is a test for both AcrossEmptyLines and AcrossComments. Maybe I'm not understanding your comment?

MyDeveloperDay added inline comments.Jun 1 2023, 10:28 AM
clang/docs/ClangFormatStyleOptions.rst
790

that doesn't feel right to me.. not saying its not dump_format_style.py but it shouldn't do that in my view

When I read the title I thought "Yay, some one is doing what I want and don't find the time.", but (for me) sadly you're not.
I'd like to align the colon (and thus the statement behind that). Do you think you can add that option too?

Hmm, it had not occurred to me that there are folks who would want to insert the spaces after the 'case'. I can think about how that might be accomplished, but it doesn't seem straightforward given the current alignment infrastructure since the token you want to align (the colon) isn't the token which should be padded (the token after the case keyword). I think I'd have to write custom alignment code to allow for the separation of these two.

After sleeping over it I want to revoke my request. Aligning the statements is sufficient, we don't need too much options. It just has to work with SpaceBeforeCaseColon, which I assume it already does.

clang/docs/ClangFormatStyleOptions.rst
790

What shouldn't it be doing?
The struct is used for multiple options and the documentation is that ways since we have the struct.

clang/include/clang/Format/Format.h
308

Maybe just AlignConsecutiveShortCaseStatements?

clang/unittests/Format/FormatTest.cpp
19247

Could you add test cases with not short cases between/at the begin of/at the end of the short ones?

19307

A test where both are true.

galenelias marked 3 inline comments as done.
galenelias retitled this revision from clang-format: Add AlignConsecutiveShortCaseLabels to clang-format: Add AlignConsecutiveShortCaseStatements.
galenelias edited the summary of this revision. (Show Details)
galenelias marked 8 inline comments as done.Jun 2 2023, 10:37 PM
clang/unittests/Format/FormatTest.cpp
19269
19270

If both strings are the same, you only need to supply it once.

Or are they different and I can't see it?

19309

For what is this?

Fixup up review comments.

galenelias marked 3 inline comments as done.Jun 3 2023, 10:08 AM
galenelias added inline comments.
clang/unittests/Format/FormatTest.cpp
19258

I'll get used to adding full stops eventually... sorry for not catching this.

19270

They are the same, but I can't use the single string version, as that one calls test::messUp on the string which will strip blank lines, which then invalidates the test case. It seems pretty much all tests which are trying to validate behavior around empty spaces has to use the two string version.

19309

Oops, I was trying to set ColumnLimit = 0 before to stop it from merging multi-line case statements, but it wasn't working as expected, so I ended up inserting comments instead, and forgot to remove resetting this. Good catch!

Please wait for some other approval (or comments) for a few days.

clang/unittests/Format/FormatTest.cpp
19270

Check.

This revision is now accepted and ready to land.Jun 3 2023, 12:04 PM
MyDeveloperDay added inline comments.Jun 5 2023, 1:05 AM
clang/docs/ClangFormatStyleOptions.rst
790

I understand why its there, I just don't like that the text is repeated and doesn't really reference the case statements, (it could be confusing).

for example what would PadOperators mean in this case

Apart from the documentation this looks fine.. thats probably outside the scope of this change

MyDeveloperDay added inline comments.Jun 5 2023, 1:09 AM
clang/docs/ClangFormatStyleOptions.rst
798

Do you think the documentation should give examples of the the other cases?

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"
galenelias marked 3 inline comments as done.Jun 6 2023, 9:46 AM
galenelias added inline comments.
clang/docs/ClangFormatStyleOptions.rst
790

I agree that it's confusing, I've actually gotten confused a few times while reading the documentation for various 'AlignConsecutive*' options. PadOperators and AlignCompound both explicitly state they only apply to AlignConsecutiveAssignments. Not sure what the fix would be, as this seems to be a fairly by design aspect of the struct sharing with regards to the documentation generation.

798

Hmm, I'm not sure what other cases? Cases where it doesn't align? In general, for the 'Align*' options we only show examples of the resulting formatting.

galenelias marked an inline comment as done.Jun 6 2023, 9:56 AM

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"

That's a great point. I didn't really consider this, and currently this particular case won't align the case statements if they have an empty case block, however if you had some tokens (e.g. // fallthrough) it would. It's not immediately clear to me what the expectation would be. I guess to align as if there was an invisible trailing token, but it's a bit awkward if the cases missing a body are the 'long' cases that push out the alignment. Also, I don't think it's possible to use AlignTokens and get this behavior, as there is no token on those lines to align, so it's not straightforward to handle. I guess I'll be curious to see if there is feedback or cases where this behavior is desired, and if so, I can look into adding that functionality later. Since right now it would involve a completely custom AlignTokens clone, my preference would be to just leave this as not supported.

HazardyKnusperkeks requested changes to this revision.Jun 6 2023, 12:25 PM

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"

That's a great point. I didn't really consider this, and currently this particular case won't align the case statements if they have an empty case block, however if you had some tokens (e.g. // fallthrough) it would. It's not immediately clear to me what the expectation would be. I guess to align as if there was an invisible trailing token, but it's a bit awkward if the cases missing a body are the 'long' cases that push out the alignment. Also, I don't think it's possible to use AlignTokens and get this behavior, as there is no token on those lines to align, so it's not straightforward to handle. I guess I'll be curious to see if there is feedback or cases where this behavior is desired, and if so, I can look into adding that functionality later. Since right now it would involve a completely custom AlignTokens clone, my preference would be to just leave this as not supported.

I'd say: align it.

This revision now requires changes to proceed.Jun 6 2023, 12:25 PM

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"

That's a great point. I didn't really consider this, and currently this particular case won't align the case statements if they have an empty case block, however if you had some tokens (e.g. // fallthrough) it would. It's not immediately clear to me what the expectation would be. I guess to align as if there was an invisible trailing token, but it's a bit awkward if the cases missing a body are the 'long' cases that push out the alignment. Also, I don't think it's possible to use AlignTokens and get this behavior, as there is no token on those lines to align, so it's not straightforward to handle. I guess I'll be curious to see if there is feedback or cases where this behavior is desired, and if so, I can look into adding that functionality later. Since right now it would involve a completely custom AlignTokens clone, my preference would be to just leave this as not supported.

Can you add a unit test with a // fallthough comment, and a /* FALLTHROUGH */ and [[fallthrough]] so we know whats going to happen in those cases at a minimum.

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"

That's a great point. I didn't really consider this, and currently this particular case won't align the case statements if they have an empty case block, however if you had some tokens (e.g. // fallthrough) it would. It's not immediately clear to me what the expectation would be. I guess to align as if there was an invisible trailing token, but it's a bit awkward if the cases missing a body are the 'long' cases that push out the alignment. Also, I don't think it's possible to use AlignTokens and get this behavior, as there is no token on those lines to align, so it's not straightforward to handle. I guess I'll be curious to see if there is feedback or cases where this behavior is desired, and if so, I can look into adding that functionality later. Since right now it would involve a completely custom AlignTokens clone, my preference would be to just leave this as not supported.

I'd say: align it.

If it was straightforward, I would definitely agree to just align across empty case labels, but unfortunately there is no way to do that while using the generic AlignTokens (since the line with just a case has no token which matches the pattern, but needs to not break the alignment streak). I guess the way to do it generically would be to add some sort of ExcludeLine lambda to allow filtering out lines. Given that I don't think this is a common pattern with these 'Short Case Labels', and it's fairly easy to work around with [[fallthrough]]; my plan is just to leave this as is (and add a test to make the behavior explicit).

did you consider a case where the case falls through? (i.e. no return)

"case log::info :    return \"info\";\n"
"case log::warning :\n"
"default :           return \"default\";\n"

That's a great point. I didn't really consider this, and currently this particular case won't align the case statements if they have an empty case block, however if you had some tokens (e.g. // fallthrough) it would. It's not immediately clear to me what the expectation would be. I guess to align as if there was an invisible trailing token, but it's a bit awkward if the cases missing a body are the 'long' cases that push out the alignment. Also, I don't think it's possible to use AlignTokens and get this behavior, as there is no token on those lines to align, so it's not straightforward to handle. I guess I'll be curious to see if there is feedback or cases where this behavior is desired, and if so, I can look into adding that functionality later. Since right now it would involve a completely custom AlignTokens clone, my preference would be to just leave this as not supported.

Can you add a unit test with a // fallthough comment, and a /* FALLTHROUGH */ and [[fallthrough]] so we know whats going to happen in those cases at a minimum.

Done. This actually caught an issue I wasn't aware of where if you use //fallthrough and the comment needs to be reflowed, you get two Change entries pointing to the same comment token, which throws off the algorithm, and results in broken alignment. Attempted to fix it up to ignore the inner reflow change and it seems to work in my basic validation.

I'd say: align it.

If it was straightforward, I would definitely agree to just align across empty case labels, but unfortunately there is no way to do that while using the generic AlignTokens (since the line with just a case has no token which matches the pattern, but needs to not break the alignment streak). I guess the way to do it generically would be to add some sort of ExcludeLine lambda to allow filtering out lines. Given that I don't think this is a common pattern with these 'Short Case Labels', and it's fairly easy to work around with [[fallthrough]]; my plan is just to leave this as is (and add a test to make the behavior explicit).

Leaving it open (and documenting that) I could get behind, but making it explicit as desired behavior will not get my approval. On the other hand I will not stand in the way, if the others approve.

I'd say: align it.

If it was straightforward, I would definitely agree to just align across empty case labels, but unfortunately there is no way to do that while using the generic AlignTokens (since the line with just a case has no token which matches the pattern, but needs to not break the alignment streak). I guess the way to do it generically would be to add some sort of ExcludeLine lambda to allow filtering out lines. Given that I don't think this is a common pattern with these 'Short Case Labels', and it's fairly easy to work around with [[fallthrough]]; my plan is just to leave this as is (and add a test to make the behavior explicit).

Leaving it open (and documenting that) I could get behind, but making it explicit as desired behavior will not get my approval. On the other hand I will not stand in the way, if the others approve.

Yah, I think leaving it open would be my preference at this point. Not sure how to properly document that though? Just be explicit in the tests? Mention it in alignConsecutiveShortCaseStatements? Should it be documented in the generated documentation (that feels a bit heavy)?

Yah, I think leaving it open would be my preference at this point. Not sure how to properly document that though? Just be explicit in the tests? Mention it in alignConsecutiveShortCaseStatements? Should it be documented in the generated documentation (that feels a bit heavy)?

It will be a known issue, and thus it should be documented explicitly in my opinion. Otherwise there will be bug reports. So I would do:

  • Mention it in the options documentation.
  • Add a FIXME comment where the fix most likely would be applied.
  • Comment on test cases that they have to be changed once this is fixed - or add tests which are within an #if 0, don't know what @MyDeveloperDay or @owenpan like better.

After I came across some of my code, where I'd really like a feature like this, I'm back at wishing to align the colons. Same as in a bit field. And when you would do that I think there would be no open issue with empty statements, right?

So for my code I'd favor

switch (level) {
case log::info    : return "info:     ";
case log::warning : return "warning:  ";
case log::error   : return "error:    ";
case log::critical: return "critical: ";
default           : return "";
}

over

switch (level) {
case log::info:     return "info:     ";
case log::warning:  return "warning:  ";
case log::error:    return "error:    ";
case log::critical: return "critical: ";
default:            return "";
}

(For me actually there would always be at least one space before the colon.)
Maybe think about it?

galenelias edited the summary of this revision. (Show Details)

Ok, I added the ability to align the case label colons. In your original message you mentioned "I'd like to align the colon (and thus the statement behind that)" which implies actually adding the whitespace after the 'case' token itself. Not sure if that would still be your preference in an ideal world, or if I just misinterpreted your request. Aligning the colons themselves is very straightforward.

I opted to make this an option on AlignConsecutiveStyle, as that is consistent with how we customize some of the other AlignConsecutive* options, and it seemed awkward to add a floating top level boolean config option which applied to just this scenario - although it has the similar downside that it muddies the AlignConsecutiveStyle options for the other use cases.

Well, I guess I didn't put quite enough thought into the AlignCaseColons option. While this solves the empty case label problem, it will also match in non-short case label scenarios such as the following, which doesn't seem desirable:

switch (level) {
case log::info  :
case log::error :
  return true;
case log::none     :
case log::warning  :
case log::critical :
  return false;
}

In order to solve this (and the other) issues, I think the only solution is to roll a custom alignment method instead of using AlignTokens, so that the alignment can be more correctly based on the detection of short case statements.

This is going to take considerably more time and code, so not sure when I'll be able to work on it.

Yah, I think leaving it open would be my preference at this point. Not sure how to properly document that though? Just be explicit in the tests? Mention it in alignConsecutiveShortCaseStatements? Should it be documented in the generated documentation (that feels a bit heavy)?

It will be a known issue, and thus it should be documented explicitly in my opinion. Otherwise there will be bug reports. So I would do:

  • Mention it in the options documentation.
  • Add a FIXME comment where the fix most likely would be applied.
  • Comment on test cases that they have to be changed once this is fixed - or add tests which are within an #if 0, don't know what @MyDeveloperDay or @owenpan like better.

I prefer the latter, and IIRC @MyDeveloperDay doesn't use the former.

Well, I guess I didn't put quite enough thought into the AlignCaseColons option. While this solves the empty case label problem, it will also match in non-short case label scenarios such as the following, which doesn't seem desirable:

switch (level) {
case log::info  :
case log::error :
  return true;
case log::none     :
case log::warning  :
case log::critical :
  return false;
}

In order to solve this (and the other) issues, I think the only solution is to roll a custom alignment method instead of using AlignTokens, so that the alignment can be more correctly based on the detection of short case statements.

This is going to take considerably more time and code, so not sure when I'll be able to work on it.

For me this would actually be desired. But from the name ShortCaseStatements I can see that it may be not what we want. This could be fixed with just renaming to ConsecutiveCaseStatements. :)

Ok, I added the ability to align the case label colons. In your original message you mentioned "I'd like to align the colon (and thus the statement behind that)" which implies actually adding the whitespace after the 'case' token itself. Not sure if that would still be your preference in an ideal world, or if I just misinterpreted your request. Aligning the colons themselves is very straightforward.

I opted to make this an option on AlignConsecutiveStyle, as that is consistent with how we customize some of the other AlignConsecutive* options, and it seemed awkward to add a floating top level boolean config option which applied to just this scenario - although it has the similar downside that it muddies the AlignConsecutiveStyle options for the other use cases.

I have no problem with that, but the full disclosure is: @MyDeveloperDay isn't happy with e.g. PadOperators and thus will most likely not like this.

I think we need some input what should be able to be aligned - the statement vs. the colon - and only short case statements vs all case statements.

clang/include/clang/Format/Format.h
257

I'd also sort this alphabetically.

clang/lib/Format/WhitespaceManager.cpp
854

else after return can be dropped.

I think we need some input what should be able to be aligned - the statement vs. the colon - and only short case statements vs all case statements.

I think we should align the colons only for short case statements and don't align if AllowShortCaseLabelsOnASingleLine is false.

galenelias updated this revision to Diff 537383.Jul 5 2023, 9:24 AM
galenelias edited the summary of this revision. (Show Details)

I re-wrote the alignment to stop using AlignTokens so that I can now handle all the edge cases that came up. Specifically:

  • Allowing empty case labels (implicit fall through) to not break the alignment, but only if they are sandwiched by short case statements.
  • Don't align the colon of a non-short case label that follows short case labels when using 'AlignCaseColons=true'.
  • Empty case labels will also now push out the alignment of the statements when using AlignCaseColons=false.

Also, this now avoids having to add the IgnoreNestedScopes parameter to AlignTokens which didn't feel great.

I refactored AlignMacroSequence so I could re-use the core aligning method, since it's the same logic I need, but I removed some of the dead code just to simplify things along the way. But even with that, this version is quite a bit more code (~100 lines vs. ~30 lines).

I re-wrote the alignment to stop using AlignTokens so that I can now handle all the edge cases that came up. Specifically:

  • Allowing empty case labels (implicit fall through) to not break the alignment, but only if they are sandwiched by short case statements.
  • Don't align the colon of a non-short case label that follows short case labels when using 'AlignCaseColons=true'.
  • Empty case labels will also now push out the alignment of the statements when using AlignCaseColons=false.

Also, this now avoids having to add the IgnoreNestedScopes parameter to AlignTokens which didn't feel great.

I refactored AlignMacroSequence so I could re-use the core aligning method, since it's the same logic I need, but I removed some of the dead code just to simplify things along the way. But even with that, this version is quite a bit more code (~100 lines vs. ~30 lines).

Nice work!

clang/include/clang/Format/Format.h
311

Since you are not using AlignTokens anymore, I'd say use your own struct. You don't have the not used memberand you don't have to add a new member which is not used by AlignTokens.

clang/lib/Format/WhitespaceManager.cpp
109

Is this the right position?
Could you add a test with aligning assignments and case statements?

case XX: xx = 2; break;
case X: x = 1; break;

It should end up as

case XX: xx = 2; break;
case X:  x  = 1; break;
galenelias marked an inline comment as done.Jul 7 2023, 12:23 PM
galenelias added inline comments.
clang/include/clang/Format/Format.h
311

Sure. Will post an iteration with this - hopefully I'm getting all the plumbing correct.

clang/lib/Format/WhitespaceManager.cpp
109

Great point, I hadn't actually really fully considered the ordering dependency here. I agree that aligning short case statements before assignments (and probably declarations?) seems more correct. However, these other alignConsecutive* methods don't actually align across scopes, so won't align declarations/assignments within the body of a case statement. I verified that these don't align today using AlignConsecutiveAssignments. I will however move this up to try to make it as logically correct as possible.

galenelias marked an inline comment as done.
galenelias edited the summary of this revision. (Show Details)

This iteration switches away from using AlignConsecutiveStyle and instead uses a new ShortCaseStatementsAlignmentStyle.

clang/include/clang/Format/Format.h
380

I'd drop that. We don't have it for any other struct.

And with C++20 you don't need this anymore (although I don't know when llvm will switch to c++20).

clang/lib/Format/WhitespaceManager.cpp
109

Too bad, that would really be nice. :)
But certainly out of scope for this change.

clang/unittests/Format/ConfigParseTest.cpp
326

You now have to write your own checks for the parsing. (It's just copy & paste.)

galenelias marked 6 inline comments as done.Jul 7 2023, 3:49 PM
galenelias added inline comments.
clang/include/clang/Format/Format.h
380

We do have it for TrailingCommentsAlignmentStyle and AlignConsecutiveStyle, but I will drop it.

clang/unittests/Format/ConfigParseTest.cpp
326

Aah, I had missed the CHECK_PARSE_NESTED_BOOLs for the existing alignConsecutive options within their macro. Will fix. Thanks

galenelias updated this revision to Diff 538288.Jul 7 2023, 3:50 PM
galenelias marked 2 inline comments as done.

Addressed outstanding review comments.

Thanks for the patience, I'm really looking forward to use this.

But please wait for other opinions.

This revision is now accepted and ready to land.Jul 8 2023, 1:13 PM

Thanks for the patience, I'm really looking forward to use this.

But please wait for other opinions.

Thanks so much @HazardyKnusperkeks for all the feedback and help. Out of curiosity, how long is typical to wait for additional opinions? I just want to make sure this doesn't get lost.

FWIW, I think we can use a shorter name AlignConsecutiveCaseStatements instead of AlignConsecutiveShortCaseStatements.

clang/lib/Format/WhitespaceManager.cpp
854

No else after return.

859–860

Please remove the redundant parentheses.

909
913
clang/unittests/Format/FormatTest.cpp
19270

They are the same, but I can't use the single string version, as that one calls test::messUp on the string which will strip blank lines, which then invalidates the test case. It seems pretty much all tests which are trying to validate behavior around empty spaces has to use the two string version.

We have verifyNoChange for that now.

19284–19293
galenelias marked 6 inline comments as done.Jul 24 2023, 8:08 AM

FWIW, I think we can use a shorter name AlignConsecutiveCaseStatements instead of AlignConsecutiveShortCaseStatements.

My only hesitation with that name is that it might seem like something like there should be some alignment being applied to 'normal' consecutive case statements, which there isn't. Maybe it's fine because the documentation makes it clear? I'm definitely not picky about the name, whatever sounds idiomatic. @HazardyKnusperkeks, thoughts on just AlignConsecutiveCaseStatements?

switch (level) {
case 0:
case 100:
   return "error";
}

Addresses latest review comments.

owenpan accepted this revision.Jul 24 2023, 9:52 AM

FWIW, I think we can use a shorter name AlignConsecutiveCaseStatements instead of AlignConsecutiveShortCaseStatements.

My only hesitation with that name is that it might seem like something like there should be some alignment being applied to 'normal' consecutive case statements, which there isn't. Maybe it's fine because the documentation makes it clear? I'm definitely not picky about the name, whatever sounds idiomatic. @HazardyKnusperkeks, thoughts on just AlignConsecutiveCaseStatements?

switch (level) {
case 0:
case 100:
   return "error";
}

Strictly speaking, case 0: in the example above is an empty case statement, so if we really want to be precise and verbose, we should use AlignConsecutiveNonEmptyCaseStatements or even AlignConsecutiveNonEmptyShortCaseStatements? I still prefer the shorter AlignConsecutiveCaseStatements, but will leave it to others.

All of those variants are fine by me, but I'd stick with the current version, because it is linked to AllowShortCaseLabelsOnASingleLine.

This revision was automatically updated to reflect the committed changes.