This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Fix comment levels between '}' and PPDirective
ClosedPublic

Authored by krasimir on Jul 17 2017, 7:53 AM.

Details

Summary

This fixes a regression exposed by r307795 in which the level of a comment line
between '}' and a preprocessor directive is incorrectly set as the level of the
line before the '}'. In effect, this:

int f(int i) {
  int j = i;
  return i + j;
}
// comment

#ifdef A
#endif

was formatted as:

int f(int i) {
  int j = i;
  return i + j;
}
  // comment

#ifdef A
#endif

Diff Detail

Repository
rL LLVM

Event Timeline

krasimir created this revision.Jul 17 2017, 7:53 AM
krasimir added a subscriber: cfe-commits.
djasper added inline comments.Jul 18 2017, 2:22 AM
lib/Format/UnwrappedLineParser.cpp
489 ↗(On Diff #106871)

What happens if you instead change the Line->Level = InitialLevel; statement from below to before this line? That seems like the more intuitively correct fix.

2378 ↗(On Diff #106871)

LLVM style requires a line break.

unittests/Format/FormatTestComments.cpp
848 ↗(On Diff #106871)

Generally, mess up the code in some way to ensure that it is actually being formatted.

krasimir updated this revision to Diff 107038.Jul 18 2017, 2:58 AM
krasimir marked 2 inline comments as done.
  • Fix formatting
krasimir added inline comments.Jul 18 2017, 2:58 AM
lib/Format/UnwrappedLineParser.cpp
489 ↗(On Diff #106871)

This doesn't work since comments before the right brace haven't been emitted yet and would get the wrong level.

unittests/Format/FormatTestComments.cpp
848 ↗(On Diff #106871)

Messing up doesn't work in this case, because we rely on the original columns of the comment and the previous line. That's why I added a bunch of tests.

krasimir updated this revision to Diff 107087.Jul 18 2017, 6:14 AM
  • Remove TODO test case
djasper added inline comments.Jul 18 2017, 7:38 AM
lib/Format/UnwrappedLineParser.cpp
2378 ↗(On Diff #107038)

What happens if we always set the Level to 0 here?

489 ↗(On Diff #106871)

So that means this seems to be the interesting case:

void f() {
  DoSomething();
  // This was a fun function.
}
// Cool macro:
#define A a

Now, both comments are basically read when we are reading the "}", but they should have different indentation levels. I have another suggestion, see below.

unittests/Format/FormatTestComments.cpp
848 ↗(On Diff #106871)

I meant *manually* mess up. So add spaces here and there.

krasimir marked 2 inline comments as done.Jul 18 2017, 8:02 AM
krasimir added inline comments.
lib/Format/UnwrappedLineParser.cpp
2378 ↗(On Diff #107038)

If we always set the Level to 0 here, then

void  f() {
  int i;
  /* comment */

#define A
}

gets indented as

void  f() {
  int i;
/* comment */

#define A
}
489 ↗(On Diff #106871)

Here is another breaking test in case we change Line->Level = InitialLevel to above this line:

switch (x) {
default: {
  // Do nothing.
}
}

gets reformatted as:

switch (x) {
default: {
// Do nothing.
}
}
krasimir updated this revision to Diff 107285.Jul 19 2017, 5:26 AM
krasimir marked 2 inline comments as done.
  • Manually messed up tests
djasper added inline comments.Jul 19 2017, 7:43 AM
lib/Format/UnwrappedLineParser.cpp
489 ↗(On Diff #106871)

I think we can fix all of these cases by doing:

flushComments(isOnNewLine(*FormatTok));
Line->Level = InitialLevel;
nextToken(); // Munch the closing brace.

(so add the first two lines here, remove Line->Level = InitialLevel; below.

krasimir updated this revision to Diff 107314.Jul 19 2017, 8:51 AM
  • Adapt the fix from comment suggestion
lib/Format/UnwrappedLineParser.cpp
489 ↗(On Diff #106871)

Cool! Thanks!

djasper accepted this revision.Jul 21 2017, 2:04 AM

Looks good.

This revision is now accepted and ready to land.Jul 21 2017, 2:04 AM
This revision was automatically updated to reflect the committed changes.