Implemented tab usage only for indentation (http://llvm.org/PR17363)

Summary:
Changed UseTab to be a enum with three options: Never, Always,
ForIndentation (true/false are still supported when reading .clang-format).
IndentLevel should currently be propagated correctly for all tokens, except for
block comments. Please take a look at the general idea before I start dealing
with block comments.

Reviewers: klimek, djasper

Reviewed By: klimek

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1770

llvm-svn: 191527
This commit is contained in:
Alexander Kornienko 2013-09-27 16:14:22 +00:00
parent ca9bd8fac1
commit 3c3d09c885
8 changed files with 228 additions and 96 deletions

View File

@ -166,9 +166,19 @@ struct FormatStyle {
/// \brief If \c true, always break before multiline string literals.
bool AlwaysBreakBeforeMultilineStrings;
/// \brief If \c true, \c IndentWidth consecutive spaces will be replaced
/// with tab characters.
bool UseTab;
/// \brief Different ways to use tab in formatting.
enum UseTabStyle {
/// Never use tab.
UT_Never,
/// Use tabs only for indentation.
UT_ForIndentation,
/// Use tabs whenever we need to fill whitespace that spans at least from
/// one tab stop to the next one.
UT_Always
};
/// \brief The way to use tab characters in the resulting file.
UseTabStyle UseTab;
/// \brief If \c true, binary operators will be placed after line breaks.
bool BreakBeforeBinaryOperators;

View File

@ -145,10 +145,10 @@ unsigned BreakableSingleLineToken::getLineLengthAfterSplit(
}
BreakableSingleLineToken::BreakableSingleLineToken(
const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style)
: BreakableToken(Tok, InPPDirective, Encoding, Style),
const FormatToken &Tok, unsigned IndentLevel, unsigned StartColumn,
StringRef Prefix, StringRef Postfix, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableToken(Tok, IndentLevel, InPPDirective, Encoding, Style),
StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix) {
assert(Tok.TokenText.startswith(Prefix) && Tok.TokenText.endswith(Postfix));
Line = Tok.TokenText.substr(
@ -156,11 +156,11 @@ BreakableSingleLineToken::BreakableSingleLineToken(
}
BreakableStringLiteral::BreakableStringLiteral(
const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style)
: BreakableSingleLineToken(Tok, StartColumn, Prefix, Postfix, InPPDirective,
Encoding, Style) {}
const FormatToken &Tok, unsigned IndentLevel, unsigned StartColumn,
StringRef Prefix, StringRef Postfix, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableSingleLineToken(Tok, IndentLevel, StartColumn, Prefix, Postfix,
InPPDirective, Encoding, Style) {}
BreakableToken::Split
BreakableStringLiteral::getSplit(unsigned LineIndex, unsigned TailOffset,
@ -175,7 +175,7 @@ void BreakableStringLiteral::insertBreak(unsigned LineIndex,
WhitespaceManager &Whitespaces) {
Whitespaces.replaceWhitespaceInToken(
Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
Prefix, InPPDirective, 1, StartColumn);
Prefix, InPPDirective, 1, IndentLevel, StartColumn);
}
static StringRef getLineCommentPrefix(StringRef Comment) {
@ -186,12 +186,10 @@ static StringRef getLineCommentPrefix(StringRef Comment) {
return "";
}
BreakableLineComment::BreakableLineComment(const FormatToken &Token,
unsigned StartColumn,
bool InPPDirective,
encoding::Encoding Encoding,
const FormatStyle &Style)
: BreakableSingleLineToken(Token, StartColumn,
BreakableLineComment::BreakableLineComment(
const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn,
bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableSingleLineToken(Token, IndentLevel, StartColumn,
getLineCommentPrefix(Token.TokenText), "",
InPPDirective, Encoding, Style) {
OriginalPrefix = Prefix;
@ -216,7 +214,7 @@ void BreakableLineComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
WhitespaceManager &Whitespaces) {
Whitespaces.replaceWhitespaceInToken(
Tok, OriginalPrefix.size() + TailOffset + Split.first, Split.second,
Postfix, Prefix, InPPDirective, 1, StartColumn);
Postfix, Prefix, InPPDirective, 1, IndentLevel, StartColumn);
}
void
@ -224,15 +222,15 @@ BreakableLineComment::replaceWhitespaceBefore(unsigned LineIndex,
WhitespaceManager &Whitespaces) {
if (OriginalPrefix != Prefix) {
Whitespaces.replaceWhitespaceInToken(Tok, OriginalPrefix.size(), 0, "", "",
false, 0, 1);
false, 0, /*IndentLevel=*/0, 1);
}
}
BreakableBlockComment::BreakableBlockComment(
const FormatToken &Token, unsigned StartColumn,
const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn,
unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableToken(Token, InPPDirective, Encoding, Style) {
: BreakableToken(Token, IndentLevel, InPPDirective, Encoding, Style) {
StringRef TokenText(Token.TokenText);
assert(TokenText.startswith("/*") && TokenText.endswith("*/"));
TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n");
@ -327,12 +325,6 @@ void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
LeadingWhitespace[LineIndex] =
Lines[LineIndex].begin() - Lines[LineIndex - 1].end();
// FIXME: We currently count tabs as 1 character. To solve this, we need to
// get the correct indentation width of the start of the comment, which
// requires correct counting of the tab expansions before the comment, and
// a configurable tab width. Since the current implementation only breaks
// if leading tabs are intermixed with spaces, that is not a high priority.
// Adjust the start column uniformly accross all lines.
StartOfLineColumn[LineIndex] = std::max<int>(
0,
@ -376,9 +368,9 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
Text.data() - Tok.TokenText.data() + Split.first;
unsigned CharsToRemove = Split.second;
assert(IndentAtLineBreak >= Decoration.size());
Whitespaces.replaceWhitespaceInToken(Tok, BreakOffsetInToken, CharsToRemove,
"", Prefix, InPPDirective, 1,
IndentAtLineBreak - Decoration.size());
Whitespaces.replaceWhitespaceInToken(
Tok, BreakOffsetInToken, CharsToRemove, "", Prefix, InPPDirective, 1,
IndentLevel, IndentAtLineBreak - Decoration.size());
}
void
@ -412,7 +404,8 @@ BreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex,
assert(StartOfLineColumn[LineIndex] >= Prefix.size());
Whitespaces.replaceWhitespaceInToken(
Tok, WhitespaceOffsetInToken, LeadingWhitespace[LineIndex], "", Prefix,
InPPDirective, 1, StartOfLineColumn[LineIndex] - Prefix.size());
InPPDirective, 1, IndentLevel,
StartOfLineColumn[LineIndex] - Prefix.size());
}
unsigned

View File

@ -66,12 +66,14 @@ public:
WhitespaceManager &Whitespaces) {}
protected:
BreakableToken(const FormatToken &Tok, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
: Tok(Tok), InPPDirective(InPPDirective), Encoding(Encoding),
Style(Style) {}
BreakableToken(const FormatToken &Tok, unsigned IndentLevel,
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style)
: Tok(Tok), IndentLevel(IndentLevel), InPPDirective(InPPDirective),
Encoding(Encoding), Style(Style) {}
const FormatToken &Tok;
const unsigned IndentLevel;
const bool InPPDirective;
const encoding::Encoding Encoding;
const FormatStyle &Style;
@ -88,9 +90,10 @@ public:
StringRef::size_type Length) const;
protected:
BreakableSingleLineToken(const FormatToken &Tok, unsigned StartColumn,
StringRef Prefix, StringRef Postfix,
bool InPPDirective, encoding::Encoding Encoding,
BreakableSingleLineToken(const FormatToken &Tok, unsigned IndentLevel,
unsigned StartColumn, StringRef Prefix,
StringRef Postfix, bool InPPDirective,
encoding::Encoding Encoding,
const FormatStyle &Style);
// The column in which the token starts.
@ -109,10 +112,10 @@ public:
///
/// \p StartColumn specifies the column in which the token will start
/// after formatting.
BreakableStringLiteral(const FormatToken &Tok, unsigned StartColumn,
StringRef Prefix, StringRef Postfix,
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
BreakableStringLiteral(const FormatToken &Tok, unsigned IndentLevel,
unsigned StartColumn, StringRef Prefix,
StringRef Postfix, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style);
virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit) const;
@ -126,9 +129,9 @@ public:
///
/// \p StartColumn specifies the column in which the comment will start
/// after formatting.
BreakableLineComment(const FormatToken &Token, unsigned StartColumn,
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
BreakableLineComment(const FormatToken &Token, unsigned IndentLevel,
unsigned StartColumn, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style);
virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit) const;
@ -150,10 +153,10 @@ public:
/// after formatting, while \p OriginalStartColumn specifies in which
/// column the comment started before formatting.
/// If the comment starts a line after formatting, set \p FirstInLine to true.
BreakableBlockComment(const FormatToken &Token, unsigned StartColumn,
unsigned OriginaStartColumn, bool FirstInLine,
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
BreakableBlockComment(const FormatToken &Token, unsigned IndentLevel,
unsigned StartColumn, unsigned OriginaStartColumn,
bool FirstInLine, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style);
virtual unsigned getLineCount() const;
virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,

View File

@ -303,12 +303,13 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
State.Stack.back().BreakBeforeParameter = false;
if (!DryRun) {
unsigned NewLines = 1;
unsigned Newlines = 1;
if (Current.is(tok::comment))
NewLines = std::max(NewLines, std::min(Current.NewlinesBefore,
Newlines = std::max(Newlines, std::min(Current.NewlinesBefore,
Style.MaxEmptyLinesToKeep + 1));
Whitespaces.replaceWhitespace(Current, NewLines, State.Column,
State.Column, State.Line->InPPDirective);
Whitespaces.replaceWhitespace(Current, Newlines, State.Line->Level,
State.Column, State.Column,
State.Line->InPPDirective);
}
if (!Current.isTrailingComment())
@ -363,7 +364,8 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
unsigned Spaces = State.NextToken->SpacesRequiredBefore + ExtraSpaces;
if (!DryRun)
Whitespaces.replaceWhitespace(Current, 0, Spaces, State.Column + Spaces);
Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0,
Spaces, State.Column + Spaces);
if (Current.Type == TT_ObjCSelectorName &&
State.Stack.back().ColonPos == 0) {
@ -693,21 +695,22 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
Text.startswith(Prefix = "L\""))) ||
(Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")")) ||
getRawStringLiteralPrefixPostfix(Text, Prefix, Postfix)) {
Token.reset(new BreakableStringLiteral(Current, StartColumn, Prefix,
Postfix, State.Line->InPPDirective,
Encoding, Style));
Token.reset(new BreakableStringLiteral(
Current, State.Line->Level, StartColumn, Prefix, Postfix,
State.Line->InPPDirective, Encoding, Style));
} else {
return 0;
}
} else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {
Token.reset(new BreakableBlockComment(
Current, StartColumn, Current.OriginalColumn, !Current.Previous,
State.Line->InPPDirective, Encoding, Style));
Current, State.Line->Level, StartColumn, Current.OriginalColumn,
!Current.Previous, State.Line->InPPDirective, Encoding, Style));
} else if (Current.Type == TT_LineComment &&
(Current.Previous == NULL ||
Current.Previous->Type != TT_ImplicitStringLiteral)) {
Token.reset(new BreakableLineComment(
Current, StartColumn, State.Line->InPPDirective, Encoding, Style));
Token.reset(new BreakableLineComment(Current, State.Line->Level,
StartColumn, State.Line->InPPDirective,
Encoding, Style));
} else {
return 0;
}

View File

@ -44,6 +44,19 @@ struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {
}
};
template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::UseTabStyle> {
static void
enumeration(IO &IO, clang::format::FormatStyle::UseTabStyle &Value) {
IO.enumCase(Value, "Never", clang::format::FormatStyle::UT_Never);
IO.enumCase(Value, "false", clang::format::FormatStyle::UT_Never);
IO.enumCase(Value, "Always", clang::format::FormatStyle::UT_Always);
IO.enumCase(Value, "true", clang::format::FormatStyle::UT_Always);
IO.enumCase(Value, "ForIndentation",
clang::format::FormatStyle::UT_ForIndentation);
}
};
template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::BraceBreakingStyle> {
static void
@ -194,7 +207,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.PointerBindsToType = false;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Cpp03;
LLVMStyle.UseTab = false;
LLVMStyle.UseTab = FormatStyle::UT_Never;
LLVMStyle.SpacesInParentheses = false;
LLVMStyle.SpaceInEmptyParentheses = false;
LLVMStyle.SpacesInCStyleCastParentheses = false;
@ -237,7 +250,7 @@ FormatStyle getGoogleStyle() {
GoogleStyle.PointerBindsToType = true;
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
GoogleStyle.UseTab = false;
GoogleStyle.UseTab = FormatStyle::UT_Never;
GoogleStyle.SpacesInParentheses = false;
GoogleStyle.SpaceInEmptyParentheses = false;
GoogleStyle.SpacesInCStyleCastParentheses = false;
@ -539,7 +552,7 @@ private:
Style.MaxEmptyLinesToKeep + 1);
Newlines = std::max(1u, Newlines);
Whitespaces->replaceWhitespace(
*(*I)->First, Newlines, /*Spaces=*/Indent,
*(*I)->First, Newlines, (*I)->Level, /*Spaces=*/Indent,
/*StartOfTokenColumn=*/Indent, Line.InPPDirective);
}
UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style, **I);
@ -556,10 +569,10 @@ private:
return false;
if (!DryRun) {
Whitespaces->replaceWhitespace(*LBrace.Children[0]->First,
/*Newlines=*/0, /*Spaces=*/1,
/*StartOfTokenColumn=*/State.Column,
State.Line->InPPDirective);
Whitespaces->replaceWhitespace(
*LBrace.Children[0]->First,
/*Newlines=*/0, /*IndentLevel=*/1, /*Spaces=*/1,
/*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style,
*LBrace.Children[0]);
Penalty += Formatter.format(State.Column + 1, DryRun);
@ -847,8 +860,9 @@ public:
if (TheLine.First->is(tok::eof)) {
if (PreviousLineWasTouched) {
unsigned NewLines = std::min(FirstTok->NewlinesBefore, 1u);
Whitespaces.replaceWhitespace(*TheLine.First, NewLines, /*Indent*/ 0,
/*TargetColumn*/ 0);
Whitespaces.replaceWhitespace(*TheLine.First, NewLines,
/*IndentLevel=*/0, /*Spaces=*/0,
/*TargetColumn=*/0);
}
} else if (TheLine.Type != LT_Invalid &&
(WasMoved || FormatPPDirective || touchesLine(TheLine))) {
@ -1225,7 +1239,7 @@ private:
++Newlines;
Whitespaces.replaceWhitespace(
RootToken, Newlines, Indent, Indent,
RootToken, Newlines, Indent / Style.IndentWidth, Indent, Indent,
InPPDirective && !RootToken.HasUnescapedNewline);
}

