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.

llvm-svn: 175152
This commit is contained in:
Daniel Jasper 2013-02-14 09:58:41 +00:00
parent 66e9dee707
commit 2457010b1c
2 changed files with 25 additions and 13 deletions

View File

@ -960,16 +960,17 @@ public:
Annotator.calculateFormattingInformation(AnnotatedLines[i]);
}
std::vector<int> IndentForLevel;
bool PreviousLineWasTouched = false;
for (std::vector<AnnotatedLine>::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<int>(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<int>(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<int> IndentForLevel,
unsigned getIndent(const std::vector<int> 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))

View File

@ -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.
//===----------------------------------------------------------------------===//