From: Daniel Jasper Date: Sun, 1 Nov 2015 00:27:35 +0000 (+0000) Subject: clang-format: Be slightly more cautious when formatting subsequent lines after a... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49747fe0fe3344f5e9010fd0d269af9d17e32f28;p=clang 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251760 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index fcf45c9286..5b4f5d5b09 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -812,13 +812,28 @@ UnwrappedLineFormatter::format(const SmallVectorImpl &Lines, 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 SmallVectorImpl &Lines, 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 SmallVectorImpl &Lines, Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective); } NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker); - PreviousLineFormatted = false; + RangeMinLevel = UINT_MAX; } if (!DryRun) markFinalized(TheLine.First); diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp index a28dfd32e1..9c4d1c3d2b 100644 --- a/unittests/Format/FormatTestSelective.cpp +++ b/unittests/Format/FormatTestSelective.cpp @@ -446,6 +446,27 @@ TEST_F(FormatTestSelective, UnderstandsTabs) { 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