Commit 0b67f617 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r323904:

------------------------------------------------------------------------
r323904 | mzeren-vmw | 2018-01-31 21:05:50 +0100 (Wed, 31 Jan 2018) | 34 lines

[clang-format] Align preprocessor comments with #

Summary:
r312125, which introduced preprocessor indentation, shipped with a known
issue where "indentation of comments immediately before indented
preprocessor lines is toggled on each run". For example these two forms
toggle:

  #ifndef HEADER_H
  #define HEADER_H
  #if 1
  // comment
  #   define A 0
  #endif
  #endif

  #ifndef HEADER_H
  #define HEADER_H
  #if 1
     // comment
  #   define A 0
  #endif
  #endif

This happens because we check vertical alignment against the '#' yet
indent to the level of the 'define'. This patch resolves this issue by
aligning against the '#'.

Reviewers: krasimir, klimek, djasper

Reviewed By: krasimir

Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D42408
------------------------------------------------------------------------

llvm-svn: 324329
parent d85785aa
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -1723,15 +1723,18 @@ void TokenAnnotator::setCommentLineLevels(
      }
    }

    if (NextNonCommentLine && CommentLine) {
    // If the comment is currently aligned with the line immediately following
    // it, that's probably intentional and we should keep it.
      bool AlignedWithNextLine =
    if (NextNonCommentLine && CommentLine &&
        NextNonCommentLine->First->NewlinesBefore <= 1 &&
        NextNonCommentLine->First->OriginalColumn ==
              (*I)->First->OriginalColumn;
      if (AlignedWithNextLine)
        (*I)->Level = NextNonCommentLine->Level;
            (*I)->First->OriginalColumn) {
      // Align comments for preprocessor lines with the # in column 0.
      // Otherwise, align with the next line.
      (*I)->Level = (NextNonCommentLine->Type == LT_PreprocessorDirective ||
                     NextNonCommentLine->Type == LT_ImportStatement)
                        ? 0
                        : NextNonCommentLine->Level;
    } else {
      NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
    }
+79 −15
Original line number Diff line number Diff line
@@ -2580,21 +2580,85 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
                   "code();\n"
                   "#endif",
                   Style));
  // FIXME: The comment indent corrector in TokenAnnotator gets thrown off by
  // preprocessor indentation.
  EXPECT_EQ("#if 1\n"
            "  // comment\n"
  // Keep comments aligned with #, otherwise indent comments normally. These
  // tests cannot use verifyFormat because messUp manipulates leading
  // whitespace.
  {
    const char *Expected = ""
                           "void f() {\n"
                           "#if 1\n"
                           "// Preprocessor aligned.\n"
                           "#  define A 0\n"
            "// comment\n"
                           "  // Code. Separated by blank line.\n"
                           "\n"
                           "#  define B 0\n"
            "#endif",
            format("#if 1\n"
                   "// comment\n"
                           "  // Code. Not aligned with #\n"
                           "#  define C 0\n"
                           "#endif";
    const char *ToFormat = ""
                           "void f() {\n"
                           "#if 1\n"
                           "// Preprocessor aligned.\n"
                           "#  define A 0\n"
                   "   // comment\n"
                           "// Code. Separated by blank line.\n"
                           "\n"
                           "#  define B 0\n"
                   "#endif",
                   Style));
                           "   // Code. Not aligned with #\n"
                           "#  define C 0\n"
                           "#endif";
    EXPECT_EQ(Expected, format(ToFormat, Style));
    EXPECT_EQ(Expected, format(Expected, Style));
  }
  // Keep block quotes aligned.
  {
    const char *Expected = ""
                           "void f() {\n"
                           "#if 1\n"
                           "/* Preprocessor aligned. */\n"
                           "#  define A 0\n"
                           "  /* Code. Separated by blank line. */\n"
                           "\n"
                           "#  define B 0\n"
                           "  /* Code. Not aligned with # */\n"
                           "#  define C 0\n"
                           "#endif";
    const char *ToFormat = ""
                           "void f() {\n"
                           "#if 1\n"
                           "/* Preprocessor aligned. */\n"
                           "#  define A 0\n"
                           "/* Code. Separated by blank line. */\n"
                           "\n"
                           "#  define B 0\n"
                           "   /* Code. Not aligned with # */\n"
                           "#  define C 0\n"
                           "#endif";
    EXPECT_EQ(Expected, format(ToFormat, Style));
    EXPECT_EQ(Expected, format(Expected, Style));
  }
  // Keep comments aligned with un-indented directives.
  {
    const char *Expected = ""
                           "void f() {\n"
                           "// Preprocessor aligned.\n"
                           "#define A 0\n"
                           "  // Code. Separated by blank line.\n"
                           "\n"
                           "#define B 0\n"
                           "  // Code. Not aligned with #\n"
                           "#define C 0\n";
    const char *ToFormat = ""
                           "void f() {\n"
                           "// Preprocessor aligned.\n"
                           "#define A 0\n"
                           "// Code. Separated by blank line.\n"
                           "\n"
                           "#define B 0\n"
                           "   // Code. Not aligned with #\n"
                           "#define C 0\n";
    EXPECT_EQ(Expected, format(ToFormat, Style));
    EXPECT_EQ(Expected, format(Expected, Style));
  }
  // Test with tabs.
  Style.UseTab = FormatStyle::UT_Always;
  Style.IndentWidth = 8;