/// \brief The column limit.
unsigned ColumnLimit;
- /// \brief The penalty for each character outside of the column limit.
- unsigned PenaltyExcessCharacter;
-
/// \brief The maximum number of consecutive empty lines to keep.
unsigned MaxEmptyLinesToKeep;
+ /// \brief The penalty for each line break introduced inside a comment.
+ unsigned PenaltyBreakComment;
+
+ /// \brief The penalty for each line break introduced inside a string literal.
+ unsigned PenaltyBreakString;
+
+ /// \brief The penalty for each character outside of the column limit.
+ unsigned PenaltyExcessCharacter;
+
/// \brief Set whether & and * bind to the type as opposed to the variable.
bool PointerBindsToType;
IndentWidth == R.IndentWidth &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
+ PenaltyBreakString == R.PenaltyBreakString &&
+ PenaltyBreakComment == R.PenaltyBreakComment &&
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
PointerBindsToType == R.PointerBindsToType &&
unsigned BreakableSingleLineToken::getLineCount() const { return 1; }
-unsigned
-BreakableSingleLineToken::getLineLengthAfterSplit(unsigned LineIndex,
- unsigned TailOffset) const {
+unsigned BreakableSingleLineToken::getLineLengthAfterSplit(
+ unsigned LineIndex, unsigned Offset, StringRef::size_type Length) const {
return StartColumn + Prefix.size() + Postfix.size() +
- encoding::getCodePointCount(Line.substr(TailOffset), Encoding);
+ encoding::getCodePointCount(Line.substr(Offset, Length), Encoding);
}
void BreakableSingleLineToken::insertBreak(unsigned LineIndex,
unsigned BreakableBlockComment::getLineCount() const { return Lines.size(); }
-unsigned
-BreakableBlockComment::getLineLengthAfterSplit(unsigned LineIndex,
- unsigned TailOffset) const {
- return getContentStartColumn(LineIndex, TailOffset) +
- encoding::getCodePointCount(Lines[LineIndex].substr(TailOffset),
+unsigned BreakableBlockComment::getLineLengthAfterSplit(
+ unsigned LineIndex, unsigned Offset, StringRef::size_type Length) const {
+ return getContentStartColumn(LineIndex, Offset) +
+ encoding::getCodePointCount(Lines[LineIndex].substr(Offset, Length),
Encoding) +
// The last line gets a "*/" postfix.
(LineIndex + 1 == Lines.size() ? 2 : 0);
/// strategy into the class, instead of controlling it from the outside.
class BreakableToken {
public:
- // Contains starting character index and length of split.
+ /// \brief Contains starting character index and length of split.
typedef std::pair<StringRef::size_type, unsigned> Split;
virtual ~BreakableToken() {}
/// \brief Returns the number of lines in this token in the original code.
virtual unsigned getLineCount() const = 0;
- /// \brief Returns the rest of the length of the line at \p LineIndex,
- /// when broken at \p TailOffset.
+ /// \brief Returns the number of columns required to format the piece of line
+ /// at \p LineIndex, from byte offset \p Offset with length \p Length.
///
- /// Note that previous breaks are not taken into account. \p TailOffset
- /// is always specified from the start of the (original) line.
- virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
- unsigned TailOffset) const = 0;
+ /// Note that previous breaks are not taken into account. \p Offset is always
+ /// specified from the start of the (original) line.
+ /// \p Length can be set to StringRef::npos, which means "to the end of line".
+ virtual unsigned
+ getLineLengthAfterSplit(unsigned LineIndex, unsigned Offset,
+ StringRef::size_type Length) const = 0;
/// \brief Returns a range (offset, length) at which to break the line at
/// \p LineIndex, if previously broken at \p TailOffset. If possible, do not
public:
virtual unsigned getLineCount() const;
virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
- unsigned TailOffset) const;
+ unsigned TailOffset,
+ StringRef::size_type Length) const;
virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
bool InPPDirective, WhitespaceManager &Whitespaces);
virtual unsigned getLineCount() const;
virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
- unsigned TailOffset) const;
+ unsigned TailOffset,
+ StringRef::size_type Length) const;
virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit) const;
virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("ObjCSpaceBeforeProtocolList",
Style.ObjCSpaceBeforeProtocolList);
+ IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
+ IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.MaxEmptyLinesToKeep = 1;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
+ LLVMStyle.PenaltyBreakComment = 45;
+ LLVMStyle.PenaltyBreakString = 1000;
LLVMStyle.PenaltyExcessCharacter = 1000000;
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 75;
LLVMStyle.PointerBindsToType = false;
GoogleStyle.IndentCaseLabels = true;
GoogleStyle.MaxEmptyLinesToKeep = 1;
GoogleStyle.ObjCSpaceBeforeProtocolList = false;
+ GoogleStyle.PenaltyBreakComment = 45;
+ GoogleStyle.PenaltyBreakString = 1000;
GoogleStyle.PenaltyExcessCharacter = 1000000;
GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
GoogleStyle.PointerBindsToType = true;
Whitespaces);
}
unsigned TailOffset = 0;
- unsigned RemainingTokenColumns =
- Token->getLineLengthAfterSplit(LineIndex, TailOffset);
+ unsigned RemainingTokenColumns = Token->getLineLengthAfterSplit(
+ LineIndex, TailOffset, StringRef::npos);
while (RemainingTokenColumns > RemainingSpace) {
BreakableToken::Split Split =
Token->getSplit(LineIndex, TailOffset, getColumnLimit());
break;
assert(Split.first != 0);
unsigned NewRemainingTokenColumns = Token->getLineLengthAfterSplit(
- LineIndex, TailOffset + Split.first + Split.second);
+ LineIndex, TailOffset + Split.first + Split.second,
+ StringRef::npos);
assert(NewRemainingTokenColumns < RemainingTokenColumns);
if (!DryRun) {
Token->insertBreak(LineIndex, TailOffset, Split, Line.InPPDirective,
Whitespaces);
}
+ Penalty += Current.is(tok::string_literal) ? Style.PenaltyBreakString
+ : Style.PenaltyBreakComment;
+ unsigned ColumnsUsed =
+ Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);
+ if (ColumnsUsed > getColumnLimit()) {
+ Penalty +=
+ Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
+ }
TailOffset += Split.first + Split.second;
RemainingTokenColumns = NewRemainingTokenColumns;
- Penalty += Style.PenaltyExcessCharacter;
BreakInserted = true;
}
PositionAfterLastLineInToken = RemainingTokenColumns;
// '*' has to be a binary operator but determineStarAmpUsage() will
// categorize it as an unary operator, so set the right type here.
if (LookForDecls && CurrentToken->Next) {
- FormatToken *Prev = CurrentToken->Previous;
- FormatToken *Next = CurrentToken->Next;
- if (Prev->Previous->is(tok::identifier) &&
- Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
- CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
- Prev->Type = TT_BinaryOperator;
- LookForDecls = false;
+ FormatToken *Prev = CurrentToken->getPreviousNoneComment();
+ if (Prev) {
+ FormatToken *PrevPrev = Prev->getPreviousNoneComment();
+ FormatToken *Next = CurrentToken->Next;
+ if (PrevPrev && PrevPrev->is(tok::identifier) &&
+ Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
+ CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
+ Prev->Type = TT_BinaryOperator;
+ LookForDecls = false;
+ }
}
}
"};");
verifyGoogleFormat(
"aaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
- " aaaaaaaaaaaaaaaaaaaaaa); // 81 cols with this comment");
+ " aaaaaaaaaaaaaaaaaaaaaa); // 81_cols_with_this_comment");
EXPECT_EQ("D(a, {\n"
" // test\n"
" int a;\n"
format("// A comment before a macro definition\n"
"#define a b",
getLLVMStyleWithColumns(20)));
+}
- EXPECT_EQ("/* A comment before\n"
- " * a macro\n"
- " * definition */\n"
- "#define a b",
- format("/* A comment before a macro definition */\n"
- "#define a b",
- getLLVMStyleWithColumns(20)));
-
- EXPECT_EQ("/* some comment\n"
- " * a comment\n"
- "* that we break\n"
- " * another comment\n"
- "* we have to break\n"
- "* a left comment\n"
- " */",
- format(" /* some comment\n"
- " * a comment that we break\n"
- " * another comment we have to break\n"
- "* a left comment\n"
- " */",
- getLLVMStyleWithColumns(20)));
-
- EXPECT_EQ("/*\n"
- "\n"
- "\n"
- " */\n",
- format(" /* \n"
- " \n"
- " \n"
- " */\n"));
+TEST_F(FormatTest, PriorityOfCommentBreaking) {
+ EXPECT_EQ("if (xxx == yyy && // aaaaaaaaaaaa\n"
+ " // bbbbbbbbb\n"
+ " zzz)\n"
+ " q();",
+ format("if (xxx == yyy && // aaaaaaaaaaaa bbbbbbbbb\n"
+ " zzz) q();",
+ getLLVMStyleWithColumns(40)));
+ EXPECT_EQ("if (xxxxxxxxxx ==\n"
+ " yyy && // aaaaaa bbbbbbbb cccc\n"
+ " zzz)\n"
+ " q();",
+ format("if (xxxxxxxxxx == yyy && // aaaaaa bbbbbbbb cccc\n"
+ " zzz) q();",
+ getLLVMStyleWithColumns(40)));
+ EXPECT_EQ("if (xxxxxxxxxx &&\n"
+ " yyy || // aaaaaa bbbbbbbb cccc\n"
+ " zzz)\n"
+ " q();",
+ format("if (xxxxxxxxxx && yyy || // aaaaaa bbbbbbbb cccc\n"
+ " zzz) q();",
+ getLLVMStyleWithColumns(40)));
+ EXPECT_EQ("fffffffff(&xxx, // aaaaaaaaaaaa\n"
+ " // bbbbbbbbbbb\n"
+ " zzz);",
+ format("fffffffff(&xxx, // aaaaaaaaaaaa bbbbbbbbbbb\n"
+ " zzz);",
+ getLLVMStyleWithColumns(40)));
}
TEST_F(FormatTest, MultiLineCommentsInDefines) {
" ;\n"
"}",
getLLVMStyleWithColumns(30)));
+
+ EXPECT_EQ("/* A comment before\n"
+ " * a macro\n"
+ " * definition */\n"
+ "#define a b",
+ format("/* A comment before a macro definition */\n"
+ "#define a b",
+ getLLVMStyleWithColumns(20)));
+
+ EXPECT_EQ("/* some comment\n"
+ " * a comment\n"
+ "* that we break\n"
+ " * another comment\n"
+ "* we have to break\n"
+ "* a left comment\n"
+ " */",
+ format(" /* some comment\n"
+ " * a comment that we break\n"
+ " * another comment we have to break\n"
+ "* a left comment\n"
+ " */",
+ getLLVMStyleWithColumns(20)));
+
+ EXPECT_EQ("/*\n"
+ "\n"
+ "\n"
+ " */\n",
+ format(" /* \n"
+ " \n"
+ " \n"
+ " */\n"));
}
TEST_F(FormatTest, SplitsLongLinesInCommentsInPreprocessor) {
// FIXME: Without type knowledge, this can still fall apart miserably.
verifyFormat("void f() { my_int a = (my_int) * b; }");
+ verifyFormat("void f() { return P ? (my_int) * P : (my_int)0; }");
verifyFormat("my_int a = (my_int) ~0;");
verifyFormat("my_int a = (my_int)++ a;");
verifyFormat("my_int a = (my_int) + 2;");