r192503 - Support formatting of preprocessor branches.
Manuel Klimek
klimek at google.com
Fri Oct 11 14:25:45 PDT 2013
Author: klimek
Date: Fri Oct 11 16:25:45 2013
New Revision: 192503
URL: http://llvm.org/viewvc/llvm-project?rev=192503&view=rev
Log:
Support formatting of preprocessor branches.
We now correctly format:
void SomeFunction(int param1,
#ifdef X
NoTemplate param2,
#else
template <
#ifdef A
MyType<Some> >
#else
Type1, Type2>
#endif
param2,
#endif
param3) {
f();
}
Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/ContinuationIndenter.h
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/lib/Format/FormatToken.cpp
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.h
cfe/trunk/lib/Format/WhitespaceManager.cpp
cfe/trunk/lib/Format/WhitespaceManager.h
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Fri Oct 11 16:25:45 2013
@@ -221,7 +221,7 @@ unsigned ContinuationIndenter::addTokenT
void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
unsigned ExtraSpaces) {
- const FormatToken &Current = *State.NextToken;
+ FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *State.NextToken->Previous;
if (Current.is(tok::equal) &&
(State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) &&
@@ -301,7 +301,7 @@ void ContinuationIndenter::addTokenOnCur
unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
bool DryRun) {
- const FormatToken &Current = *State.NextToken;
+ FormatToken &Current = *State.NextToken;
const FormatToken &Previous = *State.NextToken->Previous;
// If we are continuing an expression, we want to indent an extra 4 spaces.
unsigned ContinuationIndent =
Modified: cfe/trunk/lib/Format/ContinuationIndenter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.h (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.h Fri Oct 11 16:25:45 2013
@@ -250,7 +250,7 @@ struct LineState {
unsigned Column;
/// \brief The token that needs to be next formatted.
- const FormatToken *NextToken;
+ FormatToken *NextToken;
/// \brief \c true if this line contains a continued for-loop section.
bool LineContainsContinuedForLoopSection;
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Fri Oct 11 16:25:45 2013
@@ -447,14 +447,19 @@ private:
// State already examined with lower penalty.
continue;
- addNextStateToQueue(Penalty, Node, /*NewLine=*/false);
- addNextStateToQueue(Penalty, Node, /*NewLine=*/true);
+ FormatDecision LastFormat = Node->State.NextToken->Decision;
+ if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
+ addNextStateToQueue(Penalty, Node, /*NewLine=*/false);
+ if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
+ addNextStateToQueue(Penalty, Node, /*NewLine=*/true);
}
- if (Queue.empty())
+ if (Queue.empty()) {
// We were unable to find a solution, do nothing.
// FIXME: Add diagnostic?
+ DEBUG(llvm::dbgs() << "Could not find a solution.\n");
return 0;
+ }
// Reconstruct the solution.
if (!DryRun)
@@ -815,29 +820,54 @@ public:
const std::vector<CharSourceRange> &Ranges)
: Style(Style), Lex(Lex), SourceMgr(SourceMgr),
Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())),
- Ranges(Ranges), Encoding(encoding::detectEncoding(Lex.getBuffer())) {
+ Ranges(Ranges), UnwrappedLines(1),
+ Encoding(encoding::detectEncoding(Lex.getBuffer())) {
DEBUG(llvm::dbgs() << "File encoding: "
<< (Encoding == encoding::Encoding_UTF8 ? "UTF8"
: "unknown")
<< "\n");
}
- virtual ~Formatter() {
- for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- delete AnnotatedLines[i];
- }
- }
-
tooling::Replacements format() {
+ tooling::Replacements Result;
FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);
UnwrappedLineParser Parser(Style, Tokens.lex(), *this);
bool StructuralError = Parser.parse();
+ assert(UnwrappedLines.rbegin()->empty());
+ for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
+ ++Run) {
+ DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
+ SmallVector<AnnotatedLine *, 16> AnnotatedLines;
+ for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) {
+ AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
+ }
+ tooling::Replacements RunResult =
+ format(AnnotatedLines, StructuralError, Tokens);
+ DEBUG({
+ llvm::dbgs() << "Replacements for run " << Run << ":\n";
+ for (tooling::Replacements::iterator I = RunResult.begin(),
+ E = RunResult.end();
+ I != E; ++I) {
+ llvm::dbgs() << I->toString() << "\n";
+ }
+ });
+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
+ delete AnnotatedLines[i];
+ }
+ Result.insert(RunResult.begin(), RunResult.end());
+ Whitespaces.reset();
+ }
+ return Result;
+ }
+
+ tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ bool StructuralError, FormatTokenLexer &Tokens) {
TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Annotator.annotate(*AnnotatedLines[i]);
}
- deriveLocalStyle();
+ deriveLocalStyle(AnnotatedLines);
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
}
@@ -920,8 +950,7 @@ public:
} else {
// Format the first token if necessary, and notify the WhitespaceManager
// about the unchanged whitespace.
- for (const FormatToken *Tok = TheLine.First; Tok != NULL;
- Tok = Tok->Next) {
+ for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
if (Tok == TheLine.First &&
(Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
unsigned LevelIndent = Tok->OriginalColumn;
@@ -947,6 +976,9 @@ public:
// last token.
PreviousLineWasTouched = false;
}
+ for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
+ Tok->Finalized = true;
+ }
PreviousLine = *I;
}
return Whitespaces.generateReplacements();
@@ -957,7 +989,8 @@ private:
return Text.count('\r') * 2 > Text.count('\n');
}
- void deriveLocalStyle() {
+ void
+ deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
unsigned CountBoundToVariable = 0;
unsigned CountBoundToType = 0;
bool HasCpp03IncompatibleFormat = false;
@@ -1229,13 +1262,18 @@ private:
}
virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
- AnnotatedLines.push_back(new AnnotatedLine(TheLine));
+ assert(!UnwrappedLines.empty());
+ UnwrappedLines.back().push_back(TheLine);
+ }
+
+ virtual void finishRun() {
+ UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());
}
/// \brief Add a new line and the required indent before the first Token
/// of the \c UnwrappedLine if there was no structural parsing error.
/// Returns the indent level of the \c UnwrappedLine.
- void formatFirstToken(const FormatToken &RootToken,
+ void formatFirstToken(FormatToken &RootToken,
const AnnotatedLine *PreviousLine, unsigned Indent,
bool InPPDirective) {
unsigned Newlines =
@@ -1272,7 +1310,7 @@ private:
SourceManager &SourceMgr;
WhitespaceManager Whitespaces;
std::vector<CharSourceRange> Ranges;
- SmallVector<AnnotatedLine *, 16> AnnotatedLines;
+ SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;
encoding::Encoding Encoding;
bool BinPackInconclusiveFunctions;
Modified: cfe/trunk/lib/Format/FormatToken.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.cpp (original)
+++ cfe/trunk/lib/Format/FormatToken.cpp Fri Oct 11 16:25:45 2013
@@ -145,6 +145,7 @@ void CommaSeparatedList::precomputeForma
bool HasRowWithSufficientColumns = false;
unsigned Column = 0;
for (unsigned i = 0, e = ItemLengths.size(); i != e; ++i) {
+ assert(i < MustBreakBeforeItem.size());
if (MustBreakBeforeItem[i] || Column == Columns) {
++Format.LineCount;
Column = 0;
Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Fri Oct 11 16:25:45 2013
@@ -76,6 +76,12 @@ enum ParameterPackingKind {
PPK_Inconclusive
};
+enum FormatDecision {
+ FD_Unformatted,
+ FD_Continue,
+ FD_Break
+};
+
class TokenRole;
class AnnotatedLine;
@@ -93,7 +99,8 @@ struct FormatToken {
LongestObjCSelectorName(0), FakeRParens(0),
StartsBinaryExpression(false), EndsBinaryExpression(false),
LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false),
- MatchingParen(NULL), Previous(NULL), Next(NULL) {}
+ MatchingParen(NULL), Previous(NULL), Next(NULL),
+ Decision(FD_Unformatted), Finalized(false) {}
/// \brief The \c Token.
Token Tok;
@@ -338,6 +345,14 @@ struct FormatToken {
SmallVector<AnnotatedLine *, 1> Children;
+ /// \brief Stores the formatting decision for the token once it was made.
+ FormatDecision Decision;
+
+ /// \brief If \c true, this token has been fully formatted (indented and
+ /// potentially re-formatted inside), and we do not allow further formatting
+ /// changes.
+ bool Finalized;
+
private:
// Disallow copying.
FormatToken(const FormatToken &) LLVM_DELETED_FUNCTION;
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Oct 11 16:25:45 2013
@@ -523,11 +523,17 @@ private:
if (CurrentToken != NULL)
CurrentToken = CurrentToken->Next;
- // Reset token type in case we have already looked at it and then recovered
- // from an error (e.g. failure to find the matching >).
- if (CurrentToken != NULL && CurrentToken->Type != TT_LambdaLSquare &&
- CurrentToken->Type != TT_ImplicitStringLiteral)
- CurrentToken->Type = TT_Unknown;
+ if (CurrentToken != NULL) {
+ // Reset token type in case we have already looked at it and then
+ // recovered from an error (e.g. failure to find the matching >).
+ if (CurrentToken->Type != TT_LambdaLSquare &&
+ CurrentToken->Type != TT_ImplicitStringLiteral)
+ CurrentToken->Type = TT_Unknown;
+ if (CurrentToken->Role)
+ CurrentToken->Role.reset(NULL);
+ CurrentToken->FakeLParens.clear();
+ CurrentToken->FakeRParens = 0;
+ }
}
/// \brief A struct to hold information valid in a specific context, e.g.
@@ -1482,10 +1488,13 @@ void TokenAnnotator::printDebugInfo(cons
<< " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
<< " S=" << Tok->SpacesRequiredBefore
<< " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
- << " PPK=" << Tok->PackingKind << " FakeLParens=";
+ << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
+ << " FakeLParens=";
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
+ if (Tok->Next == NULL)
+ assert(Tok == Line.Last);
Tok = Tok->Next;
}
llvm::errs() << "----\n";
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Fri Oct 11 16:25:45 2013
@@ -174,6 +174,8 @@ public:
return Tokens[Position];
}
+ void reset() { Position = -1; }
+
private:
ArrayRef<FormatToken *> Tokens;
int Position;
@@ -186,23 +188,54 @@ UnwrappedLineParser::UnwrappedLineParser
UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
CurrentLines(&Lines), StructuralError(false), Style(Style), Tokens(NULL),
- Callback(Callback), AllTokens(Tokens) {}
+ Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1) {}
+
+void UnwrappedLineParser::reset() {
+ PPBranchLevel = -1;
+ Line.reset(new UnwrappedLine);
+ CommentsBeforeNextToken.clear();
+ FormatTok = NULL;
+ MustBreakBeforeNextToken = false;
+ PreprocessorDirectives.clear();
+ CurrentLines = &Lines;
+ DeclarationScopeStack.clear();
+ StructuralError = false;
+ PPStack.clear();
+}
bool UnwrappedLineParser::parse() {
- DEBUG(llvm::dbgs() << "----\n");
IndexedTokenSource TokenSource(AllTokens);
- Tokens = &TokenSource;
- readToken();
- parseFile();
- for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),
- E = Lines.end();
- I != E; ++I) {
- Callback.consumeUnwrappedLine(*I);
- }
+ do {
+ DEBUG(llvm::dbgs() << "----\n");
+ reset();
+ Tokens = &TokenSource;
+ TokenSource.reset();
+
+ readToken();
+ parseFile();
+ // Create line with eof token.
+ pushToken(FormatTok);
+ addUnwrappedLine();
+
+ for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),
+ E = Lines.end();
+ I != E; ++I) {
+ Callback.consumeUnwrappedLine(*I);
+ }
+ Callback.finishRun();
+ Lines.clear();
+ while (!PPLevelBranchIndex.empty() &&
+ PPLevelBranchIndex.back() + 1 == PPLevelBranchCount.back()) {
+ PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
+ PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
+ }
+ if (!PPLevelBranchIndex.empty()) {
+ ++PPLevelBranchIndex.back();
+ assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
+ assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
+ }
+ } while (!PPLevelBranchIndex.empty());
- // Create line with eof token.
- pushToken(FormatTok);
- Callback.consumeUnwrappedLine(*Line);
return StructuralError;
}
@@ -379,11 +412,11 @@ void UnwrappedLineParser::parsePPDirecti
parsePPDefine();
return;
case tok::pp_if:
- parsePPIf();
+ parsePPIf(/*IfDef=*/false);
break;
case tok::pp_ifdef:
case tok::pp_ifndef:
- parsePPIfdef();
+ parsePPIf(/*IfDef=*/true);
break;
case tok::pp_else:
parsePPElse();
@@ -407,12 +440,20 @@ void UnwrappedLineParser::pushPPConditio
PPStack.push_back(PP_Conditional);
}
-void UnwrappedLineParser::parsePPIf() {
+void UnwrappedLineParser::parsePPIf(bool IfDef) {
+ ++PPBranchLevel;
+ assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
+ if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
+ PPLevelBranchIndex.push_back(0);
+ PPLevelBranchCount.push_back(0);
+ }
+ PPChainBranchIndex.push(0);
nextToken();
- if ((FormatTok->Tok.isLiteral() &&
- StringRef(FormatTok->Tok.getLiteralData(), FormatTok->Tok.getLength()) ==
- "0") ||
- FormatTok->Tok.is(tok::kw_false)) {
+ bool IsLiteralFalse = (FormatTok->Tok.isLiteral() &&
+ StringRef(FormatTok->Tok.getLiteralData(),
+ FormatTok->Tok.getLength()) == "0") ||
+ FormatTok->Tok.is(tok::kw_false);
+ if ((!IfDef && IsLiteralFalse) || PPLevelBranchIndex[PPBranchLevel] > 0) {
PPStack.push_back(PP_Unreachable);
} else {
pushPPConditional();
@@ -420,21 +461,34 @@ void UnwrappedLineParser::parsePPIf() {
parsePPUnknown();
}
-void UnwrappedLineParser::parsePPIfdef() {
- pushPPConditional();
- parsePPUnknown();
-}
-
void UnwrappedLineParser::parsePPElse() {
if (!PPStack.empty())
PPStack.pop_back();
- pushPPConditional();
+ assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
+ if (!PPChainBranchIndex.empty())
+ ++PPChainBranchIndex.top();
+ if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
+ PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top()) {
+ PPStack.push_back(PP_Unreachable);
+ } else {
+ pushPPConditional();
+ }
parsePPUnknown();
}
void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
void UnwrappedLineParser::parsePPEndIf() {
+ assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
+ if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
+ if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) {
+ assert(PPLevelBranchCount[PPBranchLevel] == 0);
+ PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
+ }
+ }
+ --PPBranchLevel;
+ if (!PPChainBranchIndex.empty())
+ PPChainBranchIndex.pop();
if (!PPStack.empty())
PPStack.pop_back();
parsePPUnknown();
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Fri Oct 11 16:25:45 2013
@@ -52,6 +52,7 @@ class UnwrappedLineConsumer {
public:
virtual ~UnwrappedLineConsumer() {}
virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
+ virtual void finishRun() = 0;
};
class FormatTokenSource;
@@ -65,14 +66,14 @@ public:
bool parse();
private:
+ void reset();
void parseFile();
void parseLevel(bool HasOpeningBrace);
void parseBlock(bool MustBeDeclaration, bool AddLevel = true);
void parseChildBlock();
void parsePPDirective();
void parsePPDefine();
- void parsePPIf();
- void parsePPIfdef();
+ void parsePPIf(bool IfDef);
void parsePPElIf();
void parsePPElse();
void parsePPEndIf();
@@ -161,6 +162,27 @@ private:
// Keeps a stack of currently active preprocessor branching directives.
SmallVector<PPBranchKind, 16> PPStack;
+ // The \c UnwrappedLineParser re-parses the code for each combination
+ // of preprocessor branches that can be taken.
+ // To that end, we take the same branch (#if, #else, or one of the #elif
+ // branches) for each nesting level of preprocessor branches.
+ // \c PPBranchLevel stores the current nesting level of preprocessor
+ // branches during one pass over the code.
+ int PPBranchLevel;
+
+ // Contains the current branch (#if, #else or one of the #elif branches)
+ // for each nesting level.
+ SmallVector<int, 8> PPLevelBranchIndex;
+
+ // Contains the maximum number of branches at each nesting level.
+ SmallVector<int, 8> PPLevelBranchCount;
+
+ // Contains the number of branches per nesting level we are currently
+ // in while parsing a preprocessor branch sequence.
+ // This is used to update PPLevelBranchCount at the end of a branch
+ // sequence.
+ std::stack<int> PPChainBranchIndex;
+
friend class ScopedLineState;
};
Modified: cfe/trunk/lib/Format/WhitespaceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/WhitespaceManager.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/WhitespaceManager.cpp (original)
+++ cfe/trunk/lib/Format/WhitespaceManager.cpp Fri Oct 11 16:25:45 2013
@@ -39,11 +39,18 @@ WhitespaceManager::Change::Change(
ContinuesPPDirective(ContinuesPPDirective), IndentLevel(IndentLevel),
Spaces(Spaces) {}
-void WhitespaceManager::replaceWhitespace(const FormatToken &Tok,
- unsigned Newlines,
+void WhitespaceManager::reset() {
+ Changes.clear();
+ Replaces.clear();
+}
+
+void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
unsigned IndentLevel, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective) {
+ if (Tok.Finalized)
+ return;
+ Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
Changes.push_back(Change(true, Tok.WhitespaceRange, IndentLevel, Spaces,
StartOfTokenColumn, Newlines, "", "",
Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
@@ -51,6 +58,8 @@ void WhitespaceManager::replaceWhitespac
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) {
+ if (Tok.Finalized)
+ return;
Changes.push_back(Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
/*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore,
"", "", Tok.Tok.getKind(),
@@ -61,6 +70,8 @@ void WhitespaceManager::replaceWhitespac
const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
unsigned Newlines, unsigned IndentLevel, unsigned Spaces) {
+ if (Tok.Finalized)
+ return;
Changes.push_back(Change(
true, SourceRange(Tok.getStartOfNonWhitespace().getLocWithOffset(Offset),
Tok.getStartOfNonWhitespace().getLocWithOffset(
Modified: cfe/trunk/lib/Format/WhitespaceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/WhitespaceManager.h?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/lib/Format/WhitespaceManager.h (original)
+++ cfe/trunk/lib/Format/WhitespaceManager.h Fri Oct 11 16:25:45 2013
@@ -41,9 +41,12 @@ public:
bool UseCRLF)
: SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {}
+ /// \brief Prepares the \c WhitespaceManager for another run.
+ void reset();
+
/// \brief Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
- void replaceWhitespace(const FormatToken &Tok, unsigned Newlines,
+ void replaceWhitespace(FormatToken &Tok, unsigned Newlines,
unsigned IndentLevel, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective = false);
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=192503&r1=192502&r2=192503&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Fri Oct 11 16:25:45 2013
@@ -22,6 +22,7 @@ protected:
std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length,
const FormatStyle &Style) {
DEBUG(llvm::errs() << "---\n");
+ DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
tooling::Replacements Replaces = reformat(Style, Code, Ranges);
ReplacementCount = Replaces.size();
@@ -66,7 +67,14 @@ protected:
JustReplacedNewline = false;
}
}
- return MessedUp;
+ std::string WithoutWhitespace;
+ if (MessedUp[0] != ' ')
+ WithoutWhitespace.push_back(MessedUp[0]);
+ for (unsigned i = 1, e = MessedUp.size(); i != e; ++i) {
+ if (MessedUp[i] != ' ' || MessedUp[i - 1] != ' ')
+ WithoutWhitespace.push_back(MessedUp[i]);
+ }
+ return WithoutWhitespace;
}
FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
@@ -103,7 +111,7 @@ TEST_F(FormatTest, MessUp) {
EXPECT_EQ("1 2 3\n", messUp("1\n2\n3\n"));
EXPECT_EQ("a\n//b\nc", messUp("a\n//b\nc"));
EXPECT_EQ("a\n#b\nc", messUp("a\n#b\nc"));
- EXPECT_EQ("a\n#b c d\ne", messUp("a\n#b\\\nc\\\nd\ne"));
+ EXPECT_EQ("a\n#b c d\ne", messUp("a\n#b\\\nc\\\nd\ne"));
}
//===----------------------------------------------------------------------===//
@@ -2263,6 +2271,38 @@ TEST_F(FormatTest, LayoutStatementsAroun
"#endif\n"
"{\n"
"}");
+ verifyFormat("void f() {\n"
+ " if (true)\n"
+ "#ifdef A\n"
+ " f(42);\n"
+ " x();\n"
+ "#else\n"
+ " g();\n"
+ " x();\n"
+ "#endif\n"
+ "}");
+ verifyFormat("void f(param1, param2,\n"
+ " param3,\n"
+ "#ifdef A\n"
+ " param4(param5,\n"
+ "#ifdef A1\n"
+ " param6,\n"
+ "#ifdef A2\n"
+ " param7),\n"
+ "#else\n"
+ " param8),\n"
+ " param9,\n"
+ "#endif\n"
+ " param10,\n"
+ "#endif\n"
+ " param11)\n"
+ "#else\n"
+ " param12)\n"
+ "#endif\n"
+ "{\n"
+ " x();\n"
+ "}",
+ getLLVMStyleWithColumns(28));
}
TEST_F(FormatTest, LayoutBlockInsideParens) {
@@ -3383,10 +3423,10 @@ TEST_F(FormatTest, AlignsPipes) {
" << aaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
verifyFormat("return out << \"somepacket = {\\n\"\n"
- " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n"
- " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n"
- " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n"
- " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n"
+ " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n"
+ " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n"
+ " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n"
+ " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n"
" << \"}\";");
verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n"
@@ -4295,7 +4335,7 @@ TEST_F(FormatTest, IncorrectCodeMissingP
TEST_F(FormatTest, DoesNotTouchUnwrappedLinesWithErrors) {
verifyFormat("namespace {\n"
- "class Foo { Foo (\n"
+ "class Foo { Foo (\n"
"};\n"
"} // comment");
}
@@ -4522,8 +4562,11 @@ TEST_F(FormatTest, UnderstandContextOfRe
}
TEST_F(FormatTest, DoNotInterfereWithErrorAndWarning) {
- verifyFormat("#error Leave all white!!!!! space* alone!\n");
- verifyFormat("#warning Leave all white!!!!! space* alone!\n");
+ EXPECT_EQ("#error Leave all white!!!!! space* alone!\n",
+ format("#error Leave all white!!!!! space* alone!\n"));
+ EXPECT_EQ(
+ "#warning Leave all white!!!!! space* alone!\n",
+ format("#warning Leave all white!!!!! space* alone!\n"));
EXPECT_EQ("#error 1", format(" # error 1"));
EXPECT_EQ("#warning 1", format(" # warning 1"));
}
@@ -4568,7 +4611,8 @@ TEST_F(FormatTest, MergeHandlingInTheFac
" if (true) continue;\n"
"#endif\n"
" // Comment\n"
- " if (true) continue;",
+ " if (true) continue;\n"
+ "}",
ShortMergedIf);
}
More information about the cfe-commits
mailing list