This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add a tweak for filling in enumerators of a switch statement.
ClosedPublic

Authored by tdeo on Sep 27 2020, 12:49 PM.

Details

Summary

Add a tweak that populates an empty switch statement of an enumeration type with all of the enumerators of that type.

Before:

enum Color { RED, GREEN, BLUE };
void f(Color color) {
  switch (color) {}
}

After:

enum Color { RED, GREEN, BLUE };
void f(Color color) {
  switch (color) {
  case RED:
  case GREEN:
  case BLUE:
    break;
  }
}

Diff Detail

Event Timeline

tdeo created this revision.Sep 27 2020, 12:49 PM
tdeo requested review of this revision.Sep 27 2020, 12:49 PM
nridge added a subscriber: nridge.Sep 27 2020, 2:36 PM
sammccall accepted this revision.Sep 28 2020, 2:31 AM

This is really nice!

We'd actually debated how to add such a feature, but had assumed it should be a "fix" rather than a "tweak" - I think this way is much better.

Obviously making it fill in the remaining enumerators in the general case would be great to have later. It looks like making prepare() make a cheap decision is the tricky part, but seems doable:

  • bail out if there's a default or a gnu ... case
  • bail out if there are at least as many cases as enumerators
  • bail out if any case expression is value-dependent
  • otherwise we should be able to find some cases to insert

(We're subject to AST error-recovery weirdness - e.g. CaseStmt with non-constants seem to just be deleted - but probably fine to ignore all these).

clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
97

while it's uncommon, there can be stuff other than cases in a switch stmt.
Maybe we simply want to bail out if the body is nonempty?

105

can we add a defensive nullcheck to getCond()?

code like switch() {} is the sort of thing that is often represented in AST as a null pointer.
AFAICT that doesn't happen today (we get no AST nodes at all instead) but I can see that being changed in future to improve recovery.

125

in the case where there's already stuff in the body (just not cases), it seems like RBracLoc-1 might be safer?

This revision is now accepted and ready to land.Sep 28 2020, 2:31 AM
tdeo updated this revision to Diff 294644.EditedSep 28 2020, 4:08 AM
  • Check body is empty instead of having no case statements.
  • Null check the return value from SwitchStmt::getCond.
  • Insert replacement before the right bracket instead of after the left one, for future improvements.
tdeo marked 3 inline comments as done.Sep 28 2020, 4:09 AM

@sammccall, I don't have commit access, so if this revision has no issues, can you land it? Thanks.

@sammccall, I don't have commit access, so if this revision has no issues, can you land it? Thanks.

Absolutely, thanks a lot for the patch!

Any interest in extending to non-empty switches? Or better for someone else to pick that up?

tdeo added a comment.Sep 28 2020, 4:42 AM

@sammccall, I don't have commit access, so if this revision has no issues, can you land it? Thanks.

Absolutely, thanks a lot for the patch!

Any interest in extending to non-empty switches? Or better for someone else to pick that up?

I'd like to give it a shot soon, but I wouldn't mind if someone else did it first.