r251760 - clang-format: Be slightly more cautious when formatting subsequent lines after a change. With r251474, clang-format could indent the entire rest of the file, if there is a missing closing brace, e.g. while writing code in an editor.

Daniel Jasper via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 31 17:27:36 PDT 2015


Author: djasper
Date: Sat Oct 31 19:27:35 2015
New Revision: 251760

URL: http://llvm.org/viewvc/llvm-project?rev=251760&view=rev
Log:
clang-format: Be slightly more cautious when formatting subsequent lines after a change. With r251474, clang-format could indent the entire rest of the file, if there is a missing closing brace, e.g. while writing code in an editor.

Summary:
With this change, clang-format stops formatting when either it leaves
the current scope or when it comes back to the initial scope after
going into a nested one.

Reviewers: klimek

Subscribers: cfe-commits, klimek

Differential Revision: http://reviews.llvm.org/D14213

Modified:
    cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
    cfe/trunk/unittests/Format/FormatTestSelective.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=251760&r1=251759&r2=251760&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp Sat Oct 31 19:27:35 2015
@@ -812,13 +812,28 @@ UnwrappedLineFormatter::format(const Sma
                                    AdditionalIndent);
   const AnnotatedLine *PreviousLine = nullptr;
   const AnnotatedLine *NextLine = nullptr;
-  bool PreviousLineFormatted = false;
+
+  // The minimum level of consecutive lines that have been formatted.
+  unsigned RangeMinLevel = UINT_MAX;
+  // The level of the previous line.
+  unsigned PreviousLineLevel = Lines.front()->Level;
+
   for (const AnnotatedLine *Line =
            Joiner.getNextMergedLine(DryRun, IndentTracker);
        Line; Line = NextLine) {
     const AnnotatedLine &TheLine = *Line;
     unsigned Indent = IndentTracker.getIndent();
-    bool FixIndentation = (FixBadIndentation || PreviousLineFormatted) &&
+
+    // We continue formatting unchanged lines to adjust their indent, e.g. if a
+    // scope was added. However, we need to carefully stop doing this when we
+    // exit the scope of affected lines to prevent indenting a the entire
+    // remaining file if it currently missing a closing brace.
+    bool ContinueFormatting =
+        TheLine.Level > RangeMinLevel ||
+        (TheLine.Level == RangeMinLevel && PreviousLineLevel <= TheLine.Level);
+    PreviousLineLevel = TheLine.Level;
+
+    bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
                           Indent != TheLine.First->OriginalColumn;
     bool ShouldFormat = TheLine.Affected || FixIndentation;
     // We cannot format this line; if the reason is that the line had a
@@ -846,7 +861,7 @@ UnwrappedLineFormatter::format(const Sma
       else
         Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
                        .formatLine(TheLine, Indent, DryRun);
-      PreviousLineFormatted = true;
+      RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);
     } else {
       // If no token in the current line is affected, we still need to format
       // affected children.
@@ -877,7 +892,7 @@ UnwrappedLineFormatter::format(const Sma
           Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
       }
       NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
-      PreviousLineFormatted = false;
+      RangeMinLevel = UINT_MAX;
     }
     if (!DryRun)
       markFinalized(TheLine.First);

Modified: cfe/trunk/unittests/Format/FormatTestSelective.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestSelective.cpp?rev=251760&r1=251759&r2=251760&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestSelective.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestSelective.cpp Sat Oct 31 19:27:35 2015
@@ -446,6 +446,27 @@ TEST_F(FormatTestSelective, UnderstandsT
                    21, 0));
 }
 
+TEST_F(FormatTestSelective, StopFormattingWhenLeavingScope) {
+  EXPECT_EQ(
+      "void f() {\n"
+      "  if (a) {\n"
+      "    g();\n"
+      "    h();\n"
+      "}\n"
+      "\n"
+      "void g() {\n"
+      "}",
+      format("void f() {\n"
+             "  if (a) {\n" // Assume this was added without the closing brace.
+             "  g();\n"
+             "  h();\n"
+             "}\n"
+             "\n"
+             "void g() {\n" // Make sure not to format this.
+             "}",
+             15, 0));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang




More information about the cfe-commits mailing list