Fixes multiple formatting bugs.

Fixes:
- incorrect handling of multiple consecutive preprocessor directives
- crash when trying to right align the escpaed newline for a line that
  is longer than the column limit
- using only ColumnLimit-1 columns when layouting with escaped newlines
  inside preprocessor directives

llvm-svn: 171401
This commit is contained in:
Manuel Klimek 2013-01-02 18:33:23 +00:00
parent 90e51fdbab
commit b69e3c6201
2 changed files with 58 additions and 11 deletions

View File

@ -237,6 +237,7 @@ private:
unsigned ParenLevel = State.Indent.size() - 1;
if (Newline) {
unsigned WhitespaceStartColumn = State.Column;
if (Current.Tok.is(tok::string_literal) &&
Previous.Tok.is(tok::string_literal)) {
State.Column = State.Column - Previous.Tok.getLength();
@ -264,8 +265,12 @@ private:
State.LineContainsContinuedForLoopSection =
Previous.Tok.isNot(tok::semi);
if (!DryRun)
replaceWhitespace(Current, 1, State.Column);
if (!DryRun) {
if (!Line.InPPDirective)
replaceWhitespace(Current, 1, State.Column);
else
replacePPWhitespace(Current, 1, State.Column, WhitespaceStartColumn);
}
State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
if (Current.Tok.is(tok::colon) &&
@ -398,7 +403,7 @@ private:
addTokenToState(NewLine, true, State);
// Exceeding column limit is bad.
if (State.Column > Style.ColumnLimit)
if (State.Column > Style.ColumnLimit - (Line.InPPDirective ? 1 : 0))
return UINT_MAX;
if (StopAt <= CurrentPenalty)
@ -434,12 +439,22 @@ private:
/// each \c FormatToken.
void replaceWhitespace(const FormatToken &Tok, unsigned NewLines,
unsigned Spaces) {
Replaces.insert(tooling::Replacement(
SourceMgr, Tok.WhiteSpaceStart, Tok.WhiteSpaceLength,
std::string(NewLines, '\n') + std::string(Spaces, ' ')));
}
/// \brief Like \c replaceWhitespace, but additionally adds right-aligned
/// backslashes to escape newlines inside a preprocessor directive.
///
/// This function and \c replaceWhitespace have the same behavior if
/// \c Newlines == 0.
void replacePPWhitespace(const FormatToken &Tok, unsigned NewLines,
unsigned Spaces, unsigned WhitespaceStartColumn) {
std::string NewLineText;
if (!Line.InPPDirective) {
NewLineText = std::string(NewLines, '\n');
} else if (NewLines > 0) {
if (NewLines > 0) {
unsigned Offset =
SourceMgr.getSpellingColumnNumber(Tok.WhiteSpaceStart) - 1;
std::min<int>(Style.ColumnLimit - 1, WhitespaceStartColumn);
for (unsigned i = 0; i < NewLines; ++i) {
NewLineText += std::string(Style.ColumnLimit - Offset - 1, ' ');
NewLineText += "\\\n";
@ -469,7 +484,11 @@ private:
Token.Tok.is(tok::kw_private)) &&
static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
Indent += Style.AccessModifierOffset;
replaceWhitespace(Token, Newlines, Indent);
if (!Line.InPPDirective || Token.HasUnescapedNewline)
replaceWhitespace(Token, Newlines, Indent);
else
// FIXME: Figure out how to get the previous end-of-line column.
replacePPWhitespace(Token, Newlines, Indent, 0);
return Indent;
}

View File

@ -64,12 +64,19 @@ protected:
return MessedUp;
}
void verifyFormat(llvm::StringRef Code) {
EXPECT_EQ(Code.str(), format(messUp(Code)));
FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
FormatStyle Style = getLLVMStyle();
Style.ColumnLimit = ColumnLimit;
return Style;
}
void verifyFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
EXPECT_EQ(Code.str(), format(messUp(Code), Style));
}
void verifyGoogleFormat(llvm::StringRef Code) {
EXPECT_EQ(Code.str(), format(messUp(Code), getGoogleStyle()));
verifyFormat(Code, getGoogleStyle());
}
};
@ -396,6 +403,27 @@ TEST_F(FormatTest, EndOfFileEndsPPDirective) {
EXPECT_EQ("#define A B", format("# \\\n define \\\n A \\\n B"));
}
TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) {
// If the macro fits in one line, we have the full width.
verifyFormat("#define A(B)", getLLVMStyleWithColumns(12));
verifyFormat("#define A(\\\n B)", getLLVMStyleWithColumns(11));
verifyFormat("#define AA(\\\n B)", getLLVMStyleWithColumns(11));
verifyFormat("#define A( \\\n A, B)", getLLVMStyleWithColumns(12));
}
TEST_F(FormatTest, HandlePreprocessorDirectiveContext) {
verifyFormat(
"// some comment\n"
"\n"
"#include \"a.h\"\n"
"#define A(A,\\\n"
" B)\n"
"#include \"b.h\"\n"
"\n"
"// some comment\n", getLLVMStyleWithColumns(13));
}
TEST_F(FormatTest, MixingPreprocessorDirectivesAndNormalCode) {
verifyFormat("#define ALooooooooooooooooooooooooooooooooooooooongMacro("
" \\\n"