mzeren-vmw updated this revision to Diff 130487.
mzeren-vmw added a comment.

Documented CommentAlignment enumerators. Documenting them suggested better
enumerator names.

Added tests for multi-line comments, block comments and trailing comments.


Repository:
  rC Clang

https://reviews.llvm.org/D42036

Files:
  lib/Format/TokenAnnotator.cpp
  lib/Format/TokenAnnotator.h
  lib/Format/UnwrappedLineFormatter.cpp
  unittests/Format/FormatTest.cpp

Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -2497,7 +2497,6 @@
                "code();\n"
                "#endif",
                Style);
-
   // Include guards must cover the entire file.
   verifyFormat("code();\n"
                "code();\n"
@@ -2593,21 +2592,97 @@
                    "code();\n"
                    "#endif",
                    Style));
-  // FIXME: The comment indent corrector in TokenAnnotator gets thrown off by
-  // preprocessor indentation.
-  EXPECT_EQ("#if 1\n"
-            "  // comment\n"
-            "#  define A 0\n"
-            "// comment\n"
-            "#  define B 0\n"
-            "#endif",
-            format("#if 1\n"
-                   "// comment\n"
-                   "#  define A 0\n"
-                   "   // comment\n"
-                   "#  define B 0\n"
-                   "#endif",
-                   Style));
+  // Comments aligned to macros stay aligned. This test is incompatible with
+  // verifyFormat() because messUp() removes the alignment.
+  {
+    const char *Expected = ""
+                           "// Level 0 unaligned comment\n"
+                           "// Level 0 unaligned continuation\n"
+                           "#ifndef HEADER_H\n"
+                           "// Level 0 aligned comment\n"
+                           "// Level 0 aligned continuation\n"
+                           "#define HEADER_H\n"
+                           "#if 1\n"
+                           "   // aligned comment\n"
+                           "   // aligned continuation\n"
+                           "#  define A 0\n"
+                           "// un-aligned comment\n"
+                           "// un-aligned continuation\n"
+                           "#  define B 0\n"
+                           "// Trailing aligned comment\n"
+                           "#endif\n"
+                           "#endif";
+    const char *ToFormat = ""
+                           " // Level 0 unaligned comment\n"
+                           " // Level 0 unaligned continuation\n"
+                           "#ifndef HEADER_H\n"
+                           "// Level 0 aligned comment\n"
+                           "// Level 0 aligned continuation\n"
+                           "#define HEADER_H\n"
+                           "#if 1\n"
+                           "   // aligned comment\n"
+                           "   // aligned continuation\n"
+                           "#  define A 0\n"
+                           "  // un-aligned comment\n"
+                           "  // un-aligned continuation\n"
+                           "#  define B 0\n"
+                           "   // Trailing aligned comment\n"
+                           "#endif\n"
+                           "#endif";
+    EXPECT_EQ(Expected, format(ToFormat, Style));
+    EXPECT_EQ(Expected, format(Expected, Style));
+  }
+  // Same as above, but block comments.
+  {
+    const char *Expected = ""
+                           "/*\n"
+                           " * Level 0 unaligned block comment\n"
+                           " */\n"
+                           "#ifndef HEADER_H\n"
+                           "/*\n"
+                           " *  Level 0 aligned comment\n"
+                           " */\n"
+                           "#define HEADER_H\n"
+                           "#if 1\n"
+                           "   /*\n"
+                           "    * Aligned comment\n"
+                           "    */\n"
+                           "#  define A 0\n"
+                           "/*\n"
+                           " * Unaligned comment\n"
+                           " */\n"
+                           "#  define B 0\n"
+                           "/*\n"
+                           " * Trailing aligned comment\n"
+                           " */\n"
+                           "#endif\n"
+                           "#endif";
+    const char *ToFormat = ""
+                           " /*\n"
+                           "  * Level 0 unaligned block comment\n"
+                           "  */\n"
+                           "#ifndef HEADER_H\n"
+                           "/*\n"
+                           " *  Level 0 aligned comment\n"
+                           " */\n"
+                           "#define HEADER_H\n"
+                           "#if 1\n"
+                           "   /*\n"
+                           "    * Aligned comment\n"
+                           "    */\n"
+                           "#  define A 0\n"
+                           "  /*\n"
+                           "   * Unaligned comment\n"
+                           "   */\n"
+                           "#  define B 0\n"
+                           "   /*\n"
+                           "    * Trailing aligned comment\n"
+                           "    */\n"
+                           "#endif\n"
+                           "#endif";
+    EXPECT_EQ(Expected, format(ToFormat, Style));
+    EXPECT_EQ(Expected, format(Expected, Style));
+  }
   // Test with tabs.
   Style.UseTab = FormatStyle::UT_Always;
   Style.IndentWidth = 8;