View File

@ -28,41 +28,44 @@ WhitespaceManager::Change::IsBeforeInFile::operator()(const Change &C1,
WhitespaceManager::Change::Change(
bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
unsigned Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore,
StringRef PreviousLinePostfix, StringRef CurrentLinePrefix,
tok::TokenKind Kind, bool ContinuesPPDirective)
unsigned IndentLevel, unsigned Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective)
: CreateReplacement(CreateReplacement),
OriginalWhitespaceRange(OriginalWhitespaceRange),
StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
PreviousLinePostfix(PreviousLinePostfix),
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces) {}
ContinuesPPDirective(ContinuesPPDirective), IndentLevel(IndentLevel),
Spaces(Spaces) {}
void WhitespaceManager::replaceWhitespace(const FormatToken &Tok,
unsigned Newlines, unsigned Spaces,
unsigned Newlines,
unsigned IndentLevel, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective) {
Changes.push_back(Change(true, Tok.WhitespaceRange, Spaces,
Changes.push_back(Change(true, Tok.WhitespaceRange, IndentLevel, Spaces,
StartOfTokenColumn, Newlines, "", "",
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
}
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) {
Changes.push_back(Change(false, Tok.WhitespaceRange, /*Spaces=*/0,
Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
Changes.push_back(Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
/*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore,
"", "", Tok.Tok.getKind(),
InPPDirective && !Tok.IsFirst));
}
void WhitespaceManager::replaceWhitespaceInToken(
const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
unsigned Newlines, unsigned Spaces) {
unsigned Newlines, unsigned IndentLevel, unsigned Spaces) {
Changes.push_back(Change(
true, SourceRange(Tok.getStartOfNonWhitespace().getLocWithOffset(Offset),
Tok.getStartOfNonWhitespace().getLocWithOffset(
Offset + ReplaceChars)),
Spaces, Spaces, Newlines, PreviousPostfix, CurrentPrefix,
IndentLevel, Spaces, Spaces, Newlines, PreviousPostfix, CurrentPrefix,
// If we don't add a newline this change doesn't start a comment. Thus,
// when we align line comments, we don't need to treat this change as one.
// FIXME: We still need to take this change in account to properly
@ -225,7 +228,8 @@ void WhitespaceManager::generateChanges() {
C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn);
else
appendNewlineText(ReplacementText, C.NewlinesBefore);
appendIndentText(ReplacementText, C.Spaces, C.StartOfTokenColumn - C.Spaces);
appendIndentText(ReplacementText, C.IndentLevel, C.Spaces,
C.StartOfTokenColumn - C.Spaces);
ReplacementText.append(C.CurrentLinePrefix);
storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
}
@ -264,11 +268,14 @@ void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines,
}
}
void WhitespaceManager::appendIndentText(std::string &Text, unsigned Spaces,
void WhitespaceManager::appendIndentText(std::string &Text,
unsigned IndentLevel, unsigned Spaces,
unsigned WhitespaceStartColumn) {
if (!Style.UseTab) {
switch (Style.UseTab) {
case FormatStyle::UT_Never:
Text.append(std::string(Spaces, ' '));
} else {
break;
case FormatStyle::UT_Always: {
unsigned FirstTabWidth =
Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
// Indent with tabs only when there's at least one full tab.
@ -278,6 +285,19 @@ void WhitespaceManager::appendIndentText(std::string &Text, unsigned Spaces,
}
Text.append(std::string(Spaces / Style.TabWidth, '\t'));
Text.append(std::string(Spaces % Style.TabWidth, ' '));
break;
}
case FormatStyle::UT_ForIndentation:
if (WhitespaceStartColumn == 0) {
unsigned Indentation = IndentLevel * Style.IndentWidth;
if (Indentation > Spaces)
Indentation = Spaces;
unsigned Tabs = Indentation / Style.TabWidth;
Text.append(std::string(Tabs, '\t'));
Spaces -= Tabs * Style.TabWidth;
}
Text.append(std::string(Spaces, ' '));
break;
}
}

View File

@ -44,7 +44,8 @@ public:
/// \brief Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
void replaceWhitespace(const FormatToken &Tok, unsigned Newlines,
unsigned Spaces, unsigned StartOfTokenColumn,
unsigned IndentLevel, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective = false);
/// \brief Adds information about an unchangable token's whitespace.
@ -65,7 +66,8 @@ public:
unsigned ReplaceChars,
StringRef PreviousPostfix,
StringRef CurrentPrefix, bool InPPDirective,
unsigned Newlines, unsigned Spaces);
unsigned Newlines, unsigned IndentLevel,
unsigned Spaces);
/// \brief Returns all the \c Replacements created during formatting.
const tooling::Replacements &generateReplacements();
@ -96,7 +98,7 @@ private:
/// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
/// trailing comments and escaped newlines.
Change(bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
unsigned Spaces, unsigned StartOfTokenColumn,
unsigned IndentLevel, unsigned Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind,
bool ContinuesPPDirective);
@ -116,6 +118,11 @@ private:
tok::TokenKind Kind;
bool ContinuesPPDirective;
// The number of nested blocks the token is in. This is used to add tabs
// only for the indentation, and not for alignment, when
// UseTab = US_ForIndentation.
unsigned IndentLevel;
// The number of spaces in front of the token or broken part of the token.
// This will be adapted when aligning tokens.
unsigned Spaces;
@ -157,8 +164,8 @@ private:
void appendNewlineText(std::string &Text, unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
unsigned EscapedNewlineColumn);
void appendIndentText(std::string &Text, unsigned Spaces,
unsigned WhitespaceStartColumn);
void appendIndentText(std::string &Text, unsigned IndentLevel,
unsigned Spaces, unsigned WhitespaceStartColumn);
SmallVector<Change, 16> Changes;
SourceManager &SourceMgr;

View File

@ -5758,7 +5758,7 @@ TEST_F(FormatTest, ConfigurableFunctionDeclarationIndentAfterType) {
TEST_F(FormatTest, ConfigurableUseOfTab) {
FormatStyle Tab = getLLVMStyleWithColumns(42);
Tab.IndentWidth = 8;
Tab.UseTab = true;
Tab.UseTab = FormatStyle::UT_Always;
Tab.AlignEscapedNewlinesLeft = true;
EXPECT_EQ("if (aaaaaaaa && // q\n"
@ -5858,7 +5858,83 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
" \t */",
Tab));
Tab.UseTab = false;
Tab.UseTab = FormatStyle::UT_ForIndentation;
EXPECT_EQ("if (aaaaaaaa && // q\n"
" bb) // w\n"
"\t;",
format("if (aaaaaaaa &&// q\n"
"bb)// w\n"
";",
Tab));
verifyFormat("class X {\n"
"\tvoid f() {\n"
"\t\tsomeFunction(parameter1,\n"
"\t\t parameter2);\n"
"\t}\n"
"};",
Tab);
verifyFormat("{\n"
"\tQ({\n"
"\t\t int a;\n"
"\t\t someFunction(aaaaaaaaaa,\n"
"\t\t bbbbbbbbb);\n"
"\t },\n"
"\t p);\n"
"}",
Tab);
EXPECT_EQ("{\n"
"\t/* aaaa\n"
"\t bbbb */\n"
"}",
format("{\n"
"/* aaaa\n"
" bbbb */\n"
"}",
Tab));
EXPECT_EQ("{\n"
"\t/*\n"
"\t aaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"\t bbbbbbbbbbbbb\n"
"\t*/\n"
"}",
format("{\n"
"/*\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbb\n"
"*/\n"
"}",
Tab));
EXPECT_EQ("{\n"
"\t// aaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"\t// bbbbbbbbbbbbb\n"
"}",
format("{\n"
"\t// aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbb\n"
"}",
Tab));
EXPECT_EQ("{\n"
"\t/*\n"
"\t aaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"\t bbbbbbbbbbbbb\n"
"\t*/\n"
"}",
format("{\n"
"\t/*\n"
"\t aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbb\n"
"\t*/\n"
"}",
Tab));
EXPECT_EQ("{\n"
"\t/*\n"
"\n"
"\t*/\n"
"}",
format("{\n"
"\t/*\n"
"\n"
"\t*/\n"
"}", Tab));
Tab.UseTab = FormatStyle::UT_Never;
EXPECT_EQ("/*\n"
" a\t\tcomment\n"
" in multiple lines\n"
@ -6265,7 +6341,6 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(PointerBindsToType);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
CHECK_PARSE_BOOL(UseTab);
CHECK_PARSE_BOOL(IndentFunctionDeclarationAfterType);
CHECK_PARSE_BOOL(SpacesInParentheses);
CHECK_PARSE_BOOL(SpaceInEmptyParentheses);
@ -6292,6 +6367,13 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("Standard: C++11", Standard, FormatStyle::LS_Cpp11);
CHECK_PARSE("Standard: Auto", Standard, FormatStyle::LS_Auto);
Style.UseTab = FormatStyle::UT_ForIndentation;
CHECK_PARSE("UseTab: false", UseTab, FormatStyle::UT_Never);
CHECK_PARSE("UseTab: true", UseTab, FormatStyle::UT_Always);
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);
CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation);
CHECK_PARSE("UseTab: Always", UseTab, FormatStyle::UT_Always);
Style.ColumnLimit = 123;
FormatStyle BaseStyle = getLLVMStyle();
CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);