From c78c6b35d398b4c9414e7c5c7e413e28a66c8c5f Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Thu, 14 Feb 2013 09:58:41 +0000 Subject: [PATCH] Remove the trailing whitespace of formatted lines. So far, clang-format has always assumed the whitespace belonging to the subsequent token. This has the negative side-effect that when clang-format formats a line, it does not remove its trailing whitespace, as it belongs to the next token. Thus, this patch fixes most of llvm.org/PR15062. We are not zapping a file's trailing whitespace so far, as this does not belong to any token we see during formatting. We need to fix this in a subsequent patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175152 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 34 ++++++++++++++++++++------------- unittests/Format/FormatTest.cpp | 4 ++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index f03b77853c..c50bfb0a70 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -960,16 +960,17 @@ public: Annotator.calculateFormattingInformation(AnnotatedLines[i]); } std::vector IndentForLevel; + bool PreviousLineWasTouched = false; for (std::vector::iterator I = AnnotatedLines.begin(), E = AnnotatedLines.end(); I != E; ++I) { const AnnotatedLine &TheLine = *I; - int Offset = GetIndentOffset(TheLine.First); + int Offset = getIndentOffset(TheLine.First); while (IndentForLevel.size() <= TheLine.Level) IndentForLevel.push_back(-1); IndentForLevel.resize(TheLine.Level + 1); if (touchesRanges(TheLine) && TheLine.Type != LT_Invalid) { - unsigned LevelIndent = GetIndent(IndentForLevel, TheLine.Level); + unsigned LevelIndent = getIndent(IndentForLevel, TheLine.Level); unsigned Indent = LevelIndent; if (static_cast(Indent) + Offset >= 0) Indent += Offset; @@ -987,15 +988,8 @@ public: StructuralError); PreviousEndOfLineColumn = Formatter.format(); IndentForLevel[TheLine.Level] = LevelIndent; + PreviousLineWasTouched = true; } else { - // If we did not reformat this unwrapped line, the column at the end of - // the last token is unchanged - thus, we can calculate the end of the - // last token. - PreviousEndOfLineColumn = - SourceMgr.getSpellingColumnNumber( - TheLine.Last->FormatTok.Tok.getLocation()) + - Lex.MeasureTokenLength(TheLine.Last->FormatTok.Tok.getLocation(), - SourceMgr, Lex.getLangOpts()) - 1; if (TheLine.First.FormatTok.NewlinesBefore > 0 || TheLine.First.FormatTok.IsFirst) { unsigned Indent = SourceMgr.getSpellingColumnNumber( @@ -1004,7 +998,21 @@ public: if (static_cast(LevelIndent) - Offset >= 0) LevelIndent -= Offset; IndentForLevel[TheLine.Level] = LevelIndent; + + // Remove trailing whitespace of the previous line if it was touched. + if (PreviousLineWasTouched) + formatFirstToken(TheLine.First, Indent, TheLine.InPPDirective, + PreviousEndOfLineColumn); } + // If we did not reformat this unwrapped line, the column at the end of + // the last token is unchanged - thus, we can calculate the end of the + // last token. + PreviousEndOfLineColumn = + SourceMgr.getSpellingColumnNumber( + TheLine.Last->FormatTok.Tok.getLocation()) + + Lex.MeasureTokenLength(TheLine.Last->FormatTok.Tok.getLocation(), + SourceMgr, Lex.getLangOpts()) - 1; + PreviousLineWasTouched = false; } } return Whitespaces.generateReplacements(); @@ -1016,20 +1024,20 @@ private: /// \p IndentForLevel must contain the indent for the level \c l /// at \p IndentForLevel[l], or a value < 0 if the indent for /// that level is unknown. - unsigned GetIndent(const std::vector IndentForLevel, + unsigned getIndent(const std::vector IndentForLevel, unsigned Level) { if (IndentForLevel[Level] != -1) return IndentForLevel[Level]; if (Level == 0) return 0; - return GetIndent(IndentForLevel, Level - 1) + 2; + return getIndent(IndentForLevel, Level - 1) + 2; } /// \brief Get the offset of the line relatively to the level. /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int GetIndentOffset(const AnnotatedToken &RootToken) { + int getIndentOffset(const AnnotatedToken &RootToken) { bool IsAccessModifier = false; if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) || RootToken.is(tok::kw_private)) diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index e99aad7a8c..232cd6b98a 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -162,6 +162,10 @@ TEST_F(FormatTest, OnlyGeneratesNecessaryReplacements) { EXPECT_EQ(0, ReplacementCount); } +TEST_F(FormatTest, RemovesTrailingWhitespaceOfFormattedLine) { + EXPECT_EQ("int a;\nint b;", format("int a; \nint b;", 0, 0, getLLVMStyle())); +} + //===----------------------------------------------------------------------===// // Tests for control statements. //===----------------------------------------------------------------------===// -- 2.40.0