Index: lib/Format/UnwrappedLineFormatter.cpp
===================================================================
--- lib/Format/UnwrappedLineFormatter.cpp
+++ lib/Format/UnwrappedLineFormatter.cpp
@@ -52,6 +52,7 @@
   /// next.
   void nextLine(const AnnotatedLine &Line) {
     Offset = getIndentOffset(*Line.First);
+    Offset += Line.LevelOffset;
     // Update the indent level cache size so that we can rely on it
     // having the right size in adjustToUnmodifiedline.
     while (IndentForLevel.size() <= Line.Level)
Index: lib/Format/TokenAnnotator.h
===================================================================
--- lib/Format/TokenAnnotator.h
+++ lib/Format/TokenAnnotator.h
@@ -38,7 +38,7 @@
 class AnnotatedLine {
 public:
   AnnotatedLine(const UnwrappedLine &Line)
-      : First(Line.Tokens.front().Tok), Level(Line.Level),
+      : First(Line.Tokens.front().Tok), Level(Line.Level), LevelOffset(0),
         MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
         InPPDirective(Line.InPPDirective),
         MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
@@ -111,6 +111,12 @@
 
   LineType Type;
   unsigned Level;
+
+  /// Adjustment to Level based indent. When comments are aligned to the next
+  /// preprocessor line they must use the same offset as the directive,
+  /// typically 1 due to the leading #.
+  unsigned LevelOffset;
+
   size_t MatchingOpeningBlockLineIndex;
   bool InPPDirective;
   bool MustBeDeclaration;
Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -1707,6 +1707,33 @@
   FormatToken *Current;
 };
 
+enum CommentAlignment {
+  CA_None,      // Comment is not aligned with the next line.
+  CA_First,     // Comment is aligned with the first token on the next line.
+  CA_Directive, // Comment is aligned with the indented preprocessor directive
+                // on the next line.
+};
+
+CommentAlignment getCommentAlignment(const AnnotatedLine &Comment,
+                                     const AnnotatedLine &NextNonComment) {
+  if (NextNonComment.First->NewlinesBefore > 1)
+    return CA_None;
+  // If the next line is an indented preprocessor line look at the directive,
+  // not the #.
+  if ((NextNonComment.Type == LT_PreprocessorDirective ||
+       NextNonComment.Type == LT_ImportStatement) &&
+      NextNonComment.Level > 0 && !Comment.InPPDirective)
+    return NextNonComment.First->Next &&
+                   (Comment.First->OriginalColumn ==
+                    NextNonComment.First->Next->OriginalColumn)
+               ? CA_Directive
+               : CA_None;
+  else
+    return Comment.First->OriginalColumn == NextNonComment.First->OriginalColumn
+               ? CA_First
+               : CA_None;
+}
+
 } // end anonymous namespace
 
 void TokenAnnotator::setCommentLineLevels(
@@ -1723,15 +1750,15 @@
       }
     }
 
-    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 =
-          NextNonCommentLine->First->NewlinesBefore <= 1 &&
-          NextNonCommentLine->First->OriginalColumn ==
-              (*I)->First->OriginalColumn;
-      if (AlignedWithNextLine)
+    // If the comment is aligned with the line immediately following it, that's
+    // probably intentional and we should keep it.
+    if (CommentLine && NextNonCommentLine) {
+      CommentAlignment Alignment =
+          getCommentAlignment(**I, *NextNonCommentLine);
+      if (Alignment != CA_None)
         (*I)->Level = NextNonCommentLine->Level;
+      if (Alignment == CA_Directive)
+        (*I)->LevelOffset = 1;
     } else {
       NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